Index: trunk/phase3/includes/resourceloader/ResourceLoaderFileModule.php |
— | — | @@ -26,6 +26,7 @@ |
27 | 27 | * Module based on local JS/CSS files. This is the most common type of module. |
28 | 28 | */ |
29 | 29 | class ResourceLoaderFileModule extends ResourceLoaderModule { |
| 30 | + |
30 | 31 | /* Protected Members */ |
31 | 32 | |
32 | 33 | protected $scripts = array(); |
— | — | @@ -38,7 +39,6 @@ |
39 | 40 | protected $skinScripts = array(); |
40 | 41 | protected $skinStyles = array(); |
41 | 42 | protected $loaders = array(); |
42 | | - protected $parameters = array(); |
43 | 43 | |
44 | 44 | // In-object cache for file dependencies |
45 | 45 | protected $fileDeps = array(); |
— | — | @@ -49,75 +49,65 @@ |
50 | 50 | |
51 | 51 | /** |
52 | 52 | * Construct a new module from an options array. |
53 | | - * |
54 | | - * @param $options array Options array. If empty, an empty module will be constructed |
55 | | - * |
56 | | - * $options format: |
| 53 | + * |
| 54 | + * @param {array} $options Options array. If not given or empty, an empty module will be constructed |
| 55 | + * @param {string} $basePath base path to prepend to all paths in $options |
| 56 | + * |
| 57 | + * @format $options |
57 | 58 | * array( |
58 | | - * // Required module options (mutually exclusive) |
59 | | - * 'scripts' => 'dir/script.js' | array( 'dir/script1.js', 'dir/script2.js' ... ), |
60 | | - * |
61 | | - * // Optional module options |
| 59 | + * // Scripts to always include |
| 60 | + * 'scripts' => [file path string or array of file path strings], |
| 61 | + * // Scripts to include in specific language contexts |
62 | 62 | * 'languageScripts' => array( |
63 | | - * '[lang name]' => 'dir/lang.js' | '[lang name]' => array( 'dir/lang1.js', 'dir/lang2.js' ... ) |
64 | | - * ... |
| 63 | + * [language code] => [file path string or array of file path strings], |
65 | 64 | * ), |
66 | | - * 'skinScripts' => 'dir/skin.js' | array( 'dir/skin1.js', 'dir/skin2.js' ... ), |
67 | | - * 'debugScripts' => 'dir/debug.js' | array( 'dir/debug1.js', 'dir/debug2.js' ... ), |
68 | | - * |
69 | | - * // Non-raw module options |
70 | | - * 'dependencies' => 'module' | array( 'module1', 'module2' ... ) |
71 | | - * 'loaderScripts' => 'dir/loader.js' | array( 'dir/loader1.js', 'dir/loader2.js' ... ), |
72 | | - * 'styles' => 'dir/file.css' | array( 'dir/file1.css', 'dir/file2.css' ... ), | |
73 | | - * array( 'dir/file1.css' => array( 'media' => 'print' ) ), |
| 65 | + * // Scripts to include in specific skin contexts |
| 66 | + * 'skinScripts' => array( |
| 67 | + * [skin name] => [file path string or array of file path strings], |
| 68 | + * ), |
| 69 | + * // Scripts to include in debug contexts |
| 70 | + * 'debugScripts' => [file path string or array of file path strings], |
| 71 | + * // Scripts to include in the startup module |
| 72 | + * 'loaders' => [file path string or array of file path strings], |
| 73 | + * // Modules which must be loaded before this module |
| 74 | + * 'dependencies' => [modile name string or array of module name strings], |
| 75 | + * // Styles to always load |
| 76 | + * 'styles' => [file path string or array of file path strings], |
| 77 | + * // Styles to include in specific skin contexts |
74 | 78 | * 'skinStyles' => array( |
75 | | - * '[skin name]' => 'dir/skin.css' | array( 'dir/skin1.css', 'dir/skin2.css' ... ) | |
76 | | - * array( 'dir/file1.css' => array( 'media' => 'print' ) |
77 | | - * ... |
| 79 | + * [skin name] => [file path string or array of file path strings], |
78 | 80 | * ), |
79 | | - * 'messages' => array( 'message1', 'message2' ... ), |
80 | | - * 'group' => 'stuff', |
| 81 | + * // Messages to always load |
| 82 | + * 'messages' => [array of message key strings], |
| 83 | + * // Group which this module should be loaded together with |
| 84 | + * 'group' => [group name string], |
81 | 85 | * ) |
82 | | - * |
83 | | - * @param $basePath String: base path to prepend to all paths in $options |
84 | 86 | */ |
85 | 87 | public function __construct( $options = array(), $basePath = null ) { |
86 | | - foreach ( $options as $option => $value ) { |
87 | | - switch ( $option ) { |
| 88 | + foreach ( $options as $member => $option ) { |
| 89 | + switch ( $member ) { |
| 90 | + // Lists of file paths |
88 | 91 | case 'scripts': |
89 | 92 | case 'debugScripts': |
| 93 | + case 'loaders': |
| 94 | + case 'styles': |
| 95 | + $this->{$member} = $this->prefixFilePathList( (array) $option, $basePath ); |
| 96 | + break; |
| 97 | + // Collated lists of file paths |
90 | 98 | case 'languageScripts': |
91 | 99 | case 'skinScripts': |
92 | | - case 'loaders': |
93 | | - $this->{$option} = (array)$value; |
94 | | - // Automatically prefix script paths |
95 | | - if ( is_string( $basePath ) ) { |
96 | | - foreach ( $this->{$option} as $key => $value ) { |
97 | | - $this->{$option}[$key] = $basePath . $value; |
98 | | - } |
99 | | - } |
100 | | - break; |
101 | | - case 'styles': |
102 | 100 | case 'skinStyles': |
103 | | - $this->{$option} = (array)$value; |
104 | | - // Automatically prefix style paths |
105 | | - if ( is_string( $basePath ) ) { |
106 | | - foreach ( $this->{$option} as $key => $value ) { |
107 | | - if ( is_array( $value ) ) { |
108 | | - $this->{$option}[$basePath . $key] = $value; |
109 | | - unset( $this->{$option}[$key] ); |
110 | | - } else { |
111 | | - $this->{$option}[$key] = $basePath . $value; |
112 | | - } |
113 | | - } |
| 101 | + foreach ( (array) $option as $key => $value ) { |
| 102 | + $this->{$member}[$key] = $this->prefixFilePathList( (array) $value, $basePath ); |
114 | 103 | } |
115 | | - break; |
| 104 | + // Lists of strings |
116 | 105 | case 'dependencies': |
117 | 106 | case 'messages': |
118 | | - $this->{$option} = (array)$value; |
| 107 | + $this->{$member} = (array) $option; |
119 | 108 | break; |
| 109 | + // Single strings |
120 | 110 | case 'group': |
121 | | - $this->group = (string)$value; |
| 111 | + $this->group = (string) $option; |
122 | 112 | break; |
123 | 113 | } |
124 | 114 | } |
— | — | @@ -338,11 +328,11 @@ |
339 | 329 | |
340 | 330 | // Sort of nasty way we can get a flat list of files depended on by all styles |
341 | 331 | $styles = array(); |
342 | | - foreach ( self::organizeFilesByOption( $this->styles, 'media', 'all' ) as $styleFiles ) { |
| 332 | + foreach ( self::collateFilePathListByOption( $this->styles, 'media', 'all' ) as $styleFiles ) { |
343 | 333 | $styles = array_merge( $styles, $styleFiles ); |
344 | 334 | } |
345 | 335 | $skinFiles = (array) self::getSkinFiles( |
346 | | - $context->getSkin(), self::organizeFilesByOption( $this->skinStyles, 'media', 'all' ) |
| 336 | + $context->getSkin(), self::collateFilePathListByOption( $this->skinStyles, 'media', 'all' ) |
347 | 337 | ); |
348 | 338 | foreach ( $skinFiles as $styleFiles ) { |
349 | 339 | $styles = array_merge( $styles, $styleFiles ); |
— | — | @@ -371,6 +361,53 @@ |
372 | 362 | /* Protected Members */ |
373 | 363 | |
374 | 364 | /** |
| 365 | + * Prefixes each file path in a list |
| 366 | + * |
| 367 | + * @param {array} $list List of file paths in any combination of index/path or path/options pairs |
| 368 | + * @param {string} $prefix String to prepend to each file path in $list |
| 369 | + * @return {array} List of prefixed file paths |
| 370 | + */ |
| 371 | + protected function prefixFilePathList( array $list, $prefix ) { |
| 372 | + $prefixed = array(); |
| 373 | + foreach ( $list as $key => $value ) { |
| 374 | + if ( is_array( $value ) ) { |
| 375 | + // array( [path] => array( [options] ) ) |
| 376 | + $prefixed[$prefix . $key] = $value; |
| 377 | + } else { |
| 378 | + // array( [path] ) |
| 379 | + $prefixed[$key] = $prefix . $value; |
| 380 | + } |
| 381 | + } |
| 382 | + return $prefixed; |
| 383 | + } |
| 384 | + |
| 385 | + /** |
| 386 | + * Collates file paths by option (where provided) |
| 387 | + * |
| 388 | + * @param {array} $list List of file paths in any combination of index/path or path/options pairs |
| 389 | + */ |
| 390 | + protected static function collateFilePathListByOption( array $list, $option, $default ) { |
| 391 | + $collatedFiles = array(); |
| 392 | + foreach ( (array) $list as $key => $value ) { |
| 393 | + if ( is_int( $key ) ) { |
| 394 | + // File name as the value |
| 395 | + if ( !isset( $collatedFiles[$default] ) ) { |
| 396 | + $collatedFiles[$default] = array(); |
| 397 | + } |
| 398 | + $collatedFiles[$default][] = $value; |
| 399 | + } else if ( is_array( $value ) ) { |
| 400 | + // File name as the key, options array as the value |
| 401 | + $media = isset( $value[$option] ) ? $value[$option] : $default; |
| 402 | + if ( !isset( $collatedFiles[$media] ) ) { |
| 403 | + $collatedFiles[$media] = array(); |
| 404 | + } |
| 405 | + $collatedFiles[$media][] = $key; |
| 406 | + } |
| 407 | + } |
| 408 | + return $collatedFiles; |
| 409 | + } |
| 410 | + |
| 411 | + /** |
375 | 412 | * Get the primary JS for this module. This is pulled from the |
376 | 413 | * script files added through addScripts() |
377 | 414 | * |
— | — | @@ -468,27 +505,6 @@ |
469 | 506 | array_unique( (array) $files ) ) ) ); |
470 | 507 | } |
471 | 508 | |
472 | | - protected static function organizeFilesByOption( $files, $option, $default ) { |
473 | | - $organizedFiles = array(); |
474 | | - foreach ( (array) $files as $key => $value ) { |
475 | | - if ( is_int( $key ) ) { |
476 | | - // File name as the value |
477 | | - if ( !isset( $organizedFiles[$default] ) ) { |
478 | | - $organizedFiles[$default] = array(); |
479 | | - } |
480 | | - $organizedFiles[$default][] = $value; |
481 | | - } else if ( is_array( $value ) ) { |
482 | | - // File name as the key, options array as the value |
483 | | - $media = isset( $value[$option] ) ? $value[$option] : $default; |
484 | | - if ( !isset( $organizedFiles[$media] ) ) { |
485 | | - $organizedFiles[$media] = array(); |
486 | | - } |
487 | | - $organizedFiles[$media][] = $key; |
488 | | - } |
489 | | - } |
490 | | - return $organizedFiles; |
491 | | - } |
492 | | - |
493 | 509 | /** |
494 | 510 | * Get the contents of a set of CSS files, remap then and concatenate |
495 | 511 | * them, with newlines in between. Each file is used only once. |
— | — | @@ -497,7 +513,7 @@ |
498 | 514 | * @return Array: list of concatenated and remapped contents of $files keyed by media type |
499 | 515 | */ |
500 | 516 | protected static function concatStyles( $styles ) { |
501 | | - $styles = self::organizeFilesByOption( $styles, 'media', 'all' ); |
| 517 | + $styles = self::collateFilePathListByOption( $styles, 'media', 'all' ); |
502 | 518 | foreach ( $styles as $media => $files ) { |
503 | 519 | $styles[$media] = |
504 | 520 | implode( "\n", |