danielebarchiesi@2: /*. danielebarchiesi@2: $searchdir[] = "$config/libraries"; danielebarchiesi@2: danielebarchiesi@2: // Retrieve list of directories. danielebarchiesi@2: $directories = array(); danielebarchiesi@2: $nomask = array('CVS'); danielebarchiesi@2: foreach ($searchdir as $dir) { danielebarchiesi@2: if (is_dir($dir) && $handle = opendir($dir)) { danielebarchiesi@2: while (FALSE !== ($file = readdir($handle))) { danielebarchiesi@2: if (!in_array($file, $nomask) && $file[0] != '.') { danielebarchiesi@2: if (is_dir("$dir/$file")) { danielebarchiesi@2: $directories[$file] = "$dir/$file"; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: closedir($handle); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: return $directories; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Looks for library info files. danielebarchiesi@2: * danielebarchiesi@2: * This function scans the following directories for info files: danielebarchiesi@2: * - libraries danielebarchiesi@2: * - profiles/$profilename/libraries danielebarchiesi@2: * - sites/all/libraries danielebarchiesi@2: * - sites/$sitename/libraries danielebarchiesi@2: * - any directories specified via hook_libraries_info_file_paths() danielebarchiesi@2: * danielebarchiesi@2: * @return danielebarchiesi@2: * An array of info files, keyed by library name. The values are the paths of danielebarchiesi@2: * the files. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_scan_info_files() { danielebarchiesi@2: $profile = drupal_get_path('profile', drupal_get_profile()); danielebarchiesi@2: $config = conf_path(); danielebarchiesi@2: danielebarchiesi@2: // Build a list of directories. danielebarchiesi@2: $directories = module_invoke_all('libraries_info_file_paths'); danielebarchiesi@2: $directories[] = 'libraries'; danielebarchiesi@2: $directories[] = "$profile/libraries"; danielebarchiesi@2: $directories[] = 'sites/all/libraries'; danielebarchiesi@2: $directories[] = "$config/libraries"; danielebarchiesi@2: danielebarchiesi@2: // Scan for info files. danielebarchiesi@2: $files = array(); danielebarchiesi@2: foreach ($directories as $dir) { danielebarchiesi@2: if (file_exists($dir)) { danielebarchiesi@2: $files = array_merge($files, file_scan_directory($dir, '@^[a-z0-9._-]+\.libraries\.info$@', array( danielebarchiesi@2: 'key' => 'name', danielebarchiesi@2: 'recurse' => FALSE, danielebarchiesi@2: ))); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: foreach ($files as $filename => $file) { danielebarchiesi@2: $files[basename($filename, '.libraries')] = $file; danielebarchiesi@2: unset($files[$filename]); danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: return $files; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Invokes library callbacks. danielebarchiesi@2: * danielebarchiesi@2: * @param $group danielebarchiesi@2: * A string containing the group of callbacks that is to be applied. Should be danielebarchiesi@2: * either 'info', 'pre-detect', 'post-detect', or 'load'. danielebarchiesi@2: * @param $library danielebarchiesi@2: * An array of library information, passed by reference. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_invoke($group, &$library) { danielebarchiesi@2: foreach ($library['callbacks'][$group] as $callback) { danielebarchiesi@2: libraries_traverse_library($library, $callback); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Helper function to apply a callback to all parts of a library. danielebarchiesi@2: * danielebarchiesi@2: * Because library declarations can include variants and versions, and those danielebarchiesi@2: * version declarations can in turn include variants, modifying e.g. the 'files' danielebarchiesi@2: * property everywhere it is declared can be quite cumbersome, in which case danielebarchiesi@2: * this helper function is useful. danielebarchiesi@2: * danielebarchiesi@2: * @param $library danielebarchiesi@2: * An array of library information, passed by reference. danielebarchiesi@2: * @param $callback danielebarchiesi@2: * A string containing the callback to apply to all parts of a library. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_traverse_library(&$library, $callback) { danielebarchiesi@2: // Always apply the callback to the top-level library. danielebarchiesi@2: $callback($library, NULL, NULL); danielebarchiesi@2: danielebarchiesi@2: // Apply the callback to versions. danielebarchiesi@2: if (isset($library['versions'])) { danielebarchiesi@2: foreach ($library['versions'] as $version_string => &$version) { danielebarchiesi@2: $callback($version, $version_string, NULL); danielebarchiesi@2: // Versions can include variants as well. danielebarchiesi@2: if (isset($version['variants'])) { danielebarchiesi@2: foreach ($version['variants'] as $version_variant_name => &$version_variant) { danielebarchiesi@2: $callback($version_variant, $version_string, $version_variant_name); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Apply the callback to variants. danielebarchiesi@2: if (isset($library['variants'])) { danielebarchiesi@2: foreach ($library['variants'] as $variant_name => &$variant) { danielebarchiesi@2: $callback($variant, NULL, $variant_name); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Library info callback to make all 'files' properties consistent. danielebarchiesi@2: * danielebarchiesi@2: * This turns libraries' file information declared as e.g. danielebarchiesi@2: * @code danielebarchiesi@2: * $library['files']['js'] = array('example_1.js', 'example_2.js'); danielebarchiesi@2: * @endcode danielebarchiesi@2: * into danielebarchiesi@2: * @code danielebarchiesi@2: * $library['files']['js'] = array( danielebarchiesi@2: * 'example_1.js' => array(), danielebarchiesi@2: * 'example_2.js' => array(), danielebarchiesi@2: * ); danielebarchiesi@2: * @endcode danielebarchiesi@2: * It does the same for the 'integration files' property. danielebarchiesi@2: * danielebarchiesi@2: * @param $library danielebarchiesi@2: * An associative array of library information or a part of it, passed by danielebarchiesi@2: * reference. danielebarchiesi@2: * @param $version danielebarchiesi@2: * If the library information belongs to a specific version, the version danielebarchiesi@2: * string. NULL otherwise. danielebarchiesi@2: * @param $variant danielebarchiesi@2: * If the library information belongs to a specific variant, the variant name. danielebarchiesi@2: * NULL otherwise. danielebarchiesi@2: * danielebarchiesi@2: * @see libraries_info() danielebarchiesi@2: * @see libraries_invoke() danielebarchiesi@2: */ danielebarchiesi@2: function libraries_prepare_files(&$library, $version = NULL, $variant = NULL) { danielebarchiesi@2: // Both the 'files' property and the 'integration files' property contain file danielebarchiesi@2: // declarations, and we want to make both consistent. danielebarchiesi@2: $file_types = array(); danielebarchiesi@2: if (isset($library['files'])) { danielebarchiesi@2: $file_types[] = &$library['files']; danielebarchiesi@2: } danielebarchiesi@2: if (isset($library['integration files'])) { danielebarchiesi@2: // Integration files are additionally keyed by module. danielebarchiesi@2: foreach ($library['integration files'] as &$integration_files) { danielebarchiesi@2: $file_types[] = &$integration_files; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: foreach ($file_types as &$files) { danielebarchiesi@2: // Go through all supported types of files. danielebarchiesi@2: foreach (array('js', 'css', 'php') as $type) { danielebarchiesi@2: if (isset($files[$type])) { danielebarchiesi@2: foreach ($files[$type] as $key => $value) { danielebarchiesi@2: // Unset numeric keys and turn the respective values into keys. danielebarchiesi@2: if (is_numeric($key)) { danielebarchiesi@2: $files[$type][$value] = array(); danielebarchiesi@2: unset($files[$type][$key]); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Library post-detect callback to process and detect dependencies. danielebarchiesi@2: * danielebarchiesi@2: * It checks whether each of the dependencies of a library are installed and danielebarchiesi@2: * available in a compatible version. danielebarchiesi@2: * danielebarchiesi@2: * @param $library danielebarchiesi@2: * An associative array of library information or a part of it, passed by danielebarchiesi@2: * reference. danielebarchiesi@2: * @param $version danielebarchiesi@2: * If the library information belongs to a specific version, the version danielebarchiesi@2: * string. NULL otherwise. danielebarchiesi@2: * @param $variant danielebarchiesi@2: * If the library information belongs to a specific variant, the variant name. danielebarchiesi@2: * NULL otherwise. danielebarchiesi@2: * danielebarchiesi@2: * @see libraries_info() danielebarchiesi@2: * @see libraries_invoke() danielebarchiesi@2: */ danielebarchiesi@2: function libraries_detect_dependencies(&$library, $version = NULL, $variant = NULL) { danielebarchiesi@2: if (isset($library['dependencies'])) { danielebarchiesi@2: foreach ($library['dependencies'] as &$dependency_string) { danielebarchiesi@2: $dependency_info = drupal_parse_dependency($dependency_string); danielebarchiesi@2: $dependency = libraries_detect($dependency_info['name']); danielebarchiesi@2: if (!$dependency['installed']) { danielebarchiesi@2: $library['installed'] = FALSE; danielebarchiesi@2: $library['error'] = 'missing dependency'; danielebarchiesi@2: $library['error message'] = t('The %dependency library, which the %library library depends on, is not installed.', array( danielebarchiesi@2: '%dependency' => $dependency['name'], danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: } danielebarchiesi@2: elseif (drupal_check_incompatibility($dependency_info, $dependency['version'])) { danielebarchiesi@2: $library['installed'] = FALSE; danielebarchiesi@2: $library['error'] = 'incompatible dependency'; danielebarchiesi@2: $library['error message'] = t('The version %dependency_version of the %dependency library is not compatible with the %library library.', array( danielebarchiesi@2: '%dependency_version' => $dependency['version'], danielebarchiesi@2: '%dependency' => $dependency['name'], danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Remove the version string from the dependency, so libraries_load() can danielebarchiesi@2: // load the libraries directly. danielebarchiesi@2: $dependency_string = $dependency_info['name']; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Returns information about registered libraries. danielebarchiesi@2: * danielebarchiesi@2: * The returned information is unprocessed; i.e., as registered by modules. danielebarchiesi@2: * danielebarchiesi@2: * @param $name danielebarchiesi@2: * (optional) The machine name of a library to return registered information danielebarchiesi@2: * for. If omitted, information about all registered libraries is returned. danielebarchiesi@2: * danielebarchiesi@2: * @return array|false danielebarchiesi@2: * An associative array containing registered information for all libraries, danielebarchiesi@2: * the registered information for the library specified by $name, or FALSE if danielebarchiesi@2: * the library $name is not registered. danielebarchiesi@2: * danielebarchiesi@2: * @see hook_libraries_info() danielebarchiesi@2: * danielebarchiesi@2: * @todo Re-introduce support for include file plugin system - either by copying danielebarchiesi@2: * Wysiwyg's code, or directly switching to CTools. danielebarchiesi@2: */ danielebarchiesi@2: function &libraries_info($name = NULL) { danielebarchiesi@2: // This static cache is re-used by libraries_detect() to save memory. danielebarchiesi@2: $libraries = &drupal_static(__FUNCTION__); danielebarchiesi@2: danielebarchiesi@2: if (!isset($libraries)) { danielebarchiesi@2: $libraries = array(); danielebarchiesi@2: // Gather information from hook_libraries_info(). danielebarchiesi@2: foreach (module_implements('libraries_info') as $module) { danielebarchiesi@2: foreach (module_invoke($module, 'libraries_info') as $machine_name => $properties) { danielebarchiesi@2: $properties['module'] = $module; danielebarchiesi@2: $libraries[$machine_name] = $properties; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: // Gather information from hook_libraries_info() in enabled themes. danielebarchiesi@2: // @see drupal_alter() danielebarchiesi@2: global $theme, $base_theme_info; danielebarchiesi@2: if (isset($theme)) { danielebarchiesi@2: $theme_keys = array(); danielebarchiesi@2: foreach ($base_theme_info as $base) { danielebarchiesi@2: $theme_keys[] = $base->name; danielebarchiesi@2: } danielebarchiesi@2: $theme_keys[] = $theme; danielebarchiesi@2: foreach ($theme_keys as $theme_key) { danielebarchiesi@2: $function = $theme_key . '_' . 'libraries_info'; danielebarchiesi@2: if (function_exists($function)) { danielebarchiesi@2: foreach ($function() as $machine_name => $properties) { danielebarchiesi@2: $properties['theme'] = $theme_key; danielebarchiesi@2: $libraries[$machine_name] = $properties; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Gather information from .info files. danielebarchiesi@2: // .info files override module definitions. danielebarchiesi@2: foreach (libraries_scan_info_files() as $machine_name => $file) { danielebarchiesi@2: $properties = drupal_parse_info_file($file->uri); danielebarchiesi@2: $properties['info file'] = $file->uri; danielebarchiesi@2: $libraries[$machine_name] = $properties; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Provide defaults. danielebarchiesi@2: foreach ($libraries as $machine_name => &$properties) { danielebarchiesi@2: libraries_info_defaults($properties, $machine_name); danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Allow modules to alter the registered libraries. danielebarchiesi@2: drupal_alter('libraries_info', $libraries); danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'info' group. danielebarchiesi@2: foreach ($libraries as &$properties) { danielebarchiesi@2: libraries_invoke('info', $properties); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: if (isset($name)) { danielebarchiesi@2: if (!empty($libraries[$name])) { danielebarchiesi@2: return $libraries[$name]; danielebarchiesi@2: } danielebarchiesi@2: else { danielebarchiesi@2: $false = FALSE; danielebarchiesi@2: return $false; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: return $libraries; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Applies default properties to a library definition. danielebarchiesi@2: * danielebarchiesi@2: * @library danielebarchiesi@2: * An array of library information, passed by reference. danielebarchiesi@2: * @name danielebarchiesi@2: * The machine name of the passed-in library. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_info_defaults(&$library, $name) { danielebarchiesi@2: $library += array( danielebarchiesi@2: 'machine name' => $name, danielebarchiesi@2: 'name' => $name, danielebarchiesi@2: 'vendor url' => '', danielebarchiesi@2: 'download url' => '', danielebarchiesi@2: 'path' => '', danielebarchiesi@2: 'library path' => NULL, danielebarchiesi@2: 'version callback' => 'libraries_get_version', danielebarchiesi@2: 'version arguments' => array(), danielebarchiesi@2: 'files' => array(), danielebarchiesi@2: 'dependencies' => array(), danielebarchiesi@2: 'variants' => array(), danielebarchiesi@2: 'versions' => array(), danielebarchiesi@2: 'integration files' => array(), danielebarchiesi@2: 'callbacks' => array(), danielebarchiesi@2: ); danielebarchiesi@2: $library['callbacks'] += array( danielebarchiesi@2: 'info' => array(), danielebarchiesi@2: 'pre-detect' => array(), danielebarchiesi@2: 'post-detect' => array(), danielebarchiesi@2: 'pre-dependencies-load' => array(), danielebarchiesi@2: 'pre-load' => array(), danielebarchiesi@2: 'post-load' => array(), danielebarchiesi@2: ); danielebarchiesi@2: danielebarchiesi@2: // Add our own callbacks before any others. danielebarchiesi@2: array_unshift($library['callbacks']['info'], 'libraries_prepare_files'); danielebarchiesi@2: array_unshift($library['callbacks']['post-detect'], 'libraries_detect_dependencies'); danielebarchiesi@2: danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Tries to detect a library and its installed version. danielebarchiesi@2: * danielebarchiesi@2: * @param $name danielebarchiesi@2: * The machine name of a library to return registered information for. danielebarchiesi@2: * danielebarchiesi@2: * @return array|false danielebarchiesi@2: * An associative array containing registered information for the library danielebarchiesi@2: * specified by $name, or FALSE if the library $name is not registered. danielebarchiesi@2: * In addition to the keys returned by libraries_info(), the following keys danielebarchiesi@2: * are contained: danielebarchiesi@2: * - installed: A boolean indicating whether the library is installed. Note danielebarchiesi@2: * that not only the top-level library, but also each variant contains this danielebarchiesi@2: * key. danielebarchiesi@2: * - version: If the version could be detected, the full version string. danielebarchiesi@2: * - error: If an error occurred during library detection, one of the danielebarchiesi@2: * following error statuses: "not found", "not detected", "not supported". danielebarchiesi@2: * - error message: If an error occurred during library detection, a detailed danielebarchiesi@2: * error message. danielebarchiesi@2: * danielebarchiesi@2: * @see libraries_info() danielebarchiesi@2: */ danielebarchiesi@2: function libraries_detect($name) { danielebarchiesi@2: // Re-use the statically cached value of libraries_info() to save memory. danielebarchiesi@2: $library = &libraries_info($name); danielebarchiesi@2: danielebarchiesi@2: if ($library === FALSE) { danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: // If 'installed' is set, library detection ran already. danielebarchiesi@2: if (isset($library['installed'])) { danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: $library['installed'] = FALSE; danielebarchiesi@2: danielebarchiesi@2: // Check whether the library exists. danielebarchiesi@2: if (!isset($library['library path'])) { danielebarchiesi@2: $library['library path'] = libraries_get_path($library['machine name']); danielebarchiesi@2: } danielebarchiesi@2: if ($library['library path'] === FALSE || !file_exists($library['library path'])) { danielebarchiesi@2: $library['error'] = 'not found'; danielebarchiesi@2: $library['error message'] = t('The %library library could not be found.', array( danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'pre-detect' group. danielebarchiesi@2: libraries_invoke('pre-detect', $library); danielebarchiesi@2: danielebarchiesi@2: // Detect library version, if not hardcoded. danielebarchiesi@2: if (!isset($library['version'])) { danielebarchiesi@2: // We support both a single parameter, which is an associative array, and an danielebarchiesi@2: // indexed array of multiple parameters. danielebarchiesi@2: if (isset($library['version arguments'][0])) { danielebarchiesi@2: // Add the library as the first argument. danielebarchiesi@2: $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments'])); danielebarchiesi@2: } danielebarchiesi@2: else { danielebarchiesi@2: $library['version'] = $library['version callback']($library, $library['version arguments']); danielebarchiesi@2: } danielebarchiesi@2: if (empty($library['version'])) { danielebarchiesi@2: $library['error'] = 'not detected'; danielebarchiesi@2: $library['error message'] = t('The version of the %library library could not be detected.', array( danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Determine to which supported version the installed version maps. danielebarchiesi@2: if (!empty($library['versions'])) { danielebarchiesi@2: ksort($library['versions']); danielebarchiesi@2: $version = 0; danielebarchiesi@2: foreach ($library['versions'] as $supported_version => $version_properties) { danielebarchiesi@2: if (version_compare($library['version'], $supported_version, '>=')) { danielebarchiesi@2: $version = $supported_version; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: if (!$version) { danielebarchiesi@2: $library['error'] = 'not supported'; danielebarchiesi@2: $library['error message'] = t('The installed version %version of the %library library is not supported.', array( danielebarchiesi@2: '%version' => $library['version'], danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Apply version specific definitions and overrides. danielebarchiesi@2: $library = array_merge($library, $library['versions'][$version]); danielebarchiesi@2: unset($library['versions']); danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Check each variant if it is installed. danielebarchiesi@2: if (!empty($library['variants'])) { danielebarchiesi@2: foreach ($library['variants'] as $variant_name => &$variant) { danielebarchiesi@2: // If no variant callback has been set, assume the variant to be danielebarchiesi@2: // installed. danielebarchiesi@2: if (!isset($variant['variant callback'])) { danielebarchiesi@2: $variant['installed'] = TRUE; danielebarchiesi@2: } danielebarchiesi@2: else { danielebarchiesi@2: // We support both a single parameter, which is an associative array, danielebarchiesi@2: // and an indexed array of multiple parameters. danielebarchiesi@2: if (isset($variant['variant arguments'][0])) { danielebarchiesi@2: // Add the library as the first argument, and the variant name as the second. danielebarchiesi@2: $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $variant_name), $variant['variant arguments'])); danielebarchiesi@2: } danielebarchiesi@2: else { danielebarchiesi@2: $variant['installed'] = $variant['variant callback']($library, $variant_name, $variant['variant arguments']); danielebarchiesi@2: } danielebarchiesi@2: if (!$variant['installed']) { danielebarchiesi@2: $variant['error'] = 'not found'; danielebarchiesi@2: $variant['error message'] = t('The %variant variant of the %library library could not be found.', array( danielebarchiesi@2: '%variant' => $variant_name, danielebarchiesi@2: '%library' => $library['name'], danielebarchiesi@2: )); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // If we end up here, the library should be usable. danielebarchiesi@2: $library['installed'] = TRUE; danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'post-detect' group. danielebarchiesi@2: libraries_invoke('post-detect', $library); danielebarchiesi@2: danielebarchiesi@2: return $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Loads a library. danielebarchiesi@2: * danielebarchiesi@2: * @param $name danielebarchiesi@2: * The name of the library to load. danielebarchiesi@2: * @param $variant danielebarchiesi@2: * The name of the variant to load. Note that only one variant of a library danielebarchiesi@2: * can be loaded within a single request. The variant that has been passed danielebarchiesi@2: * first is used; different variant names in subsequent calls are ignored. danielebarchiesi@2: * danielebarchiesi@2: * @return danielebarchiesi@2: * An associative array of the library information as returned from danielebarchiesi@2: * libraries_info(). The top-level properties contain the effective definition danielebarchiesi@2: * of the library (variant) that has been loaded. Additionally: danielebarchiesi@2: * - installed: Whether the library is installed, as determined by danielebarchiesi@2: * libraries_detect_library(). danielebarchiesi@2: * - loaded: Either the amount of library files that have been loaded, or danielebarchiesi@2: * FALSE if the library could not be loaded. danielebarchiesi@2: * See hook_libraries_info() for more information. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_load($name, $variant = NULL) { danielebarchiesi@2: $loaded = &drupal_static(__FUNCTION__, array()); danielebarchiesi@2: danielebarchiesi@2: if (!isset($loaded[$name])) { danielebarchiesi@2: $library = cache_get($name, 'cache_libraries'); danielebarchiesi@2: if ($library) { danielebarchiesi@2: $library = $library->data; danielebarchiesi@2: } danielebarchiesi@2: else { danielebarchiesi@2: $library = libraries_detect($name); danielebarchiesi@2: cache_set($name, $library, 'cache_libraries'); danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // If a variant was specified, override the top-level properties with the danielebarchiesi@2: // variant properties. danielebarchiesi@2: if (isset($variant)) { danielebarchiesi@2: // Ensure that the $variant key exists, and if it does not, set its danielebarchiesi@2: // 'installed' property to FALSE by default. This will prevent the loading danielebarchiesi@2: // of the library files below. danielebarchiesi@2: $library['variants'] += array($variant => array('installed' => FALSE)); danielebarchiesi@2: $library = array_merge($library, $library['variants'][$variant]); danielebarchiesi@2: } danielebarchiesi@2: // Regardless of whether a specific variant was requested or not, there can danielebarchiesi@2: // only be one variant of a library within a single request. danielebarchiesi@2: unset($library['variants']); danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'pre-dependencies-load' group. danielebarchiesi@2: libraries_invoke('pre-dependencies-load', $library); danielebarchiesi@2: danielebarchiesi@2: // If the library (variant) is installed, load it. danielebarchiesi@2: $library['loaded'] = FALSE; danielebarchiesi@2: if ($library['installed']) { danielebarchiesi@2: // Load library dependencies. danielebarchiesi@2: if (isset($library['dependencies'])) { danielebarchiesi@2: foreach ($library['dependencies'] as $dependency) { danielebarchiesi@2: libraries_load($dependency); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'pre-load' group. danielebarchiesi@2: libraries_invoke('pre-load', $library); danielebarchiesi@2: danielebarchiesi@2: // Load all the files associated with the library. danielebarchiesi@2: $library['loaded'] = libraries_load_files($library); danielebarchiesi@2: danielebarchiesi@2: // Invoke callbacks in the 'post-load' group. danielebarchiesi@2: libraries_invoke('post-load', $library); danielebarchiesi@2: } danielebarchiesi@2: $loaded[$name] = $library; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: return $loaded[$name]; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Loads a library's files. danielebarchiesi@2: * danielebarchiesi@2: * @param $library danielebarchiesi@2: * An array of library information as returned by libraries_info(). danielebarchiesi@2: * danielebarchiesi@2: * @return danielebarchiesi@2: * The number of loaded files. danielebarchiesi@2: */ danielebarchiesi@2: function libraries_load_files($library) { danielebarchiesi@2: // Load integration files. danielebarchiesi@2: if (!empty($library['integration files'])) { danielebarchiesi@2: foreach ($library['integration files'] as $module => $files) { danielebarchiesi@2: libraries_load_files(array( danielebarchiesi@2: 'files' => $files, danielebarchiesi@2: 'path' => '', danielebarchiesi@2: 'library path' => drupal_get_path('module', $module), danielebarchiesi@2: )); danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Construct the full path to the library for later use. danielebarchiesi@2: $path = $library['library path']; danielebarchiesi@2: $path = ($library['path'] !== '' ? $path . '/' . $library['path'] : $path); danielebarchiesi@2: danielebarchiesi@2: // Count the number of loaded files for the return value. danielebarchiesi@2: $count = 0; danielebarchiesi@2: danielebarchiesi@2: // Load both the JavaScript and the CSS files. danielebarchiesi@2: // The parameters for drupal_add_js() and drupal_add_css() require special danielebarchiesi@2: // handling. danielebarchiesi@2: // @see drupal_process_attached() danielebarchiesi@2: foreach (array('js', 'css') as $type) { danielebarchiesi@2: if (!empty($library['files'][$type])) { danielebarchiesi@2: foreach ($library['files'][$type] as $data => $options) { danielebarchiesi@2: // If the value is not an array, it's a filename and passed as first danielebarchiesi@2: // (and only) argument. danielebarchiesi@2: if (!is_array($options)) { danielebarchiesi@2: $data = $options; danielebarchiesi@2: $options = array(); danielebarchiesi@2: } danielebarchiesi@2: // In some cases, the first parameter ($data) is an array. Arrays can't danielebarchiesi@2: // be passed as keys in PHP, so we have to get $data from the value danielebarchiesi@2: // array. danielebarchiesi@2: if (is_numeric($data)) { danielebarchiesi@2: $data = $options['data']; danielebarchiesi@2: unset($options['data']); danielebarchiesi@2: } danielebarchiesi@2: // Prepend the library path to the file name. danielebarchiesi@2: $data = "$path/$data"; danielebarchiesi@2: // Apply the default group if the group isn't explicitly given. danielebarchiesi@2: if (!isset($options['group'])) { danielebarchiesi@2: $options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_DEFAULT; danielebarchiesi@2: } danielebarchiesi@2: call_user_func('drupal_add_' . $type, $data, $options); danielebarchiesi@2: $count++; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: // Load PHP files. danielebarchiesi@2: if (!empty($library['files']['php'])) { danielebarchiesi@2: foreach ($library['files']['php'] as $file => $array) { danielebarchiesi@2: $file_path = DRUPAL_ROOT . '/' . $path . '/' . $file; danielebarchiesi@2: if (file_exists($file_path)) { danielebarchiesi@2: require_once $file_path; danielebarchiesi@2: $count++; danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: return $count; danielebarchiesi@2: } danielebarchiesi@2: danielebarchiesi@2: /** danielebarchiesi@2: * Gets the version information from an arbitrary library. danielebarchiesi@2: * danielebarchiesi@2: * @param $library danielebarchiesi@2: * An associative array containing all information about the library. danielebarchiesi@2: * @param $options danielebarchiesi@2: * An associative array containing with the following keys: danielebarchiesi@2: * - file: The filename to parse for the version, relative to the library danielebarchiesi@2: * path. For example: 'docs/changelog.txt'. danielebarchiesi@2: * - pattern: A string containing a regular expression (PCRE) to match the danielebarchiesi@2: * library version. For example: '@version\s+([0-9a-zA-Z\.-]+)@'. Note that danielebarchiesi@2: * the returned version is not the match of the entire pattern (i.e. danielebarchiesi@2: * '@version 1.2.3' in the above example) but the match of the first danielebarchiesi@2: * sub-pattern (i.e. '1.2.3' in the above example). danielebarchiesi@2: * - lines: (optional) The maximum number of lines to search the pattern in. danielebarchiesi@2: * Defaults to 20. danielebarchiesi@2: * - cols: (optional) The maximum number of characters per line to take into danielebarchiesi@2: * account. Defaults to 200. In case of minified or compressed files, this danielebarchiesi@2: * prevents reading the entire file into memory. danielebarchiesi@2: * danielebarchiesi@2: * @return danielebarchiesi@2: * A string containing the version of the library. danielebarchiesi@2: * danielebarchiesi@2: * @see libraries_get_path() danielebarchiesi@2: */ danielebarchiesi@2: function libraries_get_version($library, $options) { danielebarchiesi@2: // Provide defaults. danielebarchiesi@2: $options += array( danielebarchiesi@2: 'file' => '', danielebarchiesi@2: 'pattern' => '', danielebarchiesi@2: 'lines' => 20, danielebarchiesi@2: 'cols' => 200, danielebarchiesi@2: ); danielebarchiesi@2: danielebarchiesi@2: $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $options['file']; danielebarchiesi@2: if (empty($options['file']) || !file_exists($file)) { danielebarchiesi@2: return; danielebarchiesi@2: } danielebarchiesi@2: $file = fopen($file, 'r'); danielebarchiesi@2: while ($options['lines'] && $line = fgets($file, $options['cols'])) { danielebarchiesi@2: if (preg_match($options['pattern'], $line, $version)) { danielebarchiesi@2: fclose($file); danielebarchiesi@2: return $version[1]; danielebarchiesi@2: } danielebarchiesi@2: $options['lines']--; danielebarchiesi@2: } danielebarchiesi@2: fclose($file); danielebarchiesi@2: }