Example #1
0
 private function getAllLibraries()
 {
     $modules = $this->moduleHandler->getModuleList();
     $themes = $this->themeHandler->rebuildThemeData();
     $extensions = array_merge($modules, $themes);
     $libraries = [];
     foreach ($extensions as $extensionName => $extension) {
         $libraryFile = $extension->getPath() . '/' . $extensionName . '.libraries.yml';
         if (is_file($this->appRoot . '/' . $libraryFile)) {
             $libraries[$extensionName] = $this->libraryDiscovery->getLibrariesByExtension($extensionName);
         }
     }
     return array_keys($libraries);
 }
 /**
  * Gets the given libraries with its dependencies.
  *
  * Helper method for ::getLibrariesWithDependencies().
  *
  * @param string[] $libraries_with_unresolved_dependencies
  *   A list of libraries, with unresolved dependencies, in the order they
  *   should be loaded.
  * @param string[] $final_libraries
  *   The final list of libraries (the return value) that is being built
  *   recursively.
  *
  * @return string[]
  *   A list of libraries, in the order they should be loaded, including their
  *   dependencies.
  */
 protected function doGetDependencies(array $libraries_with_unresolved_dependencies, array $final_libraries = [])
 {
     foreach ($libraries_with_unresolved_dependencies as $library) {
         if (!in_array($library, $final_libraries)) {
             list($extension, $name) = explode('/', $library, 2);
             $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
             if (!empty($definition['dependencies'])) {
                 $final_libraries = $this->doGetDependencies($definition['dependencies'], $final_libraries);
             }
             $final_libraries[] = $library;
         }
     }
     return $final_libraries;
 }
 /**
  * Asserts that the specified asset is not in the given library.
  *
  * @param string $asset
  *   The asset file with the path for the file.
  * @param string $extension
  *   The extension in which the $library_name is defined.
  * @param string $library_name
  *   Name of the library.
  * @param mixed $sub_key
  *   The library sub key where the given asset is defined.
  * @param string $message
  *   (optional) A message to display with the assertion.
  *
  * @return bool
  *   TRUE if the specified asset is not found in the library.
  */
 protected function assertNoAssetInLibrary($asset, $extension, $library_name, $sub_key, $message = NULL)
 {
     if (!isset($message)) {
         $message = sprintf('Asset %s not found in library "%s/%s"', $asset, $extension, $library_name);
     }
     $library = $this->libraryDiscovery->getLibraryByName($extension, $library_name);
     foreach ($library[$sub_key] as $definition) {
         if ($asset == $definition['data']) {
             return $this->fail($message);
         }
     }
     return $this->pass($message);
 }
