Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Plugin/DefaultPluginManager.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Plugin; | |
4 | |
5 use Drupal\Component\Plugin\Definition\PluginDefinitionInterface; | |
6 use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface; | |
7 use Drupal\Core\Cache\CacheableDependencyInterface; | |
8 use Drupal\Core\Cache\CacheBackendInterface; | |
9 use Drupal\Core\Cache\UseCacheBackendTrait; | |
10 use Drupal\Component\Plugin\Discovery\DiscoveryCachedTrait; | |
11 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator; | |
12 use Drupal\Component\Plugin\PluginManagerBase; | |
13 use Drupal\Component\Plugin\PluginManagerInterface; | |
14 use Drupal\Component\Utility\NestedArray; | |
15 use Drupal\Core\Cache\Cache; | |
16 use Drupal\Core\Extension\ModuleHandlerInterface; | |
17 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; | |
18 use Drupal\Core\Plugin\Factory\ContainerFactory; | |
19 | |
20 /** | |
21 * Base class for plugin managers. | |
22 * | |
23 * @ingroup plugin_api | |
24 */ | |
25 class DefaultPluginManager extends PluginManagerBase implements PluginManagerInterface, CachedDiscoveryInterface, CacheableDependencyInterface { | |
26 | |
27 use DiscoveryCachedTrait; | |
28 use UseCacheBackendTrait; | |
29 | |
30 /** | |
31 * The cache key. | |
32 * | |
33 * @var string | |
34 */ | |
35 protected $cacheKey; | |
36 | |
37 /** | |
38 * An array of cache tags to use for the cached definitions. | |
39 * | |
40 * @var array | |
41 */ | |
42 protected $cacheTags = []; | |
43 | |
44 /** | |
45 * Name of the alter hook if one should be invoked. | |
46 * | |
47 * @var string | |
48 */ | |
49 protected $alterHook; | |
50 | |
51 /** | |
52 * The subdirectory within a namespace to look for plugins, or FALSE if the | |
53 * plugins are in the top level of the namespace. | |
54 * | |
55 * @var string|bool | |
56 */ | |
57 protected $subdir; | |
58 | |
59 /** | |
60 * The module handler to invoke the alter hook. | |
61 * | |
62 * @var \Drupal\Core\Extension\ModuleHandlerInterface | |
63 */ | |
64 protected $moduleHandler; | |
65 | |
66 /** | |
67 * A set of defaults to be referenced by $this->processDefinition() if | |
68 * additional processing of plugins is necessary or helpful for development | |
69 * purposes. | |
70 * | |
71 * @var array | |
72 */ | |
73 protected $defaults = []; | |
74 | |
75 /** | |
76 * The name of the annotation that contains the plugin definition. | |
77 * | |
78 * @var string | |
79 */ | |
80 protected $pluginDefinitionAnnotationName; | |
81 | |
82 /** | |
83 * The interface each plugin should implement. | |
84 * | |
85 * @var string|null | |
86 */ | |
87 protected $pluginInterface; | |
88 | |
89 /** | |
90 * An object that implements \Traversable which contains the root paths | |
91 * keyed by the corresponding namespace to look for plugin implementations. | |
92 * | |
93 * @var \Traversable | |
94 */ | |
95 protected $namespaces; | |
96 | |
97 /** | |
98 * Additional namespaces the annotation discovery mechanism should scan for | |
99 * annotation definitions. | |
100 * | |
101 * @var string[] | |
102 */ | |
103 protected $additionalAnnotationNamespaces = []; | |
104 | |
105 /** | |
106 * Creates the discovery object. | |
107 * | |
108 * @param string|bool $subdir | |
109 * The plugin's subdirectory, for example Plugin/views/filter. | |
110 * @param \Traversable $namespaces | |
111 * An object that implements \Traversable which contains the root paths | |
112 * keyed by the corresponding namespace to look for plugin implementations. | |
113 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
114 * The module handler. | |
115 * @param string|null $plugin_interface | |
116 * (optional) The interface each plugin should implement. | |
117 * @param string $plugin_definition_annotation_name | |
118 * (optional) The name of the annotation that contains the plugin definition. | |
119 * Defaults to 'Drupal\Component\Annotation\Plugin'. | |
120 * @param string[] $additional_annotation_namespaces | |
121 * (optional) Additional namespaces to scan for annotation definitions. | |
122 */ | |
123 public function __construct($subdir, \Traversable $namespaces, ModuleHandlerInterface $module_handler, $plugin_interface = NULL, $plugin_definition_annotation_name = 'Drupal\Component\Annotation\Plugin', array $additional_annotation_namespaces = []) { | |
124 $this->subdir = $subdir; | |
125 $this->namespaces = $namespaces; | |
126 $this->pluginDefinitionAnnotationName = $plugin_definition_annotation_name; | |
127 $this->pluginInterface = $plugin_interface; | |
128 $this->moduleHandler = $module_handler; | |
129 $this->additionalAnnotationNamespaces = $additional_annotation_namespaces; | |
130 } | |
131 | |
132 /** | |
133 * Initialize the cache backend. | |
134 * | |
135 * Plugin definitions are cached using the provided cache backend. | |
136 * | |
137 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend | |
138 * Cache backend instance to use. | |
139 * @param string $cache_key | |
140 * Cache key prefix to use. | |
141 * @param array $cache_tags | |
142 * (optional) When providing a list of cache tags, the cached plugin | |
143 * definitions are tagged with the provided cache tags. These cache tags can | |
144 * then be used to clear the corresponding cached plugin definitions. Note | |
145 * that this should be used with care! For clearing all cached plugin | |
146 * definitions of a plugin manager, call that plugin manager's | |
147 * clearCachedDefinitions() method. Only use cache tags when cached plugin | |
148 * definitions should be cleared along with other, related cache entries. | |
149 */ | |
150 public function setCacheBackend(CacheBackendInterface $cache_backend, $cache_key, array $cache_tags = []) { | |
151 assert('\Drupal\Component\Assertion\Inspector::assertAllStrings($cache_tags)', 'Cache Tags must be strings.'); | |
152 $this->cacheBackend = $cache_backend; | |
153 $this->cacheKey = $cache_key; | |
154 $this->cacheTags = $cache_tags; | |
155 } | |
156 | |
157 /** | |
158 * Initializes the alter hook. | |
159 * | |
160 * @param string $alter_hook | |
161 * Name of the alter hook; for example, to invoke | |
162 * hook_mymodule_data_alter() pass in "mymodule_data". | |
163 */ | |
164 protected function alterInfo($alter_hook) { | |
165 $this->alterHook = $alter_hook; | |
166 } | |
167 | |
168 /** | |
169 * {@inheritdoc} | |
170 */ | |
171 public function getDefinitions() { | |
172 $definitions = $this->getCachedDefinitions(); | |
173 if (!isset($definitions)) { | |
174 $definitions = $this->findDefinitions(); | |
175 $this->setCachedDefinitions($definitions); | |
176 } | |
177 return $definitions; | |
178 } | |
179 | |
180 /** | |
181 * {@inheritdoc} | |
182 */ | |
183 public function clearCachedDefinitions() { | |
184 if ($this->cacheBackend) { | |
185 if ($this->cacheTags) { | |
186 // Use the cache tags to clear the cache. | |
187 Cache::invalidateTags($this->cacheTags); | |
188 } | |
189 else { | |
190 $this->cacheBackend->delete($this->cacheKey); | |
191 } | |
192 } | |
193 $this->definitions = NULL; | |
194 } | |
195 | |
196 /** | |
197 * Returns the cached plugin definitions of the decorated discovery class. | |
198 * | |
199 * @return array|null | |
200 * On success this will return an array of plugin definitions. On failure | |
201 * this should return NULL, indicating to other methods that this has not | |
202 * yet been defined. Success with no values should return as an empty array | |
203 * and would actually be returned by the getDefinitions() method. | |
204 */ | |
205 protected function getCachedDefinitions() { | |
206 if (!isset($this->definitions) && $cache = $this->cacheGet($this->cacheKey)) { | |
207 $this->definitions = $cache->data; | |
208 } | |
209 return $this->definitions; | |
210 } | |
211 | |
212 /** | |
213 * Sets a cache of plugin definitions for the decorated discovery class. | |
214 * | |
215 * @param array $definitions | |
216 * List of definitions to store in cache. | |
217 */ | |
218 protected function setCachedDefinitions($definitions) { | |
219 $this->cacheSet($this->cacheKey, $definitions, Cache::PERMANENT, $this->cacheTags); | |
220 $this->definitions = $definitions; | |
221 } | |
222 | |
223 /** | |
224 * {@inheritdoc} | |
225 */ | |
226 public function useCaches($use_caches = FALSE) { | |
227 $this->useCaches = $use_caches; | |
228 if (!$use_caches) { | |
229 $this->definitions = NULL; | |
230 } | |
231 } | |
232 | |
233 /** | |
234 * Performs extra processing on plugin definitions. | |
235 * | |
236 * By default we add defaults for the type to the definition. If a type has | |
237 * additional processing logic they can do that by replacing or extending the | |
238 * method. | |
239 */ | |
240 public function processDefinition(&$definition, $plugin_id) { | |
241 // Only array-based definitions can have defaults merged in. | |
242 if (is_array($definition) && !empty($this->defaults) && is_array($this->defaults)) { | |
243 $definition = NestedArray::mergeDeep($this->defaults, $definition); | |
244 } | |
245 | |
246 // Keep class definitions standard with no leading slash. | |
247 if ($definition instanceof PluginDefinitionInterface) { | |
248 $definition->setClass(ltrim($definition->getClass(), '\\')); | |
249 } | |
250 elseif (is_array($definition) && isset($definition['class'])) { | |
251 $definition['class'] = ltrim($definition['class'], '\\'); | |
252 } | |
253 } | |
254 | |
255 /** | |
256 * {@inheritdoc} | |
257 */ | |
258 protected function getDiscovery() { | |
259 if (!$this->discovery) { | |
260 $discovery = new AnnotatedClassDiscovery($this->subdir, $this->namespaces, $this->pluginDefinitionAnnotationName, $this->additionalAnnotationNamespaces); | |
261 $this->discovery = new ContainerDerivativeDiscoveryDecorator($discovery); | |
262 } | |
263 return $this->discovery; | |
264 } | |
265 | |
266 /** | |
267 * {@inheritdoc} | |
268 */ | |
269 protected function getFactory() { | |
270 if (!$this->factory) { | |
271 $this->factory = new ContainerFactory($this, $this->pluginInterface); | |
272 } | |
273 return $this->factory; | |
274 } | |
275 | |
276 /** | |
277 * Finds plugin definitions. | |
278 * | |
279 * @return array | |
280 * List of definitions to store in cache. | |
281 */ | |
282 protected function findDefinitions() { | |
283 $definitions = $this->getDiscovery()->getDefinitions(); | |
284 foreach ($definitions as $plugin_id => &$definition) { | |
285 $this->processDefinition($definition, $plugin_id); | |
286 } | |
287 $this->alterDefinitions($definitions); | |
288 // If this plugin was provided by a module that does not exist, remove the | |
289 // plugin definition. | |
290 foreach ($definitions as $plugin_id => $plugin_definition) { | |
291 $provider = $this->extractProviderFromDefinition($plugin_definition); | |
292 if ($provider && !in_array($provider, ['core', 'component']) && !$this->providerExists($provider)) { | |
293 unset($definitions[$plugin_id]); | |
294 } | |
295 } | |
296 return $definitions; | |
297 } | |
298 | |
299 /** | |
300 * Extracts the provider from a plugin definition. | |
301 * | |
302 * @param mixed $plugin_definition | |
303 * The plugin definition. Usually either an array or an instance of | |
304 * \Drupal\Component\Plugin\Definition\PluginDefinitionInterface | |
305 * | |
306 * @return string|null | |
307 * The provider string, if it exists. NULL otherwise. | |
308 */ | |
309 protected function extractProviderFromDefinition($plugin_definition) { | |
310 if ($plugin_definition instanceof PluginDefinitionInterface) { | |
311 return $plugin_definition->getProvider(); | |
312 } | |
313 | |
314 // Attempt to convert the plugin definition to an array. | |
315 if (is_object($plugin_definition)) { | |
316 $plugin_definition = (array) $plugin_definition; | |
317 } | |
318 | |
319 if (isset($plugin_definition['provider'])) { | |
320 return $plugin_definition['provider']; | |
321 } | |
322 } | |
323 | |
324 /** | |
325 * Invokes the hook to alter the definitions if the alter hook is set. | |
326 * | |
327 * @param $definitions | |
328 * The discovered plugin definitions. | |
329 */ | |
330 protected function alterDefinitions(&$definitions) { | |
331 if ($this->alterHook) { | |
332 $this->moduleHandler->alter($this->alterHook, $definitions); | |
333 } | |
334 } | |
335 | |
336 /** | |
337 * Determines if the provider of a definition exists. | |
338 * | |
339 * @return bool | |
340 * TRUE if provider exists, FALSE otherwise. | |
341 */ | |
342 protected function providerExists($provider) { | |
343 return $this->moduleHandler->moduleExists($provider); | |
344 } | |
345 | |
346 /** | |
347 * {@inheritdoc} | |
348 */ | |
349 public function getCacheContexts() { | |
350 return []; | |
351 } | |
352 | |
353 /** | |
354 * {@inheritdoc} | |
355 */ | |
356 public function getCacheTags() { | |
357 return $this->cacheTags; | |
358 } | |
359 | |
360 /** | |
361 * {@inheritdoc} | |
362 */ | |
363 public function getCacheMaxAge() { | |
364 return Cache::PERMANENT; | |
365 } | |
366 | |
367 } |