6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * http://www.gnu.org/copyleft/gpl.html
24 use Wikimedia\ObjectFactory\ObjectFactory
;
27 * Factory class to create Skin objects
32 private const SKIP_BY_SITECONFIG
= 1;
33 private const SKIP_BY_REGISTER
= 2;
36 * Map of skin name to object factory spec or factory function.
38 * @var array<string,array|callable>
40 private $factoryFunctions = [];
42 * Map of name => fallback human-readable name, used when the 'skinname-<skin>' message is not
47 private $displayNames = [];
51 private $objectFactory;
54 * Array of skins that should not be presented in the list of
55 * available skins in user preferences, while they're still installed.
57 * @var array<string,int>
62 * @internal For ServiceWiring only
64 * @param ObjectFactory $objectFactory
65 * @param string[] $skipSkins
67 public function __construct( ObjectFactory
$objectFactory, array $skipSkins ) {
68 $this->objectFactory
= $objectFactory;
69 $this->skipSkins
= array_fill_keys( $skipSkins, self
::SKIP_BY_SITECONFIG
);
73 * Register a new skin.
75 * This will replace any previously registered skin by the same name.
77 * @param string $name Internal skin name. See also Skin::__construct.
78 * @param string $displayName For backwards-compatibility with old skin loading system. This is
79 * the text used as skin's human-readable name when the 'skinname-<skin>' message is not
81 * @param array|callable $spec ObjectFactory spec to construct a Skin object,
82 * or callback that takes a skin name and returns a Skin object.
83 * See Skin::__construct for the constructor arguments.
84 * @param true|null $skippable Whether the skin is skippable and should be hidden
85 * from user preferences. By default, this is determined based by $wgSkipSkins.
87 public function register( $name, $displayName, $spec, ?
bool $skippable = null ) {
88 if ( !is_callable( $spec ) ) {
89 if ( is_array( $spec ) ) {
90 if ( !isset( $spec['args'] ) ) {
91 // make sure name option is set:
97 throw new InvalidArgumentException( 'Invalid callback provided' );
100 $this->factoryFunctions
[$name] = $spec;
101 $this->displayNames
[$name] = $displayName;
103 // If skipped by site config, leave as-is.
104 if ( ( $this->skipSkins
[$name] ??
null ) !== self
::SKIP_BY_SITECONFIG
) {
105 if ( $skippable === true ) {
106 $this->skipSkins
[$name] = self
::SKIP_BY_REGISTER
;
108 // Make sure the register() call is unaffected by previous calls.
109 unset( $this->skipSkins
[$name] );
115 * Return an associative array of `skin name => human readable name`.
117 * @deprecated since 1.37 Use getInstalledSkins instead
120 public function getSkinNames() {
121 wfDeprecated( __METHOD__
, '1.37' );
122 return $this->displayNames
;
126 * Create a given Skin using the registered callback for $name.
128 * @param string $name Name of the skin you want
129 * @throws SkinException If a factory function isn't registered for $name
132 public function makeSkin( $name ) {
133 if ( !isset( $this->factoryFunctions
[$name] ) ) {
134 throw new SkinException( "No registered builder available for $name." );
137 return $this->objectFactory
->createObject(
138 $this->factoryFunctions
[$name],
140 'allowCallable' => true,
141 'assertClass' => Skin
::class,
147 * Get the list of user-selectable skins.
149 * Useful for Special:Preferences and other places where you
150 * only want to show skins users _can_ select from preferences page,
151 * thus excluding those as configured by $wgSkipSkins.
156 public function getAllowedSkins() {
157 $skins = $this->getInstalledSkins();
159 foreach ( $this->skipSkins
as $name => $_ ) {
160 unset( $skins[$name] );
167 * Get the list of installed skins.
169 * Returns an associative array of skin name => human readable name
174 public function getInstalledSkins() {
175 return $this->displayNames
;
179 * Return options provided for a given skin name
181 * For documentation about keys you can expect to exist,
182 * and their default values, refer to the Skin constructor.
185 * @param string $name Name of the skin you want options from
188 public function getSkinOptions( string $name ): array {
189 $skin = $this->makeSkin( $name );
190 $options = $skin->getOptions();