Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
9.09% covered (danger)
9.09%
3 / 33
16.67% covered (danger)
16.67%
1 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
OOUIModule
9.09% covered (danger)
9.09%
3 / 33
16.67% covered (danger)
16.67%
1 / 6
161.26
0.00% covered (danger)
0.00%
0 / 1
 getSkinThemeMap
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getThemePaths
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 getThemePath
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 getThemeScriptsPath
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getThemeStylesPath
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getThemeImagesPath
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\ResourceLoader;
22
23use ExtensionRegistry;
24use InvalidArgumentException;
25
26/**
27 * Convenience methods for dealing with OOUI themes and their relations to MW skins.
28 *
29 * @ingroup ResourceLoader
30 * @internal
31 */
32trait OOUIModule {
33    protected static $knownScriptsModules = [ 'core' ];
34    protected static $knownStylesModules = [ 'core', 'widgets', 'toolbars', 'windows' ];
35    protected static $knownImagesModules = [
36        'indicators',
37        // Extra icons
38        'icons-accessibility',
39        'icons-alerts',
40        'icons-content',
41        'icons-editing-advanced',
42        'icons-editing-citation',
43        'icons-editing-core',
44        'icons-editing-list',
45        'icons-editing-styling',
46        'icons-interactions',
47        'icons-layout',
48        'icons-location',
49        'icons-media',
50        'icons-moderation',
51        'icons-movement',
52        'icons-user',
53        'icons-wikimedia',
54    ];
55
56    /** @var string[] Note that keys must be lowercase, values TitleCase. */
57    protected static $builtinSkinThemeMap = [
58        'default' => 'WikimediaUI',
59    ];
60
61    /** @var string[][] Note that keys must be TitleCase. */
62    protected static $builtinThemePaths = [
63        'WikimediaUI' => [
64            'scripts' => 'resources/lib/ooui/oojs-ui-wikimediaui.js',
65            'styles' => 'resources/lib/ooui/oojs-ui-{module}-wikimediaui.css',
66            'images' => 'resources/lib/ooui/themes/wikimediaui/{module}.json',
67        ],
68        'Apex' => [
69            'scripts' => 'resources/lib/ooui/oojs-ui-apex.js',
70            'styles' => 'resources/lib/ooui/oojs-ui-{module}-apex.css',
71            'images' => 'resources/lib/ooui/themes/apex/{module}.json',
72        ],
73    ];
74
75    /**
76     * Return a map of skin names (in lowercase) to OOUI theme names, defining which theme a given
77     * skin should use.
78     *
79     * @return array
80     */
81    public static function getSkinThemeMap() {
82        $themeMap = self::$builtinSkinThemeMap;
83        $themeMap += ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' );
84        return $themeMap;
85    }
86
87    /**
88     * Return a map of theme names to lists of paths from which a given theme should be loaded.
89     *
90     * Keys are theme names, values are associative arrays. Keys of the inner array are 'scripts',
91     * 'styles', or 'images', and values are paths. Paths may be strings or FilePaths.
92     *
93     * Additionally, the string '{module}' in paths represents the name of the module to load.
94     *
95     * @return array
96     */
97    protected static function getThemePaths() {
98        $themePaths = self::$builtinThemePaths;
99        $themePaths += ExtensionRegistry::getInstance()->getAttribute( 'OOUIThemePaths' );
100
101        [ $defaultLocalBasePath, $defaultRemoteBasePath ] =
102            FileModule::extractBasePaths();
103
104        // Allow custom themes' paths to be relative to the skin/extension that defines them,
105        // like with ResourceModuleSkinStyles
106        foreach ( $themePaths as &$paths ) {
107            [ $localBasePath, $remoteBasePath ] =
108                FileModule::extractBasePaths( $paths );
109            if ( $localBasePath !== $defaultLocalBasePath || $remoteBasePath !== $defaultRemoteBasePath ) {
110                foreach ( $paths as &$path ) {
111                    $path = new FilePath( $path, $localBasePath, $remoteBasePath );
112                }
113            }
114        }
115
116        return $themePaths;
117    }
118
119    /**
120     * Return a path to load given module of given theme from.
121     *
122     * The file at this path may not exist. This should be handled by the caller (throwing an error or
123     * falling back to default theme).
124     *
125     * @param string $theme OOUI theme name, for example 'WikimediaUI' or 'Apex'
126     * @param string $kind Kind of the module: 'scripts', 'styles', or 'images'
127     * @param string $module Module name, for valid values see $knownScriptsModules,
128     *     $knownStylesModules, $knownImagesModules
129     * @return string|FilePath
130     */
131    protected function getThemePath( $theme, $kind, $module ) {
132        $paths = self::getThemePaths();
133        $path = $paths[$theme][$kind];
134        if ( $path instanceof FilePath ) {
135            $path = new FilePath(
136                str_replace( '{module}', $module, $path->getPath() ),
137                $path->getLocalBasePath(),
138                $path->getRemoteBasePath()
139            );
140        } else {
141            $path = str_replace( '{module}', $module, $path );
142        }
143        return $path;
144    }
145
146    /**
147     * @param string $theme See getThemePath()
148     * @param string $module See getThemePath()
149     * @return string|FilePath
150     */
151    protected function getThemeScriptsPath( $theme, $module ) {
152        if ( !in_array( $module, self::$knownScriptsModules ) ) {
153            throw new InvalidArgumentException( "Invalid OOUI scripts module '$module'" );
154        }
155        return $this->getThemePath( $theme, 'scripts', $module );
156    }
157
158    /**
159     * @param string $theme See getThemePath()
160     * @param string $module See getThemePath()
161     * @return string|FilePath
162     */
163    protected function getThemeStylesPath( $theme, $module ) {
164        if ( !in_array( $module, self::$knownStylesModules ) ) {
165            throw new InvalidArgumentException( "Invalid OOUI styles module '$module'" );
166        }
167        return $this->getThemePath( $theme, 'styles', $module );
168    }
169
170    /**
171     * @param string $theme See getThemePath()
172     * @param string $module See getThemePath()
173     * @return string|FilePath
174     */
175    protected function getThemeImagesPath( $theme, $module ) {
176        if ( !in_array( $module, self::$knownImagesModules ) ) {
177            throw new InvalidArgumentException( "Invalid OOUI images module '$module'" );
178        }
179        return $this->getThemePath( $theme, 'images', $module );
180    }
181}