Update to drupal 8.0.0-rc1. For more information, see https://www.drupal.org/node/2582663

This commit is contained in:
Greg Anderson 2015-10-08 11:40:12 -07:00
parent eb34d130a8
commit f32e58e4b1
8476 changed files with 211648 additions and 170042 deletions

View file

@ -166,6 +166,7 @@ class AssetResolver implements AssetResolverInterface {
uasort($css, 'static::sort');
// Allow themes to remove CSS files by CSS files full path and file name.
// @todo Remove in Drupal 9.0.x.
if ($stylesheet_remove = $theme_info->getStyleSheetsRemove()) {
foreach ($css as $key => $options) {
if (isset($stylesheet_remove[$key])) {

View file

@ -0,0 +1,15 @@
<?php
/**
* @file
* Contains \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException.
*/
namespace Drupal\Core\Asset\Exception;
/**
* Defines a custom exception for an invalid libraries-extend specification.
*/
class InvalidLibrariesExtendSpecificationException extends \RuntimeException {
}

View file

@ -0,0 +1,15 @@
<?php
/**
* @file
* Contains \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException.
*/
namespace Drupal\Core\Asset\Exception;
/**
* Defines a custom exception if a definition refers to a non-existent library.
*/
class InvalidLibrariesOverrideSpecificationException extends \RuntimeException {
}

View file

@ -9,8 +9,6 @@ namespace Drupal\Core\Asset;
use Drupal\Core\Cache\CacheCollectorInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
/**
* Discovers available asset libraries in Drupal.
@ -87,6 +85,8 @@ class LibraryDiscovery implements LibraryDiscoveryInterface {
*/
public function clearCachedDefinitions() {
$this->cacheTagInvalidator->invalidateTags(['library_info']);
$this->libraryDefinitions = [];
$this->collector->clear();
}
}

View file

@ -7,6 +7,9 @@
namespace Drupal\Core\Asset;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException;
use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
use Drupal\Core\Cache\CacheCollector;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Lock\LockBackendInterface;
@ -79,9 +82,94 @@ class LibraryDiscoveryCollector extends CacheCollector {
* {@inheritdoc}
*/
protected function resolveCacheMiss($key) {
$this->storage[$key] = $this->discoveryParser->buildByExtension($key);
$this->storage[$key] = $this->getLibraryDefinitions($key);
$this->persist($key);
return $this->storage[$key];
}
/**
* Returns the library definitions for a given extension.
*
* This also implements libraries-overrides for entire libraries that have
* been specified by the LibraryDiscoveryParser.
*
* @param string $extension
* The name of the extension for which library definitions will be returned.
*
* @return array
* The library definitions for $extension with overrides applied.
*
* @throws \Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException
*/
protected function getLibraryDefinitions($extension) {
$libraries = $this->discoveryParser->buildByExtension($extension);
foreach ($libraries as $name => $definition) {
// Handle libraries that are marked for override or removal.
// @see \Drupal\Core\Asset\LibraryDiscoveryParser::applyLibrariesOverride()
if (isset($definition['override'])) {
if ($definition['override'] === FALSE) {
// Remove the library definition if FALSE is given.
unset($libraries[$name]);
}
else {
// Otherwise replace with existing library definition if it exists.
// Throw an exception if it doesn't.
list($replacement_extension, $replacement_name) = explode('/', $definition['override']);
$replacement_definition = $this->get($replacement_extension);
if (isset($replacement_definition[$replacement_name])) {
$libraries[$name] = $replacement_definition[$replacement_name];
}
else {
throw new InvalidLibrariesOverrideSpecificationException(sprintf('The specified library %s does not exist.', $definition['override']));
}
}
}
else {
// If libraries are not overridden, then apply libraries-extend.
$libraries[$name] = $this->applyLibrariesExtend($extension, $name, $definition);
}
}
return $libraries;
}
/**
* Applies the libraries-extend specified by the active theme.
*
* This extends the library definitions with the those specified by the
* libraries-extend specifications for the active theme.
*
* @param string $extension
* The name of the extension for which library definitions will be extended.
* @param string $library_name
* The name of the library whose definitions is to be extended.
* @param $library_definition
* The library definition to be extended.
*
* @return array
* The library definition extended as specified by libraries-extend.
*
* @throws \Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException
*/
protected function applyLibrariesExtend($extension, $library_name, $library_definition) {
$libraries_extend = $this->themeManager->getActiveTheme()->getLibrariesExtend();
if (!empty($libraries_extend["$extension/$library_name"])) {
foreach ($libraries_extend["$extension/$library_name"] as $library_extend_name) {
if (!is_string($library_extend_name)) {
// Only string library names are allowed.
throw new InvalidLibrariesExtendSpecificationException('The libraries-extend specification for each library must be a list of strings.');
}
list($new_extension, $new_library_name) = explode('/', $library_extend_name, 2);
$new_libraries = $this->get($new_extension);
if (isset($new_libraries[$new_library_name])) {
$library_definition = NestedArray::mergeDeep($library_definition, $new_libraries[$new_library_name]);
}
else {
throw new InvalidLibrariesExtendSpecificationException(sprintf('The specified library "%s" does not exist.', $library_extend_name));
}
}
}
return $library_definition;
}
}

View file

@ -8,8 +8,10 @@
namespace Drupal\Core\Asset;
use Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException;
use Drupal\Core\Asset\Exception\InvalidLibrariesOverrideSpecificationException;
use Drupal\Core\Asset\Exception\InvalidLibraryFileException;
use Drupal\Core\Asset\Exception\LibraryDefinitionMissingLicenseException;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
@ -88,6 +90,7 @@ class LibraryDiscoveryParser {
}
$libraries = $this->parseLibraryInfo($extension, $path);
$libraries = $this->applyLibrariesOverride($libraries, $extension);
foreach ($libraries as $id => &$library) {
if (!isset($library['js']) && !isset($library['css']) && !isset($library['drupalSettings'])) {
@ -185,6 +188,13 @@ class LibraryDiscoveryParser {
elseif ($this->fileValidUri($source)) {
$options['data'] = $source;
}
// A regular URI (e.g., http://example.com/example.js) without
// 'external' explicitly specified, which may happen if, e.g.
// libraries-override is used.
elseif ($this->isValidUri($source)) {
$options['type'] = 'external';
$options['data'] = $source;
}
// By default, file paths are relative to the registering extension.
else {
$options['data'] = $path . '/' . $source;
@ -313,6 +323,70 @@ class LibraryDiscoveryParser {
return $libraries;
}
/**
* Apply libraries overrides specified for the current active theme.
*
* @param array $libraries
* The libraries definitions.
* @param string $extension
* The extension in which these libraries are defined.
*
* @return array
* The modified libraries definitions.
*/
protected function applyLibrariesOverride($libraries, $extension) {
$active_theme = $this->themeManager->getActiveTheme();
// ActiveTheme::getLibrariesOverride() returns libraries-overrides for the
// current theme as well as all its base themes.
$all_libraries_overrides = $active_theme->getLibrariesOverride();
foreach ($all_libraries_overrides as $theme_path => $libraries_overrides) {
foreach ($libraries as $library_name => $library) {
// Process libraries overrides.
if (isset($libraries_overrides["$extension/$library_name"])) {
// Active theme defines an override for this library.
$override_definition = $libraries_overrides["$extension/$library_name"];
if (is_string($override_definition) || $override_definition === FALSE) {
// A string or boolean definition implies an override (or removal)
// for the whole library. Use the override key to specify that this
// library will be overridden when it is called.
// @see \Drupal\Core\Asset\LibraryDiscovery::getLibraryByName()
if ($override_definition) {
$libraries[$library_name]['override'] = $override_definition;
}
else {
$libraries[$library_name]['override'] = FALSE;
}
}
elseif (is_array($override_definition)) {
// An array definition implies an override for an asset within this
// library.
foreach ($override_definition as $sub_key => $value) {
// Throw an exception if the asset is not properly specified.
if (!is_array($value)) {
throw new InvalidLibrariesOverrideSpecificationException(sprintf('Library asset %s is not correctly specified. It should be in the form "extension/library_name/sub_key/path/to/asset.js".', "$extension/$library_name/$sub_key"));
}
if ($sub_key === 'drupalSettings') {
// drupalSettings may not be overridden.
throw new InvalidLibrariesOverrideSpecificationException(sprintf('drupalSettings may not be overridden in libraries-override. Trying to override %s. Use hook_library_info_alter() instead.', "$extension/$library_name/$sub_key"));
}
elseif ($sub_key === 'css') {
// SMACSS category should be incorporated into the asset name.
foreach ($value as $category => $overrides) {
$this->setOverrideValue($libraries[$library_name], [$sub_key, $category], $overrides, $theme_path);
}
}
else {
$this->setOverrideValue($libraries[$library_name], [$sub_key], $value, $theme_path);
}
}
}
}
}
}
return $libraries;
}
/**
* Wraps drupal_get_path().
*/
@ -327,4 +401,67 @@ class LibraryDiscoveryParser {
return file_valid_uri($source);
}
/**
* Determines if the supplied string is a valid URI.
*/
protected function isValidUri($string) {
return count(explode('://', $string)) === 2;
}
/**
* Overrides the specified library asset.
*
* @param array $library
* The containing library definition.
* @param array $sub_key
* An array containing the sub-keys specifying the library asset, e.g.
* @code['js']@endcode or @code['css', 'component']@endcode
* @param array $overrides
* Specifies the overrides, this is an array where the key is the asset to
* be overridden while the value is overriding asset.
*/
protected function setOverrideValue(array &$library, array $sub_key, array $overrides, $theme_path) {
foreach ($overrides as $original => $replacement) {
// Get the attributes of the asset to be overridden. If the key does
// not exist, then throw an exception.
$key_exists = NULL;
$parents = array_merge($sub_key, [$original]);
// Save the attributes of the library asset to be overridden.
$attributes = NestedArray::getValue($library, $parents, $key_exists);
if ($key_exists) {
// Remove asset to be overridden.
NestedArray::unsetValue($library, $parents);
// No need to replace if FALSE is specified, since that is a removal.
if ($replacement) {
// Ensure the replacement path is relative to drupal root.
$replacement = $this->resolveThemeAssetPath($theme_path, $replacement);
$new_parents = array_merge($sub_key, [$replacement]);
// Replace with an override if specified.
NestedArray::setValue($library, $new_parents, $attributes);
}
}
}
}
/**
* Ensures that a full path is returned for an overriding theme asset.
*
* @param string $theme_path
* The theme or base theme.
* @param string $overriding_asset
* The overriding library asset.
*
* @return string
* A fully resolved theme asset path relative to the Drupal directory.
*/
protected function resolveThemeAssetPath($theme_path, $overriding_asset) {
if ($overriding_asset[0] !== '/' && !$this->isValidUri($overriding_asset)) {
// The destination is not an absolute path and it's not a URI (e.g.
// public://generated_js/example.js or http://example.com/js/my_js.js), so
// it's relative to the theme.
return '/' . $theme_path . '/' . $overriding_asset;
}
return $overriding_asset;
}
}