diff --git a/libraries.api.php b/libraries.api.php
index ac09743..17c086a 100644
--- a/libraries.api.php
+++ b/libraries.api.php
@@ -164,8 +164,16 @@
* Note that in this group the 'versions' property is no longer available.
* - pre-load: Callbacks registered in this group are applied directly
* before this library is loaded. At this point the library contains
- * variant-specific information, if specified. Note that in this group the
- * 'variants' property is no longer available.
+ * variant-specific information, if specified, and following additional
+ * information is available:
+ * - $library['variant']: The variant of the library that is about to be
+ * loaded.
+ * The following pre-load callbacks are available for all libraries:
+ * - libaries_replace_filenames: Use this callback if your library files
+ * have version- or variant-dependant filenames. The callback replaces
+ * all occurences of '!version' in filenames with the detected library
+ * version and all occurences of '!variant' with the variant.
+ * Note that in this group the 'variants' property is no longer available.
* - post-load: Callbacks registered in this group are applied directly
* after this library is loaded. At this point, the library contains a
* 'loaded' key, which contains the number of files that were loaded.
diff --git a/libraries.info b/libraries.info
index 208a14e..b70306e 100644
--- a/libraries.info
+++ b/libraries.info
@@ -2,3 +2,5 @@ name = Libraries
description = Allows version dependent and shared usage of external libraries.
core = 7.x
files[] = tests/libraries.test
+; We use format_string() in libraries_replace_filenames()
+dependencies[] = system (>=7.9)
diff --git a/libraries.module b/libraries.module
index c67ce79..bed0709 100644
--- a/libraries.module
+++ b/libraries.module
@@ -311,6 +311,58 @@ function libraries_detect_dependencies(&$library, $version = NULL, $variant = NU
}
/**
+ * Library pre-load callback to replace the version and variant in filenames.
+ *
+ * This callback allows to specify a filename as e.g.
+ * example-!version-!variant.js in hook_libraries_info(). It turns that into
+ * e.g. example-1.2.3-minified.js before loading the library.
+ *
+ * @param $library
+ * An associative array of library information or a part of it, passed by
+ * reference.
+ * @param $version
+ * If the library information belongs to a specific version, the version
+ * string. NULL otherwise.
+ * @param $variant
+ * If the library information belongs to a specific variant, the variant name.
+ * NULL otherwise.
+ *
+ * @see libraries_invoke()
+ */
+function libraries_replace_filenames(&$library, $version = NULL, $variant = NULL) {
+ // Both the 'files' property and the 'integration files' property contain file
+ // declarations, and we want to replace both.
+ $file_types = array();
+ if (isset($library['files'])) {
+ $file_types[] = &$library['files'];
+ }
+ if (isset($library['integration files'])) {
+ // Integration files are additionally keyed by module.
+ foreach ($library['integration files'] as &$integration_files) {
+ $file_types[] = &$integration_files;
+ }
+ }
+ foreach ($file_types as &$files) {
+ // Go through all supported types of files.
+ foreach (array('js', 'css', 'php') as $type) {
+ if (isset($files[$type])) {
+ foreach ($files[$type] as $old => $options) {
+ unset($files[$type][$old]);
+
+ $args = array('!version' => $library['version']);
+ // A library can be loaded without specifying a variant.
+ if (isset($library['variant'])) {
+ $args['!variant'] = $library['variant'];
+ }
+ $new = format_string($old, $args);
+ $files[$type][$new] = $options;
+ }
+ }
+ }
+ }
+}
+
+/**
* Returns information about registered libraries.
*
* The returned information is unprocessed; i.e., as registered by modules.
@@ -589,6 +641,8 @@ function libraries_load($name, $variant = NULL) {
// of the library files below.
$library['variants'] += array($variant => array('installed' => FALSE));
$library = array_merge($library, $library['variants'][$variant]);
+ // Make the variant available to 'pre-load' and 'post-load' callbacks.
+ $library['variant'] = $variant;
}
// Regardless of whether a specific variant was requested or not, there can
// only be one variant of a library within a single request.
diff --git a/tests/libraries.test b/tests/libraries.test
index c361bcd..1675077 100644
--- a/tests/libraries.test
+++ b/tests/libraries.test
@@ -122,6 +122,24 @@ class LibrariesTestCase extends DrupalWebTestCase {
$this->verbose('Actual:
' . $library['error message']);
$this->assertEqual($library['error message'], $error_message, 'Correct error message for an incompatible dependency');
+ // Test libraries_replace_filename().
+ $library = array(
+ 'version' => '1',
+ 'files' => array('js' => array('example-!version.js' => array())),
+ );
+ libraries_replace_filenames($library);
+ $this->verbose(key($library['files']['js']));
+ $this->assertEqual(key($library['files']['js']), 'example-1.js', 'libraries_replace_filename() replaces the version correctly.');
+ $library = array(
+ 'version' => '1',
+ 'variant' => 'variant-1',
+ 'files' => array('js' => array('example-!variant.js' => array())),
+ );
+ libraries_replace_filenames($library);
+ $this->verbose(var_export($library['files'], TRUE));
+ $this->assertEqual(key($library['files']['js']), 'example-variant-1.js', 'libraries_replace_filename() replaces the variant correctly.');
+
+
// Test that library information is found correctly.
$expected = array(
'name' => 'Example files',
@@ -340,6 +358,7 @@ class LibrariesTestCase extends DrupalWebTestCase {
$expected['info callback'] = 'applied (version 1, variant example_variant)';
$expected['pre-detect callback'] = 'applied (version 1, variant example_variant)';
$expected['post-detect callback'] = 'applied (variant example_variant)';
+ $expected['variant'] = 'example_variant';
$library = libraries_load('example_callback', 'example_variant');
$this->verbose('Expected:
' . var_export($expected, TRUE) . ''); $this->verbose('Actual:
' . var_export($library, TRUE) . '');