summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libraries.api.php66
-rw-r--r--libraries.module180
-rw-r--r--tests/example/example_installed.txt1
-rw-r--r--tests/example/example_installed_1.css15
-rw-r--r--tests/example/example_installed_1.js19
-rw-r--r--tests/example/example_installed_1.php13
-rw-r--r--tests/example/example_installed_2.css14
-rw-r--r--tests/example/example_installed_2.js18
-rw-r--r--tests/example/example_installed_2.php5
-rw-r--r--tests/example/example_installed_variant.css1
-rw-r--r--tests/example/example_installed_variant.js1
-rw-r--r--tests/example/example_installed_variant.php8
-rw-r--r--tests/example/example_installed_variant_1.css15
-rw-r--r--tests/example/example_installed_variant_1.js19
-rw-r--r--tests/example/example_installed_variant_1.php13
-rw-r--r--tests/example/example_installed_variant_2.css15
-rw-r--r--tests/example/example_installed_variant_2.js19
-rw-r--r--tests/example/example_installed_variant_2.php13
-rw-r--r--tests/libraries.test92
-rw-r--r--tests/libraries_test.css14
-rw-r--r--tests/libraries_test.inc4
-rw-r--r--tests/libraries_test.js18
-rw-r--r--tests/libraries_test.module390
23 files changed, 816 insertions, 137 deletions
diff --git a/libraries.api.php b/libraries.api.php
index f84e6af..155874e 100644
--- a/libraries.api.php
+++ b/libraries.api.php
@@ -22,20 +22,26 @@
* 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().
+ * libraries_get_version(). The first argument is always $library, an array
+ * containing all library information as described here. The following
+ * argument(s) can either be:
+ * - options: An associative array of additional information to pass to the
+ * version callback. In this case the version arguments (see below) must
+ * be declared as an associative array.
+ * - or any number of independent arguments. In this case the version
+ * arguments (see below) must be declared as an indexed array.
* - 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:
+ * 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.
+ * - lines: (optional) The maximum number of lines to search the pattern in.
+ * Defaults to 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.
+ * account. Defaults to 200. In case of minified or compressed files, this
+ * prevents reading the entire file 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().
@@ -48,7 +54,22 @@
* 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.
+ * the variant, most often just 'files'. Additionally, each variant can
+ * contain following properties:
+ * - variant callback: (optional) The name of a function that detects
+ * returns TRUE or FALSE, depending on whether the variant is available or
+ * not. The first argument is always $library, an array containing all
+ * library information as described here. The seconds argument is always
+ * $name, a string containing the name of the variant. The following
+ * argument(s) can either be:
+ * - options: An associative array of additional information to pass to
+ * the version callback. In this case the version arguments (see below)
+ * must be declared as an associative array.
+ * - or any number of independent arguments. In this case the version
+ * arguments (see below) must be declared as an indexed array.
+ * If ommitted, the variant is expected to always be available. Variants
+ * can be version specific.
+ * - variant arguments: A list of arguments to pass to the variant callback.
* - 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
@@ -62,6 +83,8 @@
* 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.
+ *
+ * @see hook_library()
*/
function hook_libraries_info() {
// The following is a full explanation of all properties. See below for more
@@ -122,6 +145,10 @@ function hook_libraries_info() {
'skin/example.css',
),
),
+ 'variant callback' => 'mymodule_check_variant',
+ 'variant arguments' => array(
+ 'variant' => 'minified',
+ ),
),
),
// Optional, but usually required: Override top-level properties for later
@@ -203,9 +230,9 @@ function hook_libraries_info() {
'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.
+ // It can be easier to parse the first characters 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"
@@ -278,3 +305,20 @@ function hook_libraries_info() {
);
return $libraries;
}
+
+/**
+ * Alter the library information before detection and caching takes place.
+ *
+ * The library definitions are passed by reference. A common use-case is adding
+ * a module's integration files to the library array, so that the files are
+ * loaded whenever the library is. As noted above, it is important to declare
+ * integration files inside of an array, whose key is the module name.
+ *
+ * @see hook_libraries_info()
+ */
+function hook_libraries_info_alter(&$libraries) {
+ $files = array(
+ 'php' => array('example_module.php_spellchecker.inc'),
+ );
+ $libraries['php_spellchecker']['integration files']['example_module'] = $files;
+}
diff --git a/libraries.module b/libraries.module
index 1045b4a..5720373 100644
--- a/libraries.module
+++ b/libraries.module
@@ -210,18 +210,22 @@ function libraries_detect_library(&$library) {
}
if (!file_exists($library['library path'])) {
$library['error'] = t('%library could not be found.', array('%library' => $library['title']));
- continue;
+ return;
}
// Detect library version.
- // Special handling for named arguments (single array).
- if (!isset($library['version arguments'][0])) {
- $library['version arguments'] = array($library['version arguments']);
+ // We support both a single parameter, which is an associative array, and an
+ // indexed array of multiple parameters.
+ if (isset($library['version arguments'][0])) {
+ // Add the library as the first argument.
+ $library['version'] = call_user_func_array($library['version callback'], array_merge(array($library), $library['version arguments']));
+ }
+ else {
+ $library['version'] = $library['version callback']($library, $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;
+ return;
}
// Determine to which supported version the installed version maps.
@@ -229,13 +233,16 @@ function libraries_detect_library(&$library) {
ksort($library['versions']);
$version = 0;
foreach ($library['versions'] as $supported_version => $version_properties) {
- if (version_compare($library['installed version'], $supported_version, '>=')) {
+ if (version_compare($library['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;
+ $library['error'] = t('The installed version %version of %library is not supported.', array(
+ '%version' => $library['version'],
+ '%library' => $library['title'],
+ ));
+ return;
}
// Apply version specific definitions and overrides.
@@ -243,10 +250,161 @@ function libraries_detect_library(&$library) {
unset($library['versions']);
}
+ // Check each variant if it is installed.
+ if (!empty($library['variants'])) {
+ foreach ($library['variants'] as $name => &$variant) {
+ // If no variant callback has been set, assume the variant to be
+ // installed.
+ $variant['installed'] = TRUE;
+ if (!empty($variant['variant callback'])) {
+ // We support both a single parameter, which is an associative array,
+ // and an indexed array of multiple parameters.
+ if (isset($variant['variant arguments'][0])) {
+ // Add the library as the first argument, and the variant name as the second.
+ $variant['installed'] = call_user_func_array($variant['variant callback'], array_merge(array($library, $name), $variant['variant arguments']));
+ }
+ else {
+ $variant['installed'] = $variant['variant callback']($library, $name, $variant['variant arguments']);
+ }
+ if (empty($variant['installed'])) {
+ $variant['error'] = t('The %variant variant of %library could not be found.', array(
+ '%variant' => $name,
+ '%library' => $library['title'],
+ ));
+ }
+ }
+ }
+ }
+
// If we end up here, the library should be usable.
$library['installed'] = TRUE;
- if (!empty($library['path'])) {
- $library['library path'] .= '/' . $library['path'];
+}
+
+/**
+ * Loads a library.
+ *
+ * @param $library
+ * The name of the library to load.
+ * @param $variant
+ * The name of the variant to load.
+ */
+function libraries_load($library, $variant = NULL) {
+ $library = libraries_info($library);
+ libraries_detect_library($library);
+ libraries_load_files($library, $variant);
+}
+
+/**
+ * Loads a library's files.
+ *
+ * @param $library
+ * The name of the library to load.
+ * @param $variant
+ * The name of the variant to load.
+ */
+function libraries_load_files($library, $variant = NULL) {
+ // Construct the full path to the library for later use.
+ $path = !empty($library['path']) ? $library['library path'] . '/' . $library['path'] : $library['library path'];
+
+ // If a variant was specified, override the top-level properties with the
+ // variant properties.
+ if (!empty($variant) && !empty($library['variants'][$variant]['installed'])) {
+ $library = array_merge($library, $library['variants'][$variant]);
+ }
+
+ // Load integration files.
+ if (!empty($library['integration files'])) {
+ foreach ($library['integration files'] as $module => $files) {
+ libraries_load_files(array(
+ 'files' => $files,
+ 'library path' => drupal_get_path('module', $module),
+ ));
+ }
+ }
+
+ // Load both the JavaScript and the CSS files.
+ // The parameters for drupal_add_js() and drupal_add_css() require special
+ // handling.
+ // @see drupal_process_attached()
+ foreach (array('js', 'css') as $type) {
+ if (!empty($library['files'][$type])) {
+ foreach ($library['files'][$type] as $data => $options) {
+ // If the value is not an array, it's a filename and passed as first
+ // (and only) argument.
+ if (!is_array($options)) {
+ // Prepend the library path to the file name.
+ $data = "$path/$options";
+ $options = NULL;
+ }
+ // In some cases, the first parameter ($data) is an array. Arrays can't be
+ // passed as keys in PHP, so we have to get $data from the value array.
+ if (is_numeric($data)) {
+ $data = $options['data'];
+ unset($options['data']);
+ }
+ // Apply the default weight if the weight isn't explicitly given.
+ if (!isset($options['weight'])) {
+ $options['weight'] = ($type == 'js') ? JS_DEFAULT : CSS_DEFAULT;
+ }
+ call_user_func('drupal_add_' . $type, $data, $options);
+ }
+ }
+ }
+
+ // Load PHP files.
+ if (!empty($library['files']['php'])) {
+ foreach ($library['files']['php'] as $file) {
+ $file_path = DRUPAL_ROOT . '/' . $path . '/' . $file;
+ if (file_exists($file_path)) {
+ require_once $file_path;
+ }
+ }
+ }
+}
+
+/**
+ * Gets the version information from an arbitrary library.
+ *
+ * @param $library
+ * An associative array containing all information about the library.
+ * @param $options
+ * An associative array containing with the following 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: (optional) The maximum number of lines to search the pattern in.
+ * Defaults to 20.
+ * - cols: (optional) The maximum number of characters per line to take into
+ * account. Defaults to 200. In case of minified or compressed files, this
+ * prevents reading the entire file into memory.
+ *
+ * @return
+ * A string containing the version of the library.
+ *
+ * @see libraries_get_path()
+ */
+function libraries_get_version($library, $options) {
+ // Provide defaults.
+ $options += array(
+ 'file' => '',
+ 'pattern' => '',
+ 'lines' => 20,
+ 'cols' => 200,
+ );
+
+ $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $options['file'];
+ if (empty($options['file']) || !file_exists($file)) {
+ return;
+ }
+ $file = fopen($file, 'r');
+ while ($options['lines'] && $line = fgets($file, $options['cols'])) {
+ if (preg_match($options['pattern'], $line, $version)) {
+ fclose($file);
+ return $version[1];
+ }
+ $options['lines']--;
}
+ fclose($file);
}
diff --git a/tests/example/example_installed.txt b/tests/example/example_installed.txt
index cca2a47..6324b31 100644
--- a/tests/example/example_installed.txt
+++ b/tests/example/example_installed.txt
@@ -4,3 +4,4 @@ Example library
Version 2
+This file is an example file to test version detection.
diff --git a/tests/example/example_installed_1.css b/tests/example/example_installed_1.css
new file mode 100644
index 0000000..358a8cd
--- /dev/null
+++ b/tests/example/example_installed_1.css
@@ -0,0 +1,15 @@
+/* $Id$ */
+
+/**
+ * @file
+ * Test CSS file for Libraries loading.
+ *
+ * Because we cannot test CSS programatically with SimpleTest, the CSS below can
+ * be useful for debugging with SimpleTest's verbose mode. Note that since the
+ * DOM cannot be manipulated via CSS, JavaScript loading needs to be functional
+ * for this to have any visible effect.
+ */
+
+div#libraries-test {
+ color: red;
+}
diff --git a/tests/example/example_installed_1.js b/tests/example/example_installed_1.js
new file mode 100644
index 0000000..af23ac2
--- /dev/null
+++ b/tests/example/example_installed_1.js
@@ -0,0 +1,19 @@
+// $Id$
+
+/**
+ * @file
+ * Test JavaScript file for Libraries loading.
+ *
+ * Because we cannot test JavaScript programatically with SimpleTest, the
+ * JavaScript below can be useful for debugging with SimpleTest's verbose mode.
+ */
+
+(function ($) {
+
+Drupal.behaviors.librariesTest = {
+ attach: function(context, settings) {
+ $('h1#page-title').after('<div id="libraries-test">If this text shows up, the JavaScript file was loaded successfully. If this text is red, the CSS file was loaded successfully.</div>')
+ }
+};
+
+})(jQuery);
diff --git a/tests/example/example_installed_1.php b/tests/example/example_installed_1.php
new file mode 100644
index 0000000..9044604
--- /dev/null
+++ b/tests/example/example_installed_1.php
@@ -0,0 +1,13 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Test PHP file for Libraries loading.
+ */
+
+/**
+ * Dummy function to see if this file was loaded.
+ */
+function _libraries_example_installed_1() {
+}
diff --git a/tests/example/example_installed_2.css b/tests/example/example_installed_2.css
index a0749a0..6a8ed7e 100644
--- a/tests/example/example_installed_2.css
+++ b/tests/example/example_installed_2.css
@@ -1 +1,15 @@
/* $Id$ */
+
+/**
+ * @file
+ * Test CSS file for Libraries loading.
+ *
+ * Because we cannot test CSS programatically with SimpleTest, the CSS below can
+ * be useful for debugging with SimpleTest's verbose mode. Note that since the
+ * DOM cannot be manipulated via CSS, JavaScript loading needs to be functional
+ * for this to have any visible effect.
+ */
+
+div#libraries-test {
+ color: green;
+}
diff --git a/tests/example/example_installed_2.js b/tests/example/example_installed_2.js
index cfa1da3..f9926b2 100644
--- a/tests/example/example_installed_2.js
+++ b/tests/example/example_installed_2.js
@@ -1 +1,19 @@
// $Id$
+
+/**
+ * @file
+ * Test JavaScript file for Libraries loading.
+ *
+ * Because we cannot test JavaScript programatically with SimpleTest, the
+ * JavaScript below can be useful for debugging with SimpleTest's verbose mode.
+ */
+
+(function ($) {
+
+Drupal.behaviors.librariesTest = {
+ attach: function(context, settings) {
+ $('h1#page-title').after('<div id="libraries-test">If this text shows up, the JavaScript file was loaded successfully. If this text is green, the CSS file was loaded successfully.</div>')
+ }
+};
+
+})(jQuery);
diff --git a/tests/example/example_installed_2.php b/tests/example/example_installed_2.php
index 34950ab..3976fa9 100644
--- a/tests/example/example_installed_2.php
+++ b/tests/example/example_installed_2.php
@@ -2,6 +2,11 @@
// $Id$
/**
+ * @file
+ * Test PHP file for Libraries loading.
+ */
+
+/**
* Dummy function to see if this file was loaded.
*/
function _libraries_example_installed_2() {
diff --git a/tests/example/example_installed_variant.css b/tests/example/example_installed_variant.css
deleted file mode 100644
index a0749a0..0000000
--- a/tests/example/example_installed_variant.css
+++ /dev/null
@@ -1 +0,0 @@
-/* $Id$ */
diff --git a/tests/example/example_installed_variant.js b/tests/example/example_installed_variant.js
deleted file mode 100644
index cfa1da3..0000000
--- a/tests/example/example_installed_variant.js
+++ /dev/null
@@ -1 +0,0 @@
-// $Id$
diff --git a/tests/example/example_installed_variant.php b/tests/example/example_installed_variant.php
deleted file mode 100644
index 2b3fed7..0000000
--- a/tests/example/example_installed_variant.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-// $Id$
-
-/**
- * Dummy function to see if this file was loaded.
- */
-function _libraries_example_installed_variant() {
-}
diff --git a/tests/example/example_installed_variant_1.css b/tests/example/example_installed_variant_1.css
new file mode 100644
index 0000000..894fa3a
--- /dev/null
+++ b/tests/example/example_installed_variant_1.css
@@ -0,0 +1,15 @@
+/* $Id$ */
+
+/**
+ * @file
+ * Test CSS file for Libraries loading.
+ *
+ * Because we cannot test CSS programatically with SimpleTest, the CSS below can
+ * be useful for debugging with SimpleTest's verbose mode. Note that since the
+ * DOM cannot be manipulated via CSS, JavaScript loading needs to be functional
+ * for this to have any visible effect.
+ */
+
+div#libraries-test {
+ color: orange;
+}
diff --git a/tests/example/example_installed_variant_1.js b/tests/example/example_installed_variant_1.js
new file mode 100644
index 0000000..835d9f7
--- /dev/null
+++ b/tests/example/example_installed_variant_1.js
@@ -0,0 +1,19 @@
+// $Id$
+
+/**
+ * @file
+ * Test JavaScript file for Libraries loading.
+ *
+ * Because we cannot test JavaScript programatically with SimpleTest, the
+ * JavaScript below can be useful for debugging with SimpleTest's verbose mode.
+ */
+
+(function ($) {
+
+Drupal.behaviors.librariesTest = {
+ attach: function(context, settings) {
+ $('h1#page-title').after('<div id="libraries-test">If this text shows up, the JavaScript file was loaded successfully. If this text is orange, the CSS file was loaded successfully.</div>')
+ }
+};
+
+})(jQuery);
diff --git a/tests/example/example_installed_variant_1.php b/tests/example/example_installed_variant_1.php
new file mode 100644
index 0000000..f68ed40
--- /dev/null
+++ b/tests/example/example_installed_variant_1.php
@@ -0,0 +1,13 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Test PHP file for Libraries loading.
+ */
+
+/**
+ * Dummy function to see if this file was loaded.
+ */
+function _libraries_example_installed_variant_1() {
+}
diff --git a/tests/example/example_installed_variant_2.css b/tests/example/example_installed_variant_2.css
new file mode 100644
index 0000000..4a8a9a1
--- /dev/null
+++ b/tests/example/example_installed_variant_2.css
@@ -0,0 +1,15 @@
+/* $Id$ */
+
+/**
+ * @file
+ * Test CSS file for Libraries loading.
+ *
+ * Because we cannot test CSS programatically with SimpleTest, the CSS below can
+ * be useful for debugging with SimpleTest's verbose mode. Note that since the
+ * DOM cannot be manipulated via CSS, JavaScript loading needs to be functional
+ * for this to have any visible effect.
+ */
+
+div#libraries-test {
+ color: blue;
+}
diff --git a/tests/example/example_installed_variant_2.js b/tests/example/example_installed_variant_2.js
new file mode 100644
index 0000000..bae6104
--- /dev/null
+++ b/tests/example/example_installed_variant_2.js
@@ -0,0 +1,19 @@
+// $Id$
+
+/**
+ * @file
+ * Test JavaScript file for Libraries loading.
+ *
+ * Because we cannot test JavaScript programatically with SimpleTest, the
+ * JavaScript below can be useful for debugging with SimpleTest's verbose mode.
+ */
+
+(function ($) {
+
+Drupal.behaviors.librariesTest = {
+ attach: function(context, settings) {
+ $('h1#page-title').after('<div id="libraries-test">If this text shows up, the JavaScript file was loaded successfully. If this text is blue, the CSS file was loaded successfully.</div>')
+ }
+};
+
+})(jQuery);
diff --git a/tests/example/example_installed_variant_2.php b/tests/example/example_installed_variant_2.php
new file mode 100644
index 0000000..5d0960a
--- /dev/null
+++ b/tests/example/example_installed_variant_2.php
@@ -0,0 +1,13 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Test PHP file for Libraries loading.
+ */
+
+/**
+ * Dummy function to see if this file was loaded.
+ */
+function _libraries_example_installed_variant_2() {
+}
diff --git a/tests/libraries.test b/tests/libraries.test
index a6fb642..9381959 100644
--- a/tests/libraries.test
+++ b/tests/libraries.test
@@ -51,41 +51,103 @@ class LibrariesTestCase extends DrupalWebTestCase {
));
$this->assertEqual($library['error'], $error, 'Unsupported library version found.');
+ // Test supported library version.
+ $library = libraries_info('example_supported_version');
+ libraries_detect_library($library);
+ $this->assertEqual($library['installed'], TRUE, 'Supported library version found.');
+
// Test libraries_get_version().
- $library = libraries_info('example_installed');
+ $library = libraries_info('example_default_version_callback');
libraries_detect_library($library);
$version = '2';
$this->assertEqual($library['version'], $version, 'Expected version returned by default version callback.');
+ // Test a multiple-parameter version callback.
+ $library = libraries_info('example_multiple_parameter_version_callback');
+ libraries_detect_library($library);
+ $version = '2';
+ $this->assertEqual($library['version'], $version, 'Expected version returned by multiple parameter version callback.');
+
+ // Test a top-level files property.
+ $library = libraries_info('example_simple');
+ libraries_detect_library($library);
+ $files = array(
+ 'js' => array('example_installed_1.js'),
+ 'css' => array('example_installed_1.css'),
+ 'php' => array('example_installed_1.php'),
+ );
+ $this->assertEqual($library['files'], $files, 'Top-level files property works.');
+
// Test version-specific library files.
+ $library = libraries_info('example_versions');
+ libraries_detect_library($library);
$files = array(
'js' => array('example_installed_2.js'),
'css' => array('example_installed_2.css'),
'php' => array('example_installed_2.php'),
);
$this->assertEqual($library['files'], $files, 'Version-specific library files found.');
- // @todo Ensure that default files are not contained.
- // Test library loading.
- $this->drupalGet('libraries_test');
+ // Test missing variant.
+ $library = libraries_info('example_variant_missing');
+ libraries_detect_library($library);
+ $variants = array_keys($library['variants']);
+ $error = t('The %variant variant of %library could not be found.', array(
+ '%variant' => $variants[0],
+ '%library' => $library['title'],
+ ));
+ $this->assertEqual($library['variants']['example_variant_1']['error'], $error, 'Missing variant not found.');
+
+ // Test existing variant.
+ $library = libraries_info('example_variant');
+ libraries_detect_library($library);
+ $this->assertEqual($library['variants']['example_variant_1']['installed'], TRUE, 'Existing variant found.');
+
+ // Test loading of a simple library with a top-level files property.
+ $this->drupalGet('libraries_test/simple');
+ $this->assertRaw('example_installed_1.js', 'A JavaScript file is loaded correctly.');
+ $this->assertRaw('example_installed_1.css', 'A CSS file is loaded correctly.');
+ $this->assertText('example_installed_1.php', 'A PHP file is loaded correctly.');
- $this->assertRaw('example_installed_2.js', 'The JavaScript file is loaded.');
- $this->assertRaw('example_installed_2.css', 'The CSS file is loaded.');
- $this->assertText('example_installed_2.php', 'The PHP file is loaded.');
+ // Test loading of integration files.
+ $this->drupalGet('libraries_test/integration_files');
$this->assertRaw('libraries_test.js', 'The JavaScript integration file is loaded.');
$this->assertRaw('libraries_test.css', 'The CSS integration file is loaded.');
$this->assertText('libraries_test.inc', 'The PHP integration file is loaded.');
+ // Test version overloading.
+ $this->drupalGet('libraries_test/versions');
+ $this->assertNoRaw('example_installed_1.js', 'The JavaScript file of the wrong library version is not loaded.');
+ $this->assertNoRaw('example_installed_1.css', 'The CSS file of the wrong library version is not loaded.');
+ $this->assertNoText('example_installed_1.php', 'The PHP file of the wrong library version is not loaded.');
+ $this->assertRaw('example_installed_2.js', 'The JavaScript file of the correct library version is loaded.');
+ $this->assertRaw('example_installed_2.css', 'The CSS file of the correct library version is loaded.');
+ $this->assertText('example_installed_2.php', 'The PHP file of the correct library version is loaded.');
+
// Test variant loading.
- // @todo Move onto libraries_test/variant (maintain namespace).
- $this->drupalGet('libraries_test_variant');
+ $this->drupalGet('libraries_test/variant');
+ $this->assertNoRaw('example_installed_variant_2.js', 'The JavaScript file of the wrong library variant is not loaded.');
+ $this->assertNoRaw('example_installed_variant_2.css', 'The CSS file of the wrong library variant is not loaded.');
+ $this->assertNoText('example_installed_variant_2.php', 'The PHP file of the wrong library variant is not loaded.');
+ $this->assertRaw('example_installed_variant_1.js', 'The JavaScript file of the correct library variant is loaded.');
+ $this->assertRaw('example_installed_variant_1.css', 'The CSS file of the correct library variant is loaded.');
+ $this->assertText('example_installed_variant_1.php', 'The PHP file of the correct library variant is loaded.');
+
+ // Test version overloading and variant loading.
+ $this->drupalGet('libraries_test/versions_and_variants');
+ $this->assertNoRaw('example_installed_1.js', 'The JavaScript file of the wrong library version and variant is not loaded.');
+ $this->assertNoRaw('example_installed_1.css', 'The CSS file of the wrong library version and variant is not loaded.');
+ $this->assertNoText('example_installed_1.php', 'The PHP file of the wrong library version and variant is not loaded.');
+ $this->assertNoRaw('example_installed_2.js', 'The JavaScript file of the wrong library version and variant is not loaded.');
+ $this->assertNoRaw('example_installed_2.css', 'The CSS file of the wrong library version and variant is not loaded.');
+ $this->assertNoText('example_installed_2.php', 'The PHP file of the wrong library version and variant is not loaded.');
+ $this->assertNoRaw('example_installed_variant_1.js', 'The JavaScript file of the wrong library version and variant is not loaded.');
+ $this->assertNoRaw('example_installed_variant_1.css', 'The CSS file of the wrong library version and variant is not loaded.');
+ $this->assertNoText('example_installed_variant_1.php', 'The PHP file of the wrong library version and variant is not loaded.');
+ $this->assertRaw('example_installed_variant_2.js', 'The JavaScript file of the correct library version and variant is loaded.');
+ $this->assertRaw('example_installed_variant_2.css', 'The CSS file of the correct library version and variant is loaded.');
+ $this->assertText('example_installed_variant_2.php', 'The PHP file of the correct library version and variant is loaded.');
- $this->assertRaw('example_installed_variant.js', 'The JavaScript file is loaded.');
- $this->assertRaw('example_installed_variant.css', 'The CSS file is loaded.');
- $this->assertText('example_installed_variant.php', 'The PHP file is loaded.');
- $this->assertRaw('libraries_test.js', 'The JavaScript integration file is loaded.');
- $this->assertRaw('libraries_test.css', 'The CSS integration file is loaded.');
- $this->assertText('libraries_test.inc', 'The PHP integration file is loaded.');
}
}
diff --git a/tests/libraries_test.css b/tests/libraries_test.css
index a0749a0..f394ca6 100644
--- a/tests/libraries_test.css
+++ b/tests/libraries_test.css
@@ -1 +1,15 @@
/* $Id$ */
+
+/**
+ * @file
+ * Test CSS file for Libraries loading.
+ *
+ * Because we cannot test CSS programatically with SimpleTest, the CSS below can
+ * be useful for debugging with SimpleTest's verbose mode. Note that since the
+ * DOM cannot be manipulated via CSS, JavaScript loading needs to be functional
+ * for this to have any visible effect.
+ */
+
+div#libraries-test {
+ color: purple;
+}
diff --git a/tests/libraries_test.inc b/tests/libraries_test.inc
index fb21b71..844d4b4 100644
--- a/tests/libraries_test.inc
+++ b/tests/libraries_test.inc
@@ -2,6 +2,10 @@
// $Id$
/**
+ * @file
+ * Test PHP file for Libraries loading.
+
+/**
* Dummy function to see if this file was loaded.
*/
function libraries_test_1() {
diff --git a/tests/libraries_test.js b/tests/libraries_test.js
index cfa1da3..d16d23b 100644
--- a/tests/libraries_test.js
+++ b/tests/libraries_test.js
@@ -1 +1,19 @@
// $Id$
+
+/**
+ * @file
+ * Test JavaScript file for Libraries loading.
+ *
+ * Because we cannot test JavaScript programatically with SimpleTest, the
+ * JavaScript below can be useful for debugging with SimpleTest's verbose mode.
+ */
+
+(function ($) {
+
+Drupal.behaviors.librariesTest = {
+ attach: function(context, settings) {
+ $('h1#page-title').after('<div id="libraries-test">If this text shows up, the JavaScript file was loaded successfully. If this text is purple, the CSS file was loaded successfully.</div>')
+ }
+};
+
+})(jQuery);
diff --git a/tests/libraries_test.module b/tests/libraries_test.module
index 246cdf0..054be3b 100644
--- a/tests/libraries_test.module
+++ b/tests/libraries_test.module
@@ -10,38 +10,41 @@
* Implements hook_libraries_info().
*
* Note: DO NOT use drupal_get_path() in your implementations! Used for testing
- * purposes only.
+ * purposes only. It is strongly discouraged to declare the 'library path'
+ * property as that will be detected by Libraries API automatically.
*/
function libraries_test_libraries_info() {
// Test library detection.
$libraries['example_missing'] = array(
'library path' => drupal_get_path('module', 'libraries') . '/tests/missing',
- 'version callback' => 'libraries_test_get_version',
- 'version arguments' => array(
- 'version' => '1',
- ),
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('1'),
);
$libraries['example_undetected_version'] = array(
'library path' => drupal_get_path('module', 'libraries') . '/tests',
- 'version callback' => 'libraries_test_get_version',
- 'version arguments' => array(
- 'version' => 'undetected',
- ),
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array(FALSE),
);
$libraries['example_unsupported_version'] = array(
'library path' => drupal_get_path('module', 'libraries') . '/tests',
- 'version callback' => 'libraries_test_get_version',
- 'version arguments' => array(
- 'version' => '1',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('1'),
+ 'versions' => array(
+ '2' => array(),
),
+ );
+
+ $libraries['example_supported_version'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
'versions' => array(
'2' => array(),
),
);
- // Test version- and variant-overloading, default version callback and library
- // loading.
- $libraries['example_installed'] = array(
+ // Test the default version callback.
+ $libraries['example_default_version_callback'] = array(
'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
'version arguments' => array(
'file' => 'example_installed.txt',
@@ -49,82 +52,226 @@ function libraries_test_libraries_info() {
'pattern' => '/Version (\d+)/',
'lines' => 5,
),
- // @todo Version-less files, if library declares versions?
- // @todo These files don't exist. On purpose?
+ );
+
+ // Test a multiple-parameter version callback.
+ $libraries['example_multiple_parameter_version_callback'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ // Version 2
+ 'version callback' => '_libraries_get_version',
+ 'version arguments' => array('example_installed.txt', '/Version (\d+)/', 5),
+ );
+
+ // Test a top-level files property.
+ $libraries['example_simple'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('1'),
'files' => array(
'js' => array(
- 'example_installed.js',
+ 'example_installed_1.js',
),
'css' => array(
- 'example_installed.css',
+ 'example_installed_1.css',
),
'php' => array(
- 'example_installed.php'
+ 'example_installed_1.php'
),
),
);
- $libraries['example_installed']['versions'] = array(
- // @todo Files for version 1 do not exist. On purpose?
- '1' => array(
- 'files' => array(
+ // Test loading of integration files.
+ // Normally added by the corresponding module via hook_libraries_info_alter(),
+ // these files should be automatically loaded when the library is loaded.
+ $libraries['example_integration_files'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
+ 'integration files' => array(
+ 'libraries_test' => array(
'js' => array(
- 'example_installed_1.js',
+ 'libraries_test.js',
),
'css' => array(
- 'example_installed_1.css',
+ 'libraries_test.css',
),
'php' => array(
- 'example_installed_1.php',
+ 'libraries_test.inc',
),
),
),
- '2' => array(
- 'files' => array(
- 'js' => array(
- 'example_installed_2.js',
- ),
- 'css' => array(
- 'example_installed_2.css',
+ );
+
+ // Test version overloading.
+ $libraries['example_versions'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
+ 'versions' => array(
+ '1' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_1.js',
+ ),
+ 'css' => array(
+ 'example_installed_1.css',
+ ),
+ 'php' => array(
+ 'example_installed_1.php',
+ ),
),
- 'php' => array(
- 'example_installed_2.php',
+ ),
+ '2' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_2.js',
+ ),
+ 'css' => array(
+ 'example_installed_2.css',
+ ),
+ 'php' => array(
+ 'example_installed_2.php',
+ ),
),
),
),
);
- // @todo Variant callback missing.
- $libraries['example_installed']['variants'] = array(
- // @todo Is "variant" the name of a variant?
- 'variant' => array(
- 'files' => array(
- 'js' => array(
- 'example_installed_variant.js',
+ // Test variant detection.
+ $libraries['example_variant_missing'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
+ 'variants' => array(
+ 'example_variant_1' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_variant_1.js',
+ ),
+ 'css' => array(
+ 'example_installed_variant_1.css',
+ ),
+ 'php' => array(
+ 'example_installed_variant_1.php',
+ ),
),
- 'css' => array(
- 'example_installed_variant.css',
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(FALSE),
+ ),
+ ),
+ );
+
+ $libraries['example_variant'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
+ 'variants' => array(
+ 'example_variant_1' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_variant_1.js',
+ ),
+ 'css' => array(
+ 'example_installed_variant_1.css',
+ ),
+ 'php' => array(
+ 'example_installed_variant_1.php',
+ ),
),
- 'php' => array(
- 'example_installed_variant.php',
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
+ ),
+ 'example_variant_2' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_variant_2.js',
+ ),
+ 'css' => array(
+ 'example_installed_variant_2.css',
+ ),
+ 'php' => array(
+ 'example_installed_variant_2.php',
+ ),
),
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
),
),
);
- // Integration files for example_installed library.
- // Normally added by the corresponding module via hook_libraries_info_alter(),
- // these files should be automatically loaded when the library is loaded.
- $libraries['example_installed']['integration files'] = array(
- 'libraries_test' => array(
- 'js' => array(
- 'libraries_test.js',
- ),
- 'css' => array(
- 'libraries_test.css',
+ // Test correct behaviour with multiple versions and multiple variants.
+ $libraries['example_versions_and_variants'] = array(
+ 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
+ 'version callback' => '_libraries_test_return_version',
+ 'version arguments' => array('2'),
+ 'versions' => array(
+ '1' => array(
+ 'variants' => array(
+ 'example_variant_1' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_1.js',
+ ),
+ 'css' => array(
+ 'example_installed_1.css',
+ ),
+ 'php' => array(
+ 'example_installed_1.php',
+ ),
+ ),
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
+ ),
+ 'example_variant_2' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_variant_1.js',
+ ),
+ 'css' => array(
+ 'example_installed_variant_1.css',
+ ),
+ 'php' => array(
+ 'example_installed_variant_1.php',
+ ),
+ ),
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
+ ),
+ ),
),
- 'php' => array(
- 'libraries_test.inc',
+ '2' => array(
+ 'variants' => array(
+ 'example_variant_1' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_2.js',
+ ),
+ 'css' => array(
+ 'example_installed_2.css',
+ ),
+ 'php' => array(
+ 'example_installed_2.php',
+ ),
+ ),
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
+ ),
+ 'example_variant_2' => array(
+ 'files' => array(
+ 'js' => array(
+ 'example_installed_variant_2.js',
+ ),
+ 'css' => array(
+ 'example_installed_variant_2.css',
+ ),
+ 'php' => array(
+ 'example_installed_variant_2.php',
+ ),
+ ),
+ 'variant callback' => '_libraries_test_detect_variant',
+ 'variant arguments' => array(TRUE),
+ ),
+ ),
),
),
);
@@ -137,62 +284,125 @@ function libraries_test_libraries_info() {
*
* Returns exactly the version string entered as the $version parameter, unless
* you specify 'undetected', in which case it returns nothing.
+ */
+function _libraries_test_return_version($library, $version) {
+ return $version;
+}
+
+/**
+ * Gets the version information from an arbitrary library.
+ *
+ * This is an exact copy of libraries_get_version() except for the fact that it
+ * does not take a single associative array as a parameter but multiple
+ * parameters. Since we support both type of version callbacks this might be
+ * a useful reference for a custom version callback that uses multiple
+ * parameters
+ *
+ * @param $library
+ * An associative array containing all information about the library.
+ * @param $file
+ * The filename to parse for the version, relative to the library path. For
+ * example: 'docs/changelog.txt'.
+ * @param pattern
+ * A string containing a regular expression (PCRE) to match the library
+ * version. For example: '/@version (\d+)\.(\d+)/'.
+ * @param lines
+ * (optional) The maximum number of lines to search the pattern in. Defaults
+ * to 20.
+ * @param cols
+ * (optional) The maximum number of characters per line to take into account.
+ * Defaults to 200. In case of minified or compressed files, this prevents
+ * reading the entire file into memory.
+ *
+ * @return
+ * A string containing the version of the library.
*
- * @todo Shouldn't this get some info/arguments passed by Libraries API? (?)
+ * @see libraries_get_version()
*/
-function libraries_test_get_version($version) {
- if ($version !== 'undetected') {
- return $version;
+function _libraries_get_version($library, $file, $pattern, $lines = 20, $cols = 200) {
+
+ $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $file;
+ if (!file_exists($file)) {
+ return;
+ }
+ $file = fopen($file, 'r');
+ while ($lines && $line = fgets($file, $cols)) {
+ if (preg_match($pattern, $line, $version)) {
+ fclose($file);
+ return $version[1];
+ }
+ $lines--;
}
+ fclose($file);
+}
+
+/**
+ * Detects the variant of an example library.
+ *
+ * Returns TRUE or FALSE depending on whether the $status parameter is 'missing'
+ * or 'found'.
+ */
+function _libraries_test_detect_variant($library, $name, $status) {
+ return $status;
}
/**
* Implements hook_menu().
*/
function libraries_test_menu() {
- $items['libraries_test'] = array(
- 'title' => 'Libraries loading test',
- 'page callback' => 'libraries_test_load',
+ $items['libraries_test/simple'] = array(
+ 'title' => 'Test simple library',
+ 'page callback' => '_libraries_test_load',
+ 'page arguments' => array('example_simple'),
+ 'access callback' => TRUE,
+ );
+ $items['libraries_test/integration_files'] = array(
+ 'title' => 'Test integration files',
+ 'page callback' => '_libraries_test_load',
+ 'page arguments' => array('example_integration_files'),
+ 'access callback' => TRUE,
+ );
+ $items['libraries_test/versions'] = array(
+ 'title' => 'Test version loading',
+ 'page callback' => '_libraries_test_load',
+ 'page arguments' => array('example_versions'),
+ 'access callback' => TRUE,
+ );
+ $items['libraries_test/variant'] = array(
+ 'title' => 'Test variant loading',
+ 'page callback' => '_libraries_test_load',
+ 'page arguments' => array('example_variant', 'example_variant_1'),
'access callback' => TRUE,
);
- $items['libraries_test_variant'] = array(
- 'title' => 'Libraries variant loading test',
- 'page callback' => 'libraries_test_load_variant',
+ $items['libraries_test/versions_and_variants'] = array(
+ 'title' => 'Test concurrent version and variant loading',
+ 'page callback' => '_libraries_test_load',
+ 'page arguments' => array('example_versions_and_variants', 'example_variant_2'),
'access callback' => TRUE,
);
return $items;
}
/**
- * Loads the test library.
+ * Loads the test library with multiple versions.
*/
-function libraries_test_load() {
- libraries_load('example_installed');
+function _libraries_test_load($library, $variant = NULL) {
+ libraries_load($library, $variant);
// JavaScript and CSS files can be checked directly by SimpleTest, so we only
// need to manually check for PHP files.
$output = '';
- if (function_exists('example_installed_2')) {
+ if (function_exists('_libraries_example_installed_1')) {
+ $output .= 'example_installed_1.php';
+ }
+ if (function_exists('_libraries_example_installed_2')) {
$output .= 'example_installed_2.php';
}
- // Check for the PHP integration file.
- if (function_exists('libraries_test_1')) {
- $output .= 'libraries_test.inc';
+ if (function_exists('_libraries_example_installed_variant_1')) {
+ $output .= 'example_installed_variant_1.php';
}
- return $output;
-}
-
-/**
- * Loads the test variant of the test library.
- */
-function libraries_test_load_variant() {
- libraries_load('example_installed', 'variant');
- // JavaScript and CSS files can be checked directly by SimpleTest, so we only
- // need to manually check for PHP files.
- $output = '';
- if (function_exists('example_installed_variant')) {
- $output .= 'example_installed_variant.php';
+ if (function_exists('_libraries_example_installed_variant_2')) {
+ $output .= 'example_installed_variant_2.php';
}
- // Check for the PHP integration file.
if (function_exists('libraries_test_1')) {
$output .= 'libraries_test.inc';
}