Commit 41234e95 authored by sun's avatar sun

#719896 by tstoeckler, sun: Added starting point for hook_libraries_info().

parent 5d1eb613
......@@ -6,12 +6,13 @@ Libraries x.x-x.x, xxxx-xx-xx
Libraries 7.x-1.x, xxxx-xx-xx
-----------------------------
#496732 by tstoeckler, robphillips: Allow placing libraries in root directory.
#719896 by tstoeckler, sun: Added starting point for hook_libraries_info().
#743522 by sun: Ported to D7.
Libraries 6.x-1.x, xxxx-xx-xx
-----------------------------
#496732 by tstoeckler, robphillips: Allow placing libraries in root directory.
#480440 by markus_petrux: Fixed base_path() not applied to default library path.
#320562 by sun: Added basic functions.
<?php
// $Id$
/**
* @file
* Documents API functions for Libraries module.
*/
/**
* Return information about external libraries.
*
* @return
* An associative array whose keys are internal names of libraries and whose
* values are describing each library. Each key is the directory name below
* the 'libraries' directory, in which the library may be found. Each value is
* an associative array containing:
* - title: The official, human-readable name of the library.
* - vendor url: The URL of the homepage of the library.
* - download url: The URL of a web page on which the library can be obtained.
* - path: (optional) A relative path from the directory of the library to the
* actual library. Only required if the extracted download package contains
* the actual library files in a sub-directory.
* - version callback: (optional) The name of a function that detects and
* returns the full version string of the library. Defaults to
* libraries_get_version().
* - version arguments: A list of arguments to pass to the version callback.
* The default version callback libraries_get_version() expects a single,
* single, associative array with named keys:
* - file: The filename to parse for the version, relative to the library
* path. For example: 'docs/changelog.txt'.
* - pattern: A string containing a regular expression (PCRE) to match the
* library version. For example: '/@version (\d+)\.(\d+)/'.
* - lines: The maximum number of lines to search the pattern in. For
* example: 20.
* - cols: (optional) The maximum number of characters per line to take into
* account. For example: 40. Defaults to unlimited. To be used if the file
* containing the library version is minified/compressed, i.e. reading a
* single line would read the entire library into memory.
* - files: An associative array of library files to load. Supported keys are:
* - js: A list of JavaScript files to load, using the same syntax as Drupal
* core's hook_library().
* - css: A list of CSS files to load, using the same syntax as Drupal
* core's hook_library().
* - php: A list of PHP files to load.
* - variants: (optional) An associative array of available library variants.
* For example, the top-level 'files' property may refer to a default
* variant that is compressed. If the library also ships with a minified and
* uncompressed/source variant, those can be defined here. Each key should
* describe the variant type, e.g. 'minified' or 'source'. Each value is an
* associative array of top-level properties that are entirely overridden by
* the variant, most often just 'files'. Variants can be version specific.
* - versions: (optional) An associative array of supported library versions.
* Naturally, external libraries evolve over time and so do their APIs. In
* case a library changes between versions, different 'files' may need to be
* loaded, different 'variants' may become available, or Drupal modules need
* to load different integration files adapted to the new version.
* Each key is a version *string* (PHP does not support floats as keys).
* Each value is an associative array of top-level properties that are
* entirely overridden by the version.
* - integration files: (optional) An associative array whose keys are module
* names and whose values are sets of files to load for the module, using
* the same notion as the top-level 'files' property. Each specified file
* should contain the full path to the file.
* Additional top-level properties can be registered as needed.
*/
function hook_libraries_info() {
// The following is a full explanation of all properties. See below for more
// concrete example implementations.
// This array key lets Libraries API search for 'sites/all/libraries/example'
// directory, which should contain the entire, original extracted library.
$libraries['example'] = array(
// Only used in administrative UI of Libraries API.
'title' => 'Example library',
'vendor url' => 'http://example.com',
'download url' => 'http://example.com/download',
// Optional: If, after extraction, the actual library files are contained in
// 'sites/all/libraries/example/lib', specify the relative path here.
'path' => 'lib',
// Optional: Define a custom version detection callback, if required.
'version callback' => 'mymodule_get_version',
// Specify arguments for the version callback. By default,
// libraries_get_version() takes a named argument array:
'version arguments' => array(
'file' => 'docs/CHANGELOG.txt',
'pattern' => '/@version (\d+)\.(\d+)/',
'lines' => 5,
'cols' => 20,
),
// Default list of files of the library to load. Important: Only specify
// third-party files belonging to the library here, not integration files of
// your module.
'files' => array(
// 'js' and 'css' follow the syntax of hook_library(), but file paths are
// relative to the library path.
'js' => array(
'exlib.js',
'gadgets/foo.js',
),
'css' => array(
'lib_style.css',
'skin/example.css',
),
// For PHP libraries, specify include files here, still relative to the
// library path.
'php' => array(
'exlib.php',
'exlib.inc',
),
),
// Optional: Specify alternative variants of the library, if available.
'variants' => array(
// All properties defined for 'minified' override top-level properties.
'minified' => array(
'files' => array(
'js' => array(
'exlib.min.js',
'gadgets/foo.min.js',
),
'css' => array(
'lib_style.css',
'skin/example.css',
),
),
),
),
// Optional, but usually required: Override top-level properties for later
// versions of the library. The properties of the minimum version that is
// matched override the top-level properties. Note:
// - When registering 'versions', it usually does not make sense to register
// 'files', 'variants', and 'integration files' on the top-level, as most
// of those likely need to be different per version and there are no
// defaults.
// - The array keys have to be strings, as PHP does not support floats for
// array keys.
'versions' => array(
'2' => array(
'files' => array(
'js' => array(
'exlib.js',
),
'css' => array(
'exlib_style.css',
),
),
),
'3.0' => array(
'files' => array(
'js' => array(
'exlib.js',
),
'css' => array(
'lib_style.css',
),
),
),
'3.2' => array(
'files' => array(
'js' => array(
'exlib.js',
'gadgets/foo.js',
),
'css' => array(
'lib_style.css',
'skin/example.css',
),
),
),
),
// Optional: Register files to auto-load for your module. All files must be
// keyed by module, and follow the syntax of the 'files' property.
'integration files' => array(
'mymodule' => array(
'js' => 'ex_lib.inc',
),
),
);
// A very simple library. No changing APIs (hence, no versions), no variants.
// Expected to be extracted into 'sites/all/libraries/simple'.
$libraries['simple'] = array(
'title' => 'Simple library',
'vendor url' => 'http://example.com/simple',
'download url' => 'http://example.com/simple',
'version arguments' => array(
'file' => 'readme.txt',
// Best practice: Document the actual version strings for later reference.
// 1.x: Version 1.0
'pattern' => '/Version (\d+)\.(\d+)/',
'lines' => 5,
),
'files' => array(
'js' => array(
'simple.js',
),
),
);
// A library that (naturally) evolves over time with API changes.
$libraries['tinymce'] = array(
'title' => 'TinyMCE',
'vendor url' => 'http://tinymce.moxiecode.com',
'download url' => 'http://tinymce.moxiecode.com/download.php',
'path' => 'jscripts/tiny_mce',
'version arguments' => array(
// It can be easier to parse the first chars of a minified file instead of
// doing a multi-line pattern matching in a source file. See 'lines' and
// 'cols' below.
'file' => 'jscripts/tiny_mce/tiny_mce.js',
// Best practice: Document the actual version strings for later reference.
// 2.x: this.majorVersion="2";this.minorVersion="1.3"
// 3.x: majorVersion:'3',minorVersion:'2.0.1'
'pattern' => '@majorVersion[=:]["\'](\d).+?minorVersion[=:]["\']([\d\.]+)@',
'lines' => 1,
'cols' => 100,
),
'versions' => array(
'2.1' => array(
'files' => array(
'js' => array('tiny_mce.js'),
),
'variants' => array(
'source' => array(
'files' => array(
'js' => array('tiny_mce_src.js'),
),
),
),
'integration files' => array(
'wysiwyg' => array(
'js' => array(
drupal_get_path('module', 'wysiwyg') . '/editors/js/tinymce-2.js',
),
'css' => array(
drupal_get_path('module', 'wysiwyg') . '/editors/js/tinymce-2.css',
),
),
),
),
// Definition used if 3.1 or above is detected.
'3.1' => array(
// Does not support JS aggregation.
'files' => array(
'js' => array(
'tiny_mce.js' => array('preprocess' => FALSE),
),
),
'variants' => array(
// New variant leveraging jQuery. Not stable yet; therefore not the
// default variant.
'jquery' => array(
'files' => array(
'js' => array(
'tiny_mce_jquery.js' => array('preprocess' => FALSE),
),
),
),
'source' => array(
'files' => array(
'js' => array(
'tiny_mce_src.js' => array('preprocess' => FALSE),
),
),
),
),
'integration files' => array(
'wysiwyg' => array(
'js' => array(
drupal_get_path('module', 'wysiwyg') . '/editors/js/tinymce-3.js',
),
'css' => array(
drupal_get_path('module', 'wysiwyg') . '/editors/js/tinymce-3.css',
),
),
),
),
),
);
return $libraries;
}
; $Id$
name = Libraries
description = External library handling for Drupal modules.
description = Allows version dependent and shared usage of external libraries.
core = 7.x
files[] = libraries.module
files[] = tests/libraries.test
......@@ -112,3 +112,141 @@ function libraries_get_libraries() {
return $directories;
}
/**
* Returns information about registered libraries.
*
* The returned information is unprocessed, i.e. as registered by modules.
*
* @param $library
* (optional) The internal name of a library to return registered information
* for, or FALSE if no library with the given name exists. If omitted,
* information about all libraries is returned.
*
* @return
* An associative array containing registered information for all libraries,
* or the registered information for the library specified by $name.
*
* @see hook_libraries_info()
*
* @todo Re-introduce support for include file plugin system - either by copying
* Wysiwyg's code, or directly switching to CTools.
*/
function libraries_info($library = NULL) {
$libraries = &drupal_static(__FUNCTION__);
if (!isset($libraries)) {
$libraries = array();
foreach (module_implements('libraries_info') as $module) {
foreach (module_invoke($module, 'libraries_info') as $name => $properties) {
$properties['module'] = $module;
$properties['name'] = $name;
$properties += array(
'title' => $name,
'vendor url' => '',
'download url' => '',
'path' => '',
'version callback' => 'libraries_get_version',
'version arguments' => array(),
'files' => array(),
'variants' => array(),
'versions' => array(),
'integration files' => array(),
);
$libraries[$name] = $properties;
}
}
// Allow modules to alter the registered libraries.
drupal_alter('libraries_info', $libraries);
}
if (isset($library)) {
return !empty($libraries[$library]) ? $libraries[$library] : FALSE;
}
return $libraries;
}
/**
* Detect libraries and library versions.
*
* @todo It makes little sense to pass $libraries by reference here. We need to
* figure out whether, and if, how we want to retain the processed
* information. I.e. either use a static cache here, or make libraries_info()
* conditionally invoke libraries_detect($name). D7 only way: Re-use
* drupal_static() of libraries_info() - but would still require to update the
* (DB) cache (there likely will be one soon).
* Also, we probably do not want to ALWAYS parse ALL possible libraries; rather,
* the requesting/consuming module likely wants to know whether a list of
* supported libraries (possibly those registered by itself, or in a certain
* "category") is available... Food for thought.
*
* @param $libraries
* An array of libraries to detect, as returned from libraries_info().
*
* @see libraries_info()
*/
function libraries_detect($libraries) {
foreach ($libraries as $name => $library) {
libraries_detect_library(&$libraries[$name]);
}
return $libraries;
}
/**
* Tries to detect a library and its installed version.
*
* @param $library
* An associative array describing a single library, as returned from
* libraries_info(), passed by reference.
*/
function libraries_detect_library(&$library) {
$library['installed'] = FALSE;
$name = $library['name'];
// Check whether the library exists.
if (!isset($library['library path'])) {
$library['library path'] = libraries_get_path($name);
}
if (!file_exists($library['library path'])) {
$library['error'] = t('%library could not be found.', array('%library' => $library['title']));
continue;
}
// Detect library version.
// Special handling for named arguments (single array).
if (!isset($library['version arguments'][0])) {
$library['version arguments'] = array($library['version arguments']);
}
$library['version'] = call_user_func_array($library['version callback'], $library['version arguments']);
if (empty($library['version'])) {
$library['error'] = t('The version of %library could not be detected.', array('%library' => $library['title']));
continue;
}
// Determine to which supported version the installed version maps.
if (!empty($library['versions'])) {
ksort($library['versions']);
$version = 0;
foreach ($library['versions'] as $supported_version => $version_properties) {
if (version_compare($library['installed version'], $supported_version, '>=')) {
$version = $supported_version;
}
}
if (!$version) {
$library['error'] = t('The installed version %version of %library is not supported.', array('%version' => $library['installed version'], '%library' => $library['title']));
continue;
}
// Apply version specific definitions and overrides.
$library = array_merge($library, $library['versions'][$version]);
unset($library['versions']);
}
// If we end up here, the library should be usable.
$library['installed'] = TRUE;
if (!empty($library['path'])) {
$library['library path'] .= '/' . $library['path'];
}
}
<?php
// $Id$
/**
* @file
* Unit tests for Libraries API.
*/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment