Added missing modules, including some as submodules.
[yaffs-website] / web / modules / contrib / layout_plugin / src / Plugin / Layout / LayoutPluginManager.php
1 <?php
2
3 namespace Drupal\layout_plugin\Plugin\Layout;
4
5 use Drupal\Core\Cache\CacheBackendInterface;
6 use Drupal\Core\Extension\ModuleHandlerInterface;
7 use Drupal\Core\Extension\ThemeHandlerInterface;
8 use Drupal\Core\Plugin\CategorizingPluginManagerTrait;
9 use Drupal\Core\Plugin\DefaultPluginManager;
10 use Drupal\Core\Plugin\Discovery\YamlDiscoveryDecorator;
11
12 /**
13  * Plugin type manager for all layouts.
14  */
15 class LayoutPluginManager extends DefaultPluginManager implements LayoutPluginManagerInterface {
16
17   use CategorizingPluginManagerTrait;
18
19   /**
20    * The theme handler.
21    *
22    * @var \Drupal\Core\Extension\ThemeHandlerInterface
23    */
24   protected $themeHandler;
25
26   /**
27    * Constructs a LayoutPluginManager object.
28    *
29    * @param \Traversable $namespaces
30    *   An object that implements \Traversable which contains the root paths
31    *   keyed by the corresponding namespace to look for plugin implementations.
32    * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
33    *   Cache backend instance to use.
34    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
35    *   The module handler to invoke the alter hook with.
36    * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
37    *   The theme handle to invoke the alter hook with.
38    */
39   public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler) {
40     $plugin_interface = 'Drupal\layout_plugin\Plugin\Layout\LayoutInterface';
41     $plugin_definition_annotation_name = 'Drupal\layout_plugin\Annotation\Layout';
42     parent::__construct("Plugin/Layout", $namespaces, $module_handler, $plugin_interface, $plugin_definition_annotation_name);
43     $discovery = $this->getDiscovery();
44     $this->discovery = new YamlDiscoveryDecorator($discovery, 'layouts', $module_handler->getModuleDirectories() + $theme_handler->getThemeDirectories());
45     $this->themeHandler = $theme_handler;
46
47     $this->defaults += array(
48       'type' => 'page',
49       // Used for plugins defined in layouts.yml that do not specify a class
50       // themselves.
51       'class' => 'Drupal\layout_plugin\Plugin\Layout\LayoutDefault',
52     );
53
54     $this->setCacheBackend($cache_backend, 'layout');
55     $this->alterInfo('layout');
56   }
57
58   /**
59    * {@inheritdoc}
60    */
61   protected function providerExists($provider) {
62     return $this->moduleHandler->moduleExists($provider) || $this->themeHandler->themeExists($provider);
63   }
64
65   /**
66    * {@inheritdoc}
67    */
68   public function processDefinition(&$definition, $plugin_id) {
69     parent::processDefinition($definition, $plugin_id);
70
71     // Add the module or theme path to the 'path'.
72     if ($this->moduleHandler->moduleExists($definition['provider'])) {
73       $definition['provider_type'] = 'module';
74       $base_path = $this->moduleHandler->getModule($definition['provider'])->getPath();
75     }
76     elseif ($this->themeHandler->themeExists($definition['provider'])) {
77       $definition['provider_type'] = 'theme';
78       $base_path = $this->themeHandler->getTheme($definition['provider'])->getPath();
79     }
80     else {
81       $base_path = '';
82     }
83     $definition['path'] = !empty($definition['path']) ? $base_path . '/' . $definition['path'] : $base_path;
84
85     // Add a dependency on the provider of the library.
86     if (!empty($definition['library'])) {
87       list ($library_provider, ) = explode('/', $definition['library']);
88       if ($this->moduleHandler->moduleExists($library_provider)) {
89         $definition['dependencies'] = ['module' => [$library_provider]];
90       }
91       elseif ($this->themeHandler->themeExists($library_provider)) {
92         $definition['dependencies'] = ['theme' => [$library_provider]];
93       }
94     }
95
96     // Add the path to the icon filename.
97     if (!empty($definition['icon'])) {
98       $definition['icon'] = $definition['path'] . '/' . $definition['icon'];
99     }
100
101     // If 'template' is set, then we'll derive 'template_path' and 'theme'.
102     if (!empty($definition['template'])) {
103       $template_parts = explode('/', $definition['template']);
104
105       $definition['template'] = array_pop($template_parts);
106       $definition['theme'] = strtr($definition['template'], '-', '_');
107       $definition['template_path'] = $definition['path'];
108       if (count($template_parts) > 0) {
109         $definition['template_path'] .= '/' . implode('/', $template_parts);
110       }
111     }
112
113     // If 'css' is set, then we'll derive 'library'.
114     if (!empty($definition['css'])) {
115       $definition['css'] = $definition['path'] . '/' . $definition['css'];
116       $definition['library'] = 'layout_plugin/' . $plugin_id;
117     }
118
119     // Generate the 'region_names' key from the 'regions' key.
120     $definition['region_names'] = array();
121     if (!empty($definition['regions']) && is_array($definition['regions'])) {
122       foreach ($definition['regions'] as $region_id => $region_definition) {
123         $definition['region_names'][$region_id] = $region_definition['label'];
124       }
125     }
126   }
127
128   /**
129    * {@inheritdoc}
130    */
131   public function getLayoutOptions(array $params = []) {
132     $group_by_category = !empty($params['group_by_category']);
133     $plugins = $group_by_category ? $this->getGroupedDefinitions() : ['default' => $this->getDefinitions()];
134     $categories = $group_by_category ? $this->getCategories() : ['default'];
135
136     // Go through each category, sort it, and get just the labels out.
137     $options = array();
138     foreach ($categories as $category) {
139       // Convert from a translation to a real string.
140       $category = (string) $category;
141
142       // Sort the category.
143       $plugins[$category] = $this->getSortedDefinitions($plugins[$category]);
144
145       // Put only the label in the options array.
146       foreach ($plugins[$category] as $id => $plugin) {
147         $options[$category][$id] = $plugin['label'];
148       }
149     }
150
151     return $group_by_category ? $options : $options['default'];
152   }
153
154   /**
155    * {@inheritdoc}
156    */
157   public function getThemeImplementations() {
158     $plugins = $this->getDefinitions();
159
160     $theme_registry = [];
161     foreach ($plugins as $id => $definition) {
162       if (!empty($definition['template']) && !empty($definition['theme'])) {
163         $theme_registry[$definition['theme']] = [
164           'render element' => 'content',
165           'template' => $definition['template'],
166           'path' => $definition['template_path'],
167         ];
168       }
169     }
170
171     return $theme_registry;
172   }
173
174   /**
175    * {@inheritdoc}
176    */
177   public function alterThemeImplementations(array &$theme_registry) {
178     $plugins = $this->getDefinitions();
179
180     // Find all the theme hooks which are for automatically registered templates
181     // (we ignore manually set theme hooks because we don't know how they were
182     // registered).
183     $layout_theme_hooks = [];
184     foreach ($plugins as $id => $definition) {
185       if (!empty($definition['template']) && !empty($definition['theme']) && isset($theme_registry[$definition['theme']])) {
186         $layout_theme_hooks[] = $definition['theme'];
187       }
188     }
189
190     // Go through the theme registry looking for our theme hooks and any
191     // suggestions based on them.
192     foreach ($theme_registry as $theme_hook => &$info) {
193       if (in_array($theme_hook, $layout_theme_hooks) || (!empty($info['base hook']) && in_array($info['base hook'], $layout_theme_hooks))) {
194         // If 'template_preprocess' is included, we want to put our preprocess
195         // after to not mess up the expectation that 'template_process' always
196         // runs first.
197         if (($index = array_search('template_preprocess', $info['preprocess functions'])) !== FALSE) {
198           $index++;
199         }
200         else {
201           // Otherwise, put our preprocess function first.
202           $index = 0;
203         }
204
205         array_splice($info['preprocess functions'], $index, 0, '_layout_plugin_preprocess_layout');
206       }
207     }
208   }
209
210   /**
211    * Gets the version of the given provider.
212    *
213    * Wraps system_get_info() so that we can mock it in our tests.
214    *
215    * @param string $provider_type
216    *   The provider type (ex. module or theme).
217    * @param string $provider
218    *   The name of the provider.
219    *
220    * @return string
221    *   The version string for the provider or 'VERSION' if it can't be found.
222    */
223   protected function getProviderVersion($provider_type, $provider) {
224     $info = system_get_info($provider_type, $provider);
225     return !empty($info['version']) ? $info['version'] : 'VERSION';
226   }
227
228   /**
229    * {@inheritdoc}
230    */
231   public function getLibraryInfo() {
232     $plugins = $this->getDefinitions();
233
234     $library_info = [];
235     foreach ($plugins as $id => $definition) {
236       if (!empty($definition['css']) && !empty($definition['library'])) {
237         list ($library_module, $library_name) = explode('/', $definition['library']);
238
239         // Make sure the library is from layout_plugin.
240         if ($library_module != 'layout_plugin') {
241           continue;
242         }
243
244         $library_info[$library_name] = [
245           'version' => $this->getProviderVersion($definition['provider_type'], $definition['provider']),
246           'css' => [
247             'theme' => [
248               '/' . $definition['css'] => [],
249             ],
250           ],
251         ];
252       }
253     }
254
255     return $library_info;
256   }
257
258 }