Mercurial > hg > rr-repo
comparison sites/all/modules/libraries/libraries.module @ 3:b28be78d8160
alpha1.0 version
author | danieleb <danielebarchiesi@me.com> |
---|---|
date | Thu, 19 Sep 2013 10:33:07 +0100 |
parents | b74b41bb73f0 |
children |
comparison
equal
deleted
inserted
replaced
2:b74b41bb73f0 | 3:b28be78d8160 |
---|---|
1 <?php | 1 <?php |
2 // $Id: libraries.module,v 1.19.2.1 2011/01/27 02:31:41 sun Exp $ | |
2 | 3 |
3 /** | 4 /** |
4 * @file | 5 * @file |
5 * External library handling for Drupal modules. | 6 * External library handling for Drupal modules. |
6 */ | 7 */ |
7 | |
8 /** | |
9 * Implements hook_flush_caches(). | |
10 */ | |
11 function libraries_flush_caches() { | |
12 // @todo When upgrading from 1.x, update.php attempts to flush caches before | |
13 // the cache table has been created. | |
14 // @see http://drupal.org/node/1477932 | |
15 if (db_table_exists('cache_libraries')) { | |
16 return array('cache_libraries'); | |
17 } | |
18 } | |
19 | 8 |
20 /** | 9 /** |
21 * Gets the path of a library. | 10 * Gets the path of a library. |
22 * | 11 * |
23 * @param $name | 12 * @param $name |
24 * The machine name of a library to return the path for. | 13 * The machine name of a library to return the path for. |
25 * @param $base_path | 14 * @param $base_path |
26 * Whether to prefix the resulting path with base_path(). | 15 * Whether to prefix the resulting path with base_path(). |
27 * | 16 * |
28 * @return | 17 * @return |
29 * The path to the specified library or FALSE if the library wasn't found. | 18 * The path to the specified library. |
30 * | 19 * |
31 * @ingroup libraries | 20 * @ingroup libraries |
32 */ | 21 */ |
33 function libraries_get_path($name, $base_path = FALSE) { | 22 function libraries_get_path($name, $base_path = FALSE) { |
34 $libraries = &drupal_static(__FUNCTION__); | 23 $libraries = &drupal_static(__FUNCTION__); |
37 $libraries = libraries_get_libraries(); | 26 $libraries = libraries_get_libraries(); |
38 } | 27 } |
39 | 28 |
40 $path = ($base_path ? base_path() : ''); | 29 $path = ($base_path ? base_path() : ''); |
41 if (!isset($libraries[$name])) { | 30 if (!isset($libraries[$name])) { |
42 return FALSE; | 31 // Most often, external libraries can be shared across multiple sites, so |
32 // we return sites/all/libraries as the default path. | |
33 $path .= 'sites/all/libraries/' . $name; | |
43 } | 34 } |
44 else { | 35 else { |
45 $path .= $libraries[$name]; | 36 $path .= $libraries[$name]; |
46 } | 37 } |
47 | 38 |
63 * A list of library directories. | 54 * A list of library directories. |
64 * | 55 * |
65 * @ingroup libraries | 56 * @ingroup libraries |
66 */ | 57 */ |
67 function libraries_get_libraries() { | 58 function libraries_get_libraries() { |
59 $directory = 'libraries'; | |
68 $searchdir = array(); | 60 $searchdir = array(); |
69 $profile = drupal_get_path('profile', drupal_get_profile()); | 61 $profile = drupal_get_profile(); |
70 $config = conf_path(); | 62 $config = conf_path(); |
71 | 63 |
72 // Similar to 'modules' and 'themes' directories in the root directory, | 64 // Similar to 'modules' and 'themes' directories in the root directory, |
73 // certain distributions may want to place libraries into a 'libraries' | 65 // certain distributions may want to place libraries into a 'libraries' |
74 // directory in Drupal's root directory. | 66 // directory in Drupal's root directory. |
75 $searchdir[] = 'libraries'; | 67 $searchdir[] = $directory; |
76 | 68 |
77 // Similar to 'modules' and 'themes' directories inside an installation | 69 // The 'profiles' directory contains pristine collections of modules and |
78 // profile, installation profiles may want to place libraries into a | 70 // themes as organized by a distribution. It is pristine in the same way |
79 // 'libraries' directory. | 71 // that /modules is pristine for core; users should avoid changing anything |
80 $searchdir[] = "$profile/libraries"; | 72 // there in favor of sites/all or sites/<domain> directories. |
73 if (file_exists("profiles/$profile/$directory")) { | |
74 $searchdir[] = "profiles/$profile/$directory"; | |
75 } | |
81 | 76 |
82 // Always search sites/all/libraries. | 77 // Always search sites/all/*. |
83 $searchdir[] = 'sites/all/libraries'; | 78 $searchdir[] = 'sites/all/' . $directory; |
84 | 79 |
85 // Also search sites/<domain>/*. | 80 // Also search sites/<domain>/*. |
86 $searchdir[] = "$config/libraries"; | 81 if (file_exists("$config/$directory")) { |
82 $searchdir[] = "$config/$directory"; | |
83 } | |
87 | 84 |
88 // Retrieve list of directories. | 85 // Retrieve list of directories. |
86 // @todo Core: Allow to scan for directories. | |
89 $directories = array(); | 87 $directories = array(); |
90 $nomask = array('CVS'); | 88 $nomask = array('CVS'); |
91 foreach ($searchdir as $dir) { | 89 foreach ($searchdir as $dir) { |
92 if (is_dir($dir) && $handle = opendir($dir)) { | 90 if (is_dir($dir) && $handle = opendir($dir)) { |
93 while (FALSE !== ($file = readdir($handle))) { | 91 while (FALSE !== ($file = readdir($handle))) { |
102 } | 100 } |
103 | 101 |
104 return $directories; | 102 return $directories; |
105 } | 103 } |
106 | 104 |
107 /** | |
108 * Looks for library info files. | |
109 * | |
110 * This function scans the following directories for info files: | |
111 * - libraries | |
112 * - profiles/$profilename/libraries | |
113 * - sites/all/libraries | |
114 * - sites/$sitename/libraries | |
115 * - any directories specified via hook_libraries_info_file_paths() | |
116 * | |
117 * @return | |
118 * An array of info files, keyed by library name. The values are the paths of | |
119 * the files. | |
120 */ | |
121 function libraries_scan_info_files() { | |
122 $profile = drupal_get_path('profile', drupal_get_profile()); | |
123 $config = conf_path(); | |
124 | |
125 // Build a list of directories. | |
126 $directories = module_invoke_all('libraries_info_file_paths'); | |
127 $directories[] = 'libraries'; | |
128 $directories[] = "$profile/libraries"; | |
129 $directories[] = 'sites/all/libraries'; | |
130 $directories[] = "$config/libraries"; | |
131 | |
132 // Scan for info files. | |
133 $files = array(); | |
134 foreach ($directories as $dir) { | |
135 if (file_exists($dir)) { | |
136 $files = array_merge($files, file_scan_directory($dir, '@^[a-z0-9._-]+\.libraries\.info$@', array( | |
137 'key' => 'name', | |
138 'recurse' => FALSE, | |
139 ))); | |
140 } | |
141 } | |
142 | |
143 foreach ($files as $filename => $file) { | |
144 $files[basename($filename, '.libraries')] = $file; | |
145 unset($files[$filename]); | |
146 } | |
147 | |
148 return $files; | |
149 } | |
150 | |
151 /** | |
152 * Invokes library callbacks. | |
153 * | |
154 * @param $group | |
155 * A string containing the group of callbacks that is to be applied. Should be | |
156 * either 'info', 'pre-detect', 'post-detect', or 'load'. | |
157 * @param $library | |
158 * An array of library information, passed by reference. | |
159 */ | |
160 function libraries_invoke($group, &$library) { | |
161 foreach ($library['callbacks'][$group] as $callback) { | |
162 libraries_traverse_library($library, $callback); | |
163 } | |
164 } | |
165 | |
166 /** | |
167 * Helper function to apply a callback to all parts of a library. | |
168 * | |
169 * Because library declarations can include variants and versions, and those | |
170 * version declarations can in turn include variants, modifying e.g. the 'files' | |
171 * property everywhere it is declared can be quite cumbersome, in which case | |
172 * this helper function is useful. | |
173 * | |
174 * @param $library | |
175 * An array of library information, passed by reference. | |
176 * @param $callback | |
177 * A string containing the callback to apply to all parts of a library. | |
178 */ | |
179 function libraries_traverse_library(&$library, $callback) { | |
180 // Always apply the callback to the top-level library. | |
181 $callback($library, NULL, NULL); | |
182 | |
183 // Apply the callback to versions. | |
184 if (isset($library['versions'])) { | |
185 foreach ($library['versions'] as $version_string => &$version) { | |
186 $callback($version, $version_string, NULL); | |
187 // Versions can include variants as well. | |
188 if (isset($version['variants'])) { | |
189 foreach ($version['variants'] as $version_variant_name => &$version_variant) { | |
190 $callback($version_variant, $version_string, $version_variant_name); | |
191 } | |
192 } | |
193 } | |
194 } | |
195 | |
196 // Apply the callback to variants. | |
197 if (isset($library['variants'])) { | |
198 foreach ($library['variants'] as $variant_name => &$variant) { | |
199 $callback($variant, NULL, $variant_name); | |
200 } | |
201 } | |
202 } | |
203 | |
204 /** | |
205 * Library info callback to make all 'files' properties consistent. | |
206 * | |
207 * This turns libraries' file information declared as e.g. | |
208 * @code | |
209 * $library['files']['js'] = array('example_1.js', 'example_2.js'); | |
210 * @endcode | |
211 * into | |
212 * @code | |
213 * $library['files']['js'] = array( | |
214 * 'example_1.js' => array(), | |
215 * 'example_2.js' => array(), | |
216 * ); | |
217 * @endcode | |
218 * It does the same for the 'integration files' property. | |
219 * | |
220 * @param $library | |
221 * An associative array of library information or a part of it, passed by | |
222 * reference. | |
223 * @param $version | |
224 * If the library information belongs to a specific version, the version | |
225 * string. NULL otherwise. | |
226 * @param $variant | |
227 * If the library information belongs to a specific variant, the variant name. | |
228 * NULL otherwise. | |
229 * | |
230 * @see libraries_info() | |
231 * @see libraries_invoke() | |
232 */ | |
233 function libraries_prepare_files(&$library, $version = NULL, $variant = NULL) { | |
234 // Both the 'files' property and the 'integration files' property contain file | |
235 // declarations, and we want to make both consistent. | |
236 $file_types = array(); | |
237 if (isset($library['files'])) { | |
238 $file_types[] = &$library['files']; | |
239 } | |
240 if (isset($library['integration files'])) { | |
241 // Integration files are additionally keyed by module. | |
242 foreach ($library['integration files'] as &$integration_files) { | |
243 $file_types[] = &$integration_files; | |
244 } | |
245 } | |
246 foreach ($file_types as &$files) { | |
247 // Go through all supported types of files. | |
248 foreach (array('js', 'css', 'php') as $type) { | |
249 if (isset($files[$type])) { | |
250 foreach ($files[$type] as $key => $value) { | |
251 // Unset numeric keys and turn the respective values into keys. | |
252 if (is_numeric($key)) { | |
253 $files[$type][$value] = array(); | |
254 unset($files[$type][$key]); | |
255 } | |
256 } | |
257 } | |
258 } | |
259 } | |
260 } | |
261 | |
262 /** | |
263 * Library post-detect callback to process and detect dependencies. | |
264 * | |
265 * It checks whether each of the dependencies of a library are installed and | |
266 * available in a compatible version. | |
267 * | |
268 * @param $library | |
269 * An associative array of library information or a part of it, passed by | |
270 * reference. | |
271 * @param $version | |
272 * If the library information belongs to a specific version, the version | |
273 * string. NULL otherwise. | |
274 * @param $variant | |
275 * If the library information belongs to a specific variant, the variant name. | |
276 * NULL otherwise. | |
277 * | |
278 * @see libraries_info() | |
279 * @see libraries_invoke() | |
280 */ | |
281 function libraries_detect_dependencies(&$library, $version = NULL, $variant = NULL) { | |
282 if (isset($library['dependencies'])) { | |
283 foreach ($library['dependencies'] as &$dependency_string) { | |
284 $dependency_info = drupal_parse_dependency($dependency_string); | |
285 $dependency = libraries_detect($dependency_info['name']); | |
286 if (!$dependency['installed']) { | |
287 $library['installed'] = FALSE; | |
288 $library['error'] = 'missing dependency'; | |
289 $library['error message'] = t('The %dependency library, which the %library library depends on, is not installed.', array( | |
290 '%dependency' => $dependency['name'], | |
291 '%library' => $library['name'], | |
292 )); | |
293 } | |
294 elseif (drupal_check_incompatibility($dependency_info, $dependency['version'])) { | |
295 $library['installed'] = FALSE; | |
296 $library['error'] = 'incompatible dependency'; | |
297 $library['error message'] = t('The version %dependency_version of the %dependency library is not compatible with the %library library.', array( | |
298 '%dependency_version' => $dependency['version'], | |
299 '%dependency' => $dependency['name'], | |
300 '%library' => $library['name'], | |
301 )); | |
302 } | |
303 | |
304 // Remove the version string from the dependency, so libraries_load() can | |
305 // load the libraries directly. | |
306 $dependency_string = $dependency_info['name']; | |
307 } | |
308 } | |
309 } | |
310 | |
311 /** | |
312 * Returns information about registered libraries. | |
313 * | |
314 * The returned information is unprocessed; i.e., as registered by modules. | |
315 * | |
316 * @param $name | |
317 * (optional) The machine name of a library to return registered information | |
318 * for. If omitted, information about all registered libraries is returned. | |
319 * | |
320 * @return array|false | |
321 * An associative array containing registered information for all libraries, | |
322 * the registered information for the library specified by $name, or FALSE if | |
323 * the library $name is not registered. | |
324 * | |
325 * @see hook_libraries_info() | |
326 * | |
327 * @todo Re-introduce support for include file plugin system - either by copying | |
328 * Wysiwyg's code, or directly switching to CTools. | |
329 */ | |
330 function &libraries_info($name = NULL) { | |
331 // This static cache is re-used by libraries_detect() to save memory. | |
332 $libraries = &drupal_static(__FUNCTION__); | |
333 | |
334 if (!isset($libraries)) { | |
335 $libraries = array(); | |
336 // Gather information from hook_libraries_info(). | |
337 foreach (module_implements('libraries_info') as $module) { | |
338 foreach (module_invoke($module, 'libraries_info') as $machine_name => $properties) { | |
339 $properties['module'] = $module; | |
340 $libraries[$machine_name] = $properties; | |
341 } | |
342 } | |
343 // Gather information from hook_libraries_info() in enabled themes. | |
344 // @see drupal_alter() | |
345 global $theme, $base_theme_info; | |
346 if (isset($theme)) { | |
347 $theme_keys = array(); | |
348 foreach ($base_theme_info as $base) { | |
349 $theme_keys[] = $base->name; | |
350 } | |
351 $theme_keys[] = $theme; | |
352 foreach ($theme_keys as $theme_key) { | |
353 $function = $theme_key . '_' . 'libraries_info'; | |
354 if (function_exists($function)) { | |
355 foreach ($function() as $machine_name => $properties) { | |
356 $properties['theme'] = $theme_key; | |
357 $libraries[$machine_name] = $properties; | |
358 } | |
359 } | |
360 } | |
361 } | |
362 | |
363 // Gather information from .info files. | |
364 // .info files override module definitions. | |
365 foreach (libraries_scan_info_files() as $machine_name => $file) { | |
366 $properties = drupal_parse_info_file($file->uri); | |
367 $properties['info file'] = $file->uri; | |
368 $libraries[$machine_name] = $properties; | |
369 } | |
370 | |
371 // Provide defaults. | |
372 foreach ($libraries as $machine_name => &$properties) { | |
373 libraries_info_defaults($properties, $machine_name); | |
374 } | |
375 | |
376 // Allow modules to alter the registered libraries. | |
377 drupal_alter('libraries_info', $libraries); | |
378 | |
379 // Invoke callbacks in the 'info' group. | |
380 foreach ($libraries as &$properties) { | |
381 libraries_invoke('info', $properties); | |
382 } | |
383 } | |
384 | |
385 if (isset($name)) { | |
386 if (!empty($libraries[$name])) { | |
387 return $libraries[$name]; | |
388 } | |
389 else { | |
390 $false = FALSE; | |
391 return $false; | |
392 } | |
393 } | |
394 return $libraries; | |
395 } | |
396 | |
397 /** | |
398 * Applies default properties to a library definition. | |
399 * | |
400 * @library | |
401 * An array of library information, passed by reference. | |
402 * @name | |
403 * The machine name of the passed-in library. | |
404 */ | |
405 function libraries_info_defaults(&$library, $name) { | |
406 $library += array( | |
407 'machine name' => $name, | |
408 'name' => $name, | |
409 'vendor url' => '', | |
410 'download url' => '', | |
411 'path' => '', | |
412 'library path' => NULL, | |
413 'version callback' => 'libraries_get_version', | |
414 'version arguments' => array(), | |
415 'files' => array(), | |
416 'dependencies' => array(), | |
417 'variants' => array(), | |
418 'versions' => array(), | |
419 'integration files' => array(), | |
420 'callbacks' => array(), | |
421 ); | |
422 $library['callbacks'] += array( | |
423 'info' => array(), | |
424 'pre-detect' => array(), | |
425 'post-detect' => array(), | |
426 'pre-dependencies-load' => array(), | |
427 'pre-load' => array(), | |
428 'post-load' => array(), | |
429 ); | |
430 | |
431 // Add our own callbacks before any others. | |
432 array_unshift($library['callbacks']['info'], 'libraries_prepare_files'); | |
433 array_unshift($library['callbacks']['post-detect'], 'libraries_detect_dependencies'); | |
434 | |
435 return $library; | |
436 } | |
437 | |
438 /** | |
439 * Tries to detect a library and its installed version. | |
440 * | |
441 * @param $name | |
442 * The machine name of a library to return registered information for. | |
443 * | |
444 * @return array|false | |
445 * An associative array containing registered information for the library | |
446 * specified by $name, or FALSE if the library $name is not registered. | |
447 * In addition to the keys returned by libraries_info(), the following keys | |
448 * are contained: | |
449 * - installed: A boolean indicating whether the library is installed. Note | |
450 * that not only the top-level library, but also each variant contains this | |
451 * key. | |
452 * - version: If the version could be detected, the full version string. | |
453 * - error: If an error occurred during library detection, one of the | |
454 * following error statuses: "not found", "not detected", "not supported". | |
455 * - error message: If an error occurred during library detection, a detailed | |
456 * error message. | |
457 * | |
458 * @see libraries_info() | |
459 */ | |
460 function libraries_detect($name) { | |
461 // Re-use the statically cached value of libraries_info() to save memory. | |
462 $library = &libraries_info($name); | |
463 | |
464 if ($library === FALSE) { | |
465 return $library; | |
466 } | |
467 // If 'installed' is set, library detection ran already. | |
468 if (isset($library['installed'])) { | |
469 return $library; | |
470 } | |
471 | |
472 $library['installed'] = FALSE; | |
473 | |
474 // Check whether the library exists. | |
475 if (!isset($library['library path'])) { | |
476 $library['library path'] = libraries_get_path($library['machine name']); | |
477 } | |
478 if ($library['library path'] === FALSE || !file_exists($library['library path'])) { | |
479 $library['error'] = 'not found'; | |
480 $library['error message'] = t('The %library library could not be found.', array( | |
481 '%library' => $library['name'], | |
482 )); | |
483 return $library; | |
484 } | |
485 | |
486 // Invoke callbacks in the 'pre-detect' group. | |
487 libraries_invoke('pre-detect', $library); | |
488 | |
489 // Detect library version, if not hardcoded. | |
490 if (!isset($library['version'])) { | |
491 // We support both a single parameter, which is an associative array, and an | |
492 // indexed array of multiple parameters. | |
493 if (isset($library['version arguments'][0])) { | |
494 // Add the library as the first argument. | |
495 $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments'])); | |
496 } | |
497 else { | |
498 $library['version'] = $library['version callback']($library, $library['version arguments']); | |
499 } | |
500 if (empty($library['version'])) { | |
501 $library['error'] = 'not detected'; | |
502 $library['error message'] = t('The version of the %library library could not be detected.', array( | |
503 '%library' => $library['name'], | |
504 )); | |
505 return $library; | |
506 } | |
507 } | |
508 | |
509 // Determine to which supported version the installed version maps. | |
510 if (!empty($library['versions'])) { | |
511 ksort($library['versions']); | |
512 $version = 0; | |
513 foreach ($library['versions'] as $supported_version => $version_properties) { | |
514 if (version_compare($library['version'], $supported_version, '>=')) { | |
515 $version = $supported_version; | |
516 } | |
517 } | |
518 if (!$version) { | |
519 $library['error'] = 'not supported'; | |
520 $library['error message'] = t('The installed version %version of the %library library is not supported.', array( | |
521 '%version' => $library['version'], | |
522 '%library' => $library['name'], | |
523 )); | |
524 return $library; | |
525 } | |
526 | |
527 // Apply version specific definitions and overrides. | |
528 $library = array_merge($library, $library['versions'][$version]); | |
529 unset($library['versions']); | |
530 } | |
531 | |
532 // Check each variant if it is installed. | |
533 if (!empty($library['variants'])) { | |
534 foreach ($library['variants'] as $variant_name => &$variant) { | |
535 // If no variant callback has been set, assume the variant to be | |
536 // installed. | |
537 if (!isset($variant['variant callback'])) { | |
538 $variant['installed'] = TRUE; | |
539 } | |
540 else { | |
541 // We support both a single parameter, which is an associative array, | |
542 // and an indexed array of multiple parameters. | |
543 if (isset($variant['variant arguments'][0])) { | |
544 // Add the library as the first argument, and the variant name as the second. | |
545 $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $variant_name), $variant['variant arguments'])); | |
546 } | |
547 else { | |
548 $variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']); | |
549 } | |
550 if (!$variant['installed']) { | |
551 $variant['error'] = 'not found'; | |
552 $variant['error message'] = t('The %variant variant of the %library library could not be found.', array( | |
553 '%variant' => $variant_name, | |
554 '%library' => $library['name'], | |
555 )); | |
556 } | |
557 } | |
558 } | |
559 } | |
560 | |
561 // If we end up here, the library should be usable. | |
562 $library['installed'] = TRUE; | |
563 | |
564 // Invoke callbacks in the 'post-detect' group. | |
565 libraries_invoke('post-detect', $library); | |
566 | |
567 return $library; | |
568 } | |
569 | |
570 /** | |
571 * Loads a library. | |
572 * | |
573 * @param $name | |
574 * The name of the library to load. | |
575 * @param $variant | |
576 * The name of the variant to load. Note that only one variant of a library | |
577 * can be loaded within a single request. The variant that has been passed | |
578 * first is used; different variant names in subsequent calls are ignored. | |
579 * | |
580 * @return | |
581 * An associative array of the library information as returned from | |
582 * libraries_info(). The top-level properties contain the effective definition | |
583 * of the library (variant) that has been loaded. Additionally: | |
584 * - installed: Whether the library is installed, as determined by | |
585 * libraries_detect_library(). | |
586 * - loaded: Either the amount of library files that have been loaded, or | |
587 * FALSE if the library could not be loaded. | |
588 * See hook_libraries_info() for more information. | |
589 */ | |
590 function libraries_load($name, $variant = NULL) { | |
591 $loaded = &drupal_static(__FUNCTION__, array()); | |
592 | |
593 if (!isset($loaded[$name])) { | |
594 $library = cache_get($name, 'cache_libraries'); | |
595 if ($library) { | |
596 $library = $library->data; | |
597 } | |
598 else { | |
599 $library = libraries_detect($name); | |
600 cache_set($name, $library, 'cache_libraries'); | |
601 } | |
602 | |
603 // If a variant was specified, override the top-level properties with the | |
604 // variant properties. | |
605 if (isset($variant)) { | |
606 // Ensure that the $variant key exists, and if it does not, set its | |
607 // 'installed' property to FALSE by default. This will prevent the loading | |
608 // of the library files below. | |
609 $library['variants'] += array($variant => array('installed' => FALSE)); | |
610 $library = array_merge($library, $library['variants'][$variant]); | |
611 } | |
612 // Regardless of whether a specific variant was requested or not, there can | |
613 // only be one variant of a library within a single request. | |
614 unset($library['variants']); | |
615 | |
616 // Invoke callbacks in the 'pre-dependencies-load' group. | |
617 libraries_invoke('pre-dependencies-load', $library); | |
618 | |
619 // If the library (variant) is installed, load it. | |
620 $library['loaded'] = FALSE; | |
621 if ($library['installed']) { | |
622 // Load library dependencies. | |
623 if (isset($library['dependencies'])) { | |
624 foreach ($library['dependencies'] as $dependency) { | |
625 libraries_load($dependency); | |
626 } | |
627 } | |
628 | |
629 // Invoke callbacks in the 'pre-load' group. | |
630 libraries_invoke('pre-load', $library); | |
631 | |
632 // Load all the files associated with the library. | |
633 $library['loaded'] = libraries_load_files($library); | |
634 | |
635 // Invoke callbacks in the 'post-load' group. | |
636 libraries_invoke('post-load', $library); | |
637 } | |
638 $loaded[$name] = $library; | |
639 } | |
640 | |
641 return $loaded[$name]; | |
642 } | |
643 | |
644 /** | |
645 * Loads a library's files. | |
646 * | |
647 * @param $library | |
648 * An array of library information as returned by libraries_info(). | |
649 * | |
650 * @return | |
651 * The number of loaded files. | |
652 */ | |
653 function libraries_load_files($library) { | |
654 // Load integration files. | |
655 if (!empty($library['integration files'])) { | |
656 foreach ($library['integration files'] as $module => $files) { | |
657 libraries_load_files(array( | |
658 'files' => $files, | |
659 'path' => '', | |
660 'library path' => drupal_get_path('module', $module), | |
661 )); | |
662 } | |
663 } | |
664 | |
665 // Construct the full path to the library for later use. | |
666 $path = $library['library path']; | |
667 $path = ($library['path'] !== '' ? $path . '/' . $library['path'] : $path); | |
668 | |
669 // Count the number of loaded files for the return value. | |
670 $count = 0; | |
671 | |
672 // Load both the JavaScript and the CSS files. | |
673 // The parameters for drupal_add_js() and drupal_add_css() require special | |
674 // handling. | |
675 // @see drupal_process_attached() | |
676 foreach (array('js', 'css') as $type) { | |
677 if (!empty($library['files'][$type])) { | |
678 foreach ($library['files'][$type] as $data => $options) { | |
679 // If the value is not an array, it's a filename and passed as first | |
680 // (and only) argument. | |
681 if (!is_array($options)) { | |
682 $data = $options; | |
683 $options = array(); | |
684 } | |
685 // In some cases, the first parameter ($data) is an array. Arrays can't | |
686 // be passed as keys in PHP, so we have to get $data from the value | |
687 // array. | |
688 if (is_numeric($data)) { | |
689 $data = $options['data']; | |
690 unset($options['data']); | |
691 } | |
692 // Prepend the library path to the file name. | |
693 $data = "$path/$data"; | |
694 // Apply the default group if the group isn't explicitly given. | |
695 if (!isset($options['group'])) { | |
696 $options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_DEFAULT; | |
697 } | |
698 call_user_func('drupal_add_' . $type, $data, $options); | |
699 $count++; | |
700 } | |
701 } | |
702 } | |
703 | |
704 // Load PHP files. | |
705 if (!empty($library['files']['php'])) { | |
706 foreach ($library['files']['php'] as $file => $array) { | |
707 $file_path = DRUPAL_ROOT . '/' . $path . '/' . $file; | |
708 if (file_exists($file_path)) { | |
709 require_once $file_path; | |
710 $count++; | |
711 } | |
712 } | |
713 } | |
714 | |
715 return $count; | |
716 } | |
717 | |
718 /** | |
719 * Gets the version information from an arbitrary library. | |
720 * | |
721 * @param $library | |
722 * An associative array containing all information about the library. | |
723 * @param $options | |
724 * An associative array containing with the following keys: | |
725 * - file: The filename to parse for the version, relative to the library | |
726 * path. For example: 'docs/changelog.txt'. | |
727 * - pattern: A string containing a regular expression (PCRE) to match the | |
728 * library version. For example: '@version\s+([0-9a-zA-Z\.-]+)@'. Note that | |
729 * the returned version is not the match of the entire pattern (i.e. | |
730 * '@version 1.2.3' in the above example) but the match of the first | |
731 * sub-pattern (i.e. '1.2.3' in the above example). | |
732 * - lines: (optional) The maximum number of lines to search the pattern in. | |
733 * Defaults to 20. | |
734 * - cols: (optional) The maximum number of characters per line to take into | |
735 * account. Defaults to 200. In case of minified or compressed files, this | |
736 * prevents reading the entire file into memory. | |
737 * | |
738 * @return | |
739 * A string containing the version of the library. | |
740 * | |
741 * @see libraries_get_path() | |
742 */ | |
743 function libraries_get_version($library, $options) { | |
744 // Provide defaults. | |
745 $options += array( | |
746 'file' => '', | |
747 'pattern' => '', | |
748 'lines' => 20, | |
749 'cols' => 200, | |
750 ); | |
751 | |
752 $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $options['file']; | |
753 if (empty($options['file']) || !file_exists($file)) { | |
754 return; | |
755 } | |
756 $file = fopen($file, 'r'); | |
757 while ($options['lines'] && $line = fgets($file, $options['cols'])) { | |
758 if (preg_match($options['pattern'], $line, $version)) { | |
759 fclose($file); | |
760 return $version[1]; | |
761 } | |
762 $options['lines']--; | |
763 } | |
764 fclose($file); | |
765 } |