<?php declare(strict_types=1);namespace Shopware\Storefront\Theme\Subscriber;use Shopware\Core\Framework\Context;use Shopware\Core\Framework\Feature;use Shopware\Core\Framework\Log\Package;use Shopware\Core\Framework\Plugin;use Shopware\Core\Framework\Plugin\Event\PluginLifecycleEvent;use Shopware\Core\Framework\Plugin\Event\PluginPostActivateEvent;use Shopware\Core\Framework\Plugin\Event\PluginPostDeactivationFailedEvent;use Shopware\Core\Framework\Plugin\Event\PluginPostUninstallEvent;use Shopware\Core\Framework\Plugin\Event\PluginPreActivateEvent;use Shopware\Core\Framework\Plugin\Event\PluginPreDeactivateEvent;use Shopware\Core\Framework\Plugin\Event\PluginPreUninstallEvent;use Shopware\Core\Framework\Plugin\Event\PluginPreUpdateEvent;use Shopware\Core\Framework\Plugin\PluginLifecycleService;use Shopware\Storefront\Theme\Exception\InvalidThemeBundleException;use Shopware\Storefront\Theme\Exception\ThemeCompileException;use Shopware\Storefront\Theme\StorefrontPluginConfiguration\AbstractStorefrontPluginConfigurationFactory;use Shopware\Storefront\Theme\StorefrontPluginConfiguration\StorefrontPluginConfiguration;use Shopware\Storefront\Theme\StorefrontPluginRegistryInterface;use Shopware\Storefront\Theme\ThemeLifecycleHandler;use Shopware\Storefront\Theme\ThemeLifecycleService;use Symfony\Component\EventDispatcher\EventSubscriberInterface;/** * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0 */#[Package('storefront')]class PluginLifecycleSubscriber implements EventSubscriberInterface{ private StorefrontPluginRegistryInterface $storefrontPluginRegistry; private string $projectDirectory; private AbstractStorefrontPluginConfigurationFactory $pluginConfigurationFactory; private ThemeLifecycleHandler $themeLifecycleHandler; private ThemeLifecycleService $themeLifecycleService; /** * @internal */ public function __construct( StorefrontPluginRegistryInterface $storefrontPluginRegistry, string $projectDirectory, AbstractStorefrontPluginConfigurationFactory $pluginConfigurationFactory, ThemeLifecycleHandler $themeLifecycleHandler, ThemeLifecycleService $themeLifecycleService ) { $this->storefrontPluginRegistry = $storefrontPluginRegistry; $this->projectDirectory = $projectDirectory; $this->pluginConfigurationFactory = $pluginConfigurationFactory; $this->themeLifecycleHandler = $themeLifecycleHandler; $this->themeLifecycleService = $themeLifecycleService; } /** * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>> */ public static function getSubscribedEvents() { if (Feature::isActive('v6.5.0.0')) { return [ PluginPostActivateEvent::class => 'pluginPostActivate', PluginPreUpdateEvent::class => 'pluginUpdate', PluginPreDeactivateEvent::class => 'pluginDeactivateAndUninstall', PluginPostDeactivationFailedEvent::class => 'pluginPostDeactivateFailed', PluginPreUninstallEvent::class => 'pluginDeactivateAndUninstall', PluginPostUninstallEvent::class => 'pluginPostUninstall', ]; } return [ PluginPreActivateEvent::class => 'pluginActivate', PluginPostActivateEvent::class => 'pluginPostActivate', PluginPreUpdateEvent::class => 'pluginUpdate', PluginPreDeactivateEvent::class => 'pluginDeactivateAndUninstall', PluginPostDeactivationFailedEvent::class => 'pluginPostDeactivateFailed', PluginPreUninstallEvent::class => 'pluginDeactivateAndUninstall', PluginPostUninstallEvent::class => 'pluginPostUninstall', ]; } /** * @deprecated tag:v6.5.0 - Method will be removed. use pluginPostActivate instead */ public function pluginActivate(PluginPreActivateEvent $event): void { Feature::triggerDeprecationOrThrow( 'v6.5.0.0', sprintf('Method pluginActivate of Class %s is deprecated. Use method pluginPostActivate instead', static::class) ); // do nothing } public function pluginPostActivate(PluginPostActivateEvent $event): void { $this->doPostActivate($event); } public function pluginPostDeactivateFailed(PluginPostDeactivationFailedEvent $event): void { $this->doPostActivate($event); } public function pluginUpdate(PluginPreUpdateEvent $event): void { if ($this->skipCompile($event->getContext()->getContext())) { return; } $pluginName = $event->getPlugin()->getName(); $config = $this->storefrontPluginRegistry->getConfigurations()->getByTechnicalName($pluginName); if (!$config) { return; } $this->themeLifecycleHandler->handleThemeInstallOrUpdate( $config, $this->storefrontPluginRegistry->getConfigurations(), $event->getContext()->getContext() ); } /** * @param PluginPreDeactivateEvent|PluginPreUninstallEvent $event */ public function pluginDeactivateAndUninstall($event): void { if ($this->skipCompile($event->getContext()->getContext())) { return; } $pluginName = $event->getPlugin()->getName(); $config = $this->storefrontPluginRegistry->getConfigurations()->getByTechnicalName($pluginName); if (!$config) { return; } $this->themeLifecycleHandler->handleThemeUninstall($config, $event->getContext()->getContext()); } public function pluginPostUninstall(PluginPostUninstallEvent $event): void { if ($event->getContext()->keepUserData()) { return; } $this->themeLifecycleService->removeTheme($event->getPlugin()->getName(), $event->getContext()->getContext()); } /** * @throws ThemeCompileException * @throws InvalidThemeBundleException */ private function createConfigFromClassName(string $pluginPath, string $className): StorefrontPluginConfiguration { /** @var Plugin $plugin */ $plugin = new $className(true, $pluginPath, $this->projectDirectory); if (!$plugin instanceof Plugin) { throw new \RuntimeException( sprintf('Plugin class "%s" must extend "%s"', \get_class($plugin), Plugin::class) ); } return $this->pluginConfigurationFactory->createFromBundle($plugin); } private function doPostActivate(PluginLifecycleEvent $event): void { if (!($event instanceof PluginPostActivateEvent) && !($event instanceof PluginPostDeactivationFailedEvent)) { return; } if ($this->skipCompile($event->getContext()->getContext())) { return; } // create instance of the plugin to create a configuration // (the kernel boot is already finished and the activated plugin is missing) $storefrontPluginConfig = $this->createConfigFromClassName( $event->getPlugin()->getPath() ?: '', $event->getPlugin()->getBaseClass() ); // add plugin configuration to the list of all active plugin configurations $configurationCollection = clone $this->storefrontPluginRegistry->getConfigurations(); $configurationCollection->add($storefrontPluginConfig); $this->themeLifecycleHandler->handleThemeInstallOrUpdate( $storefrontPluginConfig, $configurationCollection, $event->getContext()->getContext() ); } private function skipCompile(Context $context): bool { return $context->hasState(PluginLifecycleService::STATE_SKIP_ASSET_BUILDING); }}