4 * Contains \Drupal\bootstrap\Plugin\Alter\LibraryInfo.
7 namespace Drupal\bootstrap\Plugin\Alter;
9 use Drupal\bootstrap\Annotation\BootstrapAlter;
10 use Drupal\bootstrap\Bootstrap;
11 use Drupal\bootstrap\Plugin\PluginBase;
12 use Drupal\Component\Utility\NestedArray;
15 * Implements hook_library_info_alter().
17 * @ingroup plugins_alter
19 * @BootstrapAlter("library_info")
21 class LibraryInfo extends PluginBase implements AlterInterface {
26 public function alter(&$libraries, &$extension = NULL, &$context2 = NULL) {
27 $livereload = $this->theme->livereloadUrl();
29 // Disable preprocess on all CSS/JS if "livereload" is enabled.
31 $this->processLibrary($libraries, function (&$info, &$key, $type) {
32 if ($type === 'css' || $type === 'js') {
33 $info['preprocess'] = FALSE;
38 if ($extension === 'bootstrap') {
39 // Alter the "livereload.js" placeholder with the correct URL.
41 $libraries['livereload']['js'][$livereload] = $libraries['livereload']['js']['livereload.js'];
42 unset($libraries['livereload']['js']['livereload.js']);
45 // Retrieve the theme's CDN provider and assets.
46 $provider = $this->theme->getProvider();
47 $assets = $provider ? $provider->getAssets() : [];
49 // Immediately return if there is no provider or assets.
50 if (!$provider || !$assets) {
54 // Merge the assets into the library info.
55 $libraries['theme'] = NestedArray::mergeDeepArray([$assets, $libraries['theme']], TRUE);
57 // Add a specific version and theme CSS overrides file.
58 // @todo This should be retrieved by the Provider API.
59 $version = $this->theme->getSetting('cdn_' . $provider->getPluginId() . '_version') ?: Bootstrap::FRAMEWORK_VERSION;
60 $libraries['theme']['version'] = $version;
61 $provider_theme = $this->theme->getSetting('cdn_' . $provider->getPluginId() . '_theme') ?: 'bootstrap';
62 $provider_theme = $provider_theme === 'bootstrap' || $provider_theme === 'bootstrap_theme' ? '' : "-$provider_theme";
64 foreach ($this->theme->getAncestry(TRUE) as $ancestor) {
65 $overrides = $ancestor->getPath() . "/css/$version/overrides$provider_theme.min.css";
66 if (file_exists($overrides)) {
67 // Since this uses a relative path to the ancestor from DRUPAL_ROOT,
68 // we must prepend the entire path with forward slash (/) so it
69 // doesn't prepend the active theme's path.
70 $overrides = "/$overrides";
72 // The overrides file must also be stored in the "base" category so
73 // it isn't added after any potential sub-theme's "theme" category.
74 // There's no weight, so it will be added after the provider's assets.
75 // @see https://www.drupal.org/node/2770613
76 $libraries['theme']['css']['base'][$overrides] = [];
82 elseif ($extension === 'core') {
83 // Replace core dialog/jQuery UI implementations with Bootstrap Modals.
84 if ($this->theme->getSetting('modal_enabled')) {
85 $libraries['drupal.dialog']['override'] = 'bootstrap/drupal.dialog';
86 $libraries['drupal.dialog.ajax']['override'] = 'bootstrap/drupal.dialog.ajax';
92 * Processes library definitions.
94 * @param array $libraries
95 * The libraries array, passed by reference.
96 * @param callable $callback
97 * The callback to perform processing on the library.
99 public function processLibrary(&$libraries, callable $callback) {
100 foreach ($libraries as &$library) {
101 foreach ($library as $type => $definition) {
102 if (is_array($definition)) {
104 // CSS needs special handling since it contains grouping.
105 if ($type === 'css') {
106 foreach ($definition as $group => $files) {
107 foreach ($files as $key => $info) {
108 call_user_func_array($callback, [&$info, &$key, $type]);
109 $modified[$group][$key] = $info;
114 foreach ($definition as $key => $info) {
115 call_user_func_array($callback, [&$info, &$key, $type]);
116 $modified[$key] = $info;
119 $library[$type] = $modified;