'ResourceLoaderLessVarFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderLessVarFileModule.php',
'ResourceLoaderModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderModule.php',
'ResourceLoaderOOUIFileModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIFileModule.php',
+ 'ResourceLoaderOOUIIconPackModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIIconPackModule.php',
'ResourceLoaderOOUIImageModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIImageModule.php',
'ResourceLoaderOOUIModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderOOUIModule.php',
'ResourceLoaderSiteModule' => __DIR__ . '/includes/resourceloader/ResourceLoaderSiteModule.php',
'oojs-ui.styles.indicators',
'oojs-ui.styles.textures',
'mediawiki.widgets.styles',
- 'oojs-ui.styles.icons-content',
- 'oojs-ui.styles.icons-alerts',
- 'oojs-ui.styles.icons-interactions',
+ 'oojs-ui-core.icons',
] );
}
--- /dev/null
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * Allows loading arbitrary sets of OOUI icons.
+ *
+ * @since 1.34
+ */
+class ResourceLoaderOOUIIconPackModule extends ResourceLoaderOOUIImageModule {
+ public function __construct( $options = [], $localBasePath = null ) {
+ parent::__construct( $options, $localBasePath );
+
+ if ( !isset( $this->definition['icons'] ) || !$this->definition['icons'] ) {
+ throw new InvalidArgumentException( "Parameter 'icons' must be given." );
+ }
+
+ // A few things check for the "icons" prefix on this value, so specify it even though
+ // we don't use it for actually loading the data, like in the other modules.
+ $this->definition['themeImages'] = 'icons';
+ }
+
+ private function getIcons() {
+ return $this->definition['icons'];
+ }
+
+ protected function loadOOUIDefinition( $theme, $unused ) {
+ // This is shared between instances of this class, so we only have to load the JSON files once
+ static $data = [];
+
+ if ( !isset( $data[$theme] ) ) {
+ $data[$theme] = [];
+ // Load and merge the JSON data for all "icons-foo" modules
+ foreach ( self::$knownImagesModules as $module ) {
+ if ( substr( $module, 0, 5 ) === 'icons' ) {
+ $moreData = $this->readJSONFile( $this->getThemeImagesPath( $theme, $module ) );
+ if ( $moreData ) {
+ $data[$theme] = array_replace_recursive( $data[$theme], $moreData );
+ }
+ }
+ }
+ }
+
+ $definition = $data[$theme];
+
+ // Filter out the data for all other icons, leaving only the ones we want for this module
+ $iconsNames = $this->getIcons();
+ foreach ( array_keys( $definition['images'] ) as $iconName ) {
+ if ( !in_array( $iconName, $iconsNames ) ) {
+ unset( $definition['images'][$iconName] );
+ }
+ }
+
+ return $definition;
+ }
+}
*/
/**
- * Secret special sauce.
+ * Loads the module definition from JSON files in the format that OOUI uses, converting it to the
+ * format we use. (Previously known as secret special sauce.)
*
* @since 1.26
*/
$definition = [];
foreach ( $themes as $skin => $theme ) {
- // Find the path to the JSON file which contains the actual image definitions for this theme
- if ( $module ) {
- $dataPath = $this->getThemeImagesPath( $theme, $module );
- } else {
- // Backwards-compatibility for things that probably shouldn't have used this class...
- $dataPath =
- $this->definition['rootPath'] . '/' .
- strtolower( $theme ) . '/' .
- $this->definition['name'] . '.json';
- }
- $localDataPath = $this->localBasePath . '/' . $dataPath;
+ $data = $this->loadOOUIDefinition( $theme, $module );
- // If there's no file for this module of this theme, that's okay, it will just use the defaults
- if ( !file_exists( $localDataPath ) ) {
+ if ( !$data ) {
+ // If there's no file for this module of this theme, that's okay, it will just use the defaults
continue;
}
- $data = json_decode( file_get_contents( $localDataPath ), true );
-
- // Expand the paths to images (since they are relative to the JSON file that defines them, not
- // our base directory)
- $fixPath = function ( &$path ) use ( $dataPath ) {
- $path = dirname( $dataPath ) . '/' . $path;
- };
- array_walk( $data['images'], function ( &$value ) use ( $fixPath ) {
- if ( is_string( $value['file'] ) ) {
- $fixPath( $value['file'] );
- } elseif ( is_array( $value['file'] ) ) {
- array_walk_recursive( $value['file'], $fixPath );
- }
- } );
// Convert into a definition compatible with the parent vanilla ResourceLoaderImageModule
foreach ( $data as $key => $value ) {
parent::loadFromDefinition();
}
+
+ /**
+ * Load the module definition from the JSON file(s) for the given theme and module.
+ *
+ * @since 1.34
+ * @param string $theme
+ * @param string $module
+ * @return array
+ */
+ protected function loadOOUIDefinition( $theme, $module ) {
+ // Find the path to the JSON file which contains the actual image definitions for this theme
+ if ( $module ) {
+ $dataPath = $this->getThemeImagesPath( $theme, $module );
+ } else {
+ // Backwards-compatibility for things that probably shouldn't have used this class...
+ $dataPath =
+ $this->definition['rootPath'] . '/' .
+ strtolower( $theme ) . '/' .
+ $this->definition['name'] . '.json';
+ }
+
+ return $this->readJSONFile( $dataPath );
+ }
+
+ /**
+ * Read JSON from a file, and transform all paths in it to be relative to the module's base path.
+ *
+ * @since 1.34
+ * @param string $dataPath Path relative to the module's base bath
+ * @return array|false
+ */
+ protected function readJSONFile( $dataPath ) {
+ $localDataPath = $this->localBasePath . '/' . $dataPath;
+
+ if ( !file_exists( $localDataPath ) ) {
+ return false;
+ }
+
+ $data = json_decode( file_get_contents( $localDataPath ), true );
+
+ // Expand the paths to images (since they are relative to the JSON file that defines them, not
+ // our base directory)
+ $fixPath = function ( &$path ) use ( $dataPath ) {
+ $path = dirname( $dataPath ) . '/' . $path;
+ };
+ array_walk( $data['images'], function ( &$value ) use ( $fixPath ) {
+ if ( is_string( $value['file'] ) ) {
+ $fixPath( $value['file'] );
+ } elseif ( is_array( $value['file'] ) ) {
+ array_walk_recursive( $value['file'], $fixPath );
+ }
+ } );
+
+ return $data;
+ }
}
'dependencies' => [
'oojs',
'oojs-ui-core.styles',
+ 'oojs-ui-core.icons',
'oojs-ui.styles.indicators',
'oojs-ui.styles.textures',
'mediawiki.language',
- 'oojs-ui.styles.icons-content',
- 'oojs-ui.styles.icons-alerts',
- 'oojs-ui.styles.icons-interactions',
],
'messages' => [
'ooui-field-help',
'themeStyles' => 'core',
'targets' => [ 'desktop', 'mobile' ],
],
+ 'oojs-ui-core.icons' => [
+ 'class' => ResourceLoaderOOUIIconPackModule::class,
+ 'icons' => [ 'add', 'alert', 'notice', 'error', 'check', 'close', 'info', 'search', 'subtract' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
// Additional widgets and layouts module.
'oojs-ui-widgets' => [
'class' => ResourceLoaderOOUIFileModule::class,
'themeStyles' => 'widgets',
'dependencies' => [
'oojs-ui-core',
- 'oojs-ui.styles.icons-interactions',
- 'oojs-ui.styles.icons-content',
- 'oojs-ui.styles.icons-editing-advanced',
- 'oojs-ui.styles.icons-movement',
- 'oojs-ui.styles.icons-moderation',
+ 'oojs-ui-widgets.icons',
],
'messages' => [
'ooui-item-remove',
'themeStyles' => 'widgets',
'targets' => [ 'desktop', 'mobile' ],
],
+ 'oojs-ui-widgets.icons' => [
+ 'class' => ResourceLoaderOOUIIconPackModule::class,
+ // Do not repeat icons already used in 'oojs-ui-core.icons'
+ 'icons' => [ 'attachment', 'collapse', 'expand', 'trash', 'upload' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
// Toolbar and tools module.
'oojs-ui-toolbars' => [
'class' => ResourceLoaderOOUIFileModule::class,
'themeStyles' => 'toolbars',
'dependencies' => [
'oojs-ui-core',
- 'oojs-ui.styles.icons-movement',
+ 'oojs-ui-toolbars.icons',
],
'messages' => [
'ooui-toolbar-more',
],
'targets' => [ 'desktop', 'mobile' ],
],
+ 'oojs-ui-toolbars.icons' => [
+ 'class' => ResourceLoaderOOUIIconPackModule::class,
+ // Do not repeat icons already used in 'oojs-ui-core.icons': 'check'
+ 'icons' => [ 'collapse', 'expand' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
// Windows and dialogs module.
'oojs-ui-windows' => [
'class' => ResourceLoaderOOUIFileModule::class,
'themeStyles' => 'windows',
'dependencies' => [
'oojs-ui-core',
- 'oojs-ui.styles.icons-movement',
+ 'oojs-ui-windows.icons',
],
'messages' => [
'ooui-dialog-message-accept',
],
'targets' => [ 'desktop', 'mobile' ],
],
+ 'oojs-ui-windows.icons' => [
+ 'class' => ResourceLoaderOOUIIconPackModule::class,
+ // Do not repeat icons already used in 'oojs-ui-core.icons': 'close'
+ 'icons' => [ 'previous' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
'oojs-ui.styles.indicators' => [
'class' => ResourceLoaderOOUIImageModule::class,