diff --git a/lib/Drupal/libraries/Tests/LibrariesWebTest.php b/lib/Drupal/libraries/Tests/LibrariesWebTest.php index 95a31a1..7b83759 100644 --- a/lib/Drupal/libraries/Tests/LibrariesWebTest.php +++ b/lib/Drupal/libraries/Tests/LibrariesWebTest.php @@ -107,11 +107,14 @@ class LibrariesWebTest extends WebTestBase { */ function testLibrariesScanInfoFiles() { $expected = array('example_info_file' => (object) array( - 'uri' => drupal_get_path('module', 'libraries') . '/tests/example/example_info_file.libraries.info', - 'filename' => 'example_info_file.libraries.info', - 'name' => 'example_info_file.libraries', + 'uri' => drupal_get_path('module', 'libraries') . '/tests/example/example_info_file.libraries.info.yml', + 'filename' => 'example_info_file.libraries.info.yml', + 'name' => 'example_info_file.libraries.info', )); - $this->assertEqual(libraries_scan_info_files(), $expected, 'libraries_scan_info_files() correctly finds the example info file.'); + $actual = libraries_scan_info_files(); + $this->verbose('Expected:
' . var_export($expected, TRUE) . '
'); + $this->verbose('Actual:
' . var_export($actual, TRUE) . '
'); + $this->assertEqual($actual, $expected, 'libraries_scan_info_files() correctly finds the example info file.'); $this->verbose('
' . var_export(libraries_scan_info_files(), TRUE) . '
'); } @@ -140,7 +143,7 @@ class LibrariesWebTest extends WebTestBase { // Test a library specified with an .info file gets detected. $expected = array( 'name' => 'Example info file', - 'info file' => drupal_get_path('module', 'libraries_test') . '/example/example_info_file.libraries.info', + 'info file' => drupal_get_path('module', 'libraries') . '/tests/example/example_info_file.libraries.info.yml', ); libraries_info_defaults($expected, 'example_info_file'); $library = libraries_info('example_info_file'); @@ -451,7 +454,7 @@ class LibrariesWebTest extends WebTestBase { // DOM. $html = array( 'js' => array(''), - 'css' => array('@import url("', '");'), + 'css' => array(''), // PHP files do not get added to the DOM directly. // @see _libraries_test_load() 'php' => array('
  • ', '
  • '), @@ -459,7 +462,7 @@ class LibrariesWebTest extends WebTestBase { foreach ($names as $name => $expected) { foreach ($extensions as $extension) { - $filepath = drupal_get_path('module', 'libraries_test') . "/example/$name.$extension"; + $filepath = drupal_get_path('module', 'libraries') . "/tests/example/$name.$extension"; // JavaScript and CSS files appear as full URLs and with an appended // query string. if (in_array($extension, array('js', 'css'))) { @@ -477,5 +480,4 @@ class LibrariesWebTest extends WebTestBase { } } } - } diff --git a/libraries.info b/libraries.info deleted file mode 100644 index 1a95710..0000000 --- a/libraries.info +++ /dev/null @@ -1,3 +0,0 @@ -name = Libraries -description = Allows version-dependent and shared usage of external libraries. -core = 8.x diff --git a/libraries.info.yml b/libraries.info.yml new file mode 100644 index 0000000..1891a6f --- /dev/null +++ b/libraries.info.yml @@ -0,0 +1,4 @@ +name: Libraries +type: module +description: Allows version-dependent and shared usage of external libraries. +core: 8.x diff --git a/libraries.install b/libraries.install deleted file mode 100644 index 9d7dd00..0000000 --- a/libraries.install +++ /dev/null @@ -1,15 +0,0 @@ - 'name', 'recurse' => FALSE, ))); @@ -136,7 +136,7 @@ function libraries_scan_info_files() { } foreach ($files as $filename => $file) { - $files[basename($filename, '.libraries')] = $file; + $files[basename($filename, '.libraries.info')] = $file; unset($files[$filename]); } @@ -276,7 +276,7 @@ function libraries_prepare_files(&$library, $version = NULL, $variant = NULL) { function libraries_detect_dependencies(&$library, $version = NULL, $variant = NULL) { if (isset($library['dependencies'])) { foreach ($library['dependencies'] as &$dependency_string) { - $dependency_info = drupal_parse_dependency($dependency_string); + $dependency_info = libraries_parse_dependency($dependency_string); $dependency = libraries_detect($dependency_info['name']); if (!$dependency['installed']) { $library['installed'] = FALSE; @@ -683,7 +683,7 @@ function libraries_load_files($library) { $data = "$path/$data"; // Apply the default group if the group isn't explicitly given. if (!isset($options['group'])) { - $options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_DEFAULT; + $options['group'] = ($type == 'js') ? JS_DEFAULT : CSS_AGGREGATE_DEFAULT; } call_user_func('drupal_add_' . $type, $data, $options); $count++; @@ -753,3 +753,60 @@ function libraries_get_version($library, $options) { } fclose($file); } + +/** + * Parses a dependency for comparison by drupal_check_incompatibility(). + * + * @param $dependency + * A dependency string, for example 'foo (>=7.x-4.5-beta5, 3.x)'. + * + * @return + * An associative array with three keys: + * - 'name' includes the name of the thing to depend on (e.g. 'foo'). + * - 'original_version' contains the original version string (which can be + * used in the UI for reporting incompatibilities). + * - 'versions' is a list of associative arrays, each containing the keys + * 'op' and 'version'. 'op' can be one of: '=', '==', '!=', '<>', '<', + * '<=', '>', or '>='. 'version' is one piece like '4.5-beta3'. + * Callers should pass this structure to drupal_check_incompatibility(). + * + */ +function libraries_parse_dependency($dependency) { + // We use named subpatterns and support every op that version_compare + // supports. Also, op is optional and defaults to equals. + $p_op = '(?P!=|==|=|<|<=|>|>=|<>)?'; + // Core version is always optional: 7.x-2.x and 2.x is treated the same. + $p_core = '(?:' . preg_quote(DRUPAL_CORE_COMPATIBILITY) . '-)?'; + $p_major = '(?P\d+)'; + // By setting the minor version to x, branches can be matched. + $p_minor = '(?P(?:\d+|x)(?:-[A-Za-z]+\d+)?)'; + $value = array(); + $parts = explode('(', $dependency, 2); + $value['name'] = trim($parts[0]); + if (isset($parts[1])) { + $value['original_version'] = ' (' . $parts[1]; + foreach (explode(',', $parts[1]) as $version) { + if (preg_match("/^\s*$p_op\s*$p_core$p_major\.$p_minor/", $version, $matches)) { + $op = !empty($matches['operation']) ? $matches['operation'] : '='; + if ($matches['minor'] == 'x') { + // Drupal considers "2.x" to mean any version that begins with + // "2" (e.g. 2.0, 2.9 are all "2.x"). PHP's version_compare(), + // on the other hand, treats "x" as a string; so to + // version_compare(), "2.x" is considered less than 2.0. This + // means that >=2.x and <2.x are handled by version_compare() + // as we need, but > and <= are not. + if ($op == '>' || $op == '<=') { + $matches['major']++; + } + // Equivalence can be checked by adding two restrictions. + if ($op == '=' || $op == '==') { + $value['versions'][] = array('op' => '<', 'version' => ($matches['major'] + 1) . '.x'); + $op = '>='; + } + } + $value['versions'][] = array('op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']); + } + } + } + return $value; +} \ No newline at end of file diff --git a/libraries.services.yml b/libraries.services.yml new file mode 100644 index 0000000..bedb0b7 --- /dev/null +++ b/libraries.services.yml @@ -0,0 +1,8 @@ +services: + cache.libraries: + class: Drupal\Core\Cache\CacheBackendInterface + tags: + - { name: cache.bin } + factory_method: get + factory_service: cache_factory + arguments: [library] \ No newline at end of file diff --git a/libraries_test/lib/Drupal/libraries_test/Controller/ExampleController.php b/libraries_test/lib/Drupal/libraries_test/Controller/ExampleController.php new file mode 100644 index 0000000..2ddb0a1 --- /dev/null +++ b/libraries_test/lib/Drupal/libraries_test/Controller/ExampleController.php @@ -0,0 +1,97 @@ +JavaScript'; + $output .= '
    '; + $output .= 'If this text shows up, no JavaScript test file was loaded.'; + $output .= '
    '; + + // For easier debugging of CSS loading, the loaded CSS files will color the + // following text. + $output .= '

    CSS

    '; + $output .= '
    '; + $output .= 'If one of the CSS test files has been loaded, this text will be colored:'; + $output .= '
      '; + // Do not reference the actual CSS files (i.e. including '.css'), because that + // breaks testing. + $output .= '
    • example_1: red
    • '; + $output .= '
    • example_2: green
    • '; + $output .= '
    • example_3: orange
    • '; + $output .= '
    • example_4: blue
    • '; + $output .= '
    • libraries_test: purple
    • '; + $output .= '
    '; + $output .= '
    '; + + $output .= '

    PHP

    '; + $output .= '
    '; + $output .= 'The following is a list of all loaded test PHP files:'; + $output .= '
      '; + $files = get_included_files(); + foreach ($files as $file) { + if ((strpos($file, 'libraries/test') || strpos($file, 'libraries_test')) && !strpos($file, 'libraries_test.module') && !strpos($file, 'lib/Drupal/libraries_test')) { + $output .= '
    • ' . str_replace(DRUPAL_ROOT . '/', '', $file) . '
    • '; + } + } + $output .= '
    '; + $output .= '
    '; + + return $output; + } + + public function files() { + return $this->buildPage('example_files'); + } + + public function integration() { + return $this->buildPage('example_integration_files'); + } + + public function versions() { + return $this->buildPage('example_versions'); + } + + public function variant() { + return $this->buildPage('example_variant', 'example_variant'); + } + + public function versionsAndVariants() { + return $this->buildPage('example_versions_and_variants', 'example_variant_2'); + } + + public function cache() { + return $this->buildPage('example_callback'); + } +} \ No newline at end of file diff --git a/libraries_test/libraries_test.css b/libraries_test/libraries_test.css new file mode 100644 index 0000000..3505281 --- /dev/null +++ b/libraries_test/libraries_test.css @@ -0,0 +1,12 @@ + +/** + * @file + * Test CSS file for Libraries loading. + * + * Color the 'libraries-test-css' div purple. See README.txt for more + * information. + */ + +.libraries-test-css { + color: purple; +} diff --git a/libraries_test/libraries_test.inc b/libraries_test/libraries_test.inc new file mode 100644 index 0000000..c0cf0dc --- /dev/null +++ b/libraries_test/libraries_test.inc @@ -0,0 +1,11 @@ + 'Example missing', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/missing', + ); + $libraries['example_undetected_version'] = array( + 'name' => 'Example undetected version', + 'library path' => drupal_get_path('module', 'libraries') . '/tests', + 'version callback' => '_libraries_test_return_version', + 'version arguments' => array(FALSE), + ); + $libraries['example_unsupported_version'] = array( + 'name' => 'Example unsupported version', + 'library path' => drupal_get_path('module', 'libraries') . '/tests', + 'version callback' => '_libraries_test_return_version', + 'version arguments' => array('1'), + 'versions' => array( + '2' => array(), + ), + ); + + $libraries['example_supported_version'] = array( + 'name' => 'Example supported version', + 'library path' => drupal_get_path('module', 'libraries') . '/tests', + 'version callback' => '_libraries_test_return_version', + 'version arguments' => array('1'), + 'versions' => array( + '1' => array(), + ), + ); + + // Test the default version callback. + $libraries['example_default_version_callback'] = array( + 'name' => 'Example default version callback', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version arguments' => array( + 'file' => 'README.txt', + // Version 1 + 'pattern' => '/Version (\d+)/', + 'lines' => 5, + ), + ); + + // Test a multiple-parameter version callback. + $libraries['example_multiple_parameter_version_callback'] = array( + 'name' => 'Example multiple parameter version callback', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + // Version 1 + 'version callback' => '_libraries_test_get_version', + 'version arguments' => array('README.txt', '/Version (\d+)/', 5), + ); + + // Test a top-level files property. + $libraries['example_files'] = array( + 'name' => 'Example files', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'files' => array( + 'js' => array('example_1.js'), + 'css' => array('example_1.css'), + 'php' => array('example_1.php'), + ), + ); + + // 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( + 'name' => 'Example integration files', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'integration files' => array( + 'libraries_test' => array( + 'js' => array('libraries_test.js'), + 'css' => array('libraries_test.css'), + 'php' => array('libraries_test.inc'), + ), + ), + ); + + // Test version overloading. + $libraries['example_versions'] = array( + 'name' => 'Example versions', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '2', + 'versions' => array( + '1' => array( + 'files' => array( + 'js' => array('example_1.js'), + 'css' => array('example_1.css'), + 'php' => array('example_1.php'), + ), + ), + '2' => array( + 'files' => array( + 'js' => array('example_2.js'), + 'css' => array('example_2.css'), + 'php' => array('example_2.php'), + ), + ), + ), + ); + + // Test variant detection. + $libraries['example_variant_missing'] = array( + 'name' => 'Example variant missing', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'variants' => array( + 'example_variant' => array( + 'files' => array( + 'js' => array('example_3.js'), + 'css' => array('example_3.css'), + 'php' => array('example_3.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(FALSE), + ), + ), + ); + + $libraries['example_variant'] = array( + 'name' => 'Example variant', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'variants' => array( + 'example_variant' => array( + 'files' => array( + 'js' => array('example_3.js'), + 'css' => array('example_3.css'), + 'php' => array('example_3.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(TRUE), + ), + ), + ); + + // Test correct behaviour with multiple versions and multiple variants. + $libraries['example_versions_and_variants'] = array( + 'name' => 'Example versions and variants', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '2', + 'versions' => array( + '1' => array( + 'variants' => array( + 'example_variant_1' => array( + 'files' => array( + 'js' => array('example_1.js'), + 'css' => array('example_1.css'), + 'php' => array('example_1.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(TRUE), + ), + 'example_variant_2' => array( + 'files' => array( + 'js' => array('example_2.js'), + 'css' => array('example_2.css'), + 'php' => array('example_2.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(TRUE), + ), + ), + ), + '2' => array( + 'variants' => array( + 'example_variant_1' => array( + 'files' => array( + 'js' => array('example_3.js'), + 'css' => array('example_3.css'), + 'php' => array('example_3.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(TRUE), + ), + 'example_variant_2' => array( + 'files' => array( + 'js' => array('example_4.js'), + 'css' => array('example_4.css'), + 'php' => array('example_4.php'), + ), + 'variant callback' => '_libraries_test_return_installed', + 'variant arguments' => array(TRUE), + ), + ), + ), + ), + ); + + // Test dependency loading. + // We add one file to each library to be able to verify if it was loaded with + // libraries_load(). + // This library acts as a dependency for the libraries below. + $libraries['example_dependency'] = array( + 'name' => 'Example dependency', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1.1', + 'files' => array('js' => array('example_1.js')), + ); + $libraries['example_dependency_missing'] = array( + 'name' => 'Example dependency missing', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'dependencies' => array('example_missing'), + 'files' => array('js' => array('example_1.js')), + ); + $libraries['example_dependency_incompatible'] = array( + 'name' => 'Example dependency incompatible', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'dependencies' => array('example_dependency (>1.1)'), + 'files' => array('js' => array('example_1.js')), + ); + $libraries['example_dependency_compatible'] = array( + 'name' => 'Example dependency compatible', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'dependencies' => array('example_dependency (>=1.1)'), + 'files' => array('js' => array('example_1.js')), + ); + + // Test the applying of callbacks. + $libraries['example_callback'] = array( + 'name' => 'Example callback', + 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', + 'version' => '1', + 'versions' => array( + '1' => array( + 'variants' => array( + 'example_variant' => array( + // These keys are for testing purposes only. + 'info callback' => 'not applied', + 'pre-detect callback' => 'not applied', + 'post-detect callback' => 'not applied', + 'pre-load callback' => 'not applied', + 'post-load callback' => 'not applied', + ), + ), + // These keys are for testing purposes only. + 'info callback' => 'not applied', + 'pre-detect callback' => 'not applied', + 'post-detect callback' => 'not applied', + 'pre-load callback' => 'not applied', + 'post-load callback' => 'not applied', + ), + ), + 'variants' => array( + 'example_variant' => array( + // These keys are for testing purposes only. + 'info callback' => 'not applied', + 'pre-detect callback' => 'not applied', + 'post-detect callback' => 'not applied', + 'pre-load callback' => 'not applied', + 'post-load callback' => 'not applied', + ), + ), + 'callbacks' => array( + 'info' => array('_libraries_test_info_callback'), + 'pre-detect' => array('_libraries_test_pre_detect_callback'), + 'post-detect' => array('_libraries_test_post_detect_callback'), + 'pre-load' => array('_libraries_test_pre_load_callback'), + 'post-load' => array('_libraries_test_post_load_callback'), + ), + // These keys are for testing purposes only. + 'info callback' => 'not applied', + 'pre-detect callback' => 'not applied', + 'post-detect callback' => 'not applied', + 'pre-load callback' => 'not applied', + 'post-load callback' => 'not applied', + ); + + return $libraries; +} + +/** + * Implements hook_libraries_info_file_paths() + */ +function libraries_test_libraries_info_file_paths() { + return array(drupal_get_path('module', 'libraries') . '/tests/example'); +} + +/** + * Gets the version of an example library. + * + * Returns exactly the version string entered as the $version parameter. This + * function cannot be collapsed with _libraries_test_return_installed(), because + * of the different arguments that are passed automatically. + */ +function _libraries_test_return_version($library, $version) { + return $version; +} + +/** + * Gets the version information from an arbitrary library. + * + * Test function for a version callback with multiple arguments. This is an + * exact copy of libraries_get_version(), which uses a single $option argument, + * except for the fact that it uses multiple arguments. Since we support both + * type of version callbacks, detecting the version of a test library with this + * function ensures that the arguments are passed correctly. This function 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. + * + * @see libraries_get_version() + */ +function _libraries_test_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 exactly the value of $installed, either TRUE or FALSE. This function + * cannot be collapsed with _libraries_test_return_version(), because of the + * different arguments that are passed automatically. + */ +function _libraries_test_return_installed($library, $name, $installed) { + return $installed; +} + +/** + * Sets the 'info callback' key. + * + * This function is used as a test callback for the 'info' callback group. + * + * @see _libraries_test_callback() + */ +function _libraries_test_info_callback(&$library, $version, $variant) { + _libraries_test_callback($library, $version, $variant, 'info'); +} + +/** + * Sets the 'pre-detect callback' key. + * + * This function is used as a test callback for the 'pre-detect' callback group. + * + * @see _libraries_test_callback() + */ +function _libraries_test_pre_detect_callback(&$library, $version, $variant) { + _libraries_test_callback($library, $version, $variant, 'pre-detect'); +} + +/** + * Sets the 'post-detect callback' key. + * + * This function is used as a test callback for the 'post-detect callback group. + * + * @see _libraries_test_callback() + */ +function _libraries_test_post_detect_callback(&$library, $version, $variant) { + _libraries_test_callback($library, $version, $variant, 'post-detect'); +} + +/** + * Sets the 'pre-load callback' key. + * + * This function is used as a test callback for the 'pre-load' callback group. + * + * @see _libraries_test_callback() + */ +function _libraries_test_pre_load_callback(&$library, $version, $variant) { + _libraries_test_callback($library, $version, $variant, 'pre-load'); +} + +/** + * Sets the 'post-load callback' key. + * + * This function is used as a test callback for the 'post-load' callback group. + * + * @see _libraries_test_callback() + */ +function _libraries_test_post_load_callback(&$library, $version, $variant) { + _libraries_test_callback($library, $version, $variant, 'post-load'); +} + +/** + * Sets the '[group] callback' key, where [group] is prepare, detect, or load. + * + * This function is used as a test callback for the all callback groups. + * + * It sets the '[group] callback' (see above) key to 'applied ([part])' where + * [part] is either 'top-level', 'version x.y' (where x.y is the passed-in + * version string), 'variant example' (where example is the passed-in variant + * name), or 'version x.y, variant example' (see above), depending on the part + * of the library the passed-in library information belongs to. + * + * @param $library + * An array of library information, which may be version- or variant-specific. + * Passed by reference. + * @param $version + * The version the library information passed in $library belongs to, or NULL + * if the passed library information is not version-specific. + * @param $variant + * The variant the library information passed in $library belongs to, or NULL + * if the passed library information is not variant-specific. + */ +function _libraries_test_callback(&$library, $version, $variant, $group) { + $string = 'applied'; + if (isset($version) && isset($variant)) { + $string .= " (version $version, variant $variant)"; + } + elseif (isset($version)) { + $string .= " (version $version)"; + } + elseif (isset($variant)) { + $string .= " (variant $variant)"; + } + else { + $string .= ' (top-level)'; + } + $library["$group callback"] = $string; + + // The following is used to test caching of library information. + // Only set the message for the top-level library to prevent confusing, + // duplicate messages. + if (!isset($version) && !isset($variant) && variable_get('libraries_test_cache', FALSE)) { + drupal_set_message("The $group callback group was invoked."); + } +} + +/** + * Implements hook_menu(). + */ +function libraries_test_menu() { + $items['libraries_test/files'] = array( + 'title' => 'Test files', + 'route_name' => 'libraries_test_files', + ); + $items['libraries_test/integration_files'] = array( + 'title' => 'Test integration files', + 'route_name' => 'libraries_test_integration_files', + ); + $items['libraries_test/versions'] = array( + 'title' => 'Test version loading', + 'route_name' => 'libraries_test_versions', + ); + $items['libraries_test/variant'] = array( + 'title' => 'Test variant loading', + 'route_name' => 'libraries_test_variant', + ); + $items['libraries_test/versions_and_variants'] = array( + 'title' => 'Test concurrent version and variant loading', + 'route_name' => 'libraries_test_versions_and_variants', + ); + $items['libraries_test/cache'] = array( + 'title' => 'Test caching of library information', + 'route_name' => 'libraries_test_cache', + ); + return $items; +} diff --git a/libraries_test/libraries_test.routing.yml b/libraries_test/libraries_test.routing.yml new file mode 100644 index 0000000..fe7dac4 --- /dev/null +++ b/libraries_test/libraries_test.routing.yml @@ -0,0 +1,36 @@ +libraries_test_files: + pattern: '/libraries_test/files' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::files + requirements: + _access: 'TRUE' +libraries_test_integration_files: + pattern: '/libraries_test/integration_files' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::integration + requirements: + _access: 'TRUE' +libraries_test_versions: + pattern: '/libraries_test/versions' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::versions + requirements: + _access: 'TRUE' +libraries_test_variant: + pattern: '/libraries_test/variant' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::variant + requirements: + _access: 'TRUE' +libraries_test_versions_and_variants: + pattern: '/libraries_test/versions_and_variants' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::versionsAndVariants + requirements: + _access: 'TRUE' +libraries_test_cache: + pattern: '/libraries_test/cache' + defaults: + _content: Drupal\libraries_test\Controller\ExampleController::cache + requirements: + _access: 'TRUE' diff --git a/tests/example/example_info_file.libraries.info b/tests/example/example_info_file.libraries.info deleted file mode 100644 index ec255d4..0000000 --- a/tests/example/example_info_file.libraries.info +++ /dev/null @@ -1,4 +0,0 @@ - -; This is an example info file of a library used for testing purposes. -name = Example info file - diff --git a/tests/example/example_info_file.libraries.info.yml b/tests/example/example_info_file.libraries.info.yml new file mode 100644 index 0000000..26086f4 --- /dev/null +++ b/tests/example/example_info_file.libraries.info.yml @@ -0,0 +1,4 @@ + +# This is an example info file of a library used for testing purposes. +name: Example info file + diff --git a/tests/libraries_test.css b/tests/libraries_test.css deleted file mode 100644 index 3505281..0000000 --- a/tests/libraries_test.css +++ /dev/null @@ -1,12 +0,0 @@ - -/** - * @file - * Test CSS file for Libraries loading. - * - * Color the 'libraries-test-css' div purple. See README.txt for more - * information. - */ - -.libraries-test-css { - color: purple; -} diff --git a/tests/libraries_test.inc b/tests/libraries_test.inc deleted file mode 100644 index c0cf0dc..0000000 --- a/tests/libraries_test.inc +++ /dev/null @@ -1,11 +0,0 @@ - 'Example missing', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/missing', - ); - $libraries['example_undetected_version'] = array( - 'name' => 'Example undetected version', - 'library path' => drupal_get_path('module', 'libraries') . '/tests', - 'version callback' => '_libraries_test_return_version', - 'version arguments' => array(FALSE), - ); - $libraries['example_unsupported_version'] = array( - 'name' => 'Example unsupported version', - 'library path' => drupal_get_path('module', 'libraries') . '/tests', - 'version callback' => '_libraries_test_return_version', - 'version arguments' => array('1'), - 'versions' => array( - '2' => array(), - ), - ); - - $libraries['example_supported_version'] = array( - 'name' => 'Example supported version', - 'library path' => drupal_get_path('module', 'libraries') . '/tests', - 'version callback' => '_libraries_test_return_version', - 'version arguments' => array('1'), - 'versions' => array( - '1' => array(), - ), - ); - - // Test the default version callback. - $libraries['example_default_version_callback'] = array( - 'name' => 'Example default version callback', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version arguments' => array( - 'file' => 'README.txt', - // Version 1 - 'pattern' => '/Version (\d+)/', - 'lines' => 5, - ), - ); - - // Test a multiple-parameter version callback. - $libraries['example_multiple_parameter_version_callback'] = array( - 'name' => 'Example multiple parameter version callback', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - // Version 1 - 'version callback' => '_libraries_test_get_version', - 'version arguments' => array('README.txt', '/Version (\d+)/', 5), - ); - - // Test a top-level files property. - $libraries['example_files'] = array( - 'name' => 'Example files', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'files' => array( - 'js' => array('example_1.js'), - 'css' => array('example_1.css'), - 'php' => array('example_1.php'), - ), - ); - - // 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( - 'name' => 'Example integration files', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'integration files' => array( - 'libraries_test' => array( - 'js' => array('libraries_test.js'), - 'css' => array('libraries_test.css'), - 'php' => array('libraries_test.inc'), - ), - ), - ); - - // Test version overloading. - $libraries['example_versions'] = array( - 'name' => 'Example versions', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '2', - 'versions' => array( - '1' => array( - 'files' => array( - 'js' => array('example_1.js'), - 'css' => array('example_1.css'), - 'php' => array('example_1.php'), - ), - ), - '2' => array( - 'files' => array( - 'js' => array('example_2.js'), - 'css' => array('example_2.css'), - 'php' => array('example_2.php'), - ), - ), - ), - ); - - // Test variant detection. - $libraries['example_variant_missing'] = array( - 'name' => 'Example variant missing', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'variants' => array( - 'example_variant' => array( - 'files' => array( - 'js' => array('example_3.js'), - 'css' => array('example_3.css'), - 'php' => array('example_3.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(FALSE), - ), - ), - ); - - $libraries['example_variant'] = array( - 'name' => 'Example variant', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'variants' => array( - 'example_variant' => array( - 'files' => array( - 'js' => array('example_3.js'), - 'css' => array('example_3.css'), - 'php' => array('example_3.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(TRUE), - ), - ), - ); - - // Test correct behaviour with multiple versions and multiple variants. - $libraries['example_versions_and_variants'] = array( - 'name' => 'Example versions and variants', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '2', - 'versions' => array( - '1' => array( - 'variants' => array( - 'example_variant_1' => array( - 'files' => array( - 'js' => array('example_1.js'), - 'css' => array('example_1.css'), - 'php' => array('example_1.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(TRUE), - ), - 'example_variant_2' => array( - 'files' => array( - 'js' => array('example_2.js'), - 'css' => array('example_2.css'), - 'php' => array('example_2.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(TRUE), - ), - ), - ), - '2' => array( - 'variants' => array( - 'example_variant_1' => array( - 'files' => array( - 'js' => array('example_3.js'), - 'css' => array('example_3.css'), - 'php' => array('example_3.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(TRUE), - ), - 'example_variant_2' => array( - 'files' => array( - 'js' => array('example_4.js'), - 'css' => array('example_4.css'), - 'php' => array('example_4.php'), - ), - 'variant callback' => '_libraries_test_return_installed', - 'variant arguments' => array(TRUE), - ), - ), - ), - ), - ); - - // Test dependency loading. - // We add one file to each library to be able to verify if it was loaded with - // libraries_load(). - // This library acts as a dependency for the libraries below. - $libraries['example_dependency'] = array( - 'name' => 'Example dependency', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1.1', - 'files' => array('js' => array('example_1.js')), - ); - $libraries['example_dependency_missing'] = array( - 'name' => 'Example dependency missing', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'dependencies' => array('example_missing'), - 'files' => array('js' => array('example_1.js')), - ); - $libraries['example_dependency_incompatible'] = array( - 'name' => 'Example dependency incompatible', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'dependencies' => array('example_dependency (>1.1)'), - 'files' => array('js' => array('example_1.js')), - ); - $libraries['example_dependency_compatible'] = array( - 'name' => 'Example dependency compatible', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'dependencies' => array('example_dependency (>=1.1)'), - 'files' => array('js' => array('example_1.js')), - ); - - // Test the applying of callbacks. - $libraries['example_callback'] = array( - 'name' => 'Example callback', - 'library path' => drupal_get_path('module', 'libraries') . '/tests/example', - 'version' => '1', - 'versions' => array( - '1' => array( - 'variants' => array( - 'example_variant' => array( - // These keys are for testing purposes only. - 'info callback' => 'not applied', - 'pre-detect callback' => 'not applied', - 'post-detect callback' => 'not applied', - 'pre-load callback' => 'not applied', - 'post-load callback' => 'not applied', - ), - ), - // These keys are for testing purposes only. - 'info callback' => 'not applied', - 'pre-detect callback' => 'not applied', - 'post-detect callback' => 'not applied', - 'pre-load callback' => 'not applied', - 'post-load callback' => 'not applied', - ), - ), - 'variants' => array( - 'example_variant' => array( - // These keys are for testing purposes only. - 'info callback' => 'not applied', - 'pre-detect callback' => 'not applied', - 'post-detect callback' => 'not applied', - 'pre-load callback' => 'not applied', - 'post-load callback' => 'not applied', - ), - ), - 'callbacks' => array( - 'info' => array('_libraries_test_info_callback'), - 'pre-detect' => array('_libraries_test_pre_detect_callback'), - 'post-detect' => array('_libraries_test_post_detect_callback'), - 'pre-load' => array('_libraries_test_pre_load_callback'), - 'post-load' => array('_libraries_test_post_load_callback'), - ), - // These keys are for testing purposes only. - 'info callback' => 'not applied', - 'pre-detect callback' => 'not applied', - 'post-detect callback' => 'not applied', - 'pre-load callback' => 'not applied', - 'post-load callback' => 'not applied', - ); - - return $libraries; -} - -/** - * Implements hook_libraries_info_file_paths() - */ -function libraries_test_libraries_info_file_paths() { - return array(drupal_get_path('module', 'libraries_test') . '/example'); -} - -/** - * Gets the version of an example library. - * - * Returns exactly the version string entered as the $version parameter. This - * function cannot be collapsed with _libraries_test_return_installed(), because - * of the different arguments that are passed automatically. - */ -function _libraries_test_return_version($library, $version) { - return $version; -} - -/** - * Gets the version information from an arbitrary library. - * - * Test function for a version callback with multiple arguments. This is an - * exact copy of libraries_get_version(), which uses a single $option argument, - * except for the fact that it uses multiple arguments. Since we support both - * type of version callbacks, detecting the version of a test library with this - * function ensures that the arguments are passed correctly. This function 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. - * - * @see libraries_get_version() - */ -function _libraries_test_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 exactly the value of $installed, either TRUE or FALSE. This function - * cannot be collapsed with _libraries_test_return_version(), because of the - * different arguments that are passed automatically. - */ -function _libraries_test_return_installed($library, $name, $installed) { - return $installed; -} - -/** - * Sets the 'info callback' key. - * - * This function is used as a test callback for the 'info' callback group. - * - * @see _libraries_test_callback() - */ -function _libraries_test_info_callback(&$library, $version, $variant) { - _libraries_test_callback($library, $version, $variant, 'info'); -} - -/** - * Sets the 'pre-detect callback' key. - * - * This function is used as a test callback for the 'pre-detect' callback group. - * - * @see _libraries_test_callback() - */ -function _libraries_test_pre_detect_callback(&$library, $version, $variant) { - _libraries_test_callback($library, $version, $variant, 'pre-detect'); -} - -/** - * Sets the 'post-detect callback' key. - * - * This function is used as a test callback for the 'post-detect callback group. - * - * @see _libraries_test_callback() - */ -function _libraries_test_post_detect_callback(&$library, $version, $variant) { - _libraries_test_callback($library, $version, $variant, 'post-detect'); -} - -/** - * Sets the 'pre-load callback' key. - * - * This function is used as a test callback for the 'pre-load' callback group. - * - * @see _libraries_test_callback() - */ -function _libraries_test_pre_load_callback(&$library, $version, $variant) { - _libraries_test_callback($library, $version, $variant, 'pre-load'); -} - -/** - * Sets the 'post-load callback' key. - * - * This function is used as a test callback for the 'post-load' callback group. - * - * @see _libraries_test_callback() - */ -function _libraries_test_post_load_callback(&$library, $version, $variant) { - _libraries_test_callback($library, $version, $variant, 'post-load'); -} - -/** - * Sets the '[group] callback' key, where [group] is prepare, detect, or load. - * - * This function is used as a test callback for the all callback groups. - * - * It sets the '[group] callback' (see above) key to 'applied ([part])' where - * [part] is either 'top-level', 'version x.y' (where x.y is the passed-in - * version string), 'variant example' (where example is the passed-in variant - * name), or 'version x.y, variant example' (see above), depending on the part - * of the library the passed-in library information belongs to. - * - * @param $library - * An array of library information, which may be version- or variant-specific. - * Passed by reference. - * @param $version - * The version the library information passed in $library belongs to, or NULL - * if the passed library information is not version-specific. - * @param $variant - * The variant the library information passed in $library belongs to, or NULL - * if the passed library information is not variant-specific. - */ -function _libraries_test_callback(&$library, $version, $variant, $group) { - $string = 'applied'; - if (isset($version) && isset($variant)) { - $string .= " (version $version, variant $variant)"; - } - elseif (isset($version)) { - $string .= " (version $version)"; - } - elseif (isset($variant)) { - $string .= " (variant $variant)"; - } - else { - $string .= ' (top-level)'; - } - $library["$group callback"] = $string; - - // The following is used to test caching of library information. - // Only set the message for the top-level library to prevent confusing, - // duplicate messages. - if (!isset($version) && !isset($variant) && variable_get('libraries_test_cache', FALSE)) { - drupal_set_message("The $group callback group was invoked."); - } -} - -/** - * Implements hook_menu(). - */ -function libraries_test_menu() { - $base = array( - 'page callback' => '_libraries_test_load', - 'access callback' => TRUE, - ); - $items['libraries_test/files'] = $base + array( - 'title' => 'Test files', - 'page arguments' => array('example_files'), - ); - $items['libraries_test/integration_files'] = $base + array( - 'title' => 'Test integration files', - 'page arguments' => array('example_integration_files'), - ); - $items['libraries_test/versions'] = $base + array( - 'title' => 'Test version loading', - 'page arguments' => array('example_versions'), - ); - $items['libraries_test/variant'] = $base + array( - 'title' => 'Test variant loading', - 'page arguments' => array('example_variant', 'example_variant'), - ); - $items['libraries_test/versions_and_variants'] = $base + array( - 'title' => 'Test concurrent version and variant loading', - 'page arguments' => array('example_versions_and_variants', 'example_variant_2'), - ); - $items['libraries_test/cache'] = $base + array( - 'title' => 'Test caching of library information', - 'page arguments' => array('example_callback'), - ); - return $items; -} - -/** - * Loads a specified library (variant) for testing. - * - * JavaScript and CSS files can be checked directly by SimpleTest, so we only - * need to manually check for PHP files. We provide information about the loaded - * JavaScript and CSS files for easier debugging. See example/README.txt for - * more information. - */ -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 = ''; - - // For easer debugging of JS loading, a text is shown that the JavaScript will - // replace. - $output .= '

    JavaScript

    '; - $output .= '
    '; - $output .= 'If this text shows up, no JavaScript test file was loaded.'; - $output .= '
    '; - - // For easier debugging of CSS loading, the loaded CSS files will color the - // following text. - $output .= '

    CSS

    '; - $output .= '
    '; - $output .= 'If one of the CSS test files has been loaded, this text will be colored:'; - $output .= '
      '; - // Do not reference the actual CSS files (i.e. including '.css'), because that - // breaks testing. - $output .= '
    • example_1: red
    • '; - $output .= '
    • example_2: green
    • '; - $output .= '
    • example_3: orange
    • '; - $output .= '
    • example_4: blue
    • '; - $output .= '
    • libraries_test: purple
    • '; - $output .= '
    '; - $output .= '
    '; - - $output .= '

    PHP

    '; - $output .= '
    '; - $output .= 'The following is a list of all loaded test PHP files:'; - $output .= '
      '; - $files = get_included_files(); - foreach ($files as $file) { - if (strpos($file, 'libraries/test') && !strpos($file, 'libraries_test.module')) { - $output .= '
    • ' . str_replace(DRUPAL_ROOT . '/', '', $file) . '
    • '; - } - } - $output .= '
    '; - $output .= '
    '; - - return $output; -}