From 25927ae2c343c8d09ef2fba061a309a9ae86866c Mon Sep 17 00:00:00 2001 From: Michael Telgmann Date: Wed, 3 Jan 2024 10:46:49 +0100 Subject: [PATCH] fix: Ensure compatibility with newer xmllib2 versions on linux distributions --- .phpstan-baseline.neon | 290 ------------------ .../Service/PluginInstaller.php | 169 ++++------ .../Plugin/RequirementValidator.php | 34 +- .../Components/Plugin/XmlPluginInfoReader.php | 9 +- .../Plugin/XmlReader/XmlConfigReader.php | 2 +- .../Plugin/XmlReader/XmlMenuReader.php | 2 +- .../Plugin/XmlReader/XmlPluginReader.php | 9 +- .../Plugin/XmlReader/XmlReaderBase.php | 9 +- .../Components/Plugin/schema/plugin.xsd | 9 +- .../Plugin/XmlReader/XmlPluginReaderTest.php | 12 +- .../XmlReader/examples/plugin/plugin.xml | 6 - ...{plugin_minimal.xml => plugin_invalid.xml} | 1 - 12 files changed, 95 insertions(+), 457 deletions(-) rename tests/Unit/Components/Plugin/XmlReader/examples/plugin/{plugin_minimal.xml => plugin_invalid.xml} (88%) diff --git a/.phpstan-baseline.neon b/.phpstan-baseline.neon index e12ec30d075..6fd40252550 100644 --- a/.phpstan-baseline.neon +++ b/.phpstan-baseline.neon @@ -7775,116 +7775,6 @@ parameters: count: 1 path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginCategoryService.php - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:installCronjob\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:installForm\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:installMenu\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:installResources\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:installSnippets\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:refreshPluginList\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeCrontabEntries\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeEmotionComponents\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeEventSubscribers\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeFormsAndElements\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeMenuEntries\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeSnippets\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginInstaller\\:\\:removeTemplates\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.added\" expects value type string, got type DateTimeInterface$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.author\" expects value type string\\|null, got type mixed$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.id\" expects value type int, got type mixed$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.label\" expects value type string, got type mixed$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.link\" expects value type string\\|null, got type mixed$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.refresh_date\" expects value type string\\|null, got type DateTimeInterface$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.translations\" expects value type string\\|null, got type non\\-empty\\-string\\|false\\|null$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.update_version\" expects value type string\\|null, got type mixed$#" - count: 1 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - - - message: "#^Query error\\: Column \"s_core_plugins\\.version\" expects value type string, got type mixed$#" - count: 2 - path: engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php - - message: "#^Method Shopware\\\\Bundle\\\\PluginInstallerBundle\\\\Service\\\\PluginLicenceService\\:\\:cleanupLocalLicenseInformation\\(\\) has no return type specified\\.$#" count: 1 @@ -18500,21 +18390,6 @@ parameters: count: 1 path: engine/Shopware/Components/Plugin/PaymentInstaller.php - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\RequirementValidator\\:\\:assertRequiredPlugins\\(\\) has parameter \\$requiredPlugins with no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/RequirementValidator.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\RequirementValidator\\:\\:assertShopwareVersion\\(\\) has parameter \\$compatibility with no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/RequirementValidator.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\RequirementValidator\\:\\:validate\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/RequirementValidator.php - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\ResourceSubscriber\\:\\:onCollectCss\\(\\) return type with generic class Doctrine\\\\Common\\\\Collections\\\\ArrayCollection does not specify its types\\: TKey, T$#" count: 1 @@ -18525,31 +18400,6 @@ parameters: count: 1 path: engine/Shopware/Components/Plugin/ResourceSubscriber.php - - - message: "#^Cannot assign offset non\\-falsy\\-string to array\\\\>\\|string\\|null\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlPluginInfoReader.php - - - - message: "#^Cannot assign offset string to array\\\\>\\|string\\|null\\>\\|string\\|null\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlPluginInfoReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlPluginInfoReader\\:\\:parseInfo\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlPluginInfoReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlPluginInfoReader\\:\\:read\\(\\) has no return type specified\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlPluginInfoReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlPluginInfoReader\\:\\:read\\(\\) has parameter \\$file with no type specified\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlPluginInfoReader.php - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\StoreValueParser\\\\StoreExtjsValueParser\\:\\:parse\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 @@ -18565,141 +18415,6 @@ parameters: count: 1 path: engine/Shopware/Components/Plugin/XmlReader/StoreValueParser/StoreXmlValueParser.php - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlConfigReader\\:\\:parseElementNodeList\\(\\) has parameter \\$list with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlConfigReader\\:\\:parseElementNodeList\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlConfigReader\\:\\:parseFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlCronjobReader\\:\\:parseFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlCronjobReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlCronjobReader\\:\\:parseItem\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlCronjobReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlCronjobReader\\:\\:parseList\\(\\) has parameter \\$list with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlCronjobReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlCronjobReader\\:\\:parseList\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlCronjobReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlMenuReader\\:\\:parseEntry\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlMenuReader\\:\\:parseFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php - - - - message: "#^Parameter \\#1 \\$node of static method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:getChildren\\(\\) expects DOMNode, DOMElement\\|null given\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php - - - - message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#" - count: 2 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Call to an undefined method DOMNode\\:\\:getElementsByTagName\\(\\)\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Cannot assign offset non\\-falsy\\-string to array\\\\>\\|string\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Cannot assign offset string to array\\\\>\\|string\\>\\|string\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlPluginReader\\:\\:parseBlacklist\\(\\) has parameter \\$items with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlPluginReader\\:\\:parseBlacklist\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlPluginReader\\:\\:parseFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlPluginReader\\:\\:parseRequiredPlugins\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php - - - - message: "#^Cannot access property \\$childNodes on DOMNode\\|null\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseOptionsNodeList\\(\\) has parameter \\$optionsList with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseOptionsNodeList\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseStoreNodeList\\(\\) has parameter \\$list with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseStoreNodeList\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:parseTranslatableNodeList\\(\\) has parameter \\$list with generic class DOMNodeList but does not specify its types\\: TNode$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderBase\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php - - - - message: "#^Method Shopware\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlReaderInterface\\:\\:read\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: engine/Shopware/Components/Plugin/XmlReader/XmlReaderInterface.php - - message: "#^Method Shopware\\\\Components\\\\Privacy\\\\CookieRemoveSubscriber\\:\\:convertToArray\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 @@ -41655,11 +41370,6 @@ parameters: count: 1 path: tests/Unit/Components/Plugin/XmlReader/XmlMenuReaderTest.php - - - message: "#^Method Shopware\\\\Tests\\\\Unit\\\\Components\\\\Plugin\\\\XmlReader\\\\XmlPluginReaderTest\\:\\:readFile\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: tests/Unit/Components/Plugin/XmlReader/XmlPluginReaderTest.php - - message: "#^Method Shopware\\\\Tests\\\\Unit\\\\Components\\\\QueryAliasMapperTest\\:\\:testAliasesCanBeRetrieved\\(\\) has no return type specified\\.$#" count: 1 diff --git a/engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php b/engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php index 2350d47e84b..e21e476c069 100644 --- a/engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php +++ b/engine/Shopware/Bundle/PluginInstallerBundle/Service/PluginInstaller.php @@ -26,7 +26,8 @@ use DateTime; use DateTimeInterface; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\DBALException; +use Doctrine\ORM\OptimisticLockException; use Enlight_Event_EventManager; use Exception; use InvalidArgumentException; @@ -69,58 +70,31 @@ class PluginInstaller { - /** - * @var ModelManager - */ - private $em; + private ModelManager $em; - /** - * @var Connection - */ - private $connection; + private Connection $connection; - /** - * @var DatabaseHandler - */ - private $snippetHandler; + private DatabaseHandler $snippetHandler; - /** - * @var RequirementValidator - */ - private $requirementValidator; + private RequirementValidator $requirementValidator; - /** - * @var PDO - */ - private $pdo; + private PDO $pdo; /** - * @var string[] + * @var array */ - private $pluginDirectories; + private array $pluginDirectories; - /** - * @var ShopwareReleaseStruct - */ - private $release; + private ShopwareReleaseStruct $release; - /** - * @var Enlight_Event_EventManager - */ - private $events; + private Enlight_Event_EventManager $events; - /** - * @var LoggerInterface - */ - private $logger; + private LoggerInterface $logger; - /** - * @var Kernel - */ - private $kernel; + private Kernel $kernel; /** - * @param string|string[] $pluginDirectories + * @param array $pluginDirectories */ public function __construct( ModelManager $em, @@ -128,7 +102,7 @@ public function __construct( RequirementValidator $requirementValidator, PDO $pdo, Enlight_Event_EventManager $events, - $pluginDirectories, + array $pluginDirectories, ShopwareReleaseStruct $release, LoggerInterface $logger, Kernel $kernel @@ -139,7 +113,7 @@ public function __construct( $this->requirementValidator = $requirementValidator; $this->pdo = $pdo; $this->events = $events; - $this->pluginDirectories = (array) $pluginDirectories; + $this->pluginDirectories = $pluginDirectories; $this->release = $release; $this->logger = $logger; $this->kernel = $kernel; @@ -186,8 +160,8 @@ public function installPlugin(Plugin $plugin) * @param bool $removeData * * @throws Exception - * @throws \Doctrine\DBAL\DBALException - * @throws \Doctrine\ORM\OptimisticLockException + * @throws DBALException + * @throws OptimisticLockException * * @return UninstallContext */ @@ -267,7 +241,7 @@ public function updatePlugin(Plugin $plugin) /** * @throws Exception - * @throws \Doctrine\ORM\OptimisticLockException + * @throws OptimisticLockException * * @return ActivateContext */ @@ -292,7 +266,7 @@ public function activatePlugin(Plugin $plugin) /** * @throws Exception - * @throws \Doctrine\ORM\OptimisticLockException + * @throws OptimisticLockException * * @return DeactivateContext */ @@ -315,6 +289,8 @@ public function deactivatePlugin(Plugin $plugin) /** * @throws RuntimeException + * + * @return void */ public function refreshPluginList(DateTimeInterface $refreshDate) { @@ -323,13 +299,10 @@ public function refreshPluginList(DateTimeInterface $refreshDate) $this->pluginDirectories ); - $plugins = $initializer->initializePlugins(); - - foreach ($plugins as $plugin) { + foreach ($initializer->initializePlugins() as $plugin) { $pluginInfoPath = $plugin->getPath() . '/plugin.xml'; if (is_file($pluginInfoPath)) { - $xmlConfigReader = new XmlPluginReader(); - $info = $xmlConfigReader->read($pluginInfoPath); + $info = (new XmlPluginReader())->read($pluginInfoPath); } else { $info = []; } @@ -407,9 +380,7 @@ public function refreshPluginList(DateTimeInterface $refreshDate) */ public function getPluginPath(Plugin $plugin) { - $pluginBootstrap = $this->getPluginByName($plugin->getName()); - - return $pluginBootstrap->getPath(); + return $this->getPluginByName($plugin->getName())->getPath(); } /** @@ -423,7 +394,7 @@ private function removeSnippets(PluginBootstrap $bootstrap, $removeDirty) /** * @throws Exception */ - private function installResources(PluginBootstrap $bootstrap, Plugin $plugin) + private function installResources(PluginBootstrap $bootstrap, Plugin $plugin): void { if (is_file($bootstrap->getPath() . '/Resources/config.xml')) { $this->installForm($plugin, $bootstrap->getPath() . '/Resources/config.xml'); @@ -442,72 +413,53 @@ private function installResources(PluginBootstrap $bootstrap, Plugin $plugin) } } - private function installSnippets(PluginBootstrap $bootstrap) + private function installSnippets(PluginBootstrap $bootstrap): void { $this->snippetHandler->loadToDatabase($bootstrap->getPath() . '/Resources/snippets/'); } /** - * @param string $file - * * @throws Exception */ - private function installForm(Plugin $plugin, $file) + private function installForm(Plugin $plugin, string $file): void { - $xmlConfigReader = new XmlConfigReader(); - $config = $xmlConfigReader->read($file); + $config = (new XmlConfigReader())->read($file); $formSynchronizer = new FormSynchronizer($this->em); $formSynchronizer->synchronize($plugin, $config); } /** - * @param string $file - * * @throws InvalidArgumentException */ - private function installMenu(Plugin $plugin, $file) + private function installMenu(Plugin $plugin, string $file): void { - $menuReader = new XmlMenuReader(); - $menu = $menuReader->read($file); + $menu = (new XmlMenuReader())->read($file); $menuSynchronizer = new MenuSynchronizer($this->em); $menuSynchronizer->synchronize($plugin, $menu); } /** - * @param string $file - * * @throws InvalidArgumentException */ - private function installCronjob(Plugin $plugin, $file) + private function installCronjob(Plugin $plugin, string $file): void { - $cronjobReader = new XmlCronjobReader(); - $cronjobs = $cronjobReader->read($file); + $cronjobs = (new XmlCronjobReader())->read($file); $cronjobSynchronizer = new CronjobSynchronizer($this->em->getConnection()); $cronjobSynchronizer->synchronize($plugin, $cronjobs); } - /** - * @param string $updateVersion - * @param string $currentVersion - * - * @return bool - */ - private function hasInfoNewerVersion($updateVersion, $currentVersion) + private function hasInfoNewerVersion(string $updateVersion, string $currentVersion): bool { return version_compare($updateVersion, $currentVersion, '>'); } /** - * @param string $pluginName - * * @throws Exception - * - * @return PluginBootstrap */ - private function getPluginByName($pluginName) + private function getPluginByName(string $pluginName): PluginComponent { $plugins = $this->kernel->getPlugins(); @@ -519,11 +471,9 @@ private function getPluginByName($pluginName) } /** - * @param int $pluginId - * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - private function removeEmotionComponents($pluginId) + private function removeEmotionComponents(int $pluginId): void { // Remove emotion-components $sql = 'DELETE s_emotion_element_value, s_emotion_element @@ -546,11 +496,9 @@ private function removeEmotionComponents($pluginId) } /** - * @param int $pluginId - * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - private function removeFormsAndElements($pluginId) + private function removeFormsAndElements(int $pluginId): void { $sql = <<connection->executeStatement($sql, [':pluginId' => $pluginId]); } /** - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - private function removeMenuEntries(int $pluginId) + private function removeMenuEntries(int $pluginId): void { - $builder = $this->em->getConnection()->createQueryBuilder(); - $builder->select(['id', 'controller', 'action']); - $builder->from('s_core_menu'); - $builder->andWhere('pluginID = :pluginId'); - $builder->setParameter(':pluginId', $pluginId); - - /** @var ResultStatement $statement */ - $statement = $builder->execute(); - - $menuItems = $statement->fetchAll(); + $menuItems = $this->em->getConnection()->createQueryBuilder() + ->select(['id', 'controller', 'action']) + ->from('s_core_menu') + ->andWhere('pluginID = :pluginId') + ->setParameter(':pluginId', $pluginId) + ->execute() + ->fetchAllAssociative(); if (\count($menuItems) === 0) { return; @@ -619,22 +562,18 @@ private function removeMenuEntries(int $pluginId) } /** - * @param int $pluginId - * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - private function removeCrontabEntries($pluginId) + private function removeCrontabEntries(int $pluginId): void { $sql = 'DELETE FROM s_crontab WHERE pluginID = :pluginId'; $this->connection->executeStatement($sql, [':pluginId' => $pluginId]); } /** - * @param int $pluginId - * - * @throws \Doctrine\DBAL\DBALException + * @throws DBALException */ - private function removeEventSubscribers($pluginId) + private function removeEventSubscribers(int $pluginId): void { $sql = 'DELETE FROM s_core_subscribes WHERE pluginID = :pluginId'; $this->connection->executeStatement($sql, [':pluginId' => $pluginId]); diff --git a/engine/Shopware/Components/Plugin/RequirementValidator.php b/engine/Shopware/Components/Plugin/RequirementValidator.php index b19d5370011..48511757cac 100644 --- a/engine/Shopware/Components/Plugin/RequirementValidator.php +++ b/engine/Shopware/Components/Plugin/RequirementValidator.php @@ -32,20 +32,11 @@ class RequirementValidator { - /** - * @var ModelManager - */ - private $em; + private ModelManager $em; - /** - * @var XmlPluginReader - */ - private $infoReader; + private XmlPluginReader $infoReader; - /** - * @var Enlight_Components_Snippet_Namespace - */ - private $namespace; + private Enlight_Components_Snippet_Namespace $namespace; public function __construct(ModelManager $em, XmlPluginReader $infoReader, SnippetManager $snippetManager) { @@ -77,14 +68,7 @@ public function validate($pluginXmlFile, $shopwareVersion) } } - /** - * @param string $version - * @param string $required - * @param string $operator - * - * @return bool - */ - private function assertVersion($version, $required, $operator) + private function assertVersion(string $version, string $required, string $operator): bool { if ($version === '___VERSION___') { return true; @@ -93,9 +77,12 @@ private function assertVersion($version, $required, $operator) return version_compare($version, $required, $operator); } + /** + * @param array{minVersion?: string, maxVersion?: string, blacklist?: list} $compatibility + */ private function assertShopwareVersion(array $compatibility, string $shopwareVersion): void { - if (isset($compatibility['blacklist']) && \in_array($shopwareVersion, $compatibility['blacklist'])) { + if (isset($compatibility['blacklist']) && \in_array($shopwareVersion, $compatibility['blacklist'], true)) { throw new Exception(sprintf($this->namespace->get('shopware_version_blacklisted'), $shopwareVersion)); } @@ -114,6 +101,9 @@ private function assertShopwareVersion(array $compatibility, string $shopwareVer } } + /** + * @param array}> $requiredPlugins + */ private function assertRequiredPlugins(array $requiredPlugins): void { $pluginRepository = $this->em->getRepository(Plugin::class); @@ -135,7 +125,7 @@ private function assertRequiredPlugins(array $requiredPlugins): void throw new Exception(sprintf($this->namespace->get('required_plugin_not_active'), $requiredPlugin['pluginName'])); } - if (isset($requiredPlugin['blacklist']) && \in_array($plugin->getVersion(), $requiredPlugin['blacklist'])) { + if (isset($requiredPlugin['blacklist']) && \in_array($plugin->getVersion(), $requiredPlugin['blacklist'], true)) { throw new Exception(sprintf($this->namespace->get('required_plugin_blacklisted'), $plugin->getName(), $plugin->getVersion())); } diff --git a/engine/Shopware/Components/Plugin/XmlPluginInfoReader.php b/engine/Shopware/Components/Plugin/XmlPluginInfoReader.php index f058a577f11..0a951d6058f 100644 --- a/engine/Shopware/Components/Plugin/XmlPluginInfoReader.php +++ b/engine/Shopware/Components/Plugin/XmlPluginInfoReader.php @@ -33,11 +33,11 @@ use Symfony\Component\Config\Util\XmlUtils; /** - * @deprecated This class will be removed in 5.6 + * @deprecated This class will be removed in 5.8 * - * Use new class Shopware\Components\Plugin\XmlReader\XmlPluginInfoReader (see Shopware 5.6) + * Use new class @see XmlReader\XmlPluginReader (see Shopware 5.6) * - * https://github.com/shopware5/shopware/blob/5.6/engine/Shopware/Components/Plugin/XmlReader/XmlPluginInfoReader.php + * https://github.com/shopware5/shopware/blob/5.6/engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php */ class XmlPluginInfoReader { @@ -72,8 +72,7 @@ private function parseInfo(DOMDocument $xml): ?array $info['description'][$lang] = trim((string) $description->nodeValue); } - $simpleKeys = ['version', 'license', 'author', 'copyright', 'link']; - foreach ($simpleKeys as $simpleKey) { + foreach (['version', 'license', 'author', 'copyright', 'link'] as $simpleKey) { if ($names = $this->getChildren($entry, $simpleKey)) { $info[$simpleKey] = $names[0]->nodeValue; } diff --git a/engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php b/engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php index e70ef2b5a38..19f0834072e 100644 --- a/engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php +++ b/engine/Shopware/Components/Plugin/XmlReader/XmlConfigReader.php @@ -43,7 +43,7 @@ public static function validateAttributeScope(string $scope): int return self::SCOPE_SHOP; } - throw new InvalidArgumentException(sprintf('Invalid scope "%s"', $scope)); + throw new InvalidArgumentException(sprintf('Invalid config scope "%s" in file "%s"', $scope, static::$xmlFile)); } protected function parseFile(DOMDocument $xml): array diff --git a/engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php b/engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php index 63687060fcd..61c49abb955 100644 --- a/engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php +++ b/engine/Shopware/Components/Plugin/XmlReader/XmlMenuReader.php @@ -42,7 +42,7 @@ protected function parseFile(DOMDocument $xml): array $entries = (new DOMXPath($xml))->query('//entries/entry'); if (!$entries instanceof DOMNodeList || $entries->length === 0) { - throw new RuntimeException('Required element "entry" is missing.'); + throw new RuntimeException(sprintf('Required element "entry" is missing in file "%s".', static::$xmlFile)); } $menu = []; diff --git a/engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php b/engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php index 968567f2c8d..8e95224172c 100644 --- a/engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php +++ b/engine/Shopware/Components/Plugin/XmlReader/XmlPluginReader.php @@ -83,9 +83,8 @@ protected function parseFile(DOMDocument $xml): array } } - $simpleFields = ['version', 'license', 'author', 'copyright', 'link']; - foreach ($simpleFields as $simpleField) { - $fieldValue = self::getElementChildValueByName($pluginData, $simpleField); + foreach (['version', 'license', 'author', 'copyright', 'link'] as $simpleField) { + $fieldValue = self::getElementChildValueByName($pluginData, $simpleField, $simpleField === 'version'); if ($fieldValue !== null) { $info[$simpleField] = $fieldValue; } @@ -130,9 +129,7 @@ private function parseRequiredPlugins(DOMElement $requiredPluginNode): array { $plugins = []; - $requiredPlugins = $requiredPluginNode->getElementsByTagName('requiredPlugin'); - - foreach ($requiredPlugins as $requiredPlugin) { + foreach ($requiredPluginNode->getElementsByTagName('requiredPlugin') as $requiredPlugin) { $plugin = []; $plugin['pluginName'] = $requiredPlugin->getAttribute('pluginName'); diff --git a/engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php b/engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php index 4290af107a5..d2def0629f2 100644 --- a/engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php +++ b/engine/Shopware/Components/Plugin/XmlReader/XmlReaderBase.php @@ -45,8 +45,11 @@ abstract class XmlReaderBase implements XmlReaderInterface */ protected $xsdFile; + protected static string $xmlFile = ''; + public function read(string $xmlFile): array { + static::$xmlFile = $xmlFile; try { $dom = XmlUtils::loadFile($xmlFile, $this->xsdFile); } catch (Exception $e) { @@ -70,7 +73,7 @@ public static function parseTranslatableNodeList(DOMNodeList $list): ?array foreach ($list as $item) { $language = $item->getAttribute('lang') ?: self::DEFAULT_LANG; if (!\is_string($language)) { - throw new RuntimeException('"lang" attribute needs to be a string'); + throw new RuntimeException(sprintf('Attribute "lang" needs to be a string in file "%s"', static::$xmlFile)); } // XSD Requires en-GB, Zend uses en_GB @@ -98,7 +101,7 @@ public static function parseTranslatableElement(DOMNode $element, string $name): foreach ($list as $item) { $language = $item->getAttribute('lang') ?: self::DEFAULT_LANG; if (!\is_string($language)) { - throw new RuntimeException('"lang" attribute needs to be a string'); + throw new RuntimeException(sprintf('Attribute "lang" needs to be a string in file "%s"', static::$xmlFile)); } // XSD Requires en-GB, Zend uses en_GB @@ -198,7 +201,7 @@ public static function getElementChildValueByName(DOMElement $element, string $n if (\count($children) === 0) { if ($throwException) { - throw new InvalidArgumentException(sprintf('Element with %s not found', $name)); + throw new InvalidArgumentException(sprintf('Element with name "%s" not found in file "%s"', $name, static::$xmlFile)); } return null; diff --git a/engine/Shopware/Components/Plugin/schema/plugin.xsd b/engine/Shopware/Components/Plugin/schema/plugin.xsd index eeb75e9d0df..1dc9c058cfa 100644 --- a/engine/Shopware/Components/Plugin/schema/plugin.xsd +++ b/engine/Shopware/Components/Plugin/schema/plugin.xsd @@ -5,19 +5,18 @@ - + + + - - - - + diff --git a/tests/Unit/Components/Plugin/XmlReader/XmlPluginReaderTest.php b/tests/Unit/Components/Plugin/XmlReader/XmlPluginReaderTest.php index 752a1705c7a..31a40404acf 100644 --- a/tests/Unit/Components/Plugin/XmlReader/XmlPluginReaderTest.php +++ b/tests/Unit/Components/Plugin/XmlReader/XmlPluginReaderTest.php @@ -25,6 +25,7 @@ namespace Shopware\Tests\Unit\Components\Plugin\XmlReader; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Shopware\Components\Plugin\XmlReader\XmlPluginReader; @@ -102,10 +103,17 @@ public function testReadFile(): void static::assertArrayNotHasKey('blacklist', $secondRequiredPlugin); } - private function readFile(): array + public function testReadFileWithoutVersion(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageMatches('/Element with name "version" not found in file ".*\/tests\/Unit\/Components\/Plugin\/XmlReader\/examples\/plugin\/plugin_invalid\.xml"/'); + $this->readFile('plugin_invalid'); + } + + private function readFile(string $fileName = 'plugin'): array { return $this->pluginReader->read( - sprintf('%s/examples/plugin/%s', __DIR__, 'plugin.xml') + sprintf('%s/examples/plugin/%s.xml', __DIR__, $fileName) ); } } diff --git a/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin.xml b/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin.xml index c5c1dc86fd1..b06a09a0a25 100644 --- a/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin.xml +++ b/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin.xml @@ -48,10 +48,4 @@ 5.1.2 5.1.3 - - asdf - asdf - - asbasdf - diff --git a/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_minimal.xml b/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_invalid.xml similarity index 88% rename from tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_minimal.xml rename to tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_invalid.xml index eca28af4e0c..171f7ccae86 100644 --- a/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_minimal.xml +++ b/tests/Unit/Components/Plugin/XmlReader/examples/plugin/plugin_invalid.xml @@ -3,5 +3,4 @@ xsi:noNamespaceSchemaLocation="../../../../../../../engine/Shopware/Components/Plugin/schema/plugin.xsd"> - 0.1.0-dev