From 35d3823f2f2efbf545fb56adbdb9881b325f3922 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 18 Jul 2025 14:26:53 +0200 Subject: [PATCH 01/15] Log undeclared plugin only if it is not disabled --- .../Magento/Framework/Interception/PluginListGenerator.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 0c77360162227..44a7c57e6c4fc 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -366,9 +366,12 @@ public function trimInstanceStartingBackslash(&$plugins) public function filterPlugins(array &$plugins) { foreach ($plugins as $name => $plugin) { - if (empty($plugin['instance'])) { + if (!isset($plugin['instance'])) { unset($plugins[$name]); - $this->logger->info("Reference to undeclared plugin with name '{$name}'."); + $isDisabled = $plugin['disabled'] ?? false; + if (!$isDisabled) { + $this->logger->info("Reference to undeclared plugin with name '{$name}'."); + } } } } From 710453ea8577f23d19148a1f69acb82ad7a185bd Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 18 Jul 2025 17:26:00 +0200 Subject: [PATCH 02/15] Log in dev mode only or when plugin is actually enabled --- .../Framework/Interception/PluginListGenerator.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 44a7c57e6c4fc..bb9c9ccbd8944 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -8,6 +8,8 @@ namespace Magento\Framework\Interception; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\App\State; use Magento\Framework\Config\ReaderInterface; use Magento\Framework\Config\ScopeInterface; use Magento\Framework\Interception\ObjectManager\ConfigInterface; @@ -129,7 +131,8 @@ public function __construct( ClassDefinitions $classDefinitions, LoggerInterface $logger, DirectoryList $directoryList, - array $scopePriorityScheme = ['global'] + array $scopePriorityScheme = ['global'], + ?State $appstate = null ) { $this->reader = $reader; $this->scopeConfig = $scopeConfig; @@ -140,6 +143,7 @@ public function __construct( $this->logger = $logger; $this->directoryList = $directoryList; $this->scopePriorityScheme = $scopePriorityScheme; + $this->appState = $appstate ?? ObjectManager::getInstance()->get(State::class); } /** @@ -368,9 +372,9 @@ public function filterPlugins(array &$plugins) foreach ($plugins as $name => $plugin) { if (!isset($plugin['instance'])) { unset($plugins[$name]); - $isDisabled = $plugin['disabled'] ?? false; - if (!$isDisabled) { - $this->logger->info("Reference to undeclared plugin with name '{$name}'."); + // Log the undeclared plugin when it is not disabled or when the app is in Developer mode. + if ($this->appState->getMode() === State::MODE_DEVELOPER || !($plugin['disabled'] ?? false)) { + $this->logger->debug("Reference to undeclared plugin with name '{$name}'."); } } } From 89889024174e638111255ad9ab2d4ad5128f0323 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 18 Jul 2025 17:32:59 +0200 Subject: [PATCH 03/15] Add missing property --- .../Magento/Framework/Interception/PluginListGenerator.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index bb9c9ccbd8944..34cb34776a50f 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -106,6 +106,11 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac */ private $scopePriorityScheme; + /** + * @var State|null + */ + private ?State $appState; + /** * @var array */ From 7a404b08709a20627209cb8e7dce41e3564a0c7d Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 18 Jul 2025 17:33:44 +0200 Subject: [PATCH 04/15] Add missing phpdoc --- .../Magento/Framework/Interception/PluginListGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 34cb34776a50f..212e70751effa 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -126,6 +126,7 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac * @param LoggerInterface $logger * @param DirectoryList $directoryList * @param array $scopePriorityScheme + * @param State|null $appstate */ public function __construct( ReaderInterface $reader, From abbee11eeab5058e7c05fa9590912204be99e8ce Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 18 Jul 2025 17:35:28 +0200 Subject: [PATCH 05/15] Fix License --- .../Magento/Framework/Interception/PluginListGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 212e70751effa..9e878ad0637c1 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -1,7 +1,7 @@ Date: Sat, 19 Jul 2025 21:38:07 +0200 Subject: [PATCH 06/15] Fix typo --- .../Framework/Interception/PluginListGenerator.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 9e878ad0637c1..67a19360e2d9e 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -107,9 +107,9 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac private $scopePriorityScheme; /** - * @var State|null + * @var State */ - private ?State $appState; + private State $appState; /** * @var array @@ -126,7 +126,7 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac * @param LoggerInterface $logger * @param DirectoryList $directoryList * @param array $scopePriorityScheme - * @param State|null $appstate + * @param State|null $appState */ public function __construct( ReaderInterface $reader, @@ -138,7 +138,7 @@ public function __construct( LoggerInterface $logger, DirectoryList $directoryList, array $scopePriorityScheme = ['global'], - ?State $appstate = null + ?State $appState = null ) { $this->reader = $reader; $this->scopeConfig = $scopeConfig; @@ -149,7 +149,7 @@ public function __construct( $this->logger = $logger; $this->directoryList = $directoryList; $this->scopePriorityScheme = $scopePriorityScheme; - $this->appState = $appstate ?? ObjectManager::getInstance()->get(State::class); + $this->appState = $appState ?? ObjectManager::getInstance()->get(State::class); } /** From 3e674958b221bb5e43d553cd534f10480ba650fe Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Sun, 3 Aug 2025 23:11:05 +0200 Subject: [PATCH 07/15] Add missing signature on private methods + use CPP --- .../Interception/PluginListGenerator.php | 157 +++--------------- 1 file changed, 24 insertions(+), 133 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 67a19360e2d9e..34e09e7f1b903 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -12,6 +12,7 @@ use Magento\Framework\App\State; use Magento\Framework\Config\ReaderInterface; use Magento\Framework\Config\ScopeInterface; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Interception\ObjectManager\ConfigInterface; use Magento\Framework\ObjectManager\DefinitionInterface as ClassDefinitions; use Magento\Framework\ObjectManager\RelationsInterface; @@ -22,133 +23,33 @@ */ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterface { - /** - * @var ScopeInterface - */ - private $scopeConfig; - - /** - * Configuration reader - * - * @var ReaderInterface - */ - private $reader; - - /** - * Cache tag - * - * @var string - */ - private $cacheId = 'plugin-list'; - - /** - * @var array - */ - private $loadedScopes = []; - - /** - * Type config - * - * @var ConfigInterface - */ - private $omConfig; - - /** - * Class relations information provider - * - * @var RelationsInterface - */ - private $relations; - - /** - * List of interception methods per plugin - * - * @var DefinitionInterface - */ - private $definitions; - - /** - * List of interceptable application classes - * - * @var ClassDefinitions - */ - private $classDefinitions; - /** - * @var LoggerInterface - */ - private $logger; + private State $appState; - /** - * @var DirectoryList - */ - private $directoryList; + private string $cacheId = 'plugin-list'; - /** - * @var array - */ - private $pluginData; + private array $loadedScopes = []; - /** - * @var array - */ - private $inherited = []; + private array $pluginData; - /** - * @var array - */ - private $processed; + private array $inherited = []; - /** - * Scope priority loading scheme - * - * @var string[] - */ - private $scopePriorityScheme; + private array $processed; - /** - * @var State - */ - private State $appState; + private array $globalScopePluginData = []; - /** - * @var array - */ - private $globalScopePluginData = []; - - /** - * @param ReaderInterface $reader - * @param ScopeInterface $scopeConfig - * @param ConfigInterface $omConfig - * @param RelationsInterface $relations - * @param DefinitionInterface $definitions - * @param ClassDefinitions $classDefinitions - * @param LoggerInterface $logger - * @param DirectoryList $directoryList - * @param array $scopePriorityScheme - * @param State|null $appState - */ public function __construct( - ReaderInterface $reader, - ScopeInterface $scopeConfig, - ConfigInterface $omConfig, - RelationsInterface $relations, - DefinitionInterface $definitions, - ClassDefinitions $classDefinitions, - LoggerInterface $logger, - DirectoryList $directoryList, - array $scopePriorityScheme = ['global'], + private ReaderInterface $reader, + private ScopeInterface $scopeConfig, + private ConfigInterface $omConfig, + private RelationsInterface $relations, + private DefinitionInterface $definitions, + private ClassDefinitions $classDefinitions, + private LoggerInterface $logger, + private DirectoryList $directoryList, + private array $scopePriorityScheme = ['global'], ?State $appState = null ) { - $this->reader = $reader; - $this->scopeConfig = $scopeConfig; - $this->omConfig = $omConfig; - $this->relations = $relations; - $this->definitions = $definitions; - $this->classDefinitions = $classDefinitions; - $this->logger = $logger; - $this->directoryList = $directoryList; - $this->scopePriorityScheme = $scopePriorityScheme; $this->appState = $appState ?? ObjectManager::getInstance()->get(State::class); } @@ -255,21 +156,16 @@ public function loadScopedVirtualTypes($scopePriorityScheme, $loadedScopes, $plu /** * Returns class definitions - * - * @return array */ - private function getClassDefinitions() + private function getClassDefinitions(): array { return $this->classDefinitions->getClasses(); } /** * Whether scope code is current scope code - * - * @param string $scopeCode - * @return bool */ - private function isCurrentScope($scopeCode) + private function isCurrentScope(string $scopeCode): bool { return $this->scopeConfig->getCurrentScope() === $scopeCode; } @@ -412,28 +308,23 @@ public function merge(array $config, $pluginData) /** * Writes config in storage * - * @param string $key - * @param array $config - * @return void - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ - private function writeConfig(string $key, array $config) + private function writeConfig(string $key, array $config): void { $this->initialize(); - $configuration = sprintf('directoryList->getPath(DirectoryList::GENERATED_METADATA) . '/' . $key . '.php', - $configuration + sprintf('directoryList->getPath(DirectoryList::GENERATED_METADATA))) { mkdir($this->directoryList->getPath(DirectoryList::GENERATED_METADATA)); From 48da42179102962671d611ac1358b5b1a061fbc6 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Tue, 5 Aug 2025 11:25:19 +0200 Subject: [PATCH 08/15] Inject mode instead of State instance --- .../Interception/PluginListGenerator.php | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 34e09e7f1b903..ada89869afc82 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -23,19 +23,36 @@ */ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterface { - - private State $appState; - + /** + * Cache tag + * + * @var string + */ private string $cacheId = 'plugin-list'; + /** + * @var string[] + */ private array $loadedScopes = []; + /** + * @var array + */ private array $pluginData; + /** + * @var array + */ private array $inherited = []; + /** + * @var array + */ private array $processed; + /** + * @var array + */ private array $globalScopePluginData = []; public function __construct( @@ -48,9 +65,8 @@ public function __construct( private LoggerInterface $logger, private DirectoryList $directoryList, private array $scopePriorityScheme = ['global'], - ?State $appState = null + private string $mode = State::MODE_DEFAULT ) { - $this->appState = $appState ?? ObjectManager::getInstance()->get(State::class); } /** @@ -275,7 +291,7 @@ public function filterPlugins(array &$plugins) if (!isset($plugin['instance'])) { unset($plugins[$name]); // Log the undeclared plugin when it is not disabled or when the app is in Developer mode. - if ($this->appState->getMode() === State::MODE_DEVELOPER || !($plugin['disabled'] ?? false)) { + if ($this->mode === State::MODE_DEVELOPER || !($plugin['disabled'] ?? false)) { $this->logger->debug("Reference to undeclared plugin with name '{$name}'."); } } From bbac3c8108698c220e62698ddf7d428e215e4a48 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Tue, 5 Aug 2025 11:27:00 +0200 Subject: [PATCH 09/15] Fix typo in property name --- .../Magento/Framework/Interception/PluginListGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index ada89869afc82..cc08b55a5f91c 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -65,7 +65,7 @@ public function __construct( private LoggerInterface $logger, private DirectoryList $directoryList, private array $scopePriorityScheme = ['global'], - private string $mode = State::MODE_DEFAULT + private string $appMode = State::MODE_DEFAULT ) { } @@ -291,7 +291,7 @@ public function filterPlugins(array &$plugins) if (!isset($plugin['instance'])) { unset($plugins[$name]); // Log the undeclared plugin when it is not disabled or when the app is in Developer mode. - if ($this->mode === State::MODE_DEVELOPER || !($plugin['disabled'] ?? false)) { + if ($this->appMode === State::MODE_DEVELOPER || !($plugin['disabled'] ?? false)) { $this->logger->debug("Reference to undeclared plugin with name '{$name}'."); } } From c5233f8e0b83d5e0c72614c84cecf90422c0dc66 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Tue, 5 Aug 2025 11:28:05 +0200 Subject: [PATCH 10/15] Inject app mode in interceptor generator --- app/etc/di.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/etc/di.xml b/app/etc/di.xml index 4689a852578db..d04d7f0877433 100644 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -359,6 +359,11 @@ Magento\Framework\App\State::PARAM_MODE + + + Magento\Framework\App\State::PARAM_MODE + + Magento\Framework\App\Cache\Frontend\Factory::PARAM_CACHE_FORCED_OPTIONS From b4f5cfc03fb4446fff4f0395aa48f34e1c85015f Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 6 Aug 2025 09:56:53 +0200 Subject: [PATCH 11/15] Fix property must not be accessed before initialization --- .../Magento/Framework/Interception/PluginListGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index cc08b55a5f91c..9c7dddc0823dd 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -38,7 +38,7 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac /** * @var array */ - private array $pluginData; + private array $pluginData = []; /** * @var array @@ -48,7 +48,7 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac /** * @var array */ - private array $processed; + private array $processed = []; /** * @var array From 9e27141f59681582ee2d2688d71b7f0006407b2b Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 6 Aug 2025 12:03:18 +0200 Subject: [PATCH 12/15] Remove duplicate declaration --- app/etc/di.xml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/etc/di.xml b/app/etc/di.xml index d04d7f0877433..bc544f971cdec 100644 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -359,11 +359,6 @@ Magento\Framework\App\State::PARAM_MODE - - - Magento\Framework\App\State::PARAM_MODE - - Magento\Framework\App\Cache\Frontend\Factory::PARAM_CACHE_FORCED_OPTIONS @@ -476,6 +471,7 @@ primary global + Magento\Framework\App\State::PARAM_MODE From 56eac3ee79d80afb99b0463bacedb04d0c143c3d Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 6 Aug 2025 12:07:25 +0200 Subject: [PATCH 13/15] Fix phpcs --- .../Interception/PluginListGenerator.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 9c7dddc0823dd..12301f54746e6 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -55,6 +55,18 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac */ private array $globalScopePluginData = []; + /** + * @param ReaderInterface $reader + * @param ScopeInterface $scopeConfig + * @param ConfigInterface $omConfig + * @param RelationsInterface $relations + * @param DefinitionInterface $definitions + * @param ClassDefinitions $classDefinitions + * @param LoggerInterface $logger + * @param DirectoryList $directoryList + * @param array $scopePriorityScheme [optional] + * @param string $appMode [optional] + */ public function __construct( private ReaderInterface $reader, private ScopeInterface $scopeConfig, @@ -180,6 +192,9 @@ private function getClassDefinitions(): array /** * Whether scope code is current scope code + * + * @param string $scopeCode + * @return bool */ private function isCurrentScope(string $scopeCode): bool { @@ -324,6 +339,8 @@ public function merge(array $config, $pluginData) /** * Writes config in storage * + * @param string $key + * @param array $config * @throws FileSystemException */ private function writeConfig(string $key, array $config): void From 9fef293d5284b873922ffecc4edb0fead308f5e5 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Mon, 11 Aug 2025 11:47:12 +0200 Subject: [PATCH 14/15] scopeCode can be null --- .../Magento/Framework/Interception/PluginListGenerator.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index 12301f54746e6..a786a35929870 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -193,11 +193,12 @@ private function getClassDefinitions(): array /** * Whether scope code is current scope code * - * @param string $scopeCode + * @param string|null $scopeCode * @return bool */ - private function isCurrentScope(string $scopeCode): bool + private function isCurrentScope(?string $scopeCode): bool { + // ToDo: $scopeCode can be null in integration tests because of how scope is reset. return $this->scopeConfig->getCurrentScope() === $scopeCode; } From 4d2f9ee18a068ec1d1b43d09db943fde40ae85e8 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Wed, 13 Aug 2025 10:08:51 +0200 Subject: [PATCH 15/15] Fix phpcs --- .../Magento/Framework/Interception/PluginListGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php index a786a35929870..0153ee92a8062 100644 --- a/lib/internal/Magento/Framework/Interception/PluginListGenerator.php +++ b/lib/internal/Magento/Framework/Interception/PluginListGenerator.php @@ -66,6 +66,7 @@ class PluginListGenerator implements ConfigWriterInterface, ConfigLoaderInterfac * @param DirectoryList $directoryList * @param array $scopePriorityScheme [optional] * @param string $appMode [optional] + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( private ReaderInterface $reader,