Newer
Older
<?php
/**
* @file
* External library handling for Drupal modules.
*/
Sascha Grossenbacher
committed
use Drupal\Core\DrupalKernel;
Tobias Zimmermann
committed
use Drupal\Core\Extension\ModuleHandler;
use Drupal\libraries\ExternalLibrary\Asset\AttachableAssetLibraryRegistrationInterface;
use Drupal\libraries\ExternalLibrary\Utility\LibraryAccessorInterface;
use Drupal\libraries\ExternalLibrary\Utility\LibraryIdAccessorInterface;
use Symfony\Component\Yaml\Parser;
Andrii Podanenko
committed
use Drupal\Core\Extension\Dependency;
*
* Register external asset libraries with Drupal core's library APIs.
/** @var \Drupal\libraries\ExternalLibrary\LibraryManagerInterface $library_manager */
$attachable_libraries = [];
$libraries_with_errors = [];
Tobias Zimmermann
committed
foreach ($library_manager->getRequiredLibraryIds() as $external_library_id) {
try {
$external_library = $library_manager->getLibrary($external_library_id);
$library_type = $external_library->getType();
if ($library_type instanceof AttachableAssetLibraryRegistrationInterface) {
$attachable_libraries += $library_type->getAttachableAssetLibraries($external_library, $library_manager);
}
catch (\Exception $e) {
// Library-specific exceptions should not be allowed to kill the rest of
// the build process, but should be logged.
if ($e instanceof LibraryIdAccessorInterface || $e instanceof LibraryAccessorInterface) {
$libraries_with_errors[] = $external_library_id;
watchdog_exception('libraries', $e);
}
else {
// Re-throw exceptions that are not library-specific.
throw $e;
}
}
}
// If we had library specific errors also log an informative message to
// tell admins that detection will not be run again without a cache clear.
if ($libraries_with_errors) {
\Drupal::logger('libraries')->error('The following external libraries could not successfully be registered with Drupal core: @libs. See earlier log entries for more details. Once these issues are addressed please be sure to clear your Drupal library cache to ensure external library detection is run again.', ['@libs' => implode(',', $libraries_with_errors)]);
return $attachable_libraries;
Tobias Zimmermann
committed
* @param $name
* The machine name of a library to return the path for.
* @param $base_path
* Whether to prefix the resulting path with base_path().
*
* @return
Daniel Kudwien
committed
* The path to the specified library or FALSE if the library wasn't found.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
function libraries_get_path($name, $base_path = FALSE) {
Tobias Stoeckler
committed
$libraries = &drupal_static(__FUNCTION__);
if (!isset($libraries)) {
$libraries = libraries_get_libraries();
}
Daniel Kudwien
committed
$path = ($base_path ? base_path() : '');
if (!isset($libraries[$name])) {
Daniel Kudwien
committed
return FALSE;
Daniel Kudwien
committed
}
else {
$path .= $libraries[$name];
}
return $path;
}
/**
* Returns an array of library directories.
*
* Returns an array of library directories from the all-sites directory
* (i.e. sites/all/libraries/), the profiles directory, and site-specific
* directory (i.e. sites/somesite/libraries/). The returned array will be keyed
* by the library name. Site-specific libraries are prioritized over libraries
* in the default directories. That is, if a library with the same name appears
* in both the site-wide directory and site-specific directory, only the
* site-specific version will be listed.
*
* @return
* A list of library directories.
*
* @ingroup libraries
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
*/
function libraries_get_libraries() {
$searchdir = [];
Sascha Grossenbacher
committed
$config = DrupalKernel::findSitePath(\Drupal::request());
// @todo core/libraries
// Similar to 'modules' and 'themes' directories inside an installation
// profile, installation profiles may want to place libraries into a
// 'libraries' directory.
Andrii Podanenko
committed
if ($profile = \Drupal::installProfile()) {
IMMACULATE X
committed
$profile_path = \Drupal::service('extension.list.profile')->getPath($profile);
$searchdir[] = "$profile_path/libraries";
s_leu
committed
};
// Search sites/all/libraries for backwards-compatibility.
$searchdir[] = 'sites/all/libraries';
// Always search the root 'libraries' directory.
$searchdir[] = 'libraries';
// Also search sites/<domain>/*.
$searchdir[] = "$config/libraries";
// Retrieve list of directories.
$directories = [];
$nomask = ['CVS'];
foreach ($searchdir as $dir) {
if (is_dir($dir) && $handle = opendir($dir)) {
while (FALSE !== ($file = readdir($handle))) {
if (!in_array($file, $nomask) && $file[0] != '.') {
if (is_dir("$dir/$file")) {
$directories[$file] = "$dir/$file";
}
}
}
closedir($handle);
}
}
return $directories;
}
Tobias Stoeckler
committed
/**
* Looks for library info files.
*
* This function scans the following directories for info files:
* - libraries
* - profiles/$profilename/libraries
* - sites/all/libraries
* - sites/$sitename/libraries
* - any directories specified via hook_libraries_info_file_paths()
*
* @return
* An array of info files, keyed by library name. The values are the paths of
* the files.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Tobias Stoeckler
committed
*/
Tobias Stoeckler
committed
function libraries_scan_info_files() {
IMMACULATE X
committed
$profile = \Drupal::service('extension.list.profile')->getPath(\Drupal::installProfile());
Sascha Grossenbacher
committed
$config = DrupalKernel::findSitePath(\Drupal::request());
Tobias Stoeckler
committed
// Build a list of directories.
$directories = \Drupal::moduleHandler()->invokeAll('libraries_info_file_paths', $args = []);
$directories[] = "$profile/libraries";
Tobias Stoeckler
committed
$directories[] = 'sites/all/libraries';
$directories[] = 'libraries';
Tobias Stoeckler
committed
$directories[] = "$config/libraries";
Tobias Stoeckler
committed
// Scan for info files.
$files = [];
Tobias Stoeckler
committed
foreach ($directories as $dir) {
Tobias Stoeckler
committed
if (file_exists($dir)) {
$files = array_merge($files, \Drupal::service('file_system')->scanDirectory($dir, '@^[a-z0-9._-]+\.libraries\.info\.yml$@', [
Tobias Stoeckler
committed
'key' => 'name',
'recurse' => FALSE,
]));
Tobias Stoeckler
committed
}
Tobias Stoeckler
committed
}
foreach ($files as $filename => $file) {
Gordon Heydon
committed
$files[basename($filename, '.libraries.info')] = $file;
unset($files[$filename]);
Tobias Stoeckler
committed
}
return $files;
}
Daniel Kudwien
committed
/**
* Invokes library callbacks.
*
* @param $group
* A string containing the group of callbacks that is to be applied. Should be
* either 'info', 'pre-detect', 'post-detect', or 'load'.
Daniel Kudwien
committed
* @param $library
* An array of library information, passed by reference.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Daniel Kudwien
committed
*/
function libraries_invoke($group, &$library) {
foreach ($library['callbacks'][$group] as $callback) {
libraries_traverse_library($library, $callback);
}
}
/**
* Helper function to apply a callback to all parts of a library.
*
* Because library declarations can include variants and versions, and those
* version declarations can in turn include variants, modifying e.g. the 'files'
* property everywhere it is declared can be quite cumbersome, in which case
* this helper function is useful.
*
* @param $library
* An array of library information, passed by reference.
* @param $callback
* A string containing the callback to apply to all parts of a library.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Daniel Kudwien
committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
*/
function libraries_traverse_library(&$library, $callback) {
// Always apply the callback to the top-level library.
$callback($library, NULL, NULL);
// Apply the callback to versions.
if (isset($library['versions'])) {
foreach ($library['versions'] as $version_string => &$version) {
$callback($version, $version_string, NULL);
// Versions can include variants as well.
if (isset($version['variants'])) {
foreach ($version['variants'] as $version_variant_name => &$version_variant) {
$callback($version_variant, $version_string, $version_variant_name);
}
}
}
}
// Apply the callback to variants.
if (isset($library['variants'])) {
foreach ($library['variants'] as $variant_name => &$variant) {
$callback($variant, NULL, $variant_name);
}
}
}
/**
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
* Library info callback to make all 'files' properties consistent.
*
* This turns libraries' file information declared as e.g.
* @code
* $library['files']['js'] = array('example_1.js', 'example_2.js');
* @endcode
* into
* @code
* $library['files']['js'] = array(
* 'example_1.js' => array(),
* 'example_2.js' => array(),
* );
* @endcode
* It does the same for the 'integration files' property.
*
* @param $library
* An associative array of library information or a part of it, passed by
* reference.
* @param $version
* If the library information belongs to a specific version, the version
* string. NULL otherwise.
* @param $variant
* If the library information belongs to a specific variant, the variant name.
* NULL otherwise.
*
* @see libraries_info()
* @see libraries_invoke()
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
function libraries_prepare_files(&$library, $version = NULL, $variant = NULL) {
// Both the 'files' property and the 'integration files' property contain file
// declarations, and we want to make both consistent.
$file_types = [];
if (isset($library['files'])) {
$file_types[] = &$library['files'];
}
if (isset($library['integration files'])) {
// Integration files are additionally keyed by module.
foreach ($library['integration files'] as &$integration_files) {
$file_types[] = &$integration_files;
}
}
foreach ($file_types as &$files) {
// Go through all supported types of files.
foreach (['js', 'css', 'php'] as $type) {
if (isset($files[$type])) {
foreach ($files[$type] as $key => $value) {
// Unset numeric keys and turn the respective values into keys.
if (is_numeric($key)) {
$files[$type][$value] = [];
unset($files[$type][$key]);
}
}
}
}
}
}
/**
* Library post-detect callback to process and detect dependencies.
*
* It checks whether each of the dependencies of a library are installed and
* available in a compatible version.
*
* @param $library
* An associative array of library information or a part of it, passed by
* reference.
* @param $version
* If the library information belongs to a specific version, the version
* string. NULL otherwise.
* @param $variant
* If the library information belongs to a specific variant, the variant name.
* NULL otherwise.
*
* @see libraries_info()
* @see libraries_invoke()
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
*/
function libraries_detect_dependencies(&$library, $version = NULL, $variant = NULL) {
if (isset($library['dependencies'])) {
foreach ($library['dependencies'] as &$dependency_string) {
Andrii Podanenko
committed
$dependency = Dependency::createFromString($dependency_string);
$info = libraries_detect($dependency->getName());
Paulo Henrique Cota Starling
committed
if (!isset($info['installed']) || !$info['installed']) {
$library['installed'] = FALSE;
$library['error'] = 'missing dependency';
$library['error message'] = t('The %dependency library, which the %library library depends on, is not installed.', [
Paulo Henrique Cota Starling
committed
'%dependency' => $dependency->getName(),
'%library' => $library['name'],
]);
}
Andrii Podanenko
committed
elseif (!$dependency->isCompatible($info['version'])) {
$library['installed'] = FALSE;
$library['error'] = 'incompatible dependency';
$library['error message'] = t('The version %dependency_version of the %dependency library is not compatible with the %library library.', [
Andrii Podanenko
committed
'%dependency_version' => $info['version'],
'%dependency' => $info['name'],
'%library' => $library['name'],
]);
}
// Remove the version string from the dependency, so libraries_load() can
// load the libraries directly.
Paulo Henrique Cota Starling
committed
$dependency_string = $info['name'] ?? NULL;
}
}
}
Daniel Kudwien
committed
/**
* Returns information about registered libraries.
*
Tobias Zimmermann
committed
* The returned information is unprocessed; i.e., as registered by modules.
Daniel Kudwien
committed
*
* @param $name
* (optional) The machine name of a library to return registered information
Tobias Zimmermann
committed
* for. If omitted, information about all registered libraries is returned.
Daniel Kudwien
committed
*
Tobias Zimmermann
committed
* @return array|false
Daniel Kudwien
committed
* An associative array containing registered information for all libraries,
Tobias Zimmermann
committed
* the registered information for the library specified by $name, or FALSE if
* the library $name is not registered.
Daniel Kudwien
committed
*
* @see hook_libraries_info()
*
* @todo Re-introduce support for include file plugin system - either by copying
* Wysiwyg's code, or directly switching to CTools.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Daniel Kudwien
committed
*/
Tobias Zimmermann
committed
function &libraries_info($name = NULL) {
// This static cache is re-used by libraries_detect() to save memory.
Daniel Kudwien
committed
$libraries = &drupal_static(__FUNCTION__);
if (!isset($libraries)) {
$libraries = [];
Tobias Stoeckler
committed
// Gather information from hook_libraries_info().
Anushka Abeyrathna
committed
$module_handler = \Drupal::moduleHandler();
Edmund Dunn
committed
$hook = 'libraries_info';
$module_handler->invokeAllWith($hook, function (callable $hook, string $module) use ($module_handler, &$libraries) {
foreach ((array) $module_handler->invoke($module, 'libraries_info') as $machine_name => $properties) {
Daniel Kudwien
committed
$properties['module'] = $module;
$libraries[$machine_name] = $properties;
Daniel Kudwien
committed
}
Edmund Dunn
committed
});
Tobias Zimmermann
committed
// Gather information from hook_libraries_info() in enabled themes.
// @see drupal_alter()
global $theme, $base_theme_info;
if (isset($theme)) {
$theme_keys = [];
Tobias Zimmermann
committed
foreach ($base_theme_info as $base) {
$theme_keys[] = $base->name;
}
$theme_keys[] = $theme;
foreach ($theme_keys as $theme_key) {
$function = $theme_key . '_libraries_info';
Tobias Zimmermann
committed
if (function_exists($function)) {
foreach ($function() as $machine_name => $properties) {
$properties['theme'] = $theme_key;
$libraries[$machine_name] = $properties;
}
}
}
}
Tobias Stoeckler
committed
// Gather information from .info files.
Tobias Stoeckler
committed
// .info files override module definitions.
// In order to stop Drupal's extension and the Drupal.org packaging
// system from finding library info files we use the 'libraries.info.yml'
// file extension. Therefore, having a 'type' key, like info files of
// modules, themes, and profiles have, is superfluous.
// \Drupal\Core\Extension\InfoParser, however, enforces the existence of a
// 'type' key in info files. We therefore use Symfony's YAML parser
// directly.
// @todo Consider creating a dedicating InfoParser for library info files
// similar to \Drupal\Core\Extension\InfoParser.
foreach (libraries_scan_info_files() as $machine_name => $file) {
$properties = $parser->parse(file_get_contents($file->uri));
Tobias Stoeckler
committed
$properties['info file'] = $file->uri;
$libraries[$machine_name] = $properties;
Tobias Stoeckler
committed
}
// Provide defaults.
foreach ($libraries as $machine_name => &$properties) {
Tobias Zimmermann
committed
libraries_info_defaults($properties, $machine_name);
Tobias Stoeckler
committed
}
Daniel Kudwien
committed
// Allow modules to alter the registered libraries.
Anushka Abeyrathna
committed
$module_handler->alter('libraries_info', $libraries);
Daniel Kudwien
committed
// Invoke callbacks in the 'info' group.
Daniel Kudwien
committed
foreach ($libraries as &$properties) {
libraries_invoke('info', $properties);
Daniel Kudwien
committed
}
Daniel Kudwien
committed
}
if (isset($name)) {
Tobias Zimmermann
committed
if (!empty($libraries[$name])) {
return $libraries[$name];
}
else {
$false = FALSE;
return $false;
}
Daniel Kudwien
committed
}
return $libraries;
}
Tobias Zimmermann
committed
/**
* Applies default properties to a library definition.
*
* @library
* An array of library information, passed by reference.
* @name
* The machine name of the passed-in library.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Tobias Zimmermann
committed
*/
function libraries_info_defaults(&$library, $name) {
$library += [
Tobias Zimmermann
committed
'machine name' => $name,
'name' => $name,
'vendor url' => '',
'download url' => '',
'path' => '',
'library path' => NULL,
'version callback' => 'libraries_get_version',
'version arguments' => [],
'files' => [],
'dependencies' => [],
'variants' => [],
'versions' => [],
'integration files' => [],
'callbacks' => [],
];
$library['callbacks'] += [
'info' => [],
'pre-detect' => [],
'post-detect' => [],
'pre-load' => [],
'post-load' => [],
];
// Add our own callbacks before any others.
array_unshift($library['callbacks']['info'], 'libraries_prepare_files');
array_unshift($library['callbacks']['post-detect'], 'libraries_detect_dependencies');
Tobias Zimmermann
committed
return $library;
}
Daniel Kudwien
committed
/**
Tobias Zimmermann
committed
* Tries to detect a library and its installed version.
Daniel Kudwien
committed
*
Tobias Zimmermann
committed
* @param $name
* The machine name of a library to return registered information for.
*
Tobias Zimmermann
committed
* @return array|false
Tobias Zimmermann
committed
* An associative array containing registered information for the library
Tobias Zimmermann
committed
* specified by $name, or FALSE if the library $name is not registered.
* In addition to the keys returned by libraries_info(), the following keys
* are contained:
Tobias Zimmermann
committed
* - installed: A boolean indicating whether the library is installed. Note
* that not only the top-level library, but also each variant contains this
* key.
* - version: If the version could be detected, the full version string.
* - error: If an error occurred during library detection, one of the
* following error statuses: "not found", "not detected", "not supported".
* - error message: If an error occurred during library detection, a detailed
* error message.
Daniel Kudwien
committed
*
* @see libraries_info()
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Daniel Kudwien
committed
*/
Tobias Zimmermann
committed
function libraries_detect($name) {
Tobias Zimmermann
committed
// Re-use the statically cached value of libraries_info() to save memory.
$library = &libraries_info($name);
if ($library === FALSE) {
return $library;
}
// If 'installed' is set, library detection ran already.
if (isset($library['installed'])) {
return $library;
}
Daniel Kudwien
committed
$library['installed'] = FALSE;
// Check whether the library exists.
if (!isset($library['library path'])) {
$library['library path'] = libraries_get_path($library['machine name']);
Daniel Kudwien
committed
}
Daniel Kudwien
committed
if ($library['library path'] === FALSE || !file_exists($library['library path'])) {
$library['error'] = 'not found';
$library['error message'] = t('The %library library could not be found.', [
Tobias Stoeckler
committed
'%library' => $library['name'],
]);
Tobias Zimmermann
committed
return $library;
Daniel Kudwien
committed
}
// Invoke callbacks in the 'pre-detect' group.
libraries_invoke('pre-detect', $library);
// Detect library version, if not hardcoded.
if (!isset($library['version'])) {
// We support both a single parameter, which is an associative array, and an
// indexed array of multiple parameters.
if (isset($library['version arguments'][0])) {
// Add the library as the first argument.
$library['version'] = call_user_func_array($library['version callback'], array_merge([$library], $library['version arguments']));
}
else {
$library['version'] = $library['version callback']($library, $library['version arguments']);
}
if (empty($library['version'])) {
$library['error'] = 'not detected';
$library['error message'] = t('The version of the %library library could not be detected.', [
Tobias Stoeckler
committed
'%library' => $library['name'],
]);
Tobias Zimmermann
committed
return $library;
}
Daniel Kudwien
committed
}
// Determine to which supported version the installed version maps.
if (!empty($library['versions'])) {
ksort($library['versions']);
$version = 0;
foreach ($library['versions'] as $supported_version => $version_properties) {
Tobias Stoeckler
committed
if (version_compare($library['version'], $supported_version, '>=')) {
Daniel Kudwien
committed
$version = $supported_version;
}
}
if (!$version) {
$library['error'] = 'not supported';
$library['error message'] = t('The installed version %version of the %library library is not supported.', [
Tobias Stoeckler
committed
'%version' => $library['version'],
Tobias Stoeckler
committed
'%library' => $library['name'],
]);
Tobias Zimmermann
committed
return $library;
Daniel Kudwien
committed
}
// Apply version specific definitions and overrides.
$library = array_merge($library, $library['versions'][$version]);
unset($library['versions']);
}
Tobias Stoeckler
committed
// Check each variant if it is installed.
if (!empty($library['variants'])) {
foreach ($library['variants'] as $variant_name => &$variant) {
Tobias Stoeckler
committed
// If no variant callback has been set, assume the variant to be
// installed.
Tobias Stoeckler
committed
if (!isset($variant['variant callback'])) {
$variant['installed'] = TRUE;
}
else {
Tobias Stoeckler
committed
// We support both a single parameter, which is an associative array,
// and an indexed array of multiple parameters.
if (isset($variant['variant arguments'][0])) {
// Add the library as the first argument, and the variant name as the
// second.
$variant['installed'] = call_user_func_array($variant['variant callback'], array_merge([$library, $variant_name], $variant['variant arguments']));
Tobias Stoeckler
committed
}
else {
$variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']);
Tobias Stoeckler
committed
}
Tobias Stoeckler
committed
if (!$variant['installed']) {
$variant['error'] = 'not found';
$variant['error message'] = t('The %variant variant of the %library library could not be found.', [
'%variant' => $variant_name,
Tobias Stoeckler
committed
'%library' => $library['name'],
]);
Tobias Stoeckler
committed
}
}
}
}
Daniel Kudwien
committed
// If we end up here, the library should be usable.
$library['installed'] = TRUE;
Daniel Kudwien
committed
// Invoke callbacks in the 'post-detect' group.
libraries_invoke('post-detect', $library);
Daniel Kudwien
committed
Tobias Stoeckler
committed
}
/**
* Loads a library.
*
Tobias Stoeckler
committed
* @param $name
Tobias Stoeckler
committed
* The name of the library to load.
* @param $variant
Daniel Kudwien
committed
* The name of the variant to load. Note that only one variant of a library
* can be loaded within a single request. The variant that has been passed
* first is used; different variant names in subsequent calls are ignored.
*
* @return
* An associative array of the library information as returned from
* libraries_info(). The top-level properties contain the effective definition
* of the library (variant) that has been loaded. Additionally:
* - installed: Whether the library is installed, as determined by
* libraries_detect_library().
* - loaded: Either the amount of library files that have been loaded, or
* FALSE if the library could not be loaded.
* See hook_libraries_info() for more information.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Tobias Stoeckler
committed
*/
Tobias Stoeckler
committed
function libraries_load($name, $variant = NULL) {
$loaded = &drupal_static(__FUNCTION__, []);
Tobias Stoeckler
committed
Daniel Kudwien
committed
if (!isset($loaded[$name])) {
$library = \Drupal::cache('libraries')->get($name);
if ($library) {
$library = $library->data;
}
else {
Tobias Zimmermann
committed
$library = libraries_detect($name);
\Drupal::cache('libraries')->set($name, $library);
Daniel Kudwien
committed
// If a variant was specified, override the top-level properties with the
// variant properties.
if (isset($variant)) {
// Ensure that the $variant key exists, and if it does not, set its
// 'installed' property to FALSE by default. This will prevent the loading
// of the library files below.
$library['variants'] += [$variant => ['installed' => FALSE]];
Daniel Kudwien
committed
$library = array_merge($library, $library['variants'][$variant]);
}
// Regardless of whether a specific variant was requested or not, there can
// only be one variant of a library within a single request.
unset($library['variants']);
Daniel Kudwien
committed
// If the library (variant) is installed, load it.
$library['loaded'] = FALSE;
if ($library['installed']) {
// Load library dependencies.
if (isset($library['dependencies'])) {
foreach ($library['dependencies'] as $dependency) {
libraries_load($dependency);
}
}
// Invoke callbacks in the 'pre-load' group.
libraries_invoke('pre-load', $library);
Daniel Kudwien
committed
// Load all the files associated with the library.
Daniel Kudwien
committed
$library['loaded'] = libraries_load_files($library);
// Invoke callbacks in the 'post-load' group.
libraries_invoke('post-load', $library);
Tobias Stoeckler
committed
}
Daniel Kudwien
committed
$loaded[$name] = $library;
}
Tobias Stoeckler
committed
Daniel Kudwien
committed
return $loaded[$name];
Tobias Stoeckler
committed
}
/**
* Loads a library's files.
*
* @param $library
Tobias Stoeckler
committed
* An array of library information as returned by libraries_info().
*
* @return
* The number of loaded files.
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Tobias Stoeckler
committed
*/
Tobias Stoeckler
committed
function libraries_load_files($library) {
Tobias Stoeckler
committed
Tobias Stoeckler
committed
// Construct the full path to the library for later use.
$path = $library['library path'];
$path = ($library['path'] !== '' ? $path . '/' . $library['path'] : $path);
// Count the number of loaded files for the return value.
$count = 0;
Tobias Stoeckler
committed
// Load both the JavaScript and the CSS files.
// The parameters for drupal_add_js() and drupal_add_css() require special
// handling.
// @see drupal_process_attached()
foreach (['js', 'css'] as $type) {
Ryan Jacobs
committed
// Given the removal of core functions like _drupal_add_js and
// _drupal_add_css the logic below cannot safely be run anymore.
// @see https://www.drupal.org/node/2702563
break;
Tobias Stoeckler
committed
if (!empty($library['files'][$type])) {
foreach ($library['files'][$type] as $data => $options) {
// If the value is not an array, it's a filename and passed as first
// (and only) argument.
if (!is_array($options)) {
Tobias Zimmermann
committed
$data = $options;
$options = [];
Tobias Stoeckler
committed
}
// In some cases, the first parameter ($data) is an array. Arrays can't
// be passed as keys in PHP, so we have to get $data from the value
// array.
Tobias Stoeckler
committed
if (is_numeric($data)) {
$data = $options['data'];
unset($options['data']);
}
Tobias Zimmermann
committed
// Prepend the library path to the file name.
$data = "$path/$data";
Tobias Stoeckler
committed
// Apply the default group if the group isn't explicitly given.
if (!isset($options['group'])) {
Gordon Heydon
committed
$options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_AGGREGATE_DEFAULT;
Tobias Stoeckler
committed
}
if ($type === 'js') {
$options['version'] = -1;
}
Tobias Zimmermann
committed
// @todo Avoid the usage of _drupal_add_js() and _drupal_add_css()
call_user_func('_drupal_add_' . $type, $data, $options);
Tobias Stoeckler
committed
$count++;
Tobias Stoeckler
committed
}
}
}
// Load PHP files.
if (!empty($library['files']['php'])) {
foreach ($library['files']['php'] as $file => $array) {
Tobias Stoeckler
committed
$file_path = DRUPAL_ROOT . '/' . $path . '/' . $file;
if (file_exists($file_path)) {
require_once $file_path;
Tobias Stoeckler
committed
$count++;
Tobias Stoeckler
committed
}
}
}
Tobias Stoeckler
committed
// Load integration files.
if (!empty($library['integration files'])) {
foreach ($library['integration files'] as $module => $files) {
libraries_load_files([
'files' => $files,
'path' => '',
IMMACULATE X
committed
'library path' => \Drupal::service('extension.list.module')->getPath($module),
]);
}
}
Tobias Stoeckler
committed
return $count;
Tobias Stoeckler
committed
}
/**
* Gets the version information from an arbitrary library.
*
* @param $library
* An associative array containing all information about the library.
* @param $options
* An associative array containing with the following keys:
* - file: The filename to parse for the version, relative to the library
* path. For example: 'docs/changelog.txt'.
* - pattern: A string containing a regular expression (PCRE) to match the
Tobias Zimmermann
committed
* library version. For example: '@version\s+([0-9a-zA-Z\.-]+)@'. Note that
* the returned version is not the match of the entire pattern (i.e.
* '@version 1.2.3' in the above example) but the match of the first
* sub-pattern (i.e. '1.2.3' in the above example).
Tobias Stoeckler
committed
* - lines: (optional) The maximum number of lines to search the pattern in.
* Defaults to 20.
* - cols: (optional) The maximum number of characters per line to take into
* account. Defaults to 200. In case of minified or compressed files, this
* prevents reading the entire file into memory.
*
* @return
* A string containing the version of the library.
*
* @see libraries_get_path()
Tobias Zimmermann
committed
*
Ryan Jacobs
committed
* @deprecated Will be removed before a stable Drupal 8 release. Please use the
* new library load and managment concepts described at:
* https://www.drupal.org/node/2170763
Tobias Stoeckler
committed
*/
function libraries_get_version($library, $options) {
// Provide defaults.
$options += [
Tobias Stoeckler
committed
'file' => '',
'pattern' => '',
'lines' => 20,
'cols' => 200,
];
Tobias Stoeckler
committed
$file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $options['file'];
if (empty($options['file']) || !file_exists($file)) {
return;
}
$file = fopen($file, 'r');
while ($options['lines'] && $line = fgets($file, $options['cols'])) {
if (preg_match($options['pattern'], $line, $version)) {
fclose($file);
return $version[1];
}
$options['lines']--;
Daniel Kudwien
committed
}
Tobias Stoeckler
committed
fclose($file);