Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.57% |
31 / 35 |
|
60.00% |
3 / 5 |
CRAP | |
0.00% |
0 / 1 |
ConfigFactory | |
91.18% |
31 / 34 |
|
60.00% |
3 / 5 |
18.22 | |
0.00% |
0 / 1 |
getDefaultInstance | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
salvage | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
5 | |||
getConfigNames | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
register | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
5.05 | |||
makeConfig | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
6 |
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\Config; |
25 | |
26 | use InvalidArgumentException; |
27 | use MediaWiki\MediaWikiServices; |
28 | use UnexpectedValueException; |
29 | use Wikimedia\Assert\Assert; |
30 | use Wikimedia\Services\SalvageableService; |
31 | |
32 | /** |
33 | * Factory class to create Config objects |
34 | * |
35 | * @since 1.23 |
36 | */ |
37 | class ConfigFactory implements SalvageableService { |
38 | |
39 | /** |
40 | * Map of config name => callback |
41 | * @var array |
42 | */ |
43 | protected $factoryFunctions = []; |
44 | |
45 | /** |
46 | * Config objects that have already been created |
47 | * name => Config object |
48 | * @var array |
49 | */ |
50 | protected $configs = []; |
51 | |
52 | /** |
53 | * @deprecated since 1.27, use MediaWikiServices::getInstance()->getConfigFactory() instead. |
54 | * Emitting deprecation warnings since 1.41. |
55 | * |
56 | * @return ConfigFactory |
57 | */ |
58 | public static function getDefaultInstance() { |
59 | wfDeprecated( __METHOD__, '1.27' ); |
60 | return MediaWikiServices::getInstance()->getConfigFactory(); |
61 | } |
62 | |
63 | /** |
64 | * Re-uses existing Cache objects from $other. Cache objects are only re-used if the |
65 | * registered factory function for both is the same. Cache config is not copied, |
66 | * and only instances of caches defined on this instance with the same config |
67 | * are copied. |
68 | * |
69 | * @see SalvageableService::salvage() |
70 | * |
71 | * @param SalvageableService $other The object to salvage state from. $other must have the |
72 | * exact same type as $this. |
73 | */ |
74 | public function salvage( SalvageableService $other ) { |
75 | Assert::parameterType( self::class, $other, '$other' ); |
76 | |
77 | /** @var self $other */ |
78 | '@phan-var self $other'; |
79 | foreach ( $other->factoryFunctions as $name => $otherFunc ) { |
80 | if ( !isset( $this->factoryFunctions[$name] ) ) { |
81 | continue; |
82 | } |
83 | |
84 | // if the callback function is the same, salvage the Cache object |
85 | // XXX: Closures are never equal! |
86 | if ( isset( $other->configs[$name] ) |
87 | && $this->factoryFunctions[$name] == $otherFunc |
88 | ) { |
89 | $this->configs[$name] = $other->configs[$name]; |
90 | unset( $other->configs[$name] ); |
91 | } |
92 | } |
93 | |
94 | // disable $other |
95 | $other->factoryFunctions = []; |
96 | $other->configs = []; |
97 | } |
98 | |
99 | /** |
100 | * @return string[] |
101 | */ |
102 | public function getConfigNames() { |
103 | return array_keys( $this->factoryFunctions ); |
104 | } |
105 | |
106 | /** |
107 | * Register a new config factory function. |
108 | * Will override if it's already registered. |
109 | * Use "*" for $name to provide a fallback config for all unknown names. |
110 | * @param string $name |
111 | * @param callable|Config $callback A factory callback that takes this ConfigFactory |
112 | * as an argument and returns a Config instance, or an existing Config instance. |
113 | * @throws InvalidArgumentException If an invalid callback is provided |
114 | */ |
115 | public function register( $name, $callback ) { |
116 | if ( !is_callable( $callback ) && !( $callback instanceof Config ) ) { |
117 | if ( is_array( $callback ) ) { |
118 | $callback = '[ ' . implode( ', ', $callback ) . ' ]'; |
119 | } elseif ( is_object( $callback ) ) { |
120 | $callback = 'instanceof ' . get_class( $callback ); |
121 | } |
122 | throw new InvalidArgumentException( 'Invalid callback \'' . $callback . '\' provided' ); |
123 | } |
124 | |
125 | unset( $this->configs[$name] ); |
126 | $this->factoryFunctions[$name] = $callback; |
127 | } |
128 | |
129 | /** |
130 | * Create a given Config using the registered callback for $name. |
131 | * If an object was already created, the same Config object is returned. |
132 | * @param string $name Name of the extension/component you want a Config object for |
133 | * 'main' is used for core |
134 | * @throws ConfigException If a factory function isn't registered for $name |
135 | * @throws UnexpectedValueException If the factory function returns a non-Config object |
136 | * @return Config |
137 | */ |
138 | public function makeConfig( $name ) { |
139 | if ( !isset( $this->configs[$name] ) ) { |
140 | $key = $name; |
141 | if ( !isset( $this->factoryFunctions[$key] ) ) { |
142 | $key = '*'; |
143 | } |
144 | if ( !isset( $this->factoryFunctions[$key] ) ) { |
145 | throw new ConfigException( "No registered builder available for $name." ); |
146 | } |
147 | |
148 | if ( $this->factoryFunctions[$key] instanceof Config ) { |
149 | $conf = $this->factoryFunctions[$key]; |
150 | } else { |
151 | $conf = call_user_func( $this->factoryFunctions[$key], $this ); |
152 | } |
153 | |
154 | if ( $conf instanceof Config ) { |
155 | $this->configs[$name] = $conf; |
156 | } else { |
157 | throw new UnexpectedValueException( "The builder for $name returned a non-Config object." ); |
158 | } |
159 | } |
160 | |
161 | return $this->configs[$name]; |
162 | } |
163 | |
164 | } |
165 | |
166 | /** @deprecated class alias since 1.41 */ |
167 | class_alias( ConfigFactory::class, 'ConfigFactory' ); |