diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index c4253bf..0000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,101 +0,0 @@
-name: Testing Shopware 6.5
-
-on:
- push:
- branches:
- - dev
- - main65
- pull_request:
- branches:
- - dev
- - main65
- workflow_dispatch:
-
-env:
- MODULE_NAME: MuckiLogPlugin
- COMPOSER_NAME: muckiware/log-plugin
- TEST_DATABASE_URL: "mysql://root:root@127.0.0.1:3306/db_test"
-
-jobs:
- ci-current:
- name: SW ${{ matrix.shopware-versions }}, PHP ${{ matrix.php-versions }}, MySQL ${{ matrix.mysql-versions }}
- runs-on: ubuntu-latest
- strategy:
- max-parallel: 15
- fail-fast: false
- matrix:
- php-versions: [ '8.2' ]
- mysql-versions: [ '8.0' ]
- shopware-versions: [ 'v6.5.3.0' ]
- services:
- mysql:
- image: mysql:${{ matrix.mysql-versions }}
- env:
- MYSQL_DATABASE: db_test
- MYSQL_ROOT_PASSWORD: root
- ports:
- - 3306:3306
-
- steps:
- - name: Install PHP
- uses: shivammathur/setup-php@master
- with:
- php-version: ${{ matrix.php-versions }}
- extensions: mbstring, xdebug, curl, dom, fileinfo, gd, iconv, intl, json, xml, mbstring, pdo, phar, zip, sodium, pdo_mysql
- tools: composer:2.7.7
-
- - name: "Check PHP Version"
- run: php -v
-
- - name: "Check Composer Version"
- run: composer -V
-
- - name: "Check PHP Extensions"
- run: php -m
-
- - name: "checkout Shopware"
- uses: actions/checkout@v3
- with:
- repository: shopware/production
- ref: ${{ matrix.shopware-versions }}
-
- - name: "Checkout ${{ env.COMPOSER_NAME }}"
- uses: actions/checkout@v3
- with:
- path: custom/plugins/${{ env.MODULE_NAME }}
-
- - name: "Get composer cache directory"
- id: composer-cache
- run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
-
- - name: "Cache Composer dependencies"
- uses: actions/cache@v3
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ matrix.operating-system }}-${{ matrix.php-versions }}-${{ matrix.shopware-versions }}-${{ hashFiles('**/composer.lock') }}
-
- - name: "Install Shopware dependencies"
- # Install Shopware with --no-dev to prevent that dev-tools of the module got in conflict with the tools of shopware
- run: |
- composer req shopware/administration:${{ matrix.shopware-versions }} shopware/core:${{ matrix.shopware-versions }} shopware/elasticsearch:${{ matrix.shopware-versions }} shopware/storefront:${{ matrix.shopware-versions }} --no-update
- composer install --no-dev
-
- - name: "Install DEV-Tools"
- working-directory: custom/plugins/${{ env.MODULE_NAME }}
- run: |
- composer remove shopware/* --no-update
- composer install
-
- - name: "Install code-Tools"
- run: composer req phpunit/phpunit:^9.5 phpstan/phpstan
-
- - name: "Install Shopware"
- run: |
- echo APP_ENV=dev >> .env
- echo APP_URL=http://localhost >> .env
- echo DATABASE_URL=${{ env.TEST_DATABASE_URL }} >> .env
- echo APP_SECRET=secretf0rt3st >> .env
- bin/console system:install --basic-setup
-
- - name: "Run PHPUnit Tests"
- run: ./vendor/bin/phpunit --configuration="custom/plugins/${{ env.MODULE_NAME }}"
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..d921d74
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,198 @@
+# MuckiLogPlugin – CLAUDE.md
+
+## Zweck
+
+`muckiware/log-plugin` (v2.4.0) ersetzt das Standard-Monolog-Logging von Shopware durch **Apache Log4php** mittels des Symfony **Decorator-Patterns**. Jede Log-Ausgabe, die in Shopware oder Plugins über `Psr\Log\LoggerInterface` erfolgt, wird automatisch abgefangen und durch Log4php geroutet — ohne Codeänderungen in anderen Plugins.
+
+---
+
+## Decorator-Mechanismus (Kernprinzip)
+
+### 1. Logger-Decorator
+
+**Datei:** `src/Services/LoggerServiceDecorator.php`
+**Interface:** implementiert `Psr\Log\LoggerInterface`
+
+**Registrierung in** `src/Resources/config/services.xml`:
+
+```xml
+
+
+
+
+
+
+```
+
+**Wie es funktioniert:**
+- `decorates="Psr\Log\LoggerInterface"` weist Symfony an, diesen Service als Wrapper um den Original-Logger (Monolog) einzusetzen.
+- Der Original-Monolog-Service wird als `LoggerServiceDecorator.inner` übergeben, aber **nicht mehr aufgerufen** — alle Log-Methoden (`emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info`, `debug`, `log`) delegieren stattdessen an `MuckiLogPlugin\Logging\Logger` (Log4php).
+- `decoration-priority="10"` — höhere Zahl = äußerster Decorator (wird zuerst ausgeführt).
+
+### 2. ErrorController-Decorator
+
+**Datei:** `src/Storefront/Controller/ErrorControllerDecorator.php`
+
+```xml
+
+```
+
+Dekoriert den Shopware `ErrorController`, um Storefront-Exceptions (außer 404) automatisch mit Log4php zu loggen und eine Flash-Message mit Error-ID anzuzeigen.
+
+---
+
+## Log4php-Integration
+
+### Logging-Stack
+
+```
+Psr\Log\LoggerInterface (Aufruf aus beliebigem Plugin/Shopware)
+ └─> LoggerServiceDecorator::error/warning/info/debug(...)
+ └─> LoggerServiceDecorator::getLoggerSetup() → LoggerSetup DTO
+ └─> MuckiLogPlugin\Logging\Logger::logItem()
+ └─> Logconfig::checkConfigPath() — lädt/erstellt XML-Konfiguration
+ └─> Log4php\Logger::error/warning/info/debug()
+ └─> RollingFileAppender → var/log/..log
+```
+
+### Log-Konfiguration pro Plugin
+
+`Logconfig` erzeugt automatisch eine XML-Konfigurationsdatei pro Vendor/Plugin-Kombination:
+
+- **Pfad-Konvention:** `src/Resources/config/logconfig...xml`
+- **Log-Datei:** `var/log/..log`
+- Standard-Appender: `LoggerAppenderRollingFile` mit konfigurierbarer Dateigröße, Backup-Anzahl und Komprimierung.
+
+---
+
+## Context-Array-Konvention
+
+Damit ein Log-Eintrag der richtigen Log-Datei zugeordnet wird, muss der Context-Array eine bestimmte Struktur haben:
+
+```php
+$this->logger->error('Fehlermeldung', [
+ 'vendorName', // $context[0] → Vendor-Ordner / Log-Kategorie
+ 'pluginName', // $context[1] → Plugin-Name / Dateiname
+ // optional:
+ [
+ 'setup' => [
+ 'notificationEmail' => true,
+ 'notificationEmailReceiver' => 'admin@example.com',
+ 'notificationEmailSender' => 'shop@example.com',
+ 'notificationEmailTemplateId' => '',
+ ]
+ ]
+]);
+```
+
+Fehlt der Context, wird der Fallback `sw` / `dev` verwendet → `var/log/dev.sw.log`.
+
+---
+
+## Services im Überblick
+
+| Service | Zweck |
+|---|---|
+| `LoggerServiceDecorator` | Decorator für `Psr\Log\LoggerInterface`, Einstiegspunkt für alle Logs |
+| `MuckiLogPlugin\Logging\Logger` | Routing an Log4php, dispatcht Events vor/nach dem Logging |
+| `Logconfig` | Verwaltet Log4php XML-Config-Dateien (erstellt sie bei Bedarf) |
+| `Settings` | Liest Plugin-Konfiguration aus `SystemConfigService` |
+| `LoggingEvent` | Speichert Benachrichtigungs-Events in DB-Tabelle `muwa_logging_event` |
+| `SendNotification` | Versendet E-Mail-Benachrichtigungen per Log-Level |
+| `Mailer` | Shopware `MailService`-Wrapper für Notification-Mails |
+| `ErrorControllerDecorator` | Decorator für Storefront `ErrorController` |
+
+---
+
+## Events
+
+| Event-Konstante | Wann |
+|---|---|
+| `LoggerEvents::CREATE_LOG_EVENT_BEFORE` (`create.log.before`) | Vor dem eigentlichen Log-Schreiben |
+| `LoggerEvents::CREATE_LOG_EVENT_AFTER` (`create.log.after`) | Nach dem Log-Schreiben (inkl. DB-Speicherung) |
+
+Payload: `CreateLogEvent` mit `LoggerSetup`-DTO (enthält Vendor, Plugin, LogLevel, Message, Notification-Einstellungen).
+
+---
+
+## Entities & Migrations
+
+| Entity | DB-Tabelle | Zweck |
+|---|---|---|
+| `LoggingEventEntity` | `muwa_logging_event` | Speichert Log-Einträge, für die eine E-Mail-Benachrichtigung aussteht |
+| `EmailNotificationEntity` | — | E-Mail-Notification-Konfiguration |
+
+Migration: `src/Migration/Migration1729614227.php`
+
+---
+
+## Plugin-Konfiguration (`config.xml`)
+
+Alle Keys beginnen mit `MuckiLogPlugin.config.`:
+
+| Key | Typ | Bedeutung |
+|---|---|---|
+| `active` | bool | Plugin aktiv/inaktiv |
+| `level` | string | Mindest-Log-Level (`debug`, `info`, `warning`, `error`, `critical`) |
+| `maxbackupindex` | int | Anzahl Rolling-Backup-Dateien (Default: 10) |
+| `maxfilesize` | int | Max. Dateigröße in MB (Default: 10) |
+| `logpattern` | string | Log4php Conversion-Pattern |
+| `activeCompress` | bool | Backup-Logs komprimieren |
+| `activeNotificationMail` | bool | E-Mail-Benachrichtigung aktiv |
+| `notificationMailAddress` | string | Empfänger-Adresse |
+| `notificationMailTemplateId` | uuid | Shopware E-Mail-Template |
+| `notificationMailActive{Level}` | bool | Benachrichtigung je Log-Level |
+| `salesChannelId` | uuid | Sales-Channel für Mails |
+| `sendMailMode` | string | `eachLogLevelOneMail` (Default) |
+
+---
+
+## Scheduled Task
+
+`SendNotificationLogsTask` — läuft alle 300 Sekunden, versendet ausstehende Log-Benachrichtigungen aus `muwa_logging_event`.
+
+---
+
+## CLI-Befehle
+
+| Befehl | Klasse | Zweck |
+|---|---|---|
+| (registriert) | `Commands\Checkup` | Logger-Konfiguration prüfen |
+| (registriert) | `Commands\SendNotification` | Benachrichtigungen manuell auslösen |
+
+---
+
+## Wichtige Besonderheiten / Fallstricke
+
+- **Kein Monolog-Fallback**: Der Original-Monolog-Service (`.inner`) wird im Decorator gespeichert, aber **nie aufgerufen**. Wenn das Plugin deaktiviert ist (`Settings::isEnabled() === false`), wird **gar nicht** geloggt.
+- **Level-Mapping**: `alert` → `WARNING`, `notice` → `INFO`, `log()` → immer `DEBUG` — Abweichung von PSR-3-Semantik beachten.
+- **Context-Index-Abhängigkeit**: Der Context-Array wird per numerischem Index (`$context[0]`, `$context[1]`, `$context[2]`) ausgewertet — kein assoziativer Zugriff auf Vendor/Plugin-Namen. Bei falscher Struktur greift immer der Fallback.
+- **Config-Datei-Erstellung**: Fehlt die XML-Konfiguration für eine Vendor/Plugin-Kombination, erstellt `Logconfig::_createConfigXML()` sie automatisch via DOM — erfordert Schreibrechte auf `src/Resources/config/`.
+- **ErrorControllerDecorator-Bug**: `$this->originalLoggerService = $errorController;` — Property-Name ist falsch (`originalLoggerService` statt `originalErrorController`), führt aber zu keinem Laufzeitfehler, da die Property nur gesetzt, nie gelesen wird.
+- **`http\Message` Import**: In `LoggerServiceDecorator` wird `use http\Message;` importiert, aber nie genutzt — toter Import.
+
+---
+
+## Verwendung in eigenen Plugins
+
+```php
+// services.xml
+
+
+// PHP
+$this->logger->error('Fehlermeldung', ['lightsOn', 'myPlugin']);
+$this->logger->info('Info', ['lightsOn', 'myPlugin']);
+
+// Mit E-Mail-Benachrichtigung
+$this->logger->error('Kritischer Fehler', [
+ 'lightsOn',
+ 'myPlugin',
+ ['setup' => ['notificationEmail' => true]]
+]);
+```
+
+Log-Datei landet in: `var/log/myPlugin.lightsOn.log`
\ No newline at end of file
diff --git a/composer.json b/composer.json
index a5c96a3..ed9ceb1 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,8 @@
}
},
"require" : {
- "php" : ">= 8.1"
+ "php" : ">= 8.2",
+ "shopware/core" : ">= 6.5.8.0"
},
"require-dev" : {
"phpstan/phpstan" : "*"
diff --git a/readme.md b/readme.md
index 7ab933f..f349727 100644
--- a/readme.md
+++ b/readme.md
@@ -110,6 +110,78 @@ $loggerContext = array(
);
$this->logger->critical('Call HeaderPageletLoadedEvent with mail notification', $loggerContext);
```
+## Decorator Coverage
+
+MuckiLogPlugin intercepts Shopware and Symfony log calls through two complementary mechanisms.
+
+### 1. `Psr\Log\LoggerInterface` — via service decorator
+
+The primary decorator (`LoggerServiceDecorator`) wraps the default Symfony/Monolog logger. Any service
+that injects the logger via the standard PSR-3 interface is automatically covered:
+
+```xml
+
+```
+
+This is the recommended way to use the logger in your own plugins.
+
+### 2. `id="logger"` — via DI CompilerPass
+
+Many Shopware core services use the explicit `logger` service ID instead of the interface alias:
+
+```xml
+
+```
+
+The `LoggerDecoratorCompilerPass` runs at container compile time, traverses all service definitions
+and replaces every `id="logger"` reference with a reference to the `LoggerServiceDecorator` — except
+for services that are transitive dependencies of the decorator itself (those would create circular
+references).
+
+**What this means in practice:** Log calls from Shopware core services like `ProductStreamProcessor`,
+`StockUpdater`, or `ElasticsearchEntitySearcher` are routed through MuckiLogPlugin automatically,
+without any code changes in those services.
+
+### Why Monolog channel loggers (`id="monolog.logger.*"`) are not auto-decorated
+
+Shopware registers a dedicated Monolog logger per concern (`monolog.logger.event`,
+`monolog.logger.messenger`, `monolog.logger.request`, etc.). Decorating these channels with a
+service decorator is architecturally incompatible with the current plugin design:
+
+`LoggerServiceDecorator` → `MuckiLogPlugin\Logging\Logger` → `LoggingEvent`
+→ `muwa_logging_event.repository` → Shopware DAL → most Shopware services
+→ those Shopware services use channel loggers → **circular reference**
+
+The correct approach for intercepting channel loggers is a **Monolog Handler** (a handler is a leaf
+node in the DI graph and does not create cycles). This is documented as a future improvement.
+
+### Context array convention
+
+The decorator reads the PSR-3 context array to determine which log file to write to:
+
+```php
+// Writes to var/log/myplugin.myvendor.log
+$this->logger->error('Something failed', ['myvendor', 'myplugin']);
+
+// Writes to var/log/dev.sw.log (default fallback)
+$this->logger->error('Something failed', []);
+
+// Writes with email notification
+$this->logger->error('Critical failure', [
+ 'myvendor',
+ 'myplugin',
+ ['setup' => [
+ 'notificationEmail' => true,
+ 'notificationEmailReceiver' => 'ops@example.com',
+ 'notificationEmailSender' => 'shop@example.com',
+ ]]
+]);
+```
+
+> **Important:** The context array must use numeric indices `0` (vendor) and `1` (plugin name).
+> Associative arrays passed by Shopware core services (e.g. `['exception' => ...]`) are handled
+> gracefully — they fall back to the default `sw/dev` log file without errors.
+
## CLIs
```shell
bin/console muckiware:logger:send
@@ -118,7 +190,16 @@ This command execute the sending of open logger events by email. Regular will th
```shell
bin/console muckiware:logger:check
```
-This command is just for testing logging methods.
+This command tests the `Psr\Log\LoggerInterface` injection path and writes sample log entries
+across all log levels.
+
+```shell
+bin/console muckiware:logger:check-sw
+```
+This command tests the `id="logger"` injection path (typical Shopware core pattern) to verify
+that the `LoggerDecoratorCompilerPass` correctly routes those calls through MuckiLogPlugin.
+The first output line shows the actual class injected — it should read
+`MuckiLogPlugin\Services\LoggerServiceDecorator`, not `Monolog\Logger`.
# Testing
## phpstan
diff --git a/src/Commands/CheckupSwLogger.php b/src/Commands/CheckupSwLogger.php
new file mode 100644
index 0000000..99536b8
--- /dev/null
+++ b/src/Commands/CheckupSwLogger.php
@@ -0,0 +1,101 @@
+container = $container;
+ }
+
+ public function getContainer(): ?ContainerInterface
+ {
+ return $this->container;
+ }
+
+ public function configure(): void
+ {
+ $this->setDescription(
+ 'Tests logging via id="logger" injection (typical Shopware pattern) — verifies the CompilerPass routes calls through the MuckiLog decorator.'
+ );
+ parent::configure();
+ }
+
+ public function execute(InputInterface $input, OutputInterface $output): int
+ {
+ $output->writeln('Start SW-logger checkup (id="logger" injection)');
+ $output->writeln('Logger class: '.get_class($this->logger));
+
+ $this->writeTestLogEntries($output);
+
+ $output->writeln('Done SW-logger checkup');
+
+ return Command::SUCCESS;
+ }
+
+ private function writeTestLogEntries(OutputInterface $output): void
+ {
+ $output->writeln('Write into path: '.$this->pluginSettings->getLogPath());
+
+ foreach (LogLevel::cases() as $key => $logLevel) {
+ $method = $logLevel->value;
+
+ $output->writeln($key.' - Write '.$method.' via id="logger"');
+
+ // Einfache Nachricht — kein Context → Fallback sw/dev Log-Datei
+ $this->logger->{$method}($key.' - SW-logger test (no context): '.$method);
+
+ // Mit Vendor/Plugin-Context → eigene Log-Datei
+ $this->logger->{$method}(
+ $key.' - SW-logger test (with context): '.$method,
+ [PluginDefaults::CONTEXT, PluginDefaults::EXTENSION]
+ );
+ }
+
+ $defaultLogFile = $this->pluginSettings->getLogPath().'/'.PluginDefaults::DEFAULT_SW_EXTENSION.'.'.PluginDefaults::DEFAULT_SW_CONTEXT.'.log';
+ $contextLogFile = $this->pluginSettings->getLogPath().'/'.PluginDefaults::EXTENSION.'.'.PluginDefaults::CONTEXT.'.log';
+
+ if (file_exists($defaultLogFile)) {
+ $output->writeln('OK: default log file written → '.$defaultLogFile);
+ } else {
+ $output->writeln('FAIL: default log file missing → '.$defaultLogFile);
+ }
+
+ if (file_exists($contextLogFile)) {
+ $output->writeln('OK: context log file written → '.$contextLogFile);
+ } else {
+ $output->writeln('FAIL: context log file missing → '.$contextLogFile);
+ }
+ }
+}
diff --git a/src/DependencyInjection/LoggerDecoratorCompilerPass.php b/src/DependencyInjection/LoggerDecoratorCompilerPass.php
new file mode 100644
index 0000000..b81625b
--- /dev/null
+++ b/src/DependencyInjection/LoggerDecoratorCompilerPass.php
@@ -0,0 +1,113 @@
+hasDefinition(self::DECORATOR_ID)) {
+ return;
+ }
+
+ $decoratorDeps = [];
+ $this->collectTransitiveDeps(self::DECORATOR_ID, $container, $decoratorDeps);
+
+ $this->replaceLoggerArguments($container, $decoratorDeps);
+ }
+
+ /**
+ * Ersetzt id="logger" Injektionen durch den Decorator.
+ */
+ private function replaceLoggerArguments(ContainerBuilder $container, array $decoratorDeps): void
+ {
+ foreach ($container->getDefinitions() as $serviceId => $definition) {
+ if ($serviceId === self::DECORATOR_ID || isset($decoratorDeps[$serviceId])) {
+ continue;
+ }
+
+ foreach ($definition->getArguments() as $index => $argument) {
+ if ($argument instanceof Reference && (string) $argument === self::LOGGER_ID) {
+ $definition->replaceArgument($index, new Reference(self::DECORATOR_ID));
+ }
+ }
+
+ $methodCalls = $definition->getMethodCalls();
+ $modified = false;
+ foreach ($methodCalls as &$call) {
+ [, $arguments] = $call;
+ foreach ($arguments as $argIndex => $argument) {
+ if ($argument instanceof Reference && (string) $argument === self::LOGGER_ID) {
+ $arguments[$argIndex] = new Reference(self::DECORATOR_ID);
+ $modified = true;
+ }
+ }
+ $call[1] = $arguments;
+ }
+ unset($call);
+
+ if ($modified) {
+ $definition->setMethodCalls($methodCalls);
+ }
+ }
+ }
+
+ private function collectTransitiveDeps(string $serviceId, ContainerBuilder $container, array &$visited): void
+ {
+ $resolvedId = $this->resolveAlias($serviceId, $container);
+
+ if (isset($visited[$resolvedId])) {
+ return;
+ }
+
+ $visited[$resolvedId] = true;
+ if ($resolvedId !== $serviceId) {
+ $visited[$serviceId] = true;
+ }
+
+ if (!$container->hasDefinition($resolvedId)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($resolvedId);
+
+ foreach ($definition->getArguments() as $argument) {
+ if ($argument instanceof Reference) {
+ $this->collectTransitiveDeps((string) $argument, $container, $visited);
+ }
+ }
+
+ foreach ($definition->getMethodCalls() as [, $arguments]) {
+ foreach ($arguments as $argument) {
+ if ($argument instanceof Reference) {
+ $this->collectTransitiveDeps((string) $argument, $container, $visited);
+ }
+ }
+ }
+ }
+
+ private function resolveAlias(string $serviceId, ContainerBuilder $container): string
+ {
+ while ($container->hasAlias($serviceId)) {
+ $serviceId = (string) $container->getAlias($serviceId);
+ }
+
+ return $serviceId;
+ }
+}
diff --git a/src/Logging/Logger.php b/src/Logging/Logger.php
index 211afc1..79c8798 100644
--- a/src/Logging/Logger.php
+++ b/src/Logging/Logger.php
@@ -4,7 +4,7 @@
*
* @category Muckiware
* @package Logger
- * @copyright Copyright (c) 2021-2024 by muckiware
+ * @copyright Copyright (c) 2021-2026 by muckiware
*
*/
namespace MuckiLogPlugin\Logging;
@@ -41,6 +41,11 @@ public function __construct(
$this->logger = $this->logConfig->getLogger();
}
+ public function setLogger(LogconfigInterface $logConfig): void
+ {
+ $this->logger = $logConfig->getLogger();
+ }
+
public function executeLoggingByLogLevel(LoggerSetup $loggerSetup): void
{
$event = new CreateLogEvent($loggerSetup);
diff --git a/src/MuckiLogPlugin.php b/src/MuckiLogPlugin.php
index 690fdad..2dd6189 100644
--- a/src/MuckiLogPlugin.php
+++ b/src/MuckiLogPlugin.php
@@ -4,7 +4,7 @@
*
* @category SW6 Plugin
* @package Muckilog
- * @copyright Copyright (c) 2021-2024 by Muckiware
+ * @copyright Copyright (c) 2021-2026 by Muckiware
* @license MIT
* @author Muckiware
*
@@ -17,13 +17,21 @@
use Shopware\Core\Framework\Plugin\Context\InstallContext;
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
use Shopware\Core\Framework\Plugin\Context\UpdateContext;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use MuckiLogPlugin\DependencyInjection\LoggerDecoratorCompilerPass;
use MuckiLogPlugin\Setup\Setup;
use MuckiLogPlugin\Services\Logconfig;
use MuckiLogPlugin\Services\Settings;
class MuckiLogPlugin extends Plugin
{
+ public function build(ContainerBuilder $container): void
+ {
+ parent::build($container);
+ $container->addCompilerPass(new LoggerDecoratorCompilerPass());
+ }
+
/**
* @throws \Exception
*/
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index 67ad6f3..4c91db7 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -18,7 +18,7 @@
-
+
@@ -47,6 +47,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/Services/LoggerServiceDecorator.php b/src/Services/LoggerServiceDecorator.php
index 17d8450..0551922 100644
--- a/src/Services/LoggerServiceDecorator.php
+++ b/src/Services/LoggerServiceDecorator.php
@@ -5,12 +5,11 @@
*
* @category Muckiware
* @package Muckilog
- * @copyright Copyright (c) 2021-2024 by Muckiware
+ * @copyright Copyright (c) 2021-2026 by Muckiware
* @license MIT
* @author Muckiware
*
*/
-
namespace MuckiLogPlugin\Services;
use http\Message;
@@ -111,8 +110,9 @@ public function getLoggerSetup(LogLevel $logLevel, mixed $message, array $contex
public function contextSetupNeedNotification(array $context): bool
{
- if(
- !empty($context) && count($context) === 3 &&
+ if (
+ isset($context[2]) &&
+ is_array($context[2]) &&
array_key_exists('setup', $context[2]) &&
array_key_exists('notificationEmail', $context[2]['setup']) &&
is_bool($context[2]['setup']['notificationEmail'])
@@ -124,8 +124,9 @@ public function contextSetupNeedNotification(array $context): bool
public function setupNotificationEmailTemplateId(array $context, LoggerSetup $loggerSetup): LoggerSetup
{
- if(
- !empty($context) && count($context) === 3 &&
+ if (
+ isset($context[2]) &&
+ is_array($context[2]) &&
array_key_exists('setup', $context[2]) &&
array_key_exists('notificationEmailTemplateId', $context[2]['setup']) &&
Uuid::isValid(trim($context[2]['setup']['notificationEmailTemplateId']))
@@ -143,8 +144,9 @@ public function setupNotificationEmailTemplateId(array $context, LoggerSetup $lo
public function setupNotificationEmailReceiver(array $context, LoggerSetup $loggerSetup): LoggerSetup
{
- if(
- !empty($context) && count($context) === 3 &&
+ if (
+ isset($context[2]) &&
+ is_array($context[2]) &&
array_key_exists('setup', $context[2]) &&
array_key_exists('notificationEmailReceiver', $context[2]['setup']) &&
$this->pluginHelper->isValidEmail(trim($context[2]['setup']['notificationEmailReceiver']))
@@ -162,8 +164,9 @@ public function setupNotificationEmailReceiver(array $context, LoggerSetup $logg
public function setupNotificationEmailSender(array $context, LoggerSetup $loggerSetup): LoggerSetup
{
- if(
- !empty($context) && count($context) === 3 &&
+ if (
+ isset($context[2]) &&
+ is_array($context[2]) &&
array_key_exists('setup', $context[2]) &&
array_key_exists('notificationEmailSender', $context[2]['setup']) &&
$this->pluginHelper->isValidEmail(trim($context[2]['setup']['notificationEmailSender']))
@@ -177,12 +180,10 @@ public function setupNotificationEmailSender(array $context, LoggerSetup $logger
public function setupVendorPluginNames(array $context, LoggerSetup $loggerSetup): LoggerSetup
{
- if(!empty($context) && count($context) >= 2) {
-
+ if (isset($context[0], $context[1])) {
$loggerSetup->setVendor(trim($context[0]));
$loggerSetup->setPlugin(trim($context[1]));
} else {
-
$loggerSetup->setVendor(Defaults::DEFAULT_SW_CONTEXT);
$loggerSetup->setPlugin(Defaults::DEFAULT_SW_EXTENSION);
}
diff --git a/tests/Logging/LoggerTest.php b/tests/Logging/LoggerTest.php
new file mode 100644
index 0000000..16f8293
--- /dev/null
+++ b/tests/Logging/LoggerTest.php
@@ -0,0 +1,72 @@
+createMock(PluginSettings::class);
+ $pluginSettings->method('getConfigPath')->willReturn(TestDefaults::getLoggerConfigPath());
+ $pluginSettings->method('getLoggerFileName')->willReturn(TestDefaults::getLoggerFilePath());
+ $pluginSettings->method('getMaxBackupIndex')->willReturn(PluginSettings::CONFIG_PATH_MAX_BACKUP_INDEX_DEFAULT);
+ $pluginSettings->method('getMaxFileSize')->willReturn(PluginSettings::CONFIG_PATH_MAX_FILESIZE_DEFAULT);
+ $pluginSettings->method('isEnabledCompress')->willReturn(false);
+ $pluginSettings->method('getConversionPattern')->willReturn(PluginSettings::CONFIG_PATH_CONVERSIONPATTERN_DEFAULT);
+ $pluginSettings->method('getLoglevel')->willReturn('debug');
+ $logconfig = new Logconfig(
+ $this->createMock(KernelInterface::class),
+ $pluginSettings
+ );
+
+ //Create the log config for the test
+ $checkConfigPath = $logconfig->checkConfigPath(TestDefaults::DEFAULT_TEST_PLUGIN, TestDefaults::DEFAULT_TEST_VENDOR);
+ $this->assertIsBool($checkConfigPath);
+ $this->assertTrue($checkConfigPath, 'Logconfig path could not be created for the test.');
+
+ \MuckiLogPlugin\Log4php\Logger::configure(TestDefaults::getLoggerConfigPath());
+
+ $logconfigInterface = $this->createMock(LogconfigInterface::class);
+ $Log4phpLogger = \MuckiLogPlugin\Log4php\Logger::getLogger('muckilog');
+ $logconfigInterface->method('getLogger')->willReturn($Log4phpLogger);
+
+ $logger = new Logger(
+ $this->createMock(EventDispatcherInterface::class),
+ $logconfigInterface,
+ $this->createMock(SettingsInterface::class),
+ $this->createMock(LoggingEvent::class)
+ );
+
+ $loggerSetup = new LoggerSetup();
+ $loggerSetup->setLogLevel(LogLevel::INFO);
+ $loggerSetup->setMessage('This is a test log message.');
+ $loggerSetup->setPlugin(TestDefaults::DEFAULT_TEST_PLUGIN);
+ $loggerSetup->setVendor(TestDefaults::DEFAULT_TEST_VENDOR);
+ $loggerSetup->setPathLogFile(TestDefaults::getLoggerConfigPath());
+
+ $logger->executeLoggingByLogLevel($loggerSetup);
+
+ $checker = true;
+ }
+}
diff --git a/tests/TestCaseBase/Defaults.php b/tests/TestCaseBase/Defaults.php
new file mode 100644
index 0000000..773838e
--- /dev/null
+++ b/tests/TestCaseBase/Defaults.php
@@ -0,0 +1,39 @@
+