libraries_test.module 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. <?php
  2. /**
  3. * @file
  4. * Tests the library detection and loading.
  5. */
  6. /**
  7. * Implements hook_libraries_info().
  8. */
  9. function libraries_test_libraries_info() {
  10. // Test library detection.
  11. $libraries['example_missing'] = array(
  12. 'name' => 'Example missing',
  13. 'library path' => drupal_get_path('module', 'libraries') . '/tests/missing',
  14. );
  15. $libraries['example_undetected_version'] = array(
  16. 'name' => 'Example undetected version',
  17. 'library path' => drupal_get_path('module', 'libraries') . '/tests',
  18. 'version callback' => '_libraries_test_return_version',
  19. 'version arguments' => array(FALSE),
  20. );
  21. $libraries['example_unsupported_version'] = array(
  22. 'name' => 'Example unsupported version',
  23. 'library path' => drupal_get_path('module', 'libraries') . '/tests',
  24. 'version callback' => '_libraries_test_return_version',
  25. 'version arguments' => array('1'),
  26. 'versions' => array(
  27. '2' => array(),
  28. ),
  29. );
  30. $libraries['example_supported_version'] = array(
  31. 'name' => 'Example supported version',
  32. 'library path' => drupal_get_path('module', 'libraries') . '/tests',
  33. 'version callback' => '_libraries_test_return_version',
  34. 'version arguments' => array('1'),
  35. 'versions' => array(
  36. '1' => array(),
  37. ),
  38. );
  39. // Test the default version callback.
  40. $libraries['example_default_version_callback'] = array(
  41. 'name' => 'Example default version callback',
  42. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  43. 'version arguments' => array(
  44. 'file' => 'README.txt',
  45. // Version 1
  46. 'pattern' => '/Version (\d+)/',
  47. 'lines' => 5,
  48. ),
  49. );
  50. // Test a multiple-parameter version callback.
  51. $libraries['example_multiple_parameter_version_callback'] = array(
  52. 'name' => 'Example multiple parameter version callback',
  53. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  54. // Version 1
  55. 'version callback' => '_libraries_test_get_version',
  56. 'version arguments' => array('README.txt', '/Version (\d+)/', 5),
  57. );
  58. // Test a top-level files property.
  59. $libraries['example_files'] = array(
  60. 'name' => 'Example files',
  61. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  62. 'version' => '1',
  63. 'files' => array(
  64. 'js' => array('example_1.js'),
  65. 'css' => array('example_1.css'),
  66. 'php' => array('example_1.php'),
  67. ),
  68. );
  69. // Test loading of integration files.
  70. // Normally added by the corresponding module via hook_libraries_info_alter(),
  71. // these files should be automatically loaded when the library is loaded.
  72. $libraries['example_integration_files'] = array(
  73. 'name' => 'Example integration files',
  74. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  75. 'version' => '1',
  76. 'integration files' => array(
  77. 'libraries_test' => array(
  78. 'js' => array('libraries_test.js'),
  79. 'css' => array('libraries_test.css'),
  80. 'php' => array('libraries_test.inc'),
  81. ),
  82. ),
  83. );
  84. // Test version overloading.
  85. $libraries['example_versions'] = array(
  86. 'name' => 'Example versions',
  87. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  88. 'version' => '2',
  89. 'versions' => array(
  90. '1' => array(
  91. 'files' => array(
  92. 'js' => array('example_1.js'),
  93. 'css' => array('example_1.css'),
  94. 'php' => array('example_1.php'),
  95. ),
  96. ),
  97. '2' => array(
  98. 'files' => array(
  99. 'js' => array('example_2.js'),
  100. 'css' => array('example_2.css'),
  101. 'php' => array('example_2.php'),
  102. ),
  103. ),
  104. ),
  105. );
  106. // Test variant detection.
  107. $libraries['example_variant_missing'] = array(
  108. 'name' => 'Example variant missing',
  109. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  110. 'version' => '1',
  111. 'variants' => array(
  112. 'example_variant' => array(
  113. 'files' => array(
  114. 'js' => array('example_3.js'),
  115. 'css' => array('example_3.css'),
  116. 'php' => array('example_3.php'),
  117. ),
  118. 'variant callback' => '_libraries_test_return_installed',
  119. 'variant arguments' => array(FALSE),
  120. ),
  121. ),
  122. );
  123. $libraries['example_variant'] = array(
  124. 'name' => 'Example variant',
  125. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  126. 'version' => '1',
  127. 'variants' => array(
  128. 'example_variant' => array(
  129. 'files' => array(
  130. 'js' => array('example_3.js'),
  131. 'css' => array('example_3.css'),
  132. 'php' => array('example_3.php'),
  133. ),
  134. 'variant callback' => '_libraries_test_return_installed',
  135. 'variant arguments' => array(TRUE),
  136. ),
  137. ),
  138. );
  139. // Test correct behaviour with multiple versions and multiple variants.
  140. $libraries['example_versions_and_variants'] = array(
  141. 'name' => 'Example versions and variants',
  142. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  143. 'version' => '2',
  144. 'versions' => array(
  145. '1' => array(
  146. 'variants' => array(
  147. 'example_variant_1' => array(
  148. 'files' => array(
  149. 'js' => array('example_1.js'),
  150. 'css' => array('example_1.css'),
  151. 'php' => array('example_1.php'),
  152. ),
  153. 'variant callback' => '_libraries_test_return_installed',
  154. 'variant arguments' => array(TRUE),
  155. ),
  156. 'example_variant_2' => array(
  157. 'files' => array(
  158. 'js' => array('example_2.js'),
  159. 'css' => array('example_2.css'),
  160. 'php' => array('example_2.php'),
  161. ),
  162. 'variant callback' => '_libraries_test_return_installed',
  163. 'variant arguments' => array(TRUE),
  164. ),
  165. ),
  166. ),
  167. '2' => array(
  168. 'variants' => array(
  169. 'example_variant_1' => array(
  170. 'files' => array(
  171. 'js' => array('example_3.js'),
  172. 'css' => array('example_3.css'),
  173. 'php' => array('example_3.php'),
  174. ),
  175. 'variant callback' => '_libraries_test_return_installed',
  176. 'variant arguments' => array(TRUE),
  177. ),
  178. 'example_variant_2' => array(
  179. 'files' => array(
  180. 'js' => array('example_4.js'),
  181. 'css' => array('example_4.css'),
  182. 'php' => array('example_4.php'),
  183. ),
  184. 'variant callback' => '_libraries_test_return_installed',
  185. 'variant arguments' => array(TRUE),
  186. ),
  187. ),
  188. ),
  189. ),
  190. );
  191. // Test dependency loading.
  192. // We add one file to each library to be able to verify if it was loaded with
  193. // libraries_load().
  194. // This library acts as a dependency for the libraries below.
  195. $libraries['example_dependency'] = array(
  196. 'name' => 'Example dependency',
  197. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  198. 'version' => '1.1',
  199. 'files' => array('js' => array('example_1.js')),
  200. );
  201. $libraries['example_dependency_missing'] = array(
  202. 'name' => 'Example dependency missing',
  203. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  204. 'version' => '1',
  205. 'dependencies' => array('example_missing'),
  206. 'files' => array('js' => array('example_1.js')),
  207. );
  208. $libraries['example_dependency_incompatible'] = array(
  209. 'name' => 'Example dependency incompatible',
  210. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  211. 'version' => '1',
  212. 'dependencies' => array('example_dependency (>1.1)'),
  213. 'files' => array('js' => array('example_1.js')),
  214. );
  215. $libraries['example_dependency_compatible'] = array(
  216. 'name' => 'Example dependency compatible',
  217. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  218. 'version' => '1',
  219. 'dependencies' => array('example_dependency (>=1.1)'),
  220. 'files' => array('js' => array('example_1.js')),
  221. );
  222. // Test the applying of callbacks.
  223. $libraries['example_callback'] = array(
  224. 'name' => 'Example callback',
  225. 'library path' => drupal_get_path('module', 'libraries') . '/tests/example',
  226. 'version' => '1',
  227. 'versions' => array(
  228. '1' => array(
  229. 'variants' => array(
  230. 'example_variant' => array(
  231. // These keys are for testing purposes only.
  232. 'info callback' => 'not applied',
  233. 'pre-detect callback' => 'not applied',
  234. 'post-detect callback' => 'not applied',
  235. 'pre-dependencies-load callback' => 'not applied',
  236. 'pre-load callback' => 'not applied',
  237. 'post-load callback' => 'not applied',
  238. ),
  239. ),
  240. // These keys are for testing purposes only.
  241. 'info callback' => 'not applied',
  242. 'pre-detect callback' => 'not applied',
  243. 'post-detect callback' => 'not applied',
  244. 'pre-dependencies-load callback' => 'not applied',
  245. 'pre-load callback' => 'not applied',
  246. 'post-load callback' => 'not applied',
  247. ),
  248. ),
  249. 'variants' => array(
  250. 'example_variant' => array(
  251. // These keys are for testing purposes only.
  252. 'info callback' => 'not applied',
  253. 'pre-detect callback' => 'not applied',
  254. 'post-detect callback' => 'not applied',
  255. 'pre-dependencies-load callback' => 'not applied',
  256. 'pre-load callback' => 'not applied',
  257. 'post-load callback' => 'not applied',
  258. ),
  259. ),
  260. 'callbacks' => array(
  261. 'info' => array('_libraries_test_info_callback'),
  262. 'pre-detect' => array('_libraries_test_pre_detect_callback'),
  263. 'post-detect' => array('_libraries_test_post_detect_callback'),
  264. 'pre-dependencies-load' => array('_libraries_test_pre_dependencies_load_callback'),
  265. 'pre-load' => array('_libraries_test_pre_load_callback'),
  266. 'post-load' => array('_libraries_test_post_load_callback'),
  267. ),
  268. // These keys are for testing purposes only.
  269. 'info callback' => 'not applied',
  270. 'pre-detect callback' => 'not applied',
  271. 'post-detect callback' => 'not applied',
  272. 'pre-dependencies-load callback' => 'not applied',
  273. 'pre-load callback' => 'not applied',
  274. 'post-load callback' => 'not applied',
  275. );
  276. return $libraries;
  277. }
  278. /**
  279. * Implements hook_libraries_info_file_paths()
  280. */
  281. function libraries_test_libraries_info_file_paths() {
  282. return array(drupal_get_path('module', 'libraries_test') . '/example');
  283. }
  284. /**
  285. * Gets the version of an example library.
  286. *
  287. * Returns exactly the version string entered as the $version parameter. This
  288. * function cannot be collapsed with _libraries_test_return_installed(), because
  289. * of the different arguments that are passed automatically.
  290. */
  291. function _libraries_test_return_version($library, $version) {
  292. return $version;
  293. }
  294. /**
  295. * Gets the version information from an arbitrary library.
  296. *
  297. * Test function for a version callback with multiple arguments. This is an
  298. * exact copy of libraries_get_version(), which uses a single $option argument,
  299. * except for the fact that it uses multiple arguments. Since we support both
  300. * type of version callbacks, detecting the version of a test library with this
  301. * function ensures that the arguments are passed correctly. This function might
  302. * be a useful reference for a custom version callback that uses multiple
  303. * parameters.
  304. *
  305. * @param $library
  306. * An associative array containing all information about the library.
  307. * @param $file
  308. * The filename to parse for the version, relative to the library path. For
  309. * example: 'docs/changelog.txt'.
  310. * @param pattern
  311. * A string containing a regular expression (PCRE) to match the library
  312. * version. For example: '/@version (\d+)\.(\d+)/'.
  313. * @param lines
  314. * (optional) The maximum number of lines to search the pattern in. Defaults
  315. * to 20.
  316. * @param cols
  317. * (optional) The maximum number of characters per line to take into account.
  318. * Defaults to 200. In case of minified or compressed files, this prevents
  319. * reading the entire file into memory.
  320. *
  321. * @return
  322. * A string containing the version of the library.
  323. *
  324. * @see libraries_get_version()
  325. */
  326. function _libraries_test_get_version($library, $file, $pattern, $lines = 20, $cols = 200) {
  327. $file = DRUPAL_ROOT . '/' . $library['library path'] . '/' . $file;
  328. if (!file_exists($file)) {
  329. return;
  330. }
  331. $file = fopen($file, 'r');
  332. while ($lines && $line = fgets($file, $cols)) {
  333. if (preg_match($pattern, $line, $version)) {
  334. fclose($file);
  335. return $version[1];
  336. }
  337. $lines--;
  338. }
  339. fclose($file);
  340. }
  341. /**
  342. * Detects the variant of an example library.
  343. *
  344. * Returns exactly the value of $installed, either TRUE or FALSE. This function
  345. * cannot be collapsed with _libraries_test_return_version(), because of the
  346. * different arguments that are passed automatically.
  347. */
  348. function _libraries_test_return_installed($library, $name, $installed) {
  349. return $installed;
  350. }
  351. /**
  352. * Sets the 'info callback' key.
  353. *
  354. * This function is used as a test callback for the 'info' callback group.
  355. *
  356. * @see _libraries_test_callback()
  357. */
  358. function _libraries_test_info_callback(&$library, $version, $variant) {
  359. _libraries_test_callback($library, $version, $variant, 'info');
  360. }
  361. /**
  362. * Sets the 'pre-detect callback' key.
  363. *
  364. * This function is used as a test callback for the 'pre-detect' callback group.
  365. *
  366. * @see _libraries_test_callback()
  367. */
  368. function _libraries_test_pre_detect_callback(&$library, $version, $variant) {
  369. _libraries_test_callback($library, $version, $variant, 'pre-detect');
  370. }
  371. /**
  372. * Sets the 'post-detect callback' key.
  373. *
  374. * This function is used as a test callback for the 'post-detect callback group.
  375. *
  376. * @see _libraries_test_callback()
  377. */
  378. function _libraries_test_post_detect_callback(&$library, $version, $variant) {
  379. _libraries_test_callback($library, $version, $variant, 'post-detect');
  380. }
  381. /**
  382. * Sets the 'pre-dependencies-load callback' key.
  383. *
  384. * This function is used as a test callback for the 'pre-dependencies-load'
  385. * callback group.
  386. *
  387. * @see _libraries_test_callback()
  388. */
  389. function _libraries_test_pre_dependencies_load_callback(&$library, $version, $variant) {
  390. _libraries_test_callback($library, $version, $variant, 'pre-dependencies-load');
  391. }
  392. /**
  393. * Sets the 'pre-load callback' key.
  394. *
  395. * This function is used as a test callback for the 'pre-load' callback group.
  396. *
  397. * @see _libraries_test_callback()
  398. */
  399. function _libraries_test_pre_load_callback(&$library, $version, $variant) {
  400. _libraries_test_callback($library, $version, $variant, 'pre-load');
  401. }
  402. /**
  403. * Sets the 'post-load callback' key.
  404. *
  405. * This function is used as a test callback for the 'post-load' callback group.
  406. *
  407. * @see _libraries_test_callback()
  408. */
  409. function _libraries_test_post_load_callback(&$library, $version, $variant) {
  410. _libraries_test_callback($library, $version, $variant, 'post-load');
  411. }
  412. /**
  413. * Sets the '[group] callback' key, where [group] is prepare, detect, or load.
  414. *
  415. * This function is used as a test callback for the all callback groups.
  416. *
  417. * It sets the '[group] callback' (see above) key to 'applied ([part])' where
  418. * [part] is either 'top-level', 'version x.y' (where x.y is the passed-in
  419. * version string), 'variant example' (where example is the passed-in variant
  420. * name), or 'version x.y, variant example' (see above), depending on the part
  421. * of the library the passed-in library information belongs to.
  422. *
  423. * @param $library
  424. * An array of library information, which may be version- or variant-specific.
  425. * Passed by reference.
  426. * @param $version
  427. * The version the library information passed in $library belongs to, or NULL
  428. * if the passed library information is not version-specific.
  429. * @param $variant
  430. * The variant the library information passed in $library belongs to, or NULL
  431. * if the passed library information is not variant-specific.
  432. */
  433. function _libraries_test_callback(&$library, $version, $variant, $group) {
  434. $string = 'applied';
  435. if (isset($version) && isset($variant)) {
  436. $string .= " (version $version, variant $variant)";
  437. }
  438. elseif (isset($version)) {
  439. $string .= " (version $version)";
  440. }
  441. elseif (isset($variant)) {
  442. $string .= " (variant $variant)";
  443. }
  444. else {
  445. $string .= ' (top-level)';
  446. }
  447. $library["$group callback"] = $string;
  448. // The following is used to test caching of library information.
  449. // Only set the message for the top-level library to prevent confusing,
  450. // duplicate messages.
  451. if (!isset($version) && !isset($variant) && variable_get('libraries_test_cache', FALSE)) {
  452. drupal_set_message("The <em>$group</em> callback group was invoked.");
  453. }
  454. }
  455. /**
  456. * Implements hook_menu().
  457. */
  458. function libraries_test_menu() {
  459. $base = array(
  460. 'page callback' => '_libraries_test_load',
  461. 'access callback' => TRUE,
  462. );
  463. $items['libraries_test/files'] = $base + array(
  464. 'title' => 'Test files',
  465. 'page arguments' => array('example_files'),
  466. );
  467. $items['libraries_test/integration_files'] = $base + array(
  468. 'title' => 'Test integration files',
  469. 'page arguments' => array('example_integration_files'),
  470. );
  471. $items['libraries_test/versions'] = $base + array(
  472. 'title' => 'Test version loading',
  473. 'page arguments' => array('example_versions'),
  474. );
  475. $items['libraries_test/variant'] = $base + array(
  476. 'title' => 'Test variant loading',
  477. 'page arguments' => array('example_variant', 'example_variant'),
  478. );
  479. $items['libraries_test/versions_and_variants'] = $base + array(
  480. 'title' => 'Test concurrent version and variant loading',
  481. 'page arguments' => array('example_versions_and_variants', 'example_variant_2'),
  482. );
  483. $items['libraries_test/cache'] = $base + array(
  484. 'title' => 'Test caching of library information',
  485. 'page arguments' => array('example_callback'),
  486. );
  487. return $items;
  488. }
  489. /**
  490. * Loads a specified library (variant) for testing.
  491. *
  492. * JavaScript and CSS files can be checked directly by SimpleTest, so we only
  493. * need to manually check for PHP files. We provide information about the loaded
  494. * JavaScript and CSS files for easier debugging. See example/README.txt for
  495. * more information.
  496. */
  497. function _libraries_test_load($library, $variant = NULL) {
  498. libraries_load($library, $variant);
  499. // JavaScript and CSS files can be checked directly by SimpleTest, so we only
  500. // need to manually check for PHP files.
  501. $output = '';
  502. // For easer debugging of JS loading, a text is shown that the JavaScript will
  503. // replace.
  504. $output .= '<h2>JavaScript</h2>';
  505. $output .= '<div class="libraries-test-javascript">';
  506. $output .= 'If this text shows up, no JavaScript test file was loaded.';
  507. $output .= '</div>';
  508. // For easier debugging of CSS loading, the loaded CSS files will color the
  509. // following text.
  510. $output .= '<h2>CSS</h2>';
  511. $output .= '<div class="libraries-test-css">';
  512. $output .= 'If one of the CSS test files has been loaded, this text will be colored:';
  513. $output .= '<ul>';
  514. // Do not reference the actual CSS files (i.e. including '.css'), because that
  515. // breaks testing.
  516. $output .= '<li>example_1: red</li>';
  517. $output .= '<li>example_2: green</li>';
  518. $output .= '<li>example_3: orange</li>';
  519. $output .= '<li>example_4: blue</li>';
  520. $output .= '<li>libraries_test: purple</li>';
  521. $output .= '</ul>';
  522. $output .= '</div>';
  523. $output .= '<h2>PHP</h2>';
  524. $output .= '<div class="libraries-test-php">';
  525. $output .= 'The following is a list of all loaded test PHP files:';
  526. $output .= '<ul>';
  527. $files = get_included_files();
  528. foreach ($files as $file) {
  529. if (strpos($file, 'libraries/test') && !strpos($file, 'libraries_test.module')) {
  530. $output .= '<li>' . str_replace(DRUPAL_ROOT . '/', '', $file) . '</li>';
  531. }
  532. }
  533. $output .= '</ul>';
  534. $output .= '</div>';
  535. return $output;
  536. }