Example #4
0
 /**
  * Gets all libraries for core and all installed modules.
  *
  * @return array[]
  *   An associative array of libraries keyed by extension, then by library
  *   name, and so on.
  */
 protected function getAllLibraries()
 {
     $modules = \Drupal::moduleHandler()->getModuleList();
     $module_list = array_keys($modules);
     sort($module_list);
     $this->assertEqual($this->allModules, $module_list, 'All core modules are installed.');
     $libraries['core'] = $this->libraryDiscovery->getLibrariesByExtension('core');
     $root = \Drupal::root();
     foreach ($modules as $module_name => $module) {
         $library_file = $module->getPath() . '/' . $module_name . '.libraries.yml';
         if (is_file($root . '/' . $library_file)) {
             $libraries[$module_name] = $this->libraryDiscovery->getLibrariesByExtension($module_name);
         }
     }
     return $libraries;
 }
 /**
  * {@inheritdoc}
  */
 public function getJsAssets(AttachedAssetsInterface $assets, $optimize)
 {
     $theme_info = $this->themeManager->getActiveTheme();
     // Add the theme name to the cache key since themes may implement
     // hook_library_info_alter(). Additionally add the current language to
     // support translation of JavaScript files via hook_js_alter().
     $libraries_to_load = $this->getLibrariesToLoad($assets);
     $cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager->getCurrentLanguage()->getId() . ':' . Crypt::hashBase64(serialize($libraries_to_load)) . (int) (count($assets->getSettings()) > 0) . (int) $optimize;
     if ($cached = $this->cache->get($cid)) {
         list($js_assets_header, $js_assets_footer, $settings, $settings_in_header) = $cached->data;
     } else {
         $javascript = [];
         $default_options = ['type' => 'file', 'group' => JS_DEFAULT, 'weight' => 0, 'cache' => TRUE, 'preprocess' => TRUE, 'attributes' => [], 'version' => NULL, 'browsers' => []];
         // Collect all libraries that contain JS assets and are in the header.
         $header_js_libraries = [];
         foreach ($libraries_to_load as $library) {
             list($extension, $name) = explode('/', $library, 2);
             $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
             if (isset($definition['js']) && !empty($definition['header'])) {
                 $header_js_libraries[] = $library;
             }
         }
         // The current list of header JS libraries are only those libraries that
         // are in the header, but their dependencies must also be loaded for them
         // to function correctly, so update the list with those.
         $header_js_libraries = $this->libraryDependencyResolver->getLibrariesWithDependencies($header_js_libraries);
         foreach ($libraries_to_load as $library) {
             list($extension, $name) = explode('/', $library, 2);
             $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
             if (isset($definition['js'])) {
                 foreach ($definition['js'] as $options) {
                     $options += $default_options;
                     // 'scope' is a calculated option, based on which libraries are
                     // marked to be loaded from the header (see above).
                     $options['scope'] = in_array($library, $header_js_libraries) ? 'header' : 'footer';
                     // Preprocess can only be set if caching is enabled and no
                     // attributes are set.
                     $options['preprocess'] = $options['cache'] && empty($options['attributes']) ? $options['preprocess'] : FALSE;
                     // Always add a tiny value to the weight, to conserve the insertion
                     // order.
                     $options['weight'] += count($javascript) / 1000;
                     // Local and external files must keep their name as the associative
                     // key so the same JavaScript file is not added twice.
                     $javascript[$options['data']] = $options;
                 }
             }
         }
         // Allow modules and themes to alter the JavaScript assets.
         $this->moduleHandler->alter('js', $javascript, $assets);
         $this->themeManager->alter('js', $javascript, $assets);
         // Sort JavaScript assets, so that they appear in the correct order.
         uasort($javascript, 'static::sort');
         // Prepare the return value: filter JavaScript assets per scope.
         $js_assets_header = [];
         $js_assets_footer = [];
         foreach ($javascript as $key => $item) {
             if ($item['scope'] == 'header') {
                 $js_assets_header[$key] = $item;
             } elseif ($item['scope'] == 'footer') {
                 $js_assets_footer[$key] = $item;
             }
         }
         if ($optimize) {
             $collection_optimizer = \Drupal::service('asset.js.collection_optimizer');
             $js_assets_header = $collection_optimizer->optimize($js_assets_header);
             $js_assets_footer = $collection_optimizer->optimize($js_assets_footer);
         }
         // If the core/drupalSettings library is being loaded or is already
         // loaded, get the JavaScript settings assets, and convert them into a
         // single "regular" JavaScript asset.
         $libraries_to_load = $this->getLibrariesToLoad($assets);
         $settings_required = in_array('core/drupalSettings', $libraries_to_load) || in_array('core/drupalSettings', $this->libraryDependencyResolver->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()));
         $settings_have_changed = count($libraries_to_load) > 0 || count($assets->getSettings()) > 0;
         // Initialize settings to FALSE since they are not needed by default. This
         // distinguishes between an empty array which must still allow
         // hook_js_settings_alter() to be run.
         $settings = FALSE;
         if ($settings_required && $settings_have_changed) {
             $settings = $this->getJsSettingsAssets($assets);
             // Allow modules to add cached JavaScript settings.
             foreach ($this->moduleHandler->getImplementations('js_settings_build') as $module) {
                 $function = $module . '_' . 'js_settings_build';
                 $function($settings, $assets);
             }
         }
         $settings_in_header = in_array('core/drupalSettings', $header_js_libraries);
         $this->cache->set($cid, [$js_assets_header, $js_assets_footer, $settings, $settings_in_header], CacheBackendInterface::CACHE_PERMANENT, ['library_info']);
     }
     if ($settings !== FALSE) {
         // Attached settings override both library definitions and
         // hook_js_settings_build().
         $settings = NestedArray::mergeDeepArray([$settings, $assets->getSettings()], TRUE);
         // Allow modules and themes to alter the JavaScript settings.
         $this->moduleHandler->alter('js_settings', $settings, $assets);
         $this->themeManager->alter('js_settings', $settings, $assets);
         // Update the $assets object accordingly, so that it reflects the final
         // settings.
         $assets->setSettings($settings);
         $settings_as_inline_javascript = ['type' => 'setting', 'group' => JS_SETTING, 'weight' => 0, 'browsers' => [], 'data' => $settings];
         $settings_js_asset = ['drupalSettings' => $settings_as_inline_javascript];
         // Prepend to the list of JS assets, to render it first. Preferably in
         // the footer, but in the header if necessary.
         if ($settings_in_header) {
             $js_assets_header = $settings_js_asset + $js_assets_header;
         } else {
             $js_assets_footer = $settings_js_asset + $js_assets_footer;
         }
     }
     return [$js_assets_header, $js_assets_footer];
 }
 /**
  * Tests that an external asset library is registered as a core asset library.
  *
  * @see \Drupal\libraries\Extension\Extension
  * @see \Drupal\libraries\Extension\ExtensionHandler
  * @see \Drupal\libraries\ExternalLibrary\Asset\AssetLibrary
  * @see \Drupal\libraries\ExternalLibrary\Asset\AssetLibraryTrait
  * @see \Drupal\libraries\ExternalLibrary\ExternalLibraryManager
  * @see \Drupal\libraries\ExternalLibrary\ExternalLibraryTrait
  * @see \Drupal\libraries\ExternalLibrary\Registry\ExternalLibraryRegistry
  */
 public function testAssetLibrary()
 {
     $library = $this->libraryDiscovery->getLibraryByName('libraries', 'test_asset_library');
     $this->assertNotEquals(FALSE, $library);
     $this->assertTrue(is_array($library));
 }
