libraries.module 25 KB

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