# DfCustomCodeManager: kompletny przewodnik

> DfCustomCodeManager daje prostą odpowiedź na uniwersalny problem sklepów Shopware: gdzie umieszczać, jak wersjonować i jak zabezpieczać własny CSS i JavaScript, który prędzej czy później zawsze trafia do motywu? Plugin oferuje…

- Strona: <https://www.datafirefly.com/pl/documentation/df-custom-code-manager/>
- Język: pl
- Zaktualizowano: 2026-07-29
- Inne języki: [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), [nl](https://www.datafirefly.com/nl/documentation/df-custom-code-manager/index.md), [pt](https://www.datafirefly.com/pt/documentation/df-custom-code-manager/index.md)
- Indeks: <https://www.datafirefly.com/pl/documentation/llms.txt>

DfCustomCodeManager daje prostą odpowiedź na uniwersalny problem sklepów Shopware: **gdzie umieszczać, jak wersjonować i jak zabezpieczać własny CSS i JavaScript**, który prędzej czy później zawsze trafia do motywu? Plugin oferuje edytor kodu wbudowany w administrację, system **kontenerów** grupujących **snippety SCSS lub JavaScript**, a przede wszystkim **bezpośrednie wstrzykiwanie do kompilacji motywu** przez natywne zdarzenia Shopware. Skutek: żadnego dodatkowego serwowanego pliku, żadnego dodatkowego żądania HTTP dla odwiedzającego, a Twoje snippety SCSS automatycznie dziedziczą zmienne i mixiny aktywnego motywu. Ten przewodnik obejmuje instalację, konfigurację, tworzenie kontenerów i snippetów, kompilację motywu, historię wersji, safe mode, bibliotekę presetów, import/eksport i rozwiązywanie problemów.

## Instalacja

1. Pobierz archiwum `DfCustomCodeManager-1.0.0.zip` ze swojego panelu DataFirefly.
2. Zainstaluj je przez **Administracja → Rozszerzenia → Moje rozszerzenia → Prześlij rozszerzenie** albo rozpakuj katalog `DfCustomCodeManager` do `custom/plugins/`.
3. Uruchom instalację i aktywację: ``` bin/console plugin:refresh bin/console plugin:install --activate DfCustomCodeManager bin/console cache:clear ```
4. Przy instalacji plugin tworzy swoje 4 tabele (`df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`) i rejestruje subscribery zdarzeń kompilacji motywu.
5. Przekompiluj motyw, aby uwzględnił plugin: ``` bin/console theme:compile ```

Zgodny z Shopware 6.6.x i 6.7.x na jednym kodzie (composer `^6.6.0 || ^6.7.0`). Moduł administracji jest **prekompilowany**, **żaden build nie jest potrzebny**. Wymagane PHP 8.2+. Kompilacja SCSS opiera się na `scssphp/scssphp`, dostarczanym już przez `shopware/storefront`. Żadnych dodatkowych zależności Composera.

## Gdzie znaleźć plugin w administracji

Po aktywacji w menu **Katalogi** administracji pojawia się pozycja **Custom Code Manager** (pomarańczowa ikona, pozycja 100). To ekran centralny: lista kontenerów, wyszukiwanie, filtry oraz akcje globalne **Importuj**, **Eksportuj**, **Presety** i **Kompiluj motyw**. Cała konfiguracja niskopoziomowa (safe mode, minify, banner) odbywa się w **Rozszerzenia → Moje rozszerzenia → DfCustomCodeManager → ⋯ → Konfiguruj**.

Jeśli pozycja nie pojawia się po aktualizacji, uruchom `bin/console assets:install && bin/console cache:clear`, a następnie przeładuj administrację z wymuszonym odświeżeniem (Ctrl+Shift+R).

## Konfiguracja pluginu

Karta konfiguracji pluginu Shopware udostępnia trzy proste, ale kluczowe przełączniki:

- **Safe mode** (`DfCustomCodeManager.config.safeMode`): domyślnie wyłączony. Po włączeniu **wszystkie** kontenery są ignorowane przy następnej kompilacji, tak jakby były nieaktywne. To siatka bezpieczeństwa opisana niżej.
- **Minify JS** (`DfCustomCodeManager.config.minifyJs`): podstawowa minifikacja wstrzykiwanego JavaScriptu. Przydatna w produkcji, w developmencie zostaw wyłączoną, aby móc czytać snippety w skompilowanym bundlu.
- **Dodaj banner** (`DfCustomCodeManager.config.addBanner`): dodaje komentarz `/* DataFirefly Custom Code Manager */` na początku wstrzykiwanego kodu. Praktyczne do szybkiego namierzania swoich snippetów w skompilowanym bundlu.

## Model mentalny: kontenery i snippety

Plugin jest zorganizowany na **dwóch poziomach**:

- **Kontener** to grupowanie logiczne: _Promocja lato 2026_, _GTM analytics_, _Dark mode opt-in_, _Test A/B przycisku CTA_… Każdy kontener ma nazwę, opis, priorytet, przełącznik aktywny/nieaktywny i zakres per kanał sprzedaży.
- **Snippet** to jednostka kodu wewnątrz kontenera. Typ SCSS lub JavaScript, nazwa, kod, priorytet, przełącznik aktywny/nieaktywny, notatki Markdown oraz przełącznik włączający wstrzykiwanie zmiennych motywu.

Kontener może zawierać **wiele snippetów mieszanych typów**. To przydatne do logicznego grupowania snippetów, które idą w parze: na przykład kontener _Dark mode opt-in_ ze snippetem SCSS dla stylów i snippetem JavaScript dla przełączania klasy na `html`.

## Utworzenie pierwszego kontenera

1. Z poziomu **Katalogi → Custom Code Manager** kliknij **Nowy kontener** w prawym górnym rogu.
2. Nadaj mu wymowną nazwę (np. _Promocja lato 2026: sticky header i badge_).
3. Ustaw **priorytet** (domyślnie zostaw 0, podnieś wartość, jeśli chcesz, żeby kontener był wstrzykiwany później w bundlu i tym samym nadpisywał inne style).
4. (Opcjonalnie) Włącz **Ogranicz do kanałów sprzedaży** i wybierz jeden lub kilka kanałów. Gdy opcja jest wyłączona, kontener obowiązuje na **wszystkich** kanałach.
5. Uzupełnij opis (notatki wewnętrzne, kontekst, powiązany ticket); nigdy nie trafi on do bundla.
6. Zapisz. Możesz teraz dodawać snippety.

## Dodanie snippeta SCSS lub JavaScript

Na karcie **Fragmenty kodu** strony kontenera są dwa przyciski: **Dodaj SCSS** i **Dodaj JavaScript**. Każdy dodany snippet pojawia się jako karta z:

- Plakietką **SCSS** (info) lub **JS** (warning).
- Polem nazwy (widocznym tylko w edycji).
- Przełącznikiem aktywny/nieaktywny.
- Przyciskiem **Waliduj składnię** (✓).
- Przyciskiem **Historia** (zegar), dostępnym od pierwszego zapisu.
- Przyciskiem **Duplikuj**.
- Przyciskiem **Usuń**.
- **Edytorem kodu** z kolorowaniem składni dopasowanym do typu.
- Strefą **Notatki** w Markdown do dokumentowania działania snippeta.

Edytor kodu natywnie korzysta z komponentu `mt-code-editor` wprowadzonego w Shopware 6.7 (opartego na Meteor). Na Shopware 6.6 plugin automatycznie przełącza się na `sw-code-editor` (dawny komponent oparty na Ace). W ostateczności (komponent niedostępny) przejmuje `textarea` w foncie monospace, bez kolorowania składni, ale w pełni funkcjonalny.

## Kompilacja motywu

Zapisany snippet **nie jest jeszcze widoczny** w storefroncie, dopóki motyw nie zostanie przekompilowany. Dwa sposoby:

- Z administracji, przycisk **Kompiluj motyw** (w prawym górnym rogu listy albo na stronie kontenera). Powiadomienie potwierdza zakończenie operacji.
- Z wiersza poleceń: ``` bin/console theme:compile ```

Przy kompilacji plugin nasłuchuje trzech zdarzeń Shopware i wstrzykuje w nie Twoje snippety:

- `ThemeCompilerEnrichScssVariablesEvent`: przechwytuje mapę zmiennych SCSS aktywnego motywu. To dzięki temu Twoje snippety SCSS mogą używać `$sw-color-brand-primary`, `$font-family-base` itd.
- `ThemeCompilerConcatenatedStylesEvent`: dokleja Twój skompilowany SCSS na końcu głównego arkusza stylów.
- `ThemeCompilerConcatenatedScriptsEvent`: dokleja Twój JavaScript na końcu głównego bundla skryptów.

Rezultat: **zero dodatkowych żądań HTTP** serwowanych odwiedzającemu, Twój kod przechodzi przez cały łańcuch optymalizacji Shopware (konkatenacja, minifikacja, fingerprinting cache).

## Dziedziczenie zmiennych i mixinów motywu

Domyślnie każdy snippet SCSS korzysta z **automatycznego preambułu** zawierającego wszystkie zmienne i wszystkie mixiny udostępniane przez aktywny motyw i jego pluginy motywu. Możesz więc pisać w snippecie:

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

…nic nie importując ręcznie, dokładnie jak w pliku SCSS motywu. Jeśli z jakiegoś szczególnego powodu (konflikt zmiennej, snippet samowystarczalny) chcesz wyłączyć to dziedziczenie na konkretnym snippecie, odznacz przełącznik **Zmienne motywu dostępne** w stopce karty snippeta.

## Zakres wielokanałowy

Na karcie **Zakres i kanały** kontenera włącz **Ogranicz do kanałów sprzedaży** i wybierz właściwe kanały. Kontener będzie wtedy wstrzykiwany tylko w kompilacjach motywu dla tych kanałów. Bardzo przydatne dla:

- Banera promocyjnego zarezerwowanego dla sklepu marki drugorzędnej.
- Skryptu trackingowego specyficznego dla rynku.
- Testu A/B na jednym kanale w celu zmierzenia efektu.

## Priorytet ładowania

Priorytet to liczba całkowita (domyślnie 0), która kontroluje **kolejność wstrzykiwania** w skompilowanym bundlu: im wyższa wartość, tym później kod jest wstrzykiwany, a więc tym łatwiej może nadpisać to, co go poprzedza. Priorytet istnieje na **dwóch poziomach**:

- **Na poziomie kontenera**: kolejność między kontenerami.
- **Na poziomie snippeta**: kolejność między snippetami _wewnątrz_ tego samego kontenera.

Kolejność finalna to: `(priorytet kontenera, priorytet snippeta)` rosnąco. Prosta rada: domyślnie zostaw wszystko na 0 i używaj priorytetu tylko wtedy, gdy naprawdę musisz coś nadpisać.

## Historia wersji

Przy każdym zapisie snippeta plugin automatycznie tworzy **wersję** w tabeli `df_ccm_snippet_version`. Zachowywanych jest **5 ostatnich wersji** per snippet (najstarsza jest usuwana po osiągnięciu progu). Aby przejrzeć i przywrócić wersję:

1. Na karcie snippeta kliknij ikonę **Historia** (zegar).
2. Otwiera się okno modalne z listą wersji, datą, autorem, komentarzem i podglądem.
3. Kliknij **Przywróć** po prawej stronie wybranej wersji; kod snippeta zostaje natychmiast zastąpiony kodem tej wersji. Powstaje nowa wersja dokumentująca przywrócenie.
4. Zapisz kontener i przekompiluj, aby zobaczyć efekt.

Dla dłuższych historii pełny rejestr pozostaje w tabeli `df_ccm_snippet_version` (stare wersje są jedynie ukrywane w oknie). Deweloper może bardzo łatwo zwiększyć `VersionTracker::MAX_VERSIONS_PER_SNIPPET`, jeśli trzeba.

## Safe mode: awaryjna siatka bezpieczeństwa

Safe mode to globalny przełącznik w konfiguracji pluginu. Włączony sprawia, że **wszystkie kontenery są ignorowane przy następnej kompilacji**, bez modyfikowania jakichkolwiek danych. Typowy scenariusz:

1. Źle przetestowany snippet psuje coś na produkcji o 22:00.
2. Wejdź w **Rozszerzenia → Moje rozszerzenia → DfCustomCodeManager → ⋯ → Konfiguruj**.
3. Włącz przełącznik **Safe mode** i zapisz.
4. Przekompiluj motyw: `bin/console theme:compile`.
5. Storefront wraca do stanu natywnego (bez żadnego wstrzykniętego snippeta). Możesz teraz spokojnie namierzyć i poprawić winny snippet.
6. Po poprawce wyłącz safe mode i przekompiluj ponownie.

Safe mode to narzędzie awaryjne, nie tryb pracy. Po rozwiązaniu incydentu pamiętaj o jego wyłączeniu, inaczej żaden z Twoich kontenerów nie będzie wstrzykiwany.

## Biblioteka presetów

Przycisk **Presety** (z listy kontenerów) otwiera bibliotekę 8 kontenerów gotowych do instalacji jednym kliknięciem:

- **Sticky header**: nagłówek zmieniający się przy scrollu (klasa `is-sticky` dodawana powyżej progu).
- **Back to top**: przycisk powrotu na górę, widoczny od pewnego scrolla.
- **Cookie banner skin**: przeskórkowanie natywnego banera cookies pod Twoją identyfikację wizualną.
- **Product badge, Nowość**: plakietka "Nowość" na niedawno utworzonych produktach.
- **Free shipping bar**: pasek postępu darmowej dostawy u góry strony.
- **Rounded buttons**: zaokrąglone przyciski w całym sklepie.
- **GTM DOM-ready event**: wyzwala niestandardowe zdarzenie po gotowości DOM, aby zainicjować Twoje data layers.
- **Fade-in on scroll**: stopniowe pojawianie się elementów przy scrollu.

Kliknięcie **Zainstaluj** tworzy kontener i jego snippety w bazie. Pozostaje tylko przekompilować motyw, aby zobaczyć je online. Kontenery utworzone z presetu są kontenerami jak każde inne: możesz je edytować, rozbudowywać, dezaktywować, usuwać.

## Import / Eksport JSON

Aby migrować snippety między środowiskami (dev, staging, produkcja) lub między sklepami:

1. **Eksport**: zaznacz jeden lub kilka kontenerów na liście (checkboxy), a następnie kliknij **Eksportuj**. Pobierany jest plik JSON zawierający wszystkie wybrane kontenery z ich snippetami, priorytetem, notatkami oraz numerem wersji formatu (`EXPORT_VERSION = 1`) dla wstecznej kompatybilności.
2. **Import**: na środowisku docelowym kliknij **Importuj** i wybierz plik JSON. Kontenery i snippety są odtwarzane identycznie.

Import nie dotyka istniejących kontenerów (brak scalania po nazwie): zawsze tworzy nowe wpisy. Jeśli chcesz nadpisać istniejący kontener, usuń go ręcznie przed importem.

## Walidacja składniowa

Przycisk ✓ **Waliduj składnię** na każdej karcie snippeta uruchamia walidację po stronie serwera, niczego nie zapisując. Zależnie od typu:

- **SCSS**: plugin wykonuje **kompilację na sucho** przez `scssphp/scssphp`, wstrzykując preambułę zmiennych motywu. Jeśli kompilacja przechodzi, snippet jest poprawny. W przeciwnym razie błędy trafiają do strefy błędów na karcie (numer linii, komunikat).
- **JavaScript**: plugin oczyszcza kod z łańcuchów i komentarzy, a następnie sprawdza **równowagę klamer** `{}`, **nawiasów** `()` i **nawiasów kwadratowych** `[]`. Ta kontrola nie zastępuje prawdziwego parsera ECMAScript, ale łapie 90% błędów kopiuj-wklej (zapomniana klamra, źle domknięty łańcuch). Aby pójść dalej, zwaliduj swój JavaScript w dedykowanym narzędziu przed wklejeniem.

## Architektura techniczna

Dla deweloperów, którzy chcą zrozumieć lub rozszerzyć plugin:

- **Główny namespace PHP**: `DataFirefly` (pod-namespace: `CustomCodeManager`, klasy w `src/`).
- **Klasa pluginu**: `DfCustomCodeManager` (rozszerza `Shopware\Core\Framework\Plugin`).
- **Prefiks SystemConfig**: `DfCustomCodeManager.config.*`.
- **Tabele**: `df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`.
- **Migracje**: `Migration1779580800CreateCcmContainerTable`, `Migration1779580801CreateCcmSnippetTable`, `Migration1779580802CreateCcmSnippetVersionTable`.
- **Serwisy**: `CodeCompiler` (orkiestracja + cache), `SnippetExporter` (import/eksport JSON), `SnippetValidator` (walidacja składniowa), `VersionTracker` (snapshot + restore + trim).
- **Subscribery**: `ThemeCompilerSubscriber` (3 zdarzenia kompilacji), `SnippetWrittenSubscriber` (automatyczny snapshot przy zapisie).
- **Prywatne trasy API** pod `/api/_action/df-ccm/` (scope `api`): `validate`, `export`, `import`, `restore-version`, `recompile`, `presets`.

Wszystkie deklaracje serwisów są jawne w `services.xml` (bez autowiringu), zgodnie z konwencjami DataFirefly.

## Rozszerzanie modułu administracji

Moduł administracji jest skompilowany i umieszczony w `Resources/public/administration/js/df-custom-code-manager.js`. Jest **prekompilowany w ZIP-ie** i nie wymaga **żadnego lokalnego builda**. Aby go rozszerzyć, rozłóż komponenty (`df-ccm-list`, `df-ccm-detail`, `df-ccm-snippet-card`, `df-ccm-code-field`, `df-ccm-preset-modal`, `df-ccm-version-modal`) i dostosuj przez standardowy system override'ów Shopware (`Component.override`).

## FAQ i rozwiązywanie problemów

**Moje snippety nie pojawiają się w storefroncie.** Czy przekompilowano motyw? Dopóki `theme:compile` nie zadziała po modyfikacji, nic się nie zmienia. Sprawdź też, czy kontener i snippet są aktywne, czy dany kanał sprzedaży mieści się w zakresie (jeśli zakres jest ograniczony) i czy safe mode nie jest włączony.

**Błąd kompilacji SCSS w konsoli po theme:compile.** Najczęściej to zmienna motywu, która nie istnieje (literówka), albo snippet SCSS otwierający blok bez jego domknięcia. Wyłącz podejrzany snippet, przekompiluj dla potwierdzenia, a potem popraw na spokojnie. Walidacja składniowa na karcie snippeta łapie większość takich przypadków przed zapisem.

**Menu Custom Code Manager nie pojawia się w administracji.** Uruchom `bin/console assets:install && bin/console cache:clear`, a następnie przeładuj administrację z Ctrl+Shift+R. Moduł jest w grupie **Katalogi**.

**Edytor kodu pokazuje textarea bez kolorowania.** To fallback, gdy ani `mt-code-editor` (6.7), ani `sw-code-editor` (6.6) nie są dostępne. Sprawdź wersję Shopware i czy moduł administracji jest poprawnie załadowany.

**Chcę tymczasowo wyłączyć wszystkie snippety, niczego nie usuwając.** Dokładnie do tego służy safe mode. Przełącznik w konfiguracji pluginu, rekompilacja, gotowe.

**Przycisk "Kompiluj motyw" kręci się w nieskończoność.** Sprawdź logi Shopware. Kompilacja może trwać dłużej na dużym motywie; przy rzeczywistej blokadzie typową przyczyną jest snippet SCSS, który się zapętla albo zawiera nieznaną zmienną. Włącz safe mode, przekompiluj, a potem włączaj snippety jeden po drugim, aby namierzyć winowajcę.

**Mój snippet JavaScript się nie uruchamia.** Pamiętaj, że wstrzyknięty kod wykonuje się **w globalnym bundlu**, a więc w innym kontekście niż klasyczne pluginy Shopware. Aby wchodzić w interakcję z pluginami JavaScript storefrontu, nasłuchuj raczej `document.addEventListener('DOMContentLoaded', …)` lub globalnych zdarzeń emitowanych przez storefront.

**Co dzieje się przy odinstalowaniu?** Podczas `plugin:uninstall` Shopware wyświetla standardowy checkbox **Zachowaj dane użytkownika**. Jeśli jest **odznaczony**, plugin usuwa swoje 4 tabele i wszystkie powiązane dane (kontenery, snippety, wersje, powiązania kanałów). Jeśli jest **zaznaczony**, tabele pozostają na miejscu i odzyskasz swoje snippety, jeśli później ponownie zainstalujesz plugin.
