Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
OOUIFileModule
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 4
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 setSkinStylesOverride
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getSkinSpecific
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 extendSkinSpecific
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\ResourceLoader;
8
9/**
10 * Module which magically loads the right skinScripts and skinStyles for every
11 * skin, using the specified OOUI theme for each.
12 *
13 * @ingroup ResourceLoader
14 * @internal
15 */
16class OOUIFileModule extends FileModule {
17    use OOUIModule;
18
19    /** @var array<string,string|FilePath> */
20    private $themeStyles = [];
21
22    public function __construct( array $options = [] ) {
23        if ( isset( $options['themeScripts'] ) ) {
24            $skinScripts = $this->getSkinSpecific( $options['themeScripts'], 'scripts' );
25            $options['skinScripts'] = $this->extendSkinSpecific( $options['skinScripts'] ?? [], $skinScripts );
26        }
27        if ( isset( $options['themeStyles'] ) ) {
28            $this->themeStyles = $this->getSkinSpecific( $options['themeStyles'], 'styles' );
29        }
30
31        parent::__construct( $options );
32    }
33
34    public function setSkinStylesOverride( array $moduleSkinStyles ): void {
35        parent::setSkinStylesOverride( $moduleSkinStyles );
36
37        $this->skinStyles = $this->extendSkinSpecific( $this->skinStyles, $this->themeStyles );
38    }
39
40    /**
41     * Helper function to generate values for 'skinStyles' and 'skinScripts'.
42     *
43     * @param string $module Module to generate skinStyles/skinScripts for:
44     *   'core', 'widgets', 'toolbars', 'windows'
45     * @param string $which 'scripts' or 'styles'
46     * @return array<string,string|FilePath>
47     */
48    private function getSkinSpecific( $module, $which ): array {
49        $themes = self::getSkinThemeMap();
50
51        return array_combine(
52            array_keys( $themes ),
53            array_map( function ( $theme ) use ( $module, $which ) {
54                if ( $which === 'scripts' ) {
55                    return $this->getThemeScriptsPath( $theme, $module );
56                } else {
57                    return $this->getThemeStylesPath( $theme, $module );
58                }
59            }, array_values( $themes ) )
60        );
61    }
62
63    /**
64     * Prepend theme-specific resources on behalf of the skin.
65     *
66     * The expected order of styles and scripts in the output is:
67     *
68     * 1. Theme-specific resources for a given skin.
69     *
70     * 2. Module-defined resources for a specific skin,
71     *    falling back to module-defined "default" skin resources.
72     *
73     * 3. Skin-defined resources for a specific module, which can either
74     *    append to or replace the "default" (via ResourceModuleSkinStyles in skin.json)
75     *    Note that skins can only define resources for a module if that
76     *    module does not already explicitly provide resources for that skin.
77     *
78     * @param array $skinSpecific Module-defined 'skinScripts' or 'skinStyles'.
79     * @param array $themeSpecific
80     * @return array Modified $skinSpecific
81     */
82    private function extendSkinSpecific( array $skinSpecific, array $themeSpecific ): array {
83        // If the module or skin already set skinStyles/skinScripts, prepend ours
84        foreach ( $skinSpecific as $skin => &$files ) {
85            $prepend = $themeSpecific[$skin] ?? $themeSpecific['default'] ?? null;
86            if ( $prepend !== null ) {
87                if ( !is_array( $files ) ) {
88                    $files = [ $files ];
89                }
90                array_unshift( $files, $prepend );
91            }
92        }
93        // If the module has no skinStyles/skinScripts for a skin, then set ours
94        foreach ( $themeSpecific as $skin => $file ) {
95            $skinSpecific[$skin] ??= [ $file ];
96        }
97        return $skinSpecific;
98    }
99}