vendor/shopware/storefront/Theme/Subscriber/PluginLifecycleSubscriber.php line 132

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Theme\Subscriber;
  3. use Shopware\Core\Framework\Context;
  4. use Shopware\Core\Framework\Feature;
  5. use Shopware\Core\Framework\Log\Package;
  6. use Shopware\Core\Framework\Plugin;
  7. use Shopware\Core\Framework\Plugin\Event\PluginLifecycleEvent;
  8. use Shopware\Core\Framework\Plugin\Event\PluginPostActivateEvent;
  9. use Shopware\Core\Framework\Plugin\Event\PluginPostDeactivationFailedEvent;
  10. use Shopware\Core\Framework\Plugin\Event\PluginPostUninstallEvent;
  11. use Shopware\Core\Framework\Plugin\Event\PluginPreActivateEvent;
  12. use Shopware\Core\Framework\Plugin\Event\PluginPreDeactivateEvent;
  13. use Shopware\Core\Framework\Plugin\Event\PluginPreUninstallEvent;
  14. use Shopware\Core\Framework\Plugin\Event\PluginPreUpdateEvent;
  15. use Shopware\Core\Framework\Plugin\PluginLifecycleService;
  16. use Shopware\Storefront\Theme\Exception\InvalidThemeBundleException;
  17. use Shopware\Storefront\Theme\Exception\ThemeCompileException;
  18. use Shopware\Storefront\Theme\StorefrontPluginConfiguration\AbstractStorefrontPluginConfigurationFactory;
  19. use Shopware\Storefront\Theme\StorefrontPluginConfiguration\StorefrontPluginConfiguration;
  20. use Shopware\Storefront\Theme\StorefrontPluginRegistryInterface;
  21. use Shopware\Storefront\Theme\ThemeLifecycleHandler;
  22. use Shopware\Storefront\Theme\ThemeLifecycleService;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. /**
  25. * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  26. */
  27. #[Package('storefront')]
  28. class PluginLifecycleSubscriber implements EventSubscriberInterface
  29. {
  30. private StorefrontPluginRegistryInterface $storefrontPluginRegistry;
  31. private string $projectDirectory;
  32. private AbstractStorefrontPluginConfigurationFactory $pluginConfigurationFactory;
  33. private ThemeLifecycleHandler $themeLifecycleHandler;
  34. private ThemeLifecycleService $themeLifecycleService;
  35. /**
  36. * @internal
  37. */
  38. public function __construct(
  39. StorefrontPluginRegistryInterface $storefrontPluginRegistry,
  40. string $projectDirectory,
  41. AbstractStorefrontPluginConfigurationFactory $pluginConfigurationFactory,
  42. ThemeLifecycleHandler $themeLifecycleHandler,
  43. ThemeLifecycleService $themeLifecycleService
  44. ) {
  45. $this->storefrontPluginRegistry = $storefrontPluginRegistry;
  46. $this->projectDirectory = $projectDirectory;
  47. $this->pluginConfigurationFactory = $pluginConfigurationFactory;
  48. $this->themeLifecycleHandler = $themeLifecycleHandler;
  49. $this->themeLifecycleService = $themeLifecycleService;
  50. }
  51. /**
  52. * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
  53. */
  54. public static function getSubscribedEvents()
  55. {
  56. if (Feature::isActive('v6.5.0.0')) {
  57. return [
  58. PluginPostActivateEvent::class => 'pluginPostActivate',
  59. PluginPreUpdateEvent::class => 'pluginUpdate',
  60. PluginPreDeactivateEvent::class => 'pluginDeactivateAndUninstall',
  61. PluginPostDeactivationFailedEvent::class => 'pluginPostDeactivateFailed',
  62. PluginPreUninstallEvent::class => 'pluginDeactivateAndUninstall',
  63. PluginPostUninstallEvent::class => 'pluginPostUninstall',
  64. ];
  65. }
  66. return [
  67. PluginPreActivateEvent::class => 'pluginActivate',
  68. PluginPostActivateEvent::class => 'pluginPostActivate',
  69. PluginPreUpdateEvent::class => 'pluginUpdate',
  70. PluginPreDeactivateEvent::class => 'pluginDeactivateAndUninstall',
  71. PluginPostDeactivationFailedEvent::class => 'pluginPostDeactivateFailed',
  72. PluginPreUninstallEvent::class => 'pluginDeactivateAndUninstall',
  73. PluginPostUninstallEvent::class => 'pluginPostUninstall',
  74. ];
  75. }
  76. /**
  77. * @deprecated tag:v6.5.0 - Method will be removed. use pluginPostActivate instead
  78. */
  79. public function pluginActivate(PluginPreActivateEvent $event): void
  80. {
  81. Feature::triggerDeprecationOrThrow(
  82. 'v6.5.0.0',
  83. sprintf('Method pluginActivate of Class %s is deprecated. Use method pluginPostActivate instead', static::class)
  84. );
  85. // do nothing
  86. }
  87. public function pluginPostActivate(PluginPostActivateEvent $event): void
  88. {
  89. $this->doPostActivate($event);
  90. }
  91. public function pluginPostDeactivateFailed(PluginPostDeactivationFailedEvent $event): void
  92. {
  93. $this->doPostActivate($event);
  94. }
  95. public function pluginUpdate(PluginPreUpdateEvent $event): void
  96. {
  97. if ($this->skipCompile($event->getContext()->getContext())) {
  98. return;
  99. }
  100. $pluginName = $event->getPlugin()->getName();
  101. $config = $this->storefrontPluginRegistry->getConfigurations()->getByTechnicalName($pluginName);
  102. if (!$config) {
  103. return;
  104. }
  105. $this->themeLifecycleHandler->handleThemeInstallOrUpdate(
  106. $config,
  107. $this->storefrontPluginRegistry->getConfigurations(),
  108. $event->getContext()->getContext()
  109. );
  110. }
  111. /**
  112. * @param PluginPreDeactivateEvent|PluginPreUninstallEvent $event
  113. */
  114. public function pluginDeactivateAndUninstall($event): void
  115. {
  116. if ($this->skipCompile($event->getContext()->getContext())) {
  117. return;
  118. }
  119. $pluginName = $event->getPlugin()->getName();
  120. $config = $this->storefrontPluginRegistry->getConfigurations()->getByTechnicalName($pluginName);
  121. if (!$config) {
  122. return;
  123. }
  124. $this->themeLifecycleHandler->handleThemeUninstall($config, $event->getContext()->getContext());
  125. }
  126. public function pluginPostUninstall(PluginPostUninstallEvent $event): void
  127. {
  128. if ($event->getContext()->keepUserData()) {
  129. return;
  130. }
  131. $this->themeLifecycleService->removeTheme($event->getPlugin()->getName(), $event->getContext()->getContext());
  132. }
  133. /**
  134. * @throws ThemeCompileException
  135. * @throws InvalidThemeBundleException
  136. */
  137. private function createConfigFromClassName(string $pluginPath, string $className): StorefrontPluginConfiguration
  138. {
  139. /** @var Plugin $plugin */
  140. $plugin = new $className(true, $pluginPath, $this->projectDirectory);
  141. if (!$plugin instanceof Plugin) {
  142. throw new \RuntimeException(
  143. sprintf('Plugin class "%s" must extend "%s"', \get_class($plugin), Plugin::class)
  144. );
  145. }
  146. return $this->pluginConfigurationFactory->createFromBundle($plugin);
  147. }
  148. private function doPostActivate(PluginLifecycleEvent $event): void
  149. {
  150. if (!($event instanceof PluginPostActivateEvent) && !($event instanceof PluginPostDeactivationFailedEvent)) {
  151. return;
  152. }
  153. if ($this->skipCompile($event->getContext()->getContext())) {
  154. return;
  155. }
  156. // create instance of the plugin to create a configuration
  157. // (the kernel boot is already finished and the activated plugin is missing)
  158. $storefrontPluginConfig = $this->createConfigFromClassName(
  159. $event->getPlugin()->getPath() ?: '',
  160. $event->getPlugin()->getBaseClass()
  161. );
  162. // add plugin configuration to the list of all active plugin configurations
  163. $configurationCollection = clone $this->storefrontPluginRegistry->getConfigurations();
  164. $configurationCollection->add($storefrontPluginConfig);
  165. $this->themeLifecycleHandler->handleThemeInstallOrUpdate(
  166. $storefrontPluginConfig,
  167. $configurationCollection,
  168. $event->getContext()->getContext()
  169. );
  170. }
  171. private function skipCompile(Context $context): bool
  172. {
  173. return $context->hasState(PluginLifecycleService::STATE_SKIP_ASSET_BUILDING);
  174. }
  175. }