Further modules included.
[yaffs-website] / web / modules / contrib / libraries / libraries.module
1 <?php
2
3 /**
4  * @file
5  * External library handling for Drupal modules.
6  */
7
8 use Drupal\Core\DrupalKernel;
9 use Drupal\Core\Extension\ModuleHandler;
10 use Drupal\libraries\ExternalLibrary\Asset\AttachableAssetLibraryRegistrationInterface;
11 use Drupal\libraries\ExternalLibrary\Utility\LibraryAccessorInterface;
12 use Drupal\libraries\ExternalLibrary\Utility\LibraryIdAccessorInterface;
13 use Symfony\Component\Yaml\Parser;
14
15 /**
16  * Implements hook_library_info_build().
17  *
18  * Register external asset libraries with Drupal core's library APIs.
19  */
20 function libraries_library_info_build() {
21   /** @var \Drupal\libraries\ExternalLibrary\LibraryManagerInterface $library_manager */
22   $library_manager = \Drupal::service('libraries.manager');
23   $attachable_libraries = [];
24   $libraries_with_errors = [];
25   foreach ($library_manager->getRequiredLibraryIds() as $external_library_id) {
26     try {
27       $external_library = $library_manager->getLibrary($external_library_id);
28       $library_type = $external_library->getType();
29       if ($library_type instanceof AttachableAssetLibraryRegistrationInterface) {
30         $attachable_libraries += $library_type->getAttachableAssetLibraries($external_library, $library_manager);
31       }
32     }
33     catch (\Exception $e) {
34       // Library-specific exceptions should not be allowed to kill the rest of
35       // the build process, but should be logged.
36       if ($e instanceof LibraryIdAccessorInterface || $e instanceof LibraryAccessorInterface) {
37         $libraries_with_errors[] = $external_library_id;
38         watchdog_exception('libraries', $e);
39       }
40       else {
41         // Re-throw exceptions that are not library-specific.
42         throw $e;
43       }
44     }
45   }
46   // If we had library specific errors also log an informative message to
47   // tell admins that detection will not be run again without a cache clear.
48   if ($libraries_with_errors) {
49     \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)]);
50   }
51   return $attachable_libraries;
52 }
53
54 /**
55  * Gets the path of a library.
56  *
57  * @param $name
58  *   The machine name of a library to return the path for.
59  * @param $base_path
60  *   Whether to prefix the resulting path with base_path().
61  *
62  * @return
63  *   The path to the specified library or FALSE if the library wasn't found.
64  *
65  * @ingroup libraries
66  *
67  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
68  * new library load and managment concepts described at:
69  * https://www.drupal.org/node/2170763
70  */
71 function libraries_get_path($name, $base_path = FALSE) {
72   $libraries = &drupal_static(__FUNCTION__);
73
74   if (!isset($libraries)) {
75     $libraries = libraries_get_libraries();
76   }
77
78   $path = ($base_path ? base_path() : '');
79   if (!isset($libraries[$name])) {
80     return FALSE;
81   }
82   else {
83     $path .= $libraries[$name];
84   }
85
86   return $path;
87 }
88
89 /**
90  * Returns an array of library directories.
91  *
92  * Returns an array of library directories from the all-sites directory
93  * (i.e. sites/all/libraries/), the profiles directory, and site-specific
94  * directory (i.e. sites/somesite/libraries/). The returned array will be keyed
95  * by the library name. Site-specific libraries are prioritized over libraries
96  * in the default directories. That is, if a library with the same name appears
97  * in both the site-wide directory and site-specific directory, only the
98  * site-specific version will be listed.
99  *
100  * @return
101  *   A list of library directories.
102  *
103  * @ingroup libraries
104  *
105  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
106  * new library load and managment concepts described at:
107  * https://www.drupal.org/node/2170763
108  */
109 function libraries_get_libraries() {
110   $searchdir = array();
111   $config = DrupalKernel::findSitePath(\Drupal::request());
112
113   // @todo core/libraries
114
115   // Similar to 'modules' and 'themes' directories inside an installation
116   // profile, installation profiles may want to place libraries into a
117   // 'libraries' directory.
118   if ($profile = drupal_get_profile()) {
119     $profile_path = drupal_get_path('profile', $profile);
120     $searchdir[] = "$profile_path/libraries";
121   };
122
123   // Search sites/all/libraries for backwards-compatibility.
124   $searchdir[] = 'sites/all/libraries';
125
126   // Always search the root 'libraries' directory.
127   $searchdir[] = 'libraries';
128
129   // Also search sites/<domain>/*.
130   $searchdir[] = "$config/libraries";
131
132   // Retrieve list of directories.
133   $directories = array();
134   $nomask = array('CVS');
135   foreach ($searchdir as $dir) {
136     if (is_dir($dir) && $handle = opendir($dir)) {
137       while (FALSE !== ($file = readdir($handle))) {
138         if (!in_array($file, $nomask) && $file[0] != '.') {
139           if (is_dir("$dir/$file")) {
140             $directories[$file] = "$dir/$file";
141           }
142         }
143       }
144       closedir($handle);
145     }
146   }
147
148   return $directories;
149 }
150
151 /**
152  * Looks for library info files.
153  *
154  * This function scans the following directories for info files:
155  * - libraries
156  * - profiles/$profilename/libraries
157  * - sites/all/libraries
158  * - sites/$sitename/libraries
159  * - any directories specified via hook_libraries_info_file_paths()
160  *
161  * @return
162  *   An array of info files, keyed by library name. The values are the paths of
163  *   the files.
164  *
165  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
166  * new library load and managment concepts described at:
167  * https://www.drupal.org/node/2170763
168  */
169 function libraries_scan_info_files() {
170   $profile = drupal_get_path('profile', drupal_get_profile());
171   $config = DrupalKernel::findSitePath(\Drupal::request());
172
173   // Build a list of directories.
174   $directories = \Drupal::moduleHandler()->invokeAll('libraries_info_file_paths', $args = array());
175   $directories[] = "$profile/libraries";
176   $directories[] = 'sites/all/libraries';
177   $directories[] = 'libraries';
178   $directories[] = "$config/libraries";
179
180   // Scan for info files.
181   $files = array();
182   foreach ($directories as $dir) {
183     if (file_exists($dir)) {
184       $files = array_merge($files, file_scan_directory($dir, '@^[a-z0-9._-]+\.libraries\.info\.yml$@', array(
185         'key' => 'name',
186         'recurse' => FALSE,
187       )));
188     }
189   }
190
191   foreach ($files as $filename => $file) {
192     $files[basename($filename, '.libraries.info')] = $file;
193     unset($files[$filename]);
194   }
195
196   return $files;
197 }
198
199 /**
200  * Invokes library callbacks.
201  *
202  * @param $group
203  *   A string containing the group of callbacks that is to be applied. Should be
204  *   either 'info', 'pre-detect', 'post-detect', or 'load'.
205  * @param $library
206  *   An array of library information, passed by reference.
207  *
208  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
209  * new library load and managment concepts described at:
210  * https://www.drupal.org/node/2170763
211  */
212 function libraries_invoke($group, &$library) {
213   foreach ($library['callbacks'][$group] as $callback) {
214     libraries_traverse_library($library, $callback);
215   }
216 }
217
218 /**
219  * Helper function to apply a callback to all parts of a library.
220  *
221  * Because library declarations can include variants and versions, and those
222  * version declarations can in turn include variants, modifying e.g. the 'files'
223  * property everywhere it is declared can be quite cumbersome, in which case
224  * this helper function is useful.
225  *
226  * @param $library
227  *   An array of library information, passed by reference.
228  * @param $callback
229  *   A string containing the callback to apply to all parts of a library.
230  *
231  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
232  * new library load and managment concepts described at:
233  * https://www.drupal.org/node/2170763
234  */
235 function libraries_traverse_library(&$library, $callback) {
236   // Always apply the callback to the top-level library.
237   $callback($library, NULL, NULL);
238
239   // Apply the callback to versions.
240   if (isset($library['versions'])) {
241     foreach ($library['versions'] as $version_string => &$version) {
242       $callback($version, $version_string, NULL);
243       // Versions can include variants as well.
244       if (isset($version['variants'])) {
245         foreach ($version['variants'] as $version_variant_name => &$version_variant) {
246           $callback($version_variant, $version_string, $version_variant_name);
247         }
248       }
249     }
250   }
251
252   // Apply the callback to variants.
253   if (isset($library['variants'])) {
254     foreach ($library['variants'] as $variant_name => &$variant) {
255       $callback($variant, NULL, $variant_name);
256     }
257   }
258 }
259
260 /**
261  * Library info callback to make all 'files' properties consistent.
262  *
263  * This turns libraries' file information declared as e.g.
264  * @code
265  * $library['files']['js'] = array('example_1.js', 'example_2.js');
266  * @endcode
267  * into
268  * @code
269  * $library['files']['js'] = array(
270  *   'example_1.js' => array(),
271  *   'example_2.js' => array(),
272  * );
273  * @endcode
274  * It does the same for the 'integration files' property.
275  *
276  * @param $library
277  *   An associative array of library information or a part of it, passed by
278  *   reference.
279  * @param $version
280  *   If the library information belongs to a specific version, the version
281  *   string. NULL otherwise.
282  * @param $variant
283  *   If the library information belongs to a specific variant, the variant name.
284  *   NULL otherwise.
285  *
286  * @see libraries_info()
287  * @see libraries_invoke()
288  *
289  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
290  * new library load and managment concepts described at:
291  * https://www.drupal.org/node/2170763
292  */
293 function libraries_prepare_files(&$library, $version = NULL, $variant = NULL) {
294   // Both the 'files' property and the 'integration files' property contain file
295   // declarations, and we want to make both consistent.
296   $file_types = array();
297   if (isset($library['files'])) {
298     $file_types[] = &$library['files'];
299   }
300   if (isset($library['integration files'])) {
301     // Integration files are additionally keyed by module.
302     foreach ($library['integration files'] as &$integration_files) {
303       $file_types[] = &$integration_files;
304     }
305   }
306   foreach ($file_types as &$files) {
307     // Go through all supported types of files.
308     foreach (array('js', 'css', 'php') as $type) {
309       if (isset($files[$type])) {
310         foreach ($files[$type] as $key => $value) {
311           // Unset numeric keys and turn the respective values into keys.
312           if (is_numeric($key)) {
313             $files[$type][$value] = array();
314             unset($files[$type][$key]);
315           }
316         }
317       }
318     }
319   }
320 }
321
322 /**
323  * Library post-detect callback to process and detect dependencies.
324  *
325  * It checks whether each of the dependencies of a library are installed and
326  * available in a compatible version.
327  *
328  * @param $library
329  *   An associative array of library information or a part of it, passed by
330  *   reference.
331  * @param $version
332  *   If the library information belongs to a specific version, the version
333  *   string. NULL otherwise.
334  * @param $variant
335  *   If the library information belongs to a specific variant, the variant name.
336  *   NULL otherwise.
337  *
338  * @see libraries_info()
339  * @see libraries_invoke()
340  *
341  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
342  * new library load and managment concepts described at:
343  * https://www.drupal.org/node/2170763
344  */
345 function libraries_detect_dependencies(&$library, $version = NULL, $variant = NULL) {
346   if (isset($library['dependencies'])) {
347     foreach ($library['dependencies'] as &$dependency_string) {
348       $dependency_info = ModuleHandler::parseDependency($dependency_string);
349       $dependency = libraries_detect($dependency_info['name']);
350       if (!$dependency['installed']) {
351         $library['installed'] = FALSE;
352         $library['error'] = 'missing dependency';
353         $library['error message'] = t('The %dependency library, which the %library library depends on, is not installed.', array(
354           '%dependency' => $dependency['name'],
355           '%library' => $library['name'],
356         ));
357       }
358       elseif (drupal_check_incompatibility($dependency_info, $dependency['version'])) {
359         $library['installed'] = FALSE;
360         $library['error'] = 'incompatible dependency';
361         $library['error message'] = t('The version %dependency_version of the %dependency library is not compatible with the %library library.', array(
362           '%dependency_version' => $dependency['version'],
363           '%dependency' => $dependency['name'],
364           '%library' => $library['name'],
365         ));
366       }
367
368       // Remove the version string from the dependency, so libraries_load() can
369       // load the libraries directly.
370       $dependency_string = $dependency_info['name'];
371     }
372   }
373 }
374
375 /**
376  * Returns information about registered libraries.
377  *
378  * The returned information is unprocessed; i.e., as registered by modules.
379  *
380  * @param $name
381  *   (optional) The machine name of a library to return registered information
382  *   for. If omitted, information about all registered libraries is returned.
383  *
384  * @return array|false
385  *   An associative array containing registered information for all libraries,
386  *   the registered information for the library specified by $name, or FALSE if
387  *   the library $name is not registered.
388  *
389  * @see hook_libraries_info()
390  *
391  * @todo Re-introduce support for include file plugin system - either by copying
392  *   Wysiwyg's code, or directly switching to CTools.
393  *
394  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
395  * new library load and managment concepts described at:
396  * https://www.drupal.org/node/2170763
397  */
398 function &libraries_info($name = NULL) {
399   // This static cache is re-used by libraries_detect() to save memory.
400   $libraries = &drupal_static(__FUNCTION__);
401
402   if (!isset($libraries)) {
403     $libraries = array();
404     // Gather information from hook_libraries_info().
405     $module_handler = \Drupal::moduleHandler();
406     foreach ($module_handler->getImplementations('libraries_info') as $module) {
407       foreach ($module_handler->invoke($module, 'libraries_info') as $machine_name => $properties) {
408         $properties['module'] = $module;
409         $libraries[$machine_name] = $properties;
410       }
411     }
412     // Gather information from hook_libraries_info() in enabled themes.
413     // @see drupal_alter()
414     global $theme, $base_theme_info;
415     if (isset($theme)) {
416       $theme_keys = array();
417       foreach ($base_theme_info as $base) {
418         $theme_keys[] = $base->name;
419       }
420       $theme_keys[] = $theme;
421       foreach ($theme_keys as $theme_key) {
422         $function = $theme_key . '_' . 'libraries_info';
423         if (function_exists($function)) {
424           foreach ($function() as $machine_name => $properties) {
425             $properties['theme'] = $theme_key;
426             $libraries[$machine_name] = $properties;
427           }
428         }
429       }
430     }
431
432     // Gather information from .info files.
433     // .info files override module definitions.
434     // In order to stop Drupal's extension and the Drupal.org packaging
435     // system from finding library info files we use the 'libraries.info.yml'
436     // file extension. Therefore, having a 'type' key, like info files of
437     // modules, themes, and profiles have, is superfluous.
438     // \Drupal\Core\Extension\InfoParser, however, enforces the existence of a
439     // 'type' key in info files. We therefore use Symfony's YAML parser
440     // directly.
441     // @todo Consider creating a dedicating InfoParser for library info files
442     //   similar to \Drupal\Core\Extension\InfoParser
443     $parser = new Parser();
444     foreach (libraries_scan_info_files() as $machine_name => $file) {
445       $properties = $parser->parse(file_get_contents($file->uri));
446       $properties['info file'] = $file->uri;
447       $libraries[$machine_name] = $properties;
448     }
449
450     // Provide defaults.
451     foreach ($libraries as $machine_name => &$properties) {
452       libraries_info_defaults($properties, $machine_name);
453     }
454
455     // Allow modules to alter the registered libraries.
456     $module_handler->alter('libraries_info', $libraries);
457
458     // Invoke callbacks in the 'info' group.
459     foreach ($libraries as &$properties) {
460       libraries_invoke('info', $properties);
461     }
462   }
463
464   if (isset($name)) {
465     if (!empty($libraries[$name])) {
466       return $libraries[$name];
467     }
468     else {
469       $false = FALSE;
470       return $false;
471     }
472   }
473   return $libraries;
474 }
475
476 /**
477  * Applies default properties to a library definition.
478  *
479  * @library
480  *   An array of library information, passed by reference.
481  * @name
482  *   The machine name of the passed-in library.
483  *
484  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
485  * new library load and managment concepts described at:
486  * https://www.drupal.org/node/2170763
487  */
488 function libraries_info_defaults(&$library, $name) {
489   $library += array(
490     'machine name' => $name,
491     'name' => $name,
492     'vendor url' => '',
493     'download url' => '',
494     'path' => '',
495     'library path' => NULL,
496     'version callback' => 'libraries_get_version',
497     'version arguments' => array(),
498     'files' => array(),
499     'dependencies' => array(),
500     'variants' => array(),
501     'versions' => array(),
502     'integration files' => array(),
503     'callbacks' => array(),
504   );
505   $library['callbacks'] += array(
506     'info' => array(),
507     'pre-detect' => array(),
508     'post-detect' => array(),
509     'pre-load' => array(),
510     'post-load' => array(),
511   );
512
513   // Add our own callbacks before any others.
514   array_unshift($library['callbacks']['info'], 'libraries_prepare_files');
515   array_unshift($library['callbacks']['post-detect'], 'libraries_detect_dependencies');
516
517   return $library;
518 }
519
520 /**
521  * Tries to detect a library and its installed version.
522  *
523  * @param $name
524  *   The machine name of a library to return registered information for.
525  *
526  * @return array|false
527  *   An associative array containing registered information for the library
528  *   specified by $name, or FALSE if the library $name is not registered.
529  *   In addition to the keys returned by libraries_info(), the following keys
530  *   are contained:
531  *   - installed: A boolean indicating whether the library is installed. Note
532  *     that not only the top-level library, but also each variant contains this
533  *     key.
534  *   - version: If the version could be detected, the full version string.
535  *   - error: If an error occurred during library detection, one of the
536  *     following error statuses: "not found", "not detected", "not supported".
537  *   - error message: If an error occurred during library detection, a detailed
538  *     error message.
539  *
540  * @see libraries_info()
541  *
542  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
543  * new library load and managment concepts described at:
544  * https://www.drupal.org/node/2170763
545  */
546 function libraries_detect($name) {
547   // Re-use the statically cached value of libraries_info() to save memory.
548   $library = &libraries_info($name);
549
550   if ($library === FALSE) {
551     return $library;
552   }
553   // If 'installed' is set, library detection ran already.
554   if (isset($library['installed'])) {
555     return $library;
556   }
557
558   $library['installed'] = FALSE;
559
560   // Check whether the library exists.
561   if (!isset($library['library path'])) {
562     $library['library path'] = libraries_get_path($library['machine name']);
563   }
564   if ($library['library path'] === FALSE || !file_exists($library['library path'])) {
565     $library['error'] = 'not found';
566     $library['error message'] = t('The %library library could not be found.', array(
567       '%library' => $library['name'],
568     ));
569     return $library;
570   }
571
572   // Invoke callbacks in the 'pre-detect' group.
573   libraries_invoke('pre-detect', $library);
574
575   // Detect library version, if not hardcoded.
576   if (!isset($library['version'])) {
577     // We support both a single parameter, which is an associative array, and an
578     // indexed array of multiple parameters.
579     if (isset($library['version arguments'][0])) {
580       // Add the library as the first argument.
581       $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments']));
582     }
583     else {
584       $library['version'] = $library['version callback']($library, $library['version arguments']);
585     }
586     if (empty($library['version'])) {
587       $library['error'] = 'not detected';
588       $library['error message'] = t('The version of the %library library could not be detected.', array(
589         '%library' => $library['name'],
590       ));
591       return $library;
592     }
593   }
594
595   // Determine to which supported version the installed version maps.
596   if (!empty($library['versions'])) {
597     ksort($library['versions']);
598     $version = 0;
599     foreach ($library['versions'] as $supported_version => $version_properties) {
600       if (version_compare($library['version'], $supported_version, '>=')) {
601         $version = $supported_version;
602       }
603     }
604     if (!$version) {
605       $library['error'] = 'not supported';
606       $library['error message'] = t('The installed version %version of the %library library is not supported.', array(
607         '%version' => $library['version'],
608         '%library' => $library['name'],
609       ));
610       return $library;
611     }
612
613     // Apply version specific definitions and overrides.
614     $library = array_merge($library, $library['versions'][$version]);
615     unset($library['versions']);
616   }
617
618   // Check each variant if it is installed.
619   if (!empty($library['variants'])) {
620     foreach ($library['variants'] as $variant_name => &$variant) {
621       // If no variant callback has been set, assume the variant to be
622       // installed.
623       if (!isset($variant['variant callback'])) {
624         $variant['installed'] = TRUE;
625       }
626       else {
627         // We support both a single parameter, which is an associative array,
628         // and an indexed array of multiple parameters.
629         if (isset($variant['variant arguments'][0])) {
630           // Add the library as the first argument, and the variant name as the second.
631           $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $variant_name), $variant['variant arguments']));
632         }
633         else {
634           $variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']);
635         }
636         if (!$variant['installed']) {
637           $variant['error'] = 'not found';
638           $variant['error message'] = t('The %variant variant of the %library library could not be found.', array(
639             '%variant' => $variant_name,
640             '%library' => $library['name'],
641           ));
642         }
643       }
644     }
645   }
646
647   // If we end up here, the library should be usable.
648   $library['installed'] = TRUE;
649
650   // Invoke callbacks in the 'post-detect' group.
651   libraries_invoke('post-detect', $library);
652
653   return $library;
654 }
655
656 /**
657  * Loads a library.
658  *
659  * @param $name
660  *   The name of the library to load.
661  * @param $variant
662  *   The name of the variant to load. Note that only one variant of a library
663  *   can be loaded within a single request. The variant that has been passed
664  *   first is used; different variant names in subsequent calls are ignored.
665  *
666  * @return
667  *   An associative array of the library information as returned from
668  *   libraries_info(). The top-level properties contain the effective definition
669  *   of the library (variant) that has been loaded. Additionally:
670  *   - installed: Whether the library is installed, as determined by
671  *     libraries_detect_library().
672  *   - loaded: Either the amount of library files that have been loaded, or
673  *     FALSE if the library could not be loaded.
674  *   See hook_libraries_info() for more information.
675  *
676  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
677  * new library load and managment concepts described at:
678  * https://www.drupal.org/node/2170763
679  */
680 function libraries_load($name, $variant = NULL) {
681   $loaded = &drupal_static(__FUNCTION__, array());
682
683   if (!isset($loaded[$name])) {
684     $library = \Drupal::cache('libraries')->get($name);
685     if ($library) {
686       $library = $library->data;
687     }
688     else {
689       $library = libraries_detect($name);
690       \Drupal::cache('libraries')->set($name, $library);
691     }
692     // If a variant was specified, override the top-level properties with the
693     // variant properties.
694     if (isset($variant)) {
695       // Ensure that the $variant key exists, and if it does not, set its
696       // 'installed' property to FALSE by default. This will prevent the loading
697       // of the library files below.
698       $library['variants'] += array($variant => array('installed' => FALSE));
699       $library = array_merge($library, $library['variants'][$variant]);
700     }
701     // Regardless of whether a specific variant was requested or not, there can
702     // only be one variant of a library within a single request.
703     unset($library['variants']);
704
705     // If the library (variant) is installed, load it.
706     $library['loaded'] = FALSE;
707     if ($library['installed']) {
708       // Load library dependencies.
709       if (isset($library['dependencies'])) {
710         foreach ($library['dependencies'] as $dependency) {
711           libraries_load($dependency);
712         }
713       }
714
715       // Invoke callbacks in the 'pre-load' group.
716       libraries_invoke('pre-load', $library);
717
718       // Load all the files associated with the library.
719       $library['loaded'] = libraries_load_files($library);
720
721       // Invoke callbacks in the 'post-load' group.
722       libraries_invoke('post-load', $library);
723     }
724     $loaded[$name] = $library;
725   }
726
727   return $loaded[$name];
728 }
729
730 /**
731  * Loads a library's files.
732  *
733  * @param $library
734  *   An array of library information as returned by libraries_info().
735  *
736  * @return
737  *   The number of loaded files.
738  *
739  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
740  * new library load and managment concepts described at:
741  * https://www.drupal.org/node/2170763
742  */
743 function libraries_load_files($library) {
744
745   // Construct the full path to the library for later use.
746   $path = $library['library path'];
747   $path = ($library['path'] !== '' ? $path . '/' . $library['path'] : $path);
748
749   // Count the number of loaded files for the return value.
750   $count = 0;
751
752   // Load both the JavaScript and the CSS files.
753   // The parameters for drupal_add_js() and drupal_add_css() require special
754   // handling.
755   // @see drupal_process_attached()
756   foreach (array('js', 'css') as $type) {
757     // Given the removal of core functions like _drupal_add_js and
758     // _drupal_add_css the logic below cannot safely be run anymore.
759     // @see https://www.drupal.org/node/2702563
760     break;
761     if (!empty($library['files'][$type])) {
762       foreach ($library['files'][$type] as $data => $options) {
763         // If the value is not an array, it's a filename and passed as first
764         // (and only) argument.
765         if (!is_array($options)) {
766           $data = $options;
767           $options = array();
768         }
769         // In some cases, the first parameter ($data) is an array. Arrays can't
770         // be passed as keys in PHP, so we have to get $data from the value
771         // array.
772         if (is_numeric($data)) {
773           $data = $options['data'];
774           unset($options['data']);
775         }
776         // Prepend the library path to the file name.
777         $data = "$path/$data";
778         // Apply the default group if the group isn't explicitly given.
779         if (!isset($options['group'])) {
780           $options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_AGGREGATE_DEFAULT;
781         }
782         if ($type === 'js') {
783           $options['version'] = -1;
784         }
785         // @todo Avoid the usage of _drupal_add_js() and _drupal_add_css()
786         call_user_func('_drupal_add_' . $type, $data, $options);
787         $count++;
788       }
789     }
790   }
791
792   // Load PHP files.
793   if (!empty($library['files']['php'])) {
794     foreach ($library['files']['php'] as $file => $array) {
795       $file_path = DRUPAL_ROOT . '/' . $path . '/' . $file;
796       if (file_exists($file_path)) {
797         require_once $file_path;
798         $count++;
799       }
800     }
801   }
802
803   // Load integration files.
804   if (!empty($library['integration files'])) {
805     foreach ($library['integration files'] as $module => $files) {
806       libraries_load_files(array(
807         'files' => $files,
808         'path' => '',
809         'library path' => drupal_get_path('module', $module),
810       ));
811     }
812   }
813
814   return $count;
815 }
816
817 /**
818  * Gets the version information from an arbitrary library.
819  *
820  * @param $library
821  *   An associative array containing all information about the library.
822  * @param $options
823  *   An associative array containing with the following keys:
824  *   - file: The filename to parse for the version, relative to the library
825  *     path. For example: 'docs/changelog.txt'.
826  *   - pattern: A string containing a regular expression (PCRE) to match the
827  *     library version. For example: '@version\s+([0-9a-zA-Z\.-]+)@'. Note that
828  *     the returned version is not the match of the entire pattern (i.e.
829  *     '@version 1.2.3' in the above example) but the match of the first
830  *     sub-pattern (i.e. '1.2.3' in the above example).
831  *   - lines: (optional) The maximum number of lines to search the pattern in.
832  *     Defaults to 20.
833  *   - cols: (optional) The maximum number of characters per line to take into
834  *     account. Defaults to 200. In case of minified or compressed files, this
835  *     prevents reading the entire file into memory.
836  *
837  * @return
838  *   A string containing the version of the library.
839  *
840  * @see libraries_get_path()
841  *
842  * @deprecated Will be removed before a stable Drupal 8 release. Please use the
843  * new library load and managment concepts described at:
844  * https://www.drupal.org/node/2170763
845  */
846 function libraries_get_version($library, $options) {
847   // Provide defaults.
848   $options += array(
849     'file' => '',
850     'pattern' => '',
851     'lines' => 20,
852     'cols' => 200,
853   );
854
855   $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $options['file'];
856   if (empty($options['file']) || !file_exists($file)) {
857     return;
858   }
859   $file = fopen($file, 'r');
860   while ($options['lines'] && $line = fgets($file, $options['cols'])) {
861     if (preg_match($options['pattern'], $line, $version)) {
862       fclose($file);
863       return $version[1];
864     }
865     $options['lines']--;
866   }
867   fclose($file);
868 }