Example #7
0
 /**
  * {@inheritdoc}
  */
 public function getJsAssets(AttachedAssetsInterface $assets, $optimize)
 {
     $javascript = [];
     $default_options = ['type' => 'file', 'group' => JS_DEFAULT, 'every_page' => FALSE, 'weight' => 0, 'cache' => TRUE, 'preprocess' => TRUE, 'attributes' => [], 'version' => NULL, 'browsers' => []];
     $libraries_to_load = $this->getLibrariesToLoad($assets);
     // Collect all libraries that contain JS assets and are in the header.
     $header_js_libraries = [];
     foreach ($libraries_to_load as $library) {
         list($extension, $name) = explode('/', $library, 2);
         $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
         if (isset($definition['js']) && !empty($definition['header'])) {
             $header_js_libraries[] = $library;
         }
     }
     // The current list of header JS libraries are only those libraries that are
     // in the header, but their dependencies must also be loaded for them to
     // function correctly, so update the list with those.
     $header_js_libraries = $this->libraryDependencyResolver->getLibrariesWithDependencies($header_js_libraries);
     foreach ($libraries_to_load as $library) {
         list($extension, $name) = explode('/', $library, 2);
         $definition = $this->libraryDiscovery->getLibraryByName($extension, $name);
         if (isset($definition['js'])) {
             foreach ($definition['js'] as $options) {
                 $options += $default_options;
                 // 'scope' is a calculated option, based on which libraries are marked
                 // to be loaded from the header (see above).
                 $options['scope'] = in_array($library, $header_js_libraries) ? 'header' : 'footer';
                 // Preprocess can only be set if caching is enabled and no attributes
                 // are set.
                 $options['preprocess'] = $options['cache'] && empty($options['attributes']) ? $options['preprocess'] : FALSE;
                 // Always add a tiny value to the weight, to conserve the insertion
                 // order.
                 $options['weight'] += count($javascript) / 1000;
                 // Local and external files must keep their name as the associative
                 // key so the same JavaScript file is not added twice.
                 $javascript[$options['data']] = $options;
             }
         }
     }
     // Allow modules and themes to alter the JavaScript assets.
     $this->moduleHandler->alter('js', $javascript, $assets);
     $this->themeManager->alter('js', $javascript, $assets);
     // Sort JavaScript assets, so that they appear in the correct order.
     uasort($javascript, 'static::sort');
     // Prepare the return value: filter JavaScript assets per scope.
     $js_assets_header = [];
     $js_assets_footer = [];
     foreach ($javascript as $key => $item) {
         if ($item['scope'] == 'header') {
             $js_assets_header[$key] = $item;
         } elseif ($item['scope'] == 'footer') {
             $js_assets_footer[$key] = $item;
         }
     }
     if ($optimize) {
         $collection_optimizer = \Drupal::service('asset.js.collection_optimizer');
         $js_assets_header = $collection_optimizer->optimize($js_assets_header);
         $js_assets_footer = $collection_optimizer->optimize($js_assets_footer);
     }
     // If the core/drupalSettings library is being loaded or is already loaded,
     // get the JavaScript settings assets, and convert them into a single
     // "regular" JavaScript asset.
     $libraries_to_load = $this->getLibrariesToLoad($assets);
     $settings_needed = in_array('core/drupalSettings', $libraries_to_load) || in_array('core/drupalSettings', $this->libraryDependencyResolver->getLibrariesWithDependencies($assets->getAlreadyLoadedLibraries()));
     $settings_have_changed = count($libraries_to_load) > 0 || count($assets->getSettings()) > 0;
     if ($settings_needed && $settings_have_changed) {
         $settings = $this->getJsSettingsAssets($assets);
         if (!empty($settings)) {
             $settings_as_inline_javascript = ['type' => 'setting', 'group' => JS_SETTING, 'every_page' => TRUE, 'weight' => 0, 'browsers' => [], 'data' => $settings];
             $settings_js_asset = ['drupalSettings' => $settings_as_inline_javascript];
             // Prepend to the list of JS assets, to render it first. Preferably in
             // the footer, but in the header if necessary.
             if (in_array('core/drupalSettings', $header_js_libraries)) {
                 $js_assets_header = $settings_js_asset + $js_assets_header;
             } else {
                 $js_assets_footer = $settings_js_asset + $js_assets_footer;
             }
         }
     }
     return [$js_assets_header, $js_assets_footer];
 }
 /**
  * {@inheritdoc}
  */
 protected function setUp()
 {
     $this->libraryDiscovery = $this->getMockBuilder('Drupal\\Core\\Asset\\LibraryDiscovery')->disableOriginalConstructor()->setMethods(['getLibrariesByExtension'])->getMock();
     $this->libraryDiscovery->expects($this->any())->method('getLibrariesByExtension')->with('test')->will($this->returnValue($this->libraryData));
     $this->libraryDependencyResolver = new LibraryDependencyResolver($this->libraryDiscovery);
 }