plus-8.x-4.x-dev/src/ThemePluginManager.php
src/ThemePluginManager.php
<?php namespace Drupal\plus; use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Component\Plugin\FallbackPluginManagerInterface; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ThemeHandlerInterface; use Drupal\plus\Annotation\Theme; use Drupal\plus\Events\ThemeEvent; use Drupal\plus\Events\ThemeEvents; use Drupal\plus\Events\ThemeEventSubscriberInterface; use Drupal\plus\Plugin\PluginProviderTypeInterface; use Drupal\plus\Plugin\Theme\ThemeInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Manages discovery and instantiation of "Theme" annotations. * * @ingroup plugins_alter */ class ThemePluginManager extends ProviderPluginManager implements EventSubscriberInterface, FallbackPluginManagerInterface, ThemeEventSubscriberInterface { /** * The Theme Handler service. * * @var \Drupal\plus\Core\Extension\ThemeHandler */ protected $themeHandler; /** * An array of loaded theme plugins. * * @var \Drupal\plus\Plugin\Theme\ThemeInterface[] */ protected $themes; /** * The Theme Settings Plugin Manager service. * * @var \Drupal\plus\SettingPluginManager */ protected $themeSettingsPluginManager; /** * ThemePluginManager constructor. * * @param \Drupal\plus\Plugin\PluginProviderTypeInterface $provider_type * The plugin provider type used for discovery. * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend * (optional) The backend cache service to use. * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler * The Theme Handler service. * @param \Drupal\plus\SettingPluginManager $theme_settings_plugin_manager * The Theme Settings Plugin Manager service. */ public function __construct(PluginProviderTypeInterface $provider_type, CacheBackendInterface $cache_backend, ThemeHandlerInterface $theme_handler, SettingPluginManager $theme_settings_plugin_manager) { parent::__construct($provider_type, 'Plugin/Theme', ThemeInterface::class, Theme::class, $cache_backend); $this->themeHandler = $theme_handler; $this->themeSettingsPluginManager = $theme_settings_plugin_manager; // The plugin manager uses the "theme" provider type, thus it won't // discover the "_base" fallback plugin in this module. To get around this, // just prepend this specific module's namespace. $module_namespace = [\Drupal::root() . '/' . drupal_get_path('module', 'plus') . '/src']; $this->namespaces->prepend($module_namespace, 'Drupal\\plus'); } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('plugin.provider.theme'), $container->get('cache.discovery'), $container->get('theme_handler'), $container->get('plugin.manager.setting') ); } /** * {@inheritdoc} */ public function createInstance($plugin_id, array $configuration = []) { // If this PluginManager has fallback capabilities catch // PluginNotFoundExceptions. if ($this instanceof FallbackPluginManagerInterface) { try { return $this->getFactory()->createInstance($plugin_id, $configuration); } catch (PluginNotFoundException $e) { $fallback_id = $this->getFallbackPluginId($plugin_id, $configuration); if (strpos($fallback_id, '_base:') === 0) { $configuration['theme'] = substr($fallback_id, 6); $fallback_id = '_base'; } return $this->getFactory()->createInstance($fallback_id, $configuration); } } else { return $this->getFactory()->createInstance($plugin_id, $configuration); } } /** * Retrieves an PlusTheme plugin instance for the active theme. * * @return \Drupal\plus\Plugin\Theme\ThemeInterface * A theme object. */ public function getActiveTheme() { return $this->getTheme(); } /** * {@inheritdoc} */ public function getFallbackPluginId($plugin_id, array $configuration = []) { return "_base:$plugin_id"; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { $events[ThemeEvents::ACTIVATE][] = ['onThemeActivate', 800]; $events[ThemeEvents::ACTIVATED][] = ['onThemeActivated', 800]; $events[ThemeEvents::INSTALL][] = ['onThemeInstall', 800]; $events[ThemeEvents::INSTALLED][] = ['onThemeInstalled', 800]; $events[ThemeEvents::UNINSTALL][] = ['onThemeUninstall', 800]; $events[ThemeEvents::UNINSTALLED][] = ['onThemeUninstalled', 800]; return $events; } /** * Retrieves an Theme plugin instance for a specific theme. * * @param string|\Drupal\plus\Plugin\Theme\ThemeInterface|\Drupal\Core\Extension\Extension $theme * The name of a theme, Theme plugin instance or an Extension object. If * not provided, the active theme will be used instead. * * @return \Drupal\plus\Plugin\Theme\ThemeInterface * A theme plugin. */ public function getTheme($theme = NULL) { $name = $this->themeHandler->normalizeThemeName($theme); if (!isset($this->themes[$name])) { $instance = $this->createInstance($name); // @todo Create an event that listens to when the active theme changes. $instance->initialize(); $this->themes[$name] = $instance; } return $this->themes[$name]; } /** * Retrieves Theme plugin instances for specified themes. * * @param string[]|\Drupal\plus\Plugin\Theme\ThemeInterface[]|\Drupal\Core\Extension\Extension[] $themes * An array of theme names, Theme plugin instances or an Extension objects. * If omitted entirely, then all installed themes will be loaded. * @param bool $filter * Filters out themes that are not Plus based. * * @return \Drupal\plus\Plugin\Theme\ThemeInterface[] * An array of theme plugins, keyed by the theme machine name. */ public function getThemes(array $themes = NULL, $filter = TRUE) { if (!isset($themes)) { $themes = $this->themeHandler->listInfo(); } $objects = []; foreach ($themes as $value) { $theme = $this->getTheme($value); if ($filter && !$theme->isPlus()) { continue; } $objects[$theme->getName()] = $theme; } return $objects; } /** * {@inheritdoc} */ public function onThemeActivate(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ public function onThemeActivated(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ public function onThemeInstall(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ public function onThemeInstalled(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ public function onThemeUninstall(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ public function onThemeUninstalled(ThemeEvent $event) { return $this->proxyThemeEvent(__FUNCTION__, $event); } /** * {@inheritdoc} */ protected function providerExists($provider) { return $provider === 'plus' || parent::providerExists($provider); } /** * Proxies an event to all themes. * * @param string $method * The method to invoke. * @param \Drupal\plus\Events\ThemeEvent $event * The ThemeEvent to proxy. * * @return \Drupal\plus\Events\ThemeEvent * The ThemeEvent object. */ protected function proxyThemeEvent($method, ThemeEvent $event) { foreach ($this->getThemes() as $theme) { $event = call_user_func_array([$theme, $method], [$event]); if ($event->isPropagationStopped()) { break; } } return $event; } }