950a9d3e6609a42f35898027a381b5c34fc66b3f
[yaffs-website] / web / themes / contrib / bootstrap / src / Plugin / Provider / JsDelivr.php
1 <?php
2
3 namespace Drupal\bootstrap\Plugin\Provider;
4
5 use Drupal\bootstrap\Bootstrap;
6 use Drupal\Component\Utility\NestedArray;
7
8 /**
9  * The "jsdelivr" CDN provider plugin.
10  *
11  * @ingroup plugins_provider
12  *
13  * @BootstrapProvider(
14  *   id = "jsdelivr",
15  *   label = @Translation("jsDelivr"),
16  *   api = "https://api.jsdelivr.com/v1/bootstrap/libraries",
17  *   themes = { },
18  *   versions = { },
19  * )
20  */
21 class JsDelivr extends ProviderBase {
22
23   /**
24    * Extracts theme information from files provided by the jsDelivr API.
25    *
26    * This will place the raw files into proper "css", "js" and "min" arrays
27    * (if they exist) and prepends them with a base URL provided.
28    *
29    * @param array $files
30    *   An array of files to process.
31    * @param string $base_url
32    *   The base URL each one of the $files are relative to, this usually
33    *   should also include the version path prefix as well.
34    *
35    * @return array
36    *   An associative array containing the following keys, if there were
37    *   matching files found:
38    *   - css
39    *   - js
40    *   - min:
41    *     - css
42    *     - js
43    */
44   protected function extractThemes(array $files, $base_url = '') {
45     $themes = [];
46     foreach ($files as $file) {
47       preg_match('`([^/]*)/bootstrap(-theme)?(\.min)?\.(js|css)$`', $file, $matches);
48       if (!empty($matches[1]) && !empty($matches[4])) {
49         $path = $matches[1];
50         $min = $matches[3];
51         $filetype = $matches[4];
52
53         // Determine the "theme" name.
54         if ($path === 'css' || $path === 'js') {
55           $theme = 'bootstrap';
56           $title = (string) t('Bootstrap');
57         }
58         else {
59           $theme = $path;
60           $title = ucfirst($path);
61         }
62         if ($matches[2]) {
63           $theme = 'bootstrap_theme';
64           $title = (string) t('Bootstrap Theme');
65         }
66
67         $themes[$theme]['title'] = $title;
68         if ($min) {
69           $themes[$theme]['min'][$filetype][] = "$base_url/$path/bootstrap{$matches[2]}$min.$filetype";
70         }
71         else {
72           $themes[$theme][$filetype][] = "$base_url/$path/bootstrap{$matches[2]}$min.$filetype";
73         }
74       }
75     }
76     return $themes;
77   }
78
79   /**
80    * {@inheritdoc}
81    */
82   public function getAssets($types = NULL) {
83     $this->assets = [];
84     $error = !empty($provider['error']);
85     $version = $error ? Bootstrap::FRAMEWORK_VERSION : $this->theme->getSetting('cdn_jsdelivr_version');
86     $theme = $error ? 'bootstrap' : $this->theme->getSetting('cdn_jsdelivr_theme');
87     if (isset($this->pluginDefinition['themes'][$version][$theme])) {
88       $this->assets = $this->pluginDefinition['themes'][$version][$theme];
89     }
90     return parent::getAssets($types);
91   }
92
93   /**
94    * {@inheritdoc}
95    */
96   public function processApi(array $json, array &$definition) {
97     $definition['description'] = t('<p style="background:#EB4C36"><a href=":jsdelivr" target="_blank"><img src="//www.jsdelivr.com/img/logo.png" alt="jsDelivr Logo"/></a></p><p><a href=":jsdelivr" target="_blank">jsDelivr</a> is a free multi-CDN infrastructure that uses <a href=":maxcdn" target="_blank">MaxCDN</a>, <a href=":cloudflare" target="_blank">Cloudflare</a> and many others to combine their powers for the good of the open source community... <a href=":jsdelivr_about" target="_blank">read more</a></p>', [
98       ':jsdelivr' => 'https://www.jsdelivr.com',
99       ':jsdelivr_about' => 'https://www.jsdelivr.com/about',
100       ':maxcdn' => 'https://www.maxcdn.com',
101       ':cloudflare' => 'https://www.cloudflare.com',
102     ]);
103
104     // Expected library names from jsDelivr API v1. Must use "twitter-bootstrap"
105     // instead of "bootstrap" (which is just a directory alias).
106     // @see https://www.drupal.org/node/2504343
107     // @see https://github.com/jsdelivr/api/issues/94
108     $bootstrap = 'twitter-bootstrap';
109     $bootswatch = 'bootswatch';
110
111     // Extract the raw asset files from the JSON data for each framework.
112     $libraries = [];
113     if ($json) {
114       foreach ($json as $data) {
115         if ($data['name'] === $bootstrap || $data['name'] === $bootswatch) {
116           foreach ($data['assets'] as $asset) {
117             if (preg_match('/^' . substr(Bootstrap::FRAMEWORK_VERSION, 0, 1) . '\.\d\.\d$/', $asset['version'])) {
118               $libraries[$data['name']][$asset['version']] = $asset['files'];
119             }
120           }
121         }
122       }
123     }
124
125     // If the main bootstrap library could not be found, then provide defaults.
126     if (!isset($libraries[$bootstrap])) {
127       $definition['error'] = TRUE;
128       $definition['versions'][Bootstrap::FRAMEWORK_VERSION] = Bootstrap::FRAMEWORK_VERSION;
129       $definition['themes'][Bootstrap::FRAMEWORK_VERSION] = [
130         'bootstrap' => [
131           'title' => (string) t('Bootstrap'),
132           'css' => ['//cdn.jsdelivr.net/bootstrap/' . Bootstrap::FRAMEWORK_VERSION . '/css/bootstrap.css'],
133           'js' => ['//cdn.jsdelivr.net/bootstrap/' . Bootstrap::FRAMEWORK_VERSION . '/js/bootstrap.js'],
134           'min' => [
135             'css' => ['//cdn.jsdelivr.net/bootstrap/' . Bootstrap::FRAMEWORK_VERSION . '/css/bootstrap.min.css'],
136             'js' => ['//cdn.jsdelivr.net/bootstrap/' . Bootstrap::FRAMEWORK_VERSION . '/js/bootstrap.min.js'],
137           ],
138         ],
139       ];
140       return;
141     }
142
143     // Populate the provider array with the versions and themes available.
144     foreach (array_keys($libraries[$bootstrap]) as $version) {
145       $definition['versions'][$version] = $version;
146
147       if (!isset($definition['themes'][$version])) {
148         $definition['themes'][$version] = [];
149       }
150
151       // Extract Bootstrap themes.
152       $definition['themes'][$version] = NestedArray::mergeDeep($definition['themes'][$version], $this->extractThemes($libraries[$bootstrap][$version], "//cdn.jsdelivr.net/bootstrap/$version"));
153
154       // Extract Bootswatch themes.
155       if (isset($libraries[$bootswatch][$version])) {
156         $definition['themes'][$version] = NestedArray::mergeDeep($definition['themes'][$version], $this->extractThemes($libraries[$bootswatch][$version], "//cdn.jsdelivr.net/bootswatch/$version"));
157       }
158     }
159
160     // Post process the themes to fill in any missing assets.
161     foreach (array_keys($definition['themes']) as $version) {
162       foreach (array_keys($definition['themes'][$version]) as $theme) {
163         // Some themes actually require Bootstrap framework assets to still
164         // function properly.
165         if ($theme !== 'bootstrap') {
166           foreach (['css', 'js'] as $type) {
167             // Bootswatch themes include the Bootstrap framework in their CSS.
168             // Skip the CSS portions.
169             if ($theme !== 'bootstrap_theme' && $type === 'css') {
170               continue;
171             }
172             if (!isset($definition['themes'][$version][$theme][$type]) && !empty($definition['themes'][$version]['bootstrap'][$type])) {
173               $definition['themes'][$version][$theme][$type] = [];
174             }
175             $definition['themes'][$version][$theme][$type] = NestedArray::mergeDeep($definition['themes'][$version]['bootstrap'][$type], $definition['themes'][$version][$theme][$type]);
176             if (!isset($definition['themes'][$version][$theme]['min'][$type]) && !empty($definition['themes'][$version]['bootstrap']['min'][$type])) {
177               $definition['themes'][$version][$theme]['min'][$type] = [];
178             }
179             $definition['themes'][$version][$theme]['min'][$type] = NestedArray::mergeDeep($definition['themes'][$version]['bootstrap']['min'][$type], $definition['themes'][$version][$theme]['min'][$type]);
180           }
181         }
182         // Some themes do not have a non-minified version, clone them to the
183         // "normal" css/js arrays to ensure that the theme still loads if
184         // aggregation (minification) is disabled.
185         foreach (['css', 'js'] as $type) {
186           if (!isset($definition['themes'][$version][$theme][$type]) && isset($definition['themes'][$version][$theme]['min'][$type])) {
187             $definition['themes'][$version][$theme][$type] = $definition['themes'][$version][$theme]['min'][$type];
188           }
189         }
190       }
191     }
192   }
193
194 }