Patched to Drupal 8.4.8 level. See https://www.drupal.org/sa-core-2018-004 and patch...
[yaffs-website] / web / core / lib / Drupal / Core / Asset / LibraryDiscoveryCollector.php
1 <?php
2
3 namespace Drupal\Core\Asset;
4
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException;
7 use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
8 use Drupal\Core\Cache\CacheCollector;
9 use Drupal\Core\Cache\CacheBackendInterface;
10 use Drupal\Core\Lock\LockBackendInterface;
11 use Drupal\Core\Theme\ThemeManagerInterface;
12
13 /**
14  * A CacheCollector implementation for building library extension info.
15  */
16 class LibraryDiscoveryCollector extends CacheCollector {
17
18   /**
19    * The library discovery parser.
20    *
21    * @var \Drupal\Core\Asset\LibraryDiscoveryParser
22    */
23   protected $discoveryParser;
24
25   /**
26    * The theme manager.
27    *
28    * @var \Drupal\Core\Theme\ThemeManagerInterface
29    */
30   protected $themeManager;
31
32   /**
33    * Constructs a CacheCollector object.
34    *
35    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
36    *   The cache backend.
37    * @param \Drupal\Core\Lock\LockBackendInterface $lock
38    *   The lock backend.
39    * @param \Drupal\Core\Asset\LibraryDiscoveryParser $discovery_parser
40    *   The library discovery parser.
41    * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
42    *   The theme manager.
43    */
44   public function __construct(CacheBackendInterface $cache, LockBackendInterface $lock, LibraryDiscoveryParser $discovery_parser, ThemeManagerInterface $theme_manager) {
45     $this->themeManager = $theme_manager;
46     parent::__construct(NULL, $cache, $lock, ['library_info']);
47
48     $this->discoveryParser = $discovery_parser;
49   }
50
51   /**
52    * {@inheritdoc}
53    */
54   protected function getCid() {
55     if (!isset($this->cid)) {
56       $this->cid = 'library_info:' . $this->themeManager->getActiveTheme()->getName();
57     }
58
59     return $this->cid;
60   }
61
62   /**
63    * {@inheritdoc}
64    */
65   protected function resolveCacheMiss($key) {
66     $this->storage[$key] = $this->getLibraryDefinitions($key);
67     $this->persist($key);
68
69     return $this->storage[$key];
70   }
71
72   /**
73    * Returns the library definitions for a given extension.
74    *
75    * This also implements libraries-overrides for entire libraries that have
76    * been specified by the LibraryDiscoveryParser.
77    *
78    * @param string $extension
79    *   The name of the extension for which library definitions will be returned.
80    *
81    * @return array
82    *   The library definitions for $extension with overrides applied.
83    *
84    * @throws \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException
85    */
86   protected function getLibraryDefinitions($extension) {
87     $libraries = $this->discoveryParser->buildByExtension($extension);
88     foreach ($libraries as $name => $definition) {
89       // Handle libraries that are marked for override or removal.
90       // @see \Drupal\Core\Asset\LibraryDiscoveryParser::applyLibrariesOverride()
91       if (isset($definition['override'])) {
92         if ($definition['override'] === FALSE) {
93           // Remove the library definition if FALSE is given.
94           unset($libraries[$name]);
95         }
96         else {
97           // Otherwise replace with existing library definition if it exists.
98           // Throw an exception if it doesn't.
99           list($replacement_extension, $replacement_name) = explode('/', $definition['override']);
100           $replacement_definition = $this->get($replacement_extension);
101           if (isset($replacement_definition[$replacement_name])) {
102             $libraries[$name] = $replacement_definition[$replacement_name];
103           }
104           else {
105             throw new InvalidLibrariesOverrideSpecificationException(sprintf('The specified library %s does not exist.', $definition['override']));
106           }
107         }
108       }
109       else {
110         // If libraries are not overridden, then apply libraries-extend.
111         $libraries[$name] = $this->applyLibrariesExtend($extension, $name, $definition);
112       }
113     }
114     return $libraries;
115   }
116
117   /**
118    * Applies the libraries-extend specified by the active theme.
119    *
120    * This extends the library definitions with the those specified by the
121    * libraries-extend specifications for the active theme.
122    *
123    * @param string $extension
124    *   The name of the extension for which library definitions will be extended.
125    * @param string $library_name
126    *   The name of the library whose definitions is to be extended.
127    * @param $library_definition
128    *   The library definition to be extended.
129    *
130    * @return array
131    *   The library definition extended as specified by libraries-extend.
132    *
133    * @throws \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException
134    */
135   protected function applyLibrariesExtend($extension, $library_name, $library_definition) {
136     $libraries_extend = $this->themeManager->getActiveTheme()->getLibrariesExtend();
137     if (!empty($libraries_extend["$extension/$library_name"])) {
138       foreach ($libraries_extend["$extension/$library_name"] as $library_extend_name) {
139         if (!is_string($library_extend_name)) {
140           // Only string library names are allowed.
141           throw new InvalidLibrariesExtendSpecificationException('The libraries-extend specification for each library must be a list of strings.');
142         }
143         list($new_extension, $new_library_name) = explode('/', $library_extend_name, 2);
144         $new_libraries = $this->get($new_extension);
145         if (isset($new_libraries[$new_library_name])) {
146           $library_definition = NestedArray::mergeDeep($library_definition, $new_libraries[$new_library_name]);
147         }
148         else {
149           throw new InvalidLibrariesExtendSpecificationException(sprintf('The specified library "%s" does not exist.', $library_extend_name));
150         }
151       }
152     }
153     return $library_definition;
154   }
155
156   /**
157    * {@inheritdoc}
158    */
159   public function reset() {
160     parent::reset();
161     $this->cid = NULL;
162   }
163
164 }