Commit 4fd210b3 authored by catch's avatar catch

Issue #2422815 by Xano, fgm, tim.plunkett, dawehner: Don't initialize the...

Issue #2422815 by Xano, fgm, tim.plunkett, dawehner: Don't initialize the discovery object in plugin managers, unless needed
parent 8114a72e
......@@ -38,18 +38,36 @@ abstract class PluginManagerBase implements PluginManagerInterface {
*/
protected $mapper;
/**
* Gets the plugin discovery.
*
* @return \Drupal\Component\Plugin\Discovery\DiscoveryInterface
*/
protected function getDiscovery() {
return $this->discovery;
}
/**
* Gets the plugin factory.
*
* @return \Drupal\Component\Plugin\Factory\FactoryInterface
*/
protected function getFactory() {
return $this->factory;
}
/**
* {@inheritdoc}
*/
public function getDefinition($plugin_id, $exception_on_invalid = TRUE) {
return $this->discovery->getDefinition($plugin_id, $exception_on_invalid);
return $this->getDiscovery()->getDefinition($plugin_id, $exception_on_invalid);
}
/**
* {@inheritdoc}
*/
public function getDefinitions() {
return $this->discovery->getDefinitions();
return $this->getDiscovery()->getDefinitions();
}
/**
......@@ -60,15 +78,15 @@ public function createInstance($plugin_id, array $configuration = array()) {
// PluginNotFoundExceptions.
if ($this instanceof FallbackPluginManagerInterface) {
try {
return $this->factory->createInstance($plugin_id, $configuration);
return $this->getFactory()->createInstance($plugin_id, $configuration);
}
catch (PluginNotFoundException $e) {
$fallback_id = $this->getFallbackPluginId($plugin_id, $configuration);
return $this->factory->createInstance($fallback_id, $configuration);
return $this->getFactory()->createInstance($fallback_id, $configuration);
}
}
else {
return $this->factory->createInstance($plugin_id, $configuration);
return $this->getFactory()->createInstance($plugin_id, $configuration);
}
}
......
......@@ -52,7 +52,7 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
* Override of Drupal\Component\Plugin\PluginManagerBase::createInstance().
*/
public function createInstance($plugin_id, array $configuration = array()) {
$plugin = $this->factory->createInstance($plugin_id, $configuration);
$plugin = $this->getFactory()->createInstance($plugin_id, $configuration);
// If we receive any context values via config set it into the plugin.
if (!empty($configuration['context'])) {
......
......@@ -56,11 +56,21 @@ public function __construct(StorageInterface $configStorage, StorageInterface $s
$this->configStorage = $configStorage;
$this->schemaStorage = $schemaStorage;
$this->setCacheBackend($cache, 'typed_config_definitions');
$this->discovery = new ConfigSchemaDiscovery($schemaStorage);
$this->alterInfo('config_schema_info');
$this->moduleHandler = $module_handler;
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new ConfigSchemaDiscovery($this->schemaStorage);
}
return $this->discovery;
}
/**
* Gets typed configuration data.
*
......
......@@ -230,7 +230,7 @@ public function clearCachedDefinitions() {
* {@inheritdoc}
*/
protected function findDefinitions() {
$definitions = $this->discovery->getDefinitions();
$definitions = $this->getDiscovery()->getDefinitions();
// Directly call the hook implementations to pass the definitions to them
// by reference, so new entity types can be added.
......
......@@ -103,10 +103,7 @@ class ContextualLinkManager extends DefaultPluginManager implements ContextualLi
* The request stack.
*/
public function __construct(ControllerResolverInterface $controller_resolver, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account, RequestStack $request_stack) {
$this->discovery = new YamlDiscovery('links.contextual', $module_handler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\ContextualLinkInterface');
$this->controllerResolver = $controller_resolver;
$this->accessManager = $access_manager;
$this->account = $account;
......@@ -116,6 +113,17 @@ public function __construct(ControllerResolverInterface $controller_resolver, Mo
$this->setCacheBackend($cache_backend, 'contextual_links_plugins:' . $language_manager->getCurrentLanguage()->getId(), array('contextual_links_plugins'));
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('links.contextual', $this->moduleHandler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
......
......@@ -125,8 +125,6 @@ class LocalActionManager extends DefaultPluginManager implements LocalActionMana
public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
// Skip calling the parent constructor, since that assumes annotation-based
// discovery.
$this->discovery = new YamlDiscovery('links.action', $module_handler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this, 'Drupal\Core\Menu\LocalActionInterface');
$this->controllerResolver = $controller_resolver;
$this->requestStack = $request_stack;
......@@ -139,6 +137,17 @@ public function __construct(ControllerResolverInterface $controller_resolver, Re
$this->setCacheBackend($cache_backend, 'local_action_plugins:' . $language_manager->getCurrentLanguage()->getId(), array('local_action'));
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('links.action', $this->moduleHandler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
......
......@@ -125,8 +125,6 @@ class LocalTaskManager extends DefaultPluginManager implements LocalTaskManagerI
* The current user.
*/
public function __construct(ControllerResolverInterface $controller_resolver, RequestStack $request_stack, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, AccessManagerInterface $access_manager, AccountInterface $account) {
$this->discovery = new YamlDiscovery('links.task', $module_handler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this, '\Drupal\Core\Menu\LocalTaskInterface');
$this->controllerResolver = $controller_resolver;
$this->requestStack = $request_stack;
......@@ -139,6 +137,17 @@ public function __construct(ControllerResolverInterface $controller_resolver, Re
$this->setCacheBackend($cache, 'local_task_plugins:' . $language_manager->getCurrentLanguage()->getId(), array('local_task'));
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('links.task', $this->moduleHandler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
......
......@@ -118,7 +118,6 @@ class MenuLinkManager implements MenuLinkManagerInterface {
public function __construct(MenuTreeStorageInterface $tree_storage, StaticMenuLinkOverridesInterface $overrides, ModuleHandlerInterface $module_handler) {
$this->treeStorage = $tree_storage;
$this->overrides = $overrides;
$this->factory = new ContainerFactory($this);
$this->moduleHandler = $module_handler;
}
......@@ -143,23 +142,30 @@ protected function processDefinition(array &$definition, $plugin_id) {
}
/**
* Instantiates if necessary and returns a YamlDiscovery instance.
* Gets the plugin discovery.
*
* Since the discovery is very rarely used - only when the rebuild() method
* is called - it's instantiated only when actually needed instead of in the
* constructor.
*
* @return \Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator
* A plugin discovery instance.
* @return \Drupal\Component\Plugin\Discovery\DiscoveryInterface
*/
protected function getDiscovery() {
if (empty($this->discovery)) {
$yaml = new YamlDiscovery('links.menu', $this->moduleHandler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($yaml);
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('links.menu', $this->moduleHandler->getModuleDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* Gets the plugin factory.
*
* @return \Drupal\Component\Plugin\Factory\FactoryInterface
*/
protected function getFactory() {
if (!isset($this->factory)) {
$this->factory = new ContainerFactory($this);
}
return $this->factory;
}
/**
* {@inheritdoc}
*/
......@@ -234,7 +240,7 @@ public function hasDefinition($plugin_id) {
* If the instance cannot be created, such as if the ID is invalid.
*/
public function createInstance($plugin_id, array $configuration = array()) {
return $this->factory->createInstance($plugin_id, $configuration);
return $this->getFactory()->createInstance($plugin_id, $configuration);
}
/**
......
......@@ -87,6 +87,28 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
*/
protected $useCaches = TRUE;
/**
* The name of the annotation that contains the plugin definition.
*
* @var string
*/
protected $pluginDefinitionAnnotationName;
/**
* The interface each plugin should implement.
*
* @var string|null
*/
protected $pluginInterface;
/**
* An object that implements \Traversable which contains the root paths
* keyed by the corresponding namespace to look for plugin implementations.
*
* @var \Traversable
*/
protected $namespaces;
/**
* Creates the discovery object.
*
......@@ -105,9 +127,9 @@ class DefaultPluginManager extends PluginManagerBase implements PluginManagerInt
*/
public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInterface $module_handler, $plugin_interface = NULL, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin') {
$this->subdir = $subdir;
$this->discovery = new AnnotatedClassDiscovery($subdir, $namespaces, $plugin_definition_annotation_name);
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this, $plugin_interface);
$this->namespaces = $namespaces;
$this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name;
$this->pluginInterface = $plugin_interface;
$this->moduleHandler = $module_handler;
}
......@@ -251,6 +273,27 @@ public function processDefinition(&$definition, $plugin_id) {
}
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!$this->discovery) {
$discovery = new AnnotatedClassDiscovery($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName);
$this->discovery = new ContainerDerivativeDiscoveryDecorator($discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
protected function getFactory() {
if (!$this->factory) {
$this->factory = new ContainerFactory($this, $this->pluginInterface);
}
return $this->factory;
}
/**
* Finds plugin definitions.
*
......@@ -258,7 +301,7 @@ public function processDefinition(&$definition, $plugin_id) {
* List of definitions to store in cache.
*/
protected function findDefinitions() {
$definitions = $this->discovery->getDefinitions();
$definitions = $this->getDiscovery()->getDefinitions();
foreach ($definitions as $plugin_id => &$definition) {
$this->processDefinition($definition, $plugin_id);
}
......
......@@ -46,11 +46,22 @@ class ConstraintManager extends DefaultPluginManager {
*/
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/Validation/Constraint', $namespaces, $module_handler, NULL, 'Drupal\Core\Validation\Annotation\Constraint');
$this->discovery = new StaticDiscoveryDecorator($this->discovery, array($this, 'registerDefinitions'));
$this->alterInfo('validation_constraint');
$this->setCacheBackend($cache_backend, 'validation_constraint_plugins');
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = parent::getDiscovery();
$this->discovery = new StaticDiscoveryDecorator($this->discovery, [$this, 'registerDefinitions']);
}
return $this->discovery;
}
/**
* Creates a validation constraint.
*
......@@ -79,22 +90,22 @@ public function create($name, $options) {
* @see ConstraintManager::__construct()
*/
public function registerDefinitions() {
$this->discovery->setDefinition('Callback', array(
$this->getDiscovery()->setDefinition('Callback', array(
'label' => new TranslationWrapper('Callback'),
'class' => '\Symfony\Component\Validator\Constraints\Callback',
'type' => FALSE,
));
$this->discovery->setDefinition('Blank', array(
$this->getDiscovery()->setDefinition('Blank', array(
'label' => new TranslationWrapper('Blank'),
'class' => '\Symfony\Component\Validator\Constraints\Blank',
'type' => FALSE,
));
$this->discovery->setDefinition('NotBlank', array(
$this->getDiscovery()->setDefinition('NotBlank', array(
'label' => new TranslationWrapper('Not blank'),
'class' => '\Symfony\Component\Validator\Constraints\NotBlank',
'type' => FALSE,
));
$this->discovery->setDefinition('Email', array(
$this->getDiscovery()->setDefinition('Email', array(
'label' => new TranslationWrapper('Email'),
'class' => '\Drupal\Core\Validation\Plugin\Validation\Constraint\EmailConstraint',
'type' => array('string'),
......
......@@ -106,8 +106,6 @@ class BreakpointManager extends DefaultPluginManager implements BreakpointManage
* The string translation service.
*/
public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend, TranslationInterface $string_translation) {
$this->discovery = new YamlDiscovery('breakpoints', $module_handler->getModuleDirectories() + $theme_handler->getThemeDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this);
$this->moduleHandler = $module_handler;
$this->themeHandler = $theme_handler;
......@@ -116,6 +114,17 @@ public function __construct(ModuleHandlerInterface $module_handler, ThemeHandler
$this->setCacheBackend($cache_backend, 'breakpoints', array('breakpoints'));
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('breakpoints', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
......
......@@ -63,33 +63,12 @@ class ConfigMapperManager extends DefaultPluginManager implements ConfigMapperMa
* The module handler.
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager
* The typed config manager.
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
* The theme handler.
*/
public function __construct(CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager, ModuleHandlerInterface $module_handler, TypedConfigManagerInterface $typed_config_manager, ThemeHandlerInterface $theme_handler) {
$this->typedConfigManager = $typed_config_manager;
// Look at all themes and modules.
// @todo If the list of installed modules and themes is changed, new
// definitions are not picked up immediately and obsolete definitions are
// not removed, because the list of search directories is only compiled
// once in this constructor. The current code only works due to
// coincidence: The request that installs e.g. a new theme does not
// instantiate this plugin manager at the beginning of the request; when
// routes are being rebuilt at the end of the request, this service only
// happens to get instantiated with the updated list of installed themes.
$directories = array();
foreach ($module_handler->getModuleList() as $name => $module) {
$directories[$name] = $module->getPath();
}
foreach ($theme_handler->listInfo() as $theme) {
$directories[$theme->getName()] = $theme->getPath();
}
// Check for files named MODULE.config_translation.yml and
// THEME.config_translation.yml in module/theme roots.
$this->discovery = new YamlDiscovery('config_translation', $directories);
$this->discovery = new InfoHookDecorator($this->discovery, 'config_translation_info');
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
$this->factory = new ContainerFactory($this, '\Drupal\config_translation\ConfigMapperInterface');
// Let others alter definitions with hook_config_translation_info_alter().
......@@ -102,6 +81,37 @@ public function __construct(CacheBackendInterface $cache_backend, LanguageManage
$this->setCacheBackend($cache_backend, $cache_key, array('config_translation_info_plugins'));
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
// Look at all themes and modules.
// @todo If the list of installed modules and themes is changed, new
// definitions are not picked up immediately and obsolete definitions are
// not removed, because the list of search directories is only compiled
// once in this constructor. The current code only works due to
// coincidence: The request that installs e.g. a new theme does not
// instantiate this plugin manager at the beginning of the request; when
// routes are being rebuilt at the end of the request, this service only
// happens to get instantiated with the updated list of installed themes.
$directories = array();
foreach ($this->moduleHandler->getModuleList() as $name => $module) {
$directories[$name] = $module->getPath();
}
foreach ($this->themeHandler->listInfo() as $theme) {
$directories[$theme->getName()] = $theme->getPath();
}
// Check for files named MODULE.config_translation.yml and
// THEME.config_translation.yml in module/theme roots.
$this->discovery = new YamlDiscovery('config_translation', $directories);
$this->discovery = new InfoHookDecorator($this->discovery, 'config_translation_info');
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
......@@ -139,7 +149,7 @@ public function buildDataDefinition(array $definition, $value = NULL, $name = NU
* {@inheritdoc}
*/
protected function findDefinitions() {
$definitions = $this->discovery->getDefinitions();
$definitions = $this->getDiscovery()->getDefinitions();
foreach ($definitions as $plugin_id => &$definition) {
$this->processDefinition($definition, $plugin_id);
}
......
......@@ -48,14 +48,7 @@ protected function setUp() {
->getMock();
$module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$module_handler->expects($this->once())
->method('getModuleList')
->with()
->will($this->returnValue(array()));
$theme_handler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
$theme_handler->expects($this->any())
->method('listInfo')
->will($this->returnValue(array()));
$this->configMapperManager = new ConfigMapperManager(
$this->getMock('Drupal\Core\Cache\CacheBackendInterface'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment