Pular para o conteúdo principal

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

  1. O Omeka precisa renderizar ou editar um bloco.
  2. Consulta o mapa e encontra a factory correspondente ao block_layout.
  3. Invoca a factory com o ContainerInterface.
  4. A factory obtém FormElementManager do container.
  5. Retorna a instância do bloco para o Omeka consumir.

Blocos registrados

block_layoutFactoryClasse do bloco
accordion-blockSGMBlocks\Service\BlockLayout\AccordionBlockFactorySGMBlocks\Site\BlockLayout\AccordionBlock
banner-pageSGMBlocks\Service\BlockLayout\BannerPageFactorySGMBlocks\Site\BlockLayout\BannerPage
button-blockSGMBlocks\Service\BlockLayout\ButtonBlockFactorySGMBlocks\Site\BlockLayout\ButtonBlock
icon-blockSGMBlocks\Service\BlockLayout\IconBlockFactorySGMBlocks\Site\BlockLayout\IconBlock
page-descriptionSGMBlocks\Service\BlockLayout\PageDescriptionFactorySGMBlocks\Site\BlockLayout\PageDescription
search-bar-blockSGMBlocks\Service\BlockLayout\SearchBarBlockFactorySGMBlocks\Site\BlockLayout\SearchBarBlock
thumbnail-blockSGMBlocks\Service\BlockLayout\ThumbnailBlockFactorySGMBlocks\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:

  1. O usuário abre o modal de layout da página no admin.
  2. O Omeka constrói PageLayoutDataForm usando a factory substituída por PageLayoutDataFormFactory.
  3. A factory injeta EventManager no formulário.
  4. O formulário dispara form.add_elements.
  5. O handler adiciona o checkbox o:layout_data[fixed_header].
  6. O Omeka renderiza o formulário e persiste o valor em o:layout_data ao 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:

  1. O admin acessa a página de edição de configurações do site.
  2. O SiteSettingsForm é montado.
  3. O handler lê o valor salvo de Omeka\Settings\Site com a chave sgmblocks_search_suggestions.
  4. Normaliza o valor: se vier como string JSON, faz json_decode. Se vier como array, usa direto.
  5. Registra o element_group sgmblocks com o rótulo Sugestões de busca para o site.
  6. Adiciona um Laminas\Form\Element\Hidden nomeado sgmblocks_search_suggestions com value em JSON.

2.3. SiteSettingsForm, evento form.add_input_filters

Handler: SGMBlocks\Service\Form\SiteCustomFieldsHandler::handleSiteSettingsFilters.

Passos:

  1. O usuário submete o formulário de configurações do site.
  2. O Omeka aplica os input filters registrados.
  3. O handler adiciona um Callback que recebe o valor bruto do campo hidden, aceita array ou string JSON, faz json_decode quando necessário e retorna sempre um array.
  4. O array resultante entra no fluxo padrão do SiteSettings e é salvo.

2.4. Omeka\Controller\SiteAdmin\Index, evento view.layout

Handler: SGMBlocks\Service\Form\SiteCustomFieldsHandler::handleSiteSettingsAssets.

Passos:

  1. O controller Omeka\Controller\SiteAdmin\Index prepara o layout da página do admin do site.
  2. O handler inspeciona params()->fromRoute() e só age quando action === 'edit'.
  3. Quando a condição vale, anexa admin.css com headLink e site-settings.js com headScript usando defer.
  4. O JS assume o controle do campo hidden sgmblocks-search-suggestions e monta a interface de adicionar e remover itens.

3. Ciclo de vida do formulário no admin

  1. O usuário adiciona um bloco ao layout da página.
  2. O Omeka chama BlockLayout::form passando $view, $site, $page, e $block, sendo $block nulo para um bloco novo e SitePageBlockRepresentation para edição.
  3. A classe obtém o Fieldset via $this->formElementManager->get(...).
  4. Se $block existe e $block->data() tem conteúdo, a classe chama $form->populateValues([...]) com os valores atuais.
  5. A classe retorna $view->formCollection($form).
  6. Ao submeter, o Omeka processa os inputs nomeados o:block[__blockIndex__][o:data][...] e persiste em o:data do bloco.

Dados persistidos por bloco

BlocoCampos em o:dataTipo dos valores
AccordionBlocktitle, description, itemstitle string, description string, items array de objetos com title string e text string HTML
BannerPageimage, use_overlay, content_align, title, description, show_search_bar, show_search_suggestionsimage int id de asset, booleanos, selects como string
ButtonBlockbutton_text, button_url, button_stylestrings. button_style aceita filled ou outline
IconBlockicon, title, description, alignmenticon int id de asset, strings. alignment aceita left ou center
PageDescriptiondescriptionstring com HTML vindo do CKEditor
SearchBarBlockshow_suggestionsbooleano
ThumbnailBlockassetint id de asset

4. Ciclo de render

Passo a passo

  1. O Omeka renderiza a SitePage e itera por seus blocos.
  2. Para cada bloco chama BlockLayout::render com $view e $block.
  3. A classe chama $block->dataValue('campo') para cada chave que precisa.
  4. Quando o bloco depende de um asset, faz $view->api()->read('assets', $id)->getContent() dentro de try catch para lidar com assets removidos.
  5. A classe chama $view->partial('common/block-layout/nome', [...]) passando as variáveis.
  6. O Laminas resolve o partial pela pilha de templates. O tema ganha quando tem o mesmo caminho. O módulo age como fallback.
  7. 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.