# DfCustomCodeManager: guia completo

> O DfCustomCodeManager traz uma resposta simples a um problema universal das lojas Shopware: onde colocar, como versionar e como proteger o CSS e o JavaScript personalizado que se acaba sempre…

- Página: <https://www.datafirefly.com/pt/documentation/df-custom-code-manager/>
- Idioma: pt
- Atualizado em: 2026-09-02
- Outros idiomas: [fr](https://www.datafirefly.com/documentation/df-custom-code-manager/index.md), [en](https://www.datafirefly.com/en/documentation/df-custom-code-manager/index.md), [es](https://www.datafirefly.com/es/documentation/df-custom-code-manager/index.md), [de](https://www.datafirefly.com/de/documentation/df-custom-code-manager/index.md), [it](https://www.datafirefly.com/it/documentation/df-custom-code-manager/index.md), [pl](https://www.datafirefly.com/pl/documentation/df-custom-code-manager/index.md), [nl](https://www.datafirefly.com/nl/documentation/df-custom-code-manager/index.md)
- Índice: <https://www.datafirefly.com/pt/documentation/llms.txt>

O DfCustomCodeManager traz uma resposta simples a um problema universal das lojas Shopware: **onde colocar, como versionar e como proteger o CSS e o JavaScript personalizado** que se acaba sempre por acrescentar a um tema? A extensão oferece um editor de código integrado na administração, um sistema de **contentores** que agrupam **snippets SCSS ou JavaScript**, e sobretudo uma **injeção direta na compilação do tema** através dos eventos nativos do Shopware. Consequência: nenhum ficheiro servido a mais, nenhum pedido HTTP adicional para o visitante, e os seus snippets SCSS herdam automaticamente as variáveis e mixins do tema ativo. Este guia cobre a instalação, a configuração, a criação de contentores e snippets, a compilação do tema, o histórico de versões, o modo seguro, a biblioteca de presets, a importação e exportação e a resolução de problemas.

## Instalação

1. Transfira o arquivo `DfCustomCodeManager-1.0.0.zip` a partir da sua área DataFirefly.
2. Instale-o em **Administração → Extensões → As minhas extensões → Carregar uma extensão**, ou descomprima a pasta `DfCustomCodeManager` em `custom/plugins/`.
3. Execute a instalação e a ativação: ``` bin/console plugin:refresh bin/console plugin:install --activate DfCustomCodeManager bin/console cache:clear ```
4. Na instalação, a extensão cria as suas 4 tabelas (`df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`) e regista os seus subscribers nos eventos de compilação do tema.
5. Recompile o tema para que tenha a extensão em conta: ``` bin/console theme:compile ```

Compatível com Shopware 6.6.x e 6.7.x no mesmo código (composer `^6.6.0 || ^6.7.0`). O módulo de administração é **pré-compilado**, **não é necessário qualquer build**. PHP 8.2+ necessário. A compilação SCSS assenta no `scssphp/scssphp`, já fornecido pelo `shopware/storefront`. Sem dependências Composer adicionais.

## Onde encontrar a extensão na administração

Depois da ativação, aparece uma entrada **Custom Code Manager** no menu **Catálogos** da administração (ícone laranja, posição 100). É o ecrã central: lista dos contentores, pesquisa, filtros, e as ações globais **Importar**, **Exportar**, **Presets** e **Compilar o tema**. Toda a configuração de baixo nível (modo seguro, minificação, banner) faz-se em **Extensões → As minhas extensões → DfCustomCodeManager → ⋯ → Configurar**.

Se a entrada não aparecer depois de uma atualização, execute `bin/console assets:install && bin/console cache:clear` e recarregue a administração com uma atualização forçada (Ctrl+Shift+R).

## Configuração da extensão

O cartão de configuração da extensão no Shopware expõe três interruptores simples mas essenciais:

- **Modo seguro** (`DfCustomCodeManager.config.safeMode`): desativado por predefinição. Quando está ativo, **todos** os contentores são ignorados na próxima compilação, como se estivessem todos inativos. É a rede de segurança descrita mais abaixo.
- **Minificar JS** (`DfCustomCodeManager.config.minifyJs`): minificação básica do JavaScript injetado. Útil em produção, a deixar desativada em desenvolvimento para poder ler os snippets no bundle compilado.
- **Acrescentar um banner** (`DfCustomCodeManager.config.addBanner`): acrescenta um comentário `/* DataFirefly Custom Code Manager */` no início do código injetado. Prático para localizar rapidamente os seus snippets no bundle compilado.

## O modelo mental: contentores e snippets

A extensão organiza-se em **dois níveis**:

- Um **contentor** é um agrupamento lógico: _Promoção de verão 2026_, _GTM analytics_, _Modo escuro opcional_, _Teste A/B do botão CTA_, e por aí fora. Cada contentor tem um nome, uma descrição, uma prioridade, um interruptor de ativo ou inativo e um âmbito por canal de venda.
- Um **snippet** é uma unidade de código dentro de um contentor. Tipo SCSS ou JavaScript, nome, código, prioridade, interruptor de ativo ou inativo, notas em Markdown, e um interruptor para ativar ou não a injeção das variáveis do tema.

Um contentor pode conter **vários snippets de tipos misturados**. É útil para agrupar logicamente os snippets que andam juntos: por exemplo um contentor _Modo escuro opcional_ com um snippet SCSS para os estilos e um snippet JavaScript para a alternância da classe em `html`.

## Criar o primeiro contentor

1. A partir de **Catálogos → Custom Code Manager**, clique em **Novo contentor** no canto superior direito.
2. Dê-lhe um nome expressivo (por exemplo _Promoção de verão 2026: header fixo e selo_).
3. Defina a **prioridade** (deixe 0 por predefinição, suba o valor se quiser que este contentor seja injetado mais tarde no bundle e portanto sobreponha outros estilos).
4. (Opcional) Ative **Limitar a canais de venda** e selecione um ou vários canais. Se a opção estiver desativada, o contentor aplica-se a **todos** os canais.
5. Preencha uma descrição (notas internas, contexto, ticket associado); nunca será injetada no bundle.
6. Guarde. Está agora pronto para acrescentar snippets.

## Acrescentar um snippet SCSS ou JavaScript

No cartão **Excertos de código** da página do contentor, dois botões: **Acrescentar SCSS** e **Acrescentar JavaScript**. Cada snippet acrescentado aparece como um cartão com:

- Um selo **SCSS** (info) ou **JS** (warning).
- Um campo de nome (visível apenas em edição).
- Um interruptor de ativo ou inativo.
- Um botão **Validar a sintaxe** (✓).
- Um botão **Histórico** (relógio), disponível a partir da primeira gravação.
- Um botão **Duplicar**.
- Um botão **Eliminar**.
- Um **editor de código** com coloração sintática adaptada ao tipo.
- Uma zona de **Notas** em Markdown para documentar o que o snippet faz.

O editor de código usa nativamente o componente `mt-code-editor` introduzido no Shopware 6.7 (baseado no Meteor). No Shopware 6.6, a extensão passa automaticamente para o `sw-code-editor` (o antigo componente baseado no Ace). Em último recurso (componente indisponível), um `textarea` em fonte monoespaçada assume, sem coloração sintática mas perfeitamente funcional.

## Compilar o tema

Um snippet guardado **ainda não está visível** no storefront enquanto o tema não for recompilado. Duas formas de o fazer:

- A partir da administração, botão **Compilar o tema** (no canto superior direito da lista, ou na página do contentor). Uma notificação confirma o fim da operação.
- A partir da linha de comandos: ``` bin/console theme:compile ```

Na compilação, a extensão escuta três eventos do Shopware e injeta aí os seus snippets:

- `ThemeCompilerEnrichScssVariablesEvent`: capta o mapa das variáveis SCSS do tema ativo. É o que permite aos seus snippets SCSS usar `$sw-color-brand-primary`, `$font-family-base` e outras.
- `ThemeCompilerConcatenatedStylesEvent`: concatena o seu SCSS compilado no fim da folha de estilos principal.
- `ThemeCompilerConcatenatedScriptsEvent`: concatena o seu JavaScript no fim do bundle de scripts principal.

Resultado: **zero pedidos HTTP adicionais** servidos ao visitante, e o seu código passa por toda a cadeia de otimização do Shopware (concatenação, minificação, fingerprinting de cache).

## Herança das variáveis e mixins do tema

Por predefinição, cada snippet SCSS beneficia de um **preâmbulo automático** que contém todas as variáveis e todos os mixins expostos pelo tema ativo e pelas suas extensões de tema. Pode portanto escrever num snippet:

```
.header {
    background: $sw-color-brand-primary;
    font-family: $font-family-base;
    transition: $transition-base;
}
```

sem importar nada manualmente, exatamente como num ficheiro SCSS do tema. Se por alguma razão específica (conflito de variável, snippet autónomo) quiser desativar essa herança num snippet concreto, desmarque o interruptor **Variáveis do tema disponíveis** no rodapé do cartão do snippet.

## Âmbito multicanal

No cartão **Âmbito e canais** do contentor, ative **Limitar a canais de venda** e selecione os canais em causa. O contentor só será injetado nas compilações de tema desses canais. Muito prático para:

- Um banner promocional reservado a uma loja de marca secundária.
- Um script de tracking específico de um mercado.
- Um teste A/B num único canal para medir o impacto.

## Prioridade de carregamento

A prioridade é um inteiro (0 por predefinição) que controla a **ordem de injeção** no bundle compilado: quanto mais alto o valor, mais tarde o código é injetado, e portanto mais pode sobrepor o que o precede. A prioridade existe a **dois níveis**:

- **Ao nível do contentor**: ordem entre contentores.
- **Ao nível do snippet**: ordem entre snippets _dentro_ do mesmo contentor.

A ordem final é `(prioridade do contentor, prioridade do snippet)` por ordem crescente. Conselho simples: deixe tudo a 0 por predefinição e só use a prioridade se precisar explicitamente de sobrepor algo.

## Histórico de versões

A cada gravação de um snippet, a extensão cria automaticamente uma **versão** na tabela `df_ccm_snippet_version`. São conservadas as **5 últimas versões** por snippet (a mais antiga é eliminada quando o limite é atingido). Para consultar e restaurar uma versão:

1. No cartão do snippet, clique no ícone **Histórico** (relógio).
2. Abre-se uma janela com a lista das versões, data, autor, comentário e pré-visualização.
3. Clique em **Restaurar** à direita da versão pretendida; o código do snippet é imediatamente substituído pelo dessa versão. É criada uma nova versão para registar o restauro.
4. Guarde o contentor e recompile para ver o efeito.

Para históricos mais longos, o registo completo fica na tabela `df_ccm_snippet_version` (as versões antigas são apenas ocultadas da janela). Um programador pode facilmente estender `VersionTracker::MAX_VERSIONS_PER_SNIPPET` se for necessário.

## Modo seguro: a rede de segurança de emergência

O modo seguro é um interruptor global na configuração da extensão. Ativo, faz com que **todos os contentores sejam ignorados na próxima compilação**, sem alterar qualquer dado. Utilização típica:

1. Um snippet mal testado parte algo em produção às 22h.
2. Vá a **Extensões → As minhas extensões → DfCustomCodeManager → ⋯ → Configurar**.
3. Ative o interruptor **Modo seguro** e guarde.
4. Recompile o tema: `bin/console theme:compile`.
5. O storefront volta ao estado nativo (sem qualquer snippet injetado). Pode agora identificar e corrigir o snippet culpado com calma.
6. Depois de corrigido, desative o modo seguro e recompile de novo.

O modo seguro é uma ferramenta de emergência, não um modo de funcionamento. Depois de resolver o incidente, lembre-se de o desativar, caso contrário nenhum dos seus contentores será injetado.

## Biblioteca de presets

O botão **Presets** (a partir da lista dos contentores) abre uma biblioteca de 8 contentores prontos a instalar num clique:

- **Sticky header**: header que se transforma no scroll (classe `is-sticky` acrescentada a partir de um limiar).
- **Back to top**: botão de voltar ao topo, visível a partir de um certo scroll.
- **Cookie banner skin**: nova aparência para o banner de cookies nativo, alinhada com a sua identidade.
- **Product badge Novo**: selo «Novo» nos produtos criados recentemente.
- **Free shipping bar**: barra de progresso de portes grátis no topo da página.
- **Rounded buttons**: botões arredondados em toda a loja.
- **GTM DOM-ready event**: dispara um evento personalizado quando o DOM está pronto, para arrancar as suas data layers.
- **Fade-in on scroll**: aparecimento progressivo dos elementos ao fazer scroll.

Clicar em **Instalar** cria o contentor e os seus snippets na base de dados. Só falta recompilar o tema para os ver online. Os contentores criados a partir de um preset são contentores como os outros: pode editá-los, enriquecê-los, desativá-los, eliminá-los.

## Importação e exportação JSON

Para migrar snippets entre ambientes (desenvolvimento, staging, produção) ou entre lojas:

1. **Exportação**: selecione um ou vários contentores na lista (caixas de seleção) e clique em **Exportar**. É transferido um ficheiro JSON com todos os contentores selecionados, os seus snippets, a sua prioridade, as suas notas, e o número de versão do formato (`EXPORT_VERSION = 1`) para a retrocompatibilidade.
2. **Importação**: no ambiente de destino, clique em **Importar** e selecione o ficheiro JSON. Os contentores e snippets são recriados de forma idêntica.

A importação não toca nos contentores existentes (não há fusão por nome): cria sistematicamente novas entradas. Se quiser substituir um contentor existente, elimine-o manualmente antes de importar.

## Validação sintática

O botão ✓ **Validar a sintaxe** em cada cartão de snippet aciona uma validação do lado do servidor sem guardar nada. Consoante o tipo:

- **SCSS**: a extensão faz uma **compilação de teste** com o `scssphp/scssphp` injetando o preâmbulo das variáveis do tema. Se a compilação passar, o snippet é válido. Caso contrário, os erros aparecem numa zona de erro no cartão (número de linha, mensagem).
- **JavaScript**: a extensão limpa o código de cadeias e comentários, e depois verifica o **equilíbrio das chavetas** `{}`, **parênteses** `()` e **parênteses retos** `[]`. Esta verificação não substitui um verdadeiro parser ECMAScript, mas apanha 90 % dos erros de copiar e colar (chaveta esquecida, cadeia mal fechada). Para ir mais longe, valide o seu JavaScript numa ferramenta dedicada antes de colar.

## Arquitetura técnica

Para os programadores que querem compreender ou estender a extensão:

- **Namespace PHP raiz**: `DataFirefly` (subnamespace: `CustomCodeManager`, classes em `src/`).
- **Classe da extensão**: `DfCustomCodeManager` (estende `ShopwareCoreFrameworkPlugin`).
- **Prefixo do SystemConfig**: `DfCustomCodeManager.config.*`.
- **Tabelas**: `df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`.
- **Migrações**: `Migration1779580800CreateCcmContainerTable`, `Migration1779580801CreateCcmSnippetTable`, `Migration1779580802CreateCcmSnippetVersionTable`.
- **Serviços**: `CodeCompiler` (orquestração e cache), `SnippetExporter` (importação e exportação JSON), `SnippetValidator` (validação sintática), `VersionTracker` (snapshot, restauro e limpeza).
- **Subscribers**: `ThemeCompilerSubscriber` (os 3 eventos de compilação), `SnippetWrittenSubscriber` (snapshot automático na escrita).
- **Rotas de API privadas** em `/api/_action/df-ccm/` (scope `api`): `validate`, `export`, `import`, `restore-version`, `recompile`, `presets`.

Todas as declarações de serviços são explícitas no `services.xml` (sem autowiring) para manter o alinhamento com as convenções DataFirefly.

## Estender o módulo de administração

O módulo de administração está compilado e colocado em `Resources/public/administration/js/df-custom-code-manager.js`. Vem **pré-compilado no ZIP** e **não exige qualquer build local**. Para o estender, use os componentes (`df-ccm-list`, `df-ccm-detail`, `df-ccm-snippet-card`, `df-ccm-code-field`, `df-ccm-preset-modal`, `df-ccm-version-modal`) e personalize através do sistema de override normal do Shopware (`Component.override`).

## FAQ e resolução de problemas

**Os meus snippets não aparecem no storefront.** Recompilou o tema? Enquanto o `theme:compile` não correr depois de uma alteração, nada muda. Verifique também que o contentor e o snippet estão ativos, que o canal de venda em causa está no âmbito (se o âmbito estiver restringido), e que o modo seguro não está ativo.

**Erro de compilação SCSS na consola depois do theme:compile.** Na maioria dos casos, é uma variável do tema que não existe (erro de escrita) ou um snippet SCSS que abre um bloco sem o fechar. Desative o snippet em causa, recompile para confirmar e depois corrija com calma. A validação sintática no cartão do snippet apanha a maioria destes casos antes da gravação.

**O menu Custom Code Manager não aparece na administração.** Execute `bin/console assets:install && bin/console cache:clear` e recarregue a administração com Ctrl+Shift+R. O módulo está no grupo **Catálogos**.

**O editor de código mostra um textarea sem coloração.** É a alternativa quando nem o `mt-code-editor` (6.7) nem o `sw-code-editor` (6.6) estão disponíveis. Verifique a sua versão do Shopware e que o módulo de administração está mesmo carregado.

**Quero desativar temporariamente todos os snippets sem eliminar nada.** É exatamente o modo seguro. Interruptor na configuração da extensão, recompilação, e está feito.

**O botão «Compilar o tema» gira sem parar.** Verifique os logs do Shopware. A compilação pode demorar num tema grande; em caso de bloqueio real, a causa habitual é um snippet SCSS que entra em ciclo ou contém uma variável desconhecida. Ative o modo seguro, recompile, e depois reative os snippets um a um para identificar o culpado.

**O meu snippet JavaScript não dispara.** Não se esqueça de que o código injetado é executado **no bundle global**, portanto num contexto diferente do das extensões JavaScript clássicas do Shopware. Para interagir com as extensões JavaScript do storefront, escute antes `document.addEventListener('DOMContentLoaded', …)` ou os eventos globais que o storefront emite.

**O que acontece na desinstalação?** Durante o `plugin:uninstall`, o Shopware mostra a caixa normal **Conservar os dados do utilizador**. Se estiver **desmarcada**, a extensão elimina as suas 4 tabelas e todos os dados associados (contentores, snippets, versões, ligações a canais). Se estiver **marcada**, as tabelas mantêm-se e pode recuperar os seus snippets se reinstalar a extensão mais tarde.
