Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.57% |
31 / 35 |
|
85.71% |
6 / 7 |
CRAP | |
0.00% |
0 / 1 |
SkinFactory | |
91.18% |
31 / 34 |
|
85.71% |
6 / 7 |
14.13 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
register | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
6 | |||
getSkinNames | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
makeSkin | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
2 | |||
getAllowedSkins | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getInstalledSkins | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getSkinOptions | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Copyright 2014 |
5 | * |
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. |
10 | * |
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. |
15 | * |
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 |
20 | * |
21 | * @file |
22 | */ |
23 | |
24 | namespace MediaWiki\Skin; |
25 | |
26 | use InvalidArgumentException; |
27 | use Wikimedia\ObjectFactory\ObjectFactory; |
28 | |
29 | /** |
30 | * Factory class to create Skin objects |
31 | * |
32 | * @since 1.24 |
33 | */ |
34 | class SkinFactory { |
35 | private const SKIP_BY_SITECONFIG = 1; |
36 | private const SKIP_BY_REGISTER = 2; |
37 | |
38 | /** |
39 | * Map of skin name to object factory spec or factory function. |
40 | * |
41 | * @var array<string,array|callable> |
42 | */ |
43 | private $factoryFunctions = []; |
44 | /** |
45 | * Map of name => fallback human-readable name, used when the 'skinname-<skin>' message is not |
46 | * available |
47 | * |
48 | * @var array |
49 | */ |
50 | private $displayNames = []; |
51 | /** |
52 | * @var ObjectFactory |
53 | */ |
54 | private $objectFactory; |
55 | |
56 | /** |
57 | * Array of skins that should not be presented in the list of |
58 | * available skins in user preferences, while they're still installed. |
59 | * |
60 | * @var array<string,int> |
61 | */ |
62 | private $skipSkins; |
63 | |
64 | /** |
65 | * @internal For ServiceWiring only |
66 | * |
67 | * @param ObjectFactory $objectFactory |
68 | * @param string[] $skipSkins |
69 | */ |
70 | public function __construct( ObjectFactory $objectFactory, array $skipSkins ) { |
71 | $this->objectFactory = $objectFactory; |
72 | $this->skipSkins = array_fill_keys( $skipSkins, self::SKIP_BY_SITECONFIG ); |
73 | } |
74 | |
75 | /** |
76 | * Register a new skin. |
77 | * |
78 | * This will replace any previously registered skin by the same name. |
79 | * |
80 | * @param string $name Internal skin name. See also Skin::__construct. |
81 | * @param string $displayName For backwards-compatibility with old skin loading system. This is |
82 | * the text used as skin's human-readable name when the 'skinname-<skin>' message is not |
83 | * available. |
84 | * @param array|callable $spec ObjectFactory spec to construct a Skin object, |
85 | * or callback that takes a skin name and returns a Skin object. |
86 | * See Skin::__construct for the constructor arguments. |
87 | * @param true|null $skippable Whether the skin is skippable and should be hidden |
88 | * from user preferences. By default, this is determined based by $wgSkipSkins. |
89 | */ |
90 | public function register( $name, $displayName, $spec, ?bool $skippable = null ) { |
91 | if ( !is_callable( $spec ) ) { |
92 | if ( is_array( $spec ) ) { |
93 | if ( !isset( $spec['args'] ) ) { |
94 | // make sure name option is set: |
95 | $spec['args'] = [ |
96 | [ 'name' => $name ] |
97 | ]; |
98 | } |
99 | } else { |
100 | throw new InvalidArgumentException( 'Invalid callback provided' ); |
101 | } |
102 | } |
103 | $this->factoryFunctions[$name] = $spec; |
104 | $this->displayNames[$name] = $displayName; |
105 | |
106 | // If skipped by site config, leave as-is. |
107 | if ( ( $this->skipSkins[$name] ?? null ) !== self::SKIP_BY_SITECONFIG ) { |
108 | if ( $skippable === true ) { |
109 | $this->skipSkins[$name] = self::SKIP_BY_REGISTER; |
110 | } else { |
111 | // Make sure the register() call is unaffected by previous calls. |
112 | unset( $this->skipSkins[$name] ); |
113 | } |
114 | } |
115 | } |
116 | |
117 | /** |
118 | * Return an associative array of `skin name => human readable name`. |
119 | * |
120 | * @deprecated since 1.37 Use getInstalledSkins instead |
121 | * @return array |
122 | */ |
123 | public function getSkinNames() { |
124 | wfDeprecated( __METHOD__, '1.37' ); |
125 | return $this->displayNames; |
126 | } |
127 | |
128 | /** |
129 | * Create a given Skin using the registered callback for $name. |
130 | * |
131 | * @param string $name Name of the skin you want |
132 | * @throws SkinException If a factory function isn't registered for $name |
133 | * @return Skin |
134 | */ |
135 | public function makeSkin( $name ) { |
136 | if ( !isset( $this->factoryFunctions[$name] ) ) { |
137 | throw new SkinException( "No registered builder available for $name." ); |
138 | } |
139 | |
140 | return $this->objectFactory->createObject( |
141 | $this->factoryFunctions[$name], |
142 | [ |
143 | 'allowCallable' => true, |
144 | 'assertClass' => Skin::class, |
145 | ] |
146 | ); |
147 | } |
148 | |
149 | /** |
150 | * Get the list of user-selectable skins. |
151 | * |
152 | * Useful for Special:Preferences and other places where you |
153 | * only want to show skins users _can_ select from preferences page, |
154 | * thus excluding those as configured by $wgSkipSkins. |
155 | * |
156 | * @return string[] |
157 | * @since 1.36 |
158 | */ |
159 | public function getAllowedSkins() { |
160 | $skins = $this->getInstalledSkins(); |
161 | |
162 | foreach ( $this->skipSkins as $name => $_ ) { |
163 | unset( $skins[$name] ); |
164 | } |
165 | |
166 | return $skins; |
167 | } |
168 | |
169 | /** |
170 | * Get the list of installed skins. |
171 | * |
172 | * Returns an associative array of skin name => human readable name |
173 | * |
174 | * @return string[] |
175 | * @since 1.37 |
176 | */ |
177 | public function getInstalledSkins() { |
178 | return $this->displayNames; |
179 | } |
180 | |
181 | /** |
182 | * Return options provided for a given skin name |
183 | * |
184 | * For documentation about keys you can expect to exist, |
185 | * and their default values, refer to the Skin constructor. |
186 | * |
187 | * @since 1.38 |
188 | * @param string $name Name of the skin you want options from |
189 | * @return array |
190 | */ |
191 | public function getSkinOptions( string $name ): array { |
192 | $skin = $this->makeSkin( $name ); |
193 | $options = $skin->getOptions(); |
194 | return $options; |
195 | } |
196 | } |
197 | |
198 | /** @deprecated class alias since 1.44 */ |
199 | class_alias( SkinFactory::class, 'SkinFactory' ); |