Fluxo de Funcionamento do SGMBlocks
Este documento descreve o ciclo completo de um bloco do SGMBlocks, do registro no ServiceManager até a renderização no HTML final do site. Também cobre os três eventos anexados pelo módulo e a persistência dos dados.
1. Registro de blocos
Onde acontece
O registro vive em config/module.config.php, dentro da chave block_layouts.factories. O Omeka S funde esse mapa à sua configuração global no bootstrap.
Como o ServiceManager resolve um bloco
- O Omeka precisa renderizar ou editar um bloco.
- Consulta o mapa e encontra a factory correspondente ao
block_layout. - Invoca a factory com o
ContainerInterface. - A factory obtém
FormElementManagerdo container. - Retorna a instância do bloco para o Omeka consumir.
Blocos registrados
block_layout | Factory | Classe do bloco |
|---|---|---|
accordion-block | SGMBlocks\Service\BlockLayout\AccordionBlockFactory | SGMBlocks\Site\BlockLayout\AccordionBlock |
banner-page | SGMBlocks\Service\BlockLayout\BannerPageFactory | SGMBlocks\Site\BlockLayout\BannerPage |
button-block | SGMBlocks\Service\BlockLayout\ButtonBlockFactory | SGMBlocks\Site\BlockLayout\ButtonBlock |
icon-block | SGMBlocks\Service\BlockLayout\IconBlockFactory | SGMBlocks\Site\BlockLayout\IconBlock |
page-description | SGMBlocks\Service\BlockLayout\PageDescriptionFactory | SGMBlocks\Site\BlockLayout\PageDescription |
search-bar-block | SGMBlocks\Service\BlockLayout\SearchBarBlockFactory | SGMBlocks\Site\BlockLayout\SearchBarBlock |
thumbnail-block | SGMBlocks\Service\BlockLayout\ThumbnailBlockFactory | SGMBlocks\Site\BlockLayout\ThumbnailBlock |
Registro de formulários
Os Fieldset de bloco são registrados em form_elements.invokables. O FormElementManager instancia a classe diretamente sem factory. Dentro do bloco, o acesso é feito por $this->formElementManager->get(FormClass::class).
A única factory em form_elements.factories substitui a do core:
'form_elements' => [
'factories' => [
'Omeka\Form\PageLayoutDataForm' => Service\Form\PageLayoutDataFormFactory::class,
],
],
A substituição existe apenas para injetar EventManager no PageLayoutDataForm, sem o qual form.add_elements não dispara.
2. Eventos
O SGMBlocks anexa quatro listeners no SharedEventManager dentro de Module::attachListeners. Os alvos são dois formulários do core e um controller do admin.
2.1. PageLayoutDataForm, evento form.add_elements
Handler: SGMBlocks\Service\Form\PageCustomFieldsHandler::handlePageLayoutForm.
Passo a passo:
- O usuário abre o modal de layout da página no admin.
- O Omeka constrói
PageLayoutDataFormusando a factory substituída porPageLayoutDataFormFactory. - A factory injeta
EventManagerno formulário. - O formulário dispara
form.add_elements. - O handler adiciona o checkbox
o:layout_data[fixed_header]. - O Omeka renderiza o formulário e persiste o valor em
o:layout_dataao salvar.
Pré-requisito: a factory substituída. Sem ela o evento nunca dispara e o campo desaparece.
2.2. SiteSettingsForm, evento form.add_elements
Handler: SGMBlocks\Service\Form\SiteCustomFieldsHandler::handleSiteSettings.
Passos:
- O admin acessa a página de edição de configurações do site.
- O
SiteSettingsFormé montado. - O handler lê o valor salvo de
Omeka\Settings\Sitecom a chavesgmblocks_search_suggestions. - Normaliza o valor: se vier como string JSON, faz
json_decode. Se vier como array, usa direto. - Registra o
element_groupsgmblockscom o rótuloSugestões de busca para o site. - Adiciona um
Laminas\Form\Element\Hiddennomeadosgmblocks_search_suggestionscomvalueem JSON.
2.3. SiteSettingsForm, evento form.add_input_filters
Handler: SGMBlocks\Service\Form\SiteCustomFieldsHandler::handleSiteSettingsFilters.
Passos:
- O usuário submete o formulário de configurações do site.
- O Omeka aplica os input filters registrados.
- O handler adiciona um
Callbackque recebe o valor bruto do campo hidden, aceita array ou string JSON, fazjson_decodequando necessário e retorna sempre um array. - O array resultante entra no fluxo padrão do
SiteSettingse é salvo.
2.4. Omeka\Controller\SiteAdmin\Index, evento view.layout
Handler: SGMBlocks\Service\Form\SiteCustomFieldsHandler::handleSiteSettingsAssets.
Passos:
- O controller
Omeka\Controller\SiteAdmin\Indexprepara o layout da página do admin do site. - O handler inspeciona
params()->fromRoute()e só age quandoaction === 'edit'. - Quando a condição vale, anexa
admin.csscomheadLinkesite-settings.jscomheadScriptusandodefer. - O JS assume o controle do campo hidden
sgmblocks-search-suggestionse monta a interface de adicionar e remover itens.
3. Ciclo de vida do formulário no admin
- O usuário adiciona um bloco ao layout da página.
- O Omeka chama
BlockLayout::formpassando$view,$site,$page, e$block, sendo$blocknulo para um bloco novo eSitePageBlockRepresentationpara edição. - A classe obtém o
Fieldsetvia$this->formElementManager->get(...). - Se
$blockexiste e$block->data()tem conteúdo, a classe chama$form->populateValues([...])com os valores atuais. - A classe retorna
$view->formCollection($form). - Ao submeter, o Omeka processa os inputs nomeados
o:block[__blockIndex__][o:data][...]e persiste emo:datado bloco.
Dados persistidos por bloco
| Bloco | Campos em o:data | Tipo dos valores |
|---|---|---|
| AccordionBlock | title, description, items | title string, description string, items array de objetos com title string e text string HTML |
| BannerPage | image, use_overlay, content_align, title, description, show_search_bar, show_search_suggestions | image int id de asset, booleanos, selects como string |
| ButtonBlock | button_text, button_url, button_style | strings. button_style aceita filled ou outline |
| IconBlock | icon, title, description, alignment | icon int id de asset, strings. alignment aceita left ou center |
| PageDescription | description | string com HTML vindo do CKEditor |
| SearchBarBlock | show_suggestions | booleano |
| ThumbnailBlock | asset | int id de asset |
4. Ciclo de render
Passo a passo
- O Omeka renderiza a
SitePagee itera por seus blocos. - Para cada bloco chama
BlockLayout::rendercom$viewe$block. - A classe chama
$block->dataValue('campo')para cada chave que precisa. - Quando o bloco depende de um asset, faz
$view->api()->read('assets', $id)->getContent()dentro detry catchpara lidar com assets removidos. - A classe chama
$view->partial('common/block-layout/nome', [...])passando as variáveis. - O Laminas resolve o partial pela pilha de templates. O tema ganha quando tem o mesmo caminho. O módulo age como fallback.
- O partial pode anexar CSS via
$this->headLink()->appendStylesheet($this->assetUrl('css/style.css', 'SGMBlocks'))e emitir o HTML do bloco.
Diagrama
flowchart LR
SitePage[SitePage] --> BlockRender[BlockLayout render]
BlockRender --> DataValue["dataValue em o:data"]
BlockRender --> AssetsApi["api read assets"]
BlockRender --> Partial["view partial em common block-layout"]
Partial --> ThemeView[Tema view]
Partial --> ModuleView[Module view fallback]
ThemeView --> Html[HTML final]
ModuleView --> Html
Resolução do template
A resolução obedece à ordem registrada em view_manager.template_path_stack. O tema ativo sempre precede o módulo. Quando o tema não tem o partial, o resolver desce até o view/ do SGMBlocks e usa o fallback. Para customizar um bloco no tema, copie o .phtml do módulo para o tema mantendo o caminho relativo, por exemplo themes/<tema>/view/common/block-layout/banner-page.phtml.
Render no admin
O Omeka chama o mesmo render ao exibir o preview do bloco no editor. O contexto é o admin, mas o partial é o mesmo. Estilos específicos do admin entram por admin.css, anexado em prepareForm.
5. Persistência do campo extra de página
A gravação do fixed_header não usa o fluxo de o:block. O campo vive em o:layout_data do SitePage, que é persistido pelo core quando o formulário de layout é submetido. O tema lê o valor assim:
$layoutData = $page->layoutData();
$fixedHeader = !empty($layoutData['fixed_header']);
O nome da chave é fixed_header por motivo histórico. Renomear exige tocar o handler, o tema e migrar os dados antigos.
6. Persistência das sugestões de busca
As sugestões vivem no SiteSettings do Omeka S, não em nenhum bloco. A chave é sgmblocks_search_suggestions e o valor é um array de objetos:
[
['text' => 'Documentos', 'url' => '/s/site/documentos'],
['text' => 'Fotos', 'url' => '/s/site/fotos'],
]
Leitura canônica do lado do render:
$suggestions = $this->siteSetting('sgmblocks_search_suggestions', []);
Gravação canônica acontece através do input filter Callback descrito na seção 2.3. O site-settings.js converte a UI em JSON e grava no campo hidden antes do submit.