Merge "Remove unused 'XMPGetInfo' and 'XMPGetResults' hooks"
[lhc/web/wiklou.git] / includes / registration / ExtensionProcessor.php
1 <?php
2
3 class ExtensionProcessor implements Processor {
4
5 /**
6 * Keys that should be set to $GLOBALS
7 *
8 * @var array
9 */
10 protected static $globalSettings = array(
11 'ResourceLoaderSources',
12 'ResourceLoaderLESSVars',
13 'ResourceLoaderLESSImportPaths',
14 'DefaultUserOptions',
15 'HiddenPrefs',
16 'GroupPermissions',
17 'RevokePermissions',
18 'ImplicitGroups',
19 'GroupsAddToSelf',
20 'GroupsRemoveFromSelf',
21 'AddGroups',
22 'RemoveGroups',
23 'AvailableRights',
24 'ContentHandlers',
25 'ConfigRegistry',
26 'RateLimits',
27 'RecentChangesFlags',
28 'MediaHandlers',
29 'ExtensionFunctions',
30 'ExtensionEntryPointListFiles',
31 'SpecialPages',
32 'JobClasses',
33 'LogTypes',
34 'LogRestrictions',
35 'FilterLogTypes',
36 'LogNames',
37 'LogHeaders',
38 'LogActions',
39 'LogActionsHandlers',
40 'Actions',
41 'APIModules',
42 'APIFormatModules',
43 'APIMetaModules',
44 'APIPropModules',
45 'APIListModules',
46 'ValidSkinNames',
47 );
48
49 /**
50 * Keys that are part of the extension credits
51 *
52 * @var array
53 */
54 protected static $creditsAttributes = array(
55 'name',
56 'namemsg',
57 'author',
58 'version',
59 'url',
60 'description',
61 'descriptionmsg',
62 'license-name',
63 );
64
65 /**
66 * Things that are not 'attributes', but are not in
67 * $globalSettings or $creditsAttributes.
68 *
69 * @var array
70 */
71 protected static $notAttributes = array(
72 'callback',
73 'Hooks',
74 'namespaces',
75 'ResourceFileModulePaths',
76 'ResourceModules',
77 'ResourceModuleSkinStyles',
78 'ExtensionMessagesFiles',
79 'MessagesDirs',
80 'type',
81 'config',
82 'ParserTestFiles',
83 'AutoloadClasses',
84 );
85
86 /**
87 * Stuff that is going to be set to $GLOBALS
88 *
89 * Some keys are pre-set to arrays so we can += to them
90 *
91 * @var array
92 */
93 protected $globals = array(
94 'wgExtensionMessagesFiles' => array(),
95 'wgMessagesDirs' => array(),
96 );
97
98 /**
99 * Things that should be define()'d
100 *
101 * @var array
102 */
103 protected $defines = array();
104
105 /**
106 * Things to be called once registration of these extensions are done
107 *
108 * @var callable[]
109 */
110 protected $callbacks = array();
111
112 /**
113 * @var array
114 */
115 protected $credits = array();
116
117 /**
118 * Any thing else in the $info that hasn't
119 * already been processed
120 *
121 * @var array
122 */
123 protected $attributes = array();
124
125 /**
126 * @param string $path
127 * @param array $info
128 * @return array
129 */
130 public function extractInfo( $path, array $info ) {
131 $this->extractConfig( $info );
132 $this->extractHooks( $info );
133 $dir = dirname( $path );
134 $this->extractExtensionMessagesFiles( $dir, $info );
135 $this->extractMessagesDirs( $dir, $info );
136 $this->extractNamespaces( $info );
137 $this->extractResourceLoaderModules( $dir, $info );
138 $this->extractParserTestFiles( $dir, $info );
139 if ( isset( $info['callback'] ) ) {
140 $this->callbacks[] = $info['callback'];
141 }
142
143 $this->extractCredits( $path, $info );
144 foreach ( $info as $key => $val ) {
145 if ( in_array( $key, self::$globalSettings ) ) {
146 $this->storeToArray( "wg$key", $val, $this->globals );
147 // Ignore anything that starts with a @
148 } elseif ( $key[0] !== '@' && !in_array( $key, self::$notAttributes )
149 && !in_array( $key, self::$creditsAttributes )
150 ) {
151 $this->storeToArray( $key, $val, $this->attributes );
152 }
153 }
154 }
155
156 public function getExtractedInfo() {
157 return array(
158 'globals' => $this->globals,
159 'defines' => $this->defines,
160 'callbacks' => $this->callbacks,
161 'credits' => $this->credits,
162 'attributes' => $this->attributes,
163 );
164 }
165
166 protected function extractHooks( array $info ) {
167 if ( isset( $info['Hooks'] ) ) {
168 foreach ( $info['Hooks'] as $name => $value ) {
169 foreach ( (array)$value as $callback ) {
170 $this->globals['wgHooks'][$name][] = $callback;
171 }
172 }
173 }
174 }
175
176 /**
177 * Register namespaces with the appropriate global settings
178 *
179 * @param array $info
180 */
181 protected function extractNamespaces( array $info ) {
182 if ( isset( $info['namespaces'] ) ) {
183 foreach ( $info['namespaces'] as $ns ) {
184 $id = $ns['id'];
185 $this->defines[$ns['constant']] = $id;
186 $this->globals['wgExtraNamespaces'][$id] = $ns['name'];
187 if ( isset( $ns['gender'] ) ) {
188 $this->globals['wgExtraGenderNamespaces'][$id] = $ns['gender'];
189 }
190 if ( isset( $ns['subpages'] ) && $ns['subpages'] ) {
191 $this->globals['wgNamespacesWithSubpages'][$id] = true;
192 }
193 if ( isset( $ns['content'] ) && $ns['content'] ) {
194 $this->globals['wgContentNamespaces'][] = $id;
195 }
196 if ( isset( $ns['defaultcontentmodel'] ) ) {
197 $this->globals['wgNamespaceContentModels'][$id] = $ns['defaultcontentmodel'];
198 }
199 }
200 }
201 }
202
203 protected function extractResourceLoaderModules( $dir, array $info ) {
204 $defaultPaths = isset( $info['ResourceFileModulePaths'] )
205 ? $info['ResourceFileModulePaths']
206 : false;
207 if ( isset( $defaultPaths['localBasePath'] ) ) {
208 $defaultPaths['localBasePath'] = "$dir/{$defaultPaths['localBasePath']}";
209 }
210
211 foreach ( array( 'ResourceModules', 'ResourceModuleSkinStyles' ) as $setting ) {
212 if ( isset( $info[$setting] ) ) {
213 foreach ( $info[$setting] as $name => $data ) {
214 if ( isset( $data['localBasePath'] ) ) {
215 $data['localBasePath'] = "$dir/{$data['localBasePath']}";
216 }
217 if ( $defaultPaths ) {
218 $data += $defaultPaths;
219 }
220 $this->globals["wg$setting"][$name] = $data;
221 }
222 }
223 }
224 }
225
226 protected function extractExtensionMessagesFiles( $dir, array $info ) {
227 if ( isset( $info['ExtensionMessagesFiles'] ) ) {
228 $this->globals["wgExtensionMessagesFiles"] += array_map( function( $file ) use ( $dir ) {
229 return "$dir/$file";
230 }, $info['ExtensionMessagesFiles'] );
231 }
232 }
233
234 /**
235 * Set message-related settings, which need to be expanded to use
236 * absolute paths
237 *
238 * @param string $dir
239 * @param array $info
240 */
241 protected function extractMessagesDirs( $dir, array $info ) {
242 if ( isset( $info['MessagesDirs'] ) ) {
243 foreach ( $info['MessagesDirs'] as $name => $files ) {
244 foreach ( (array)$files as $file ) {
245 $this->globals["wgMessagesDirs"][$name][] = "$dir/$file";
246 }
247 }
248 }
249 }
250
251 protected function extractCredits( $path, array $info ) {
252 $credits = array(
253 'path' => $path,
254 'type' => isset( $info['type'] ) ? $info['type'] : 'other',
255 );
256 foreach ( self::$creditsAttributes as $attr ) {
257 if ( isset( $info[$attr] ) ) {
258 $credits[$attr] = $info[$attr];
259 }
260 }
261
262 $this->credits[$credits['name']] = $credits;
263 }
264
265 /**
266 * Set configuration settings
267 * @todo In the future, this should be done via Config interfaces
268 *
269 * @param array $info
270 */
271 protected function extractConfig( array $info ) {
272 if ( isset( $info['config'] ) ) {
273 foreach ( $info['config'] as $key => $val ) {
274 if ( $key[0] !== '@' ) {
275 $this->globals["wg$key"] = $val;
276 }
277 }
278 }
279 }
280
281 protected function extractParserTestFiles( $dir, array $info ) {
282 if ( isset( $info['ParserTestFiles'] ) ) {
283 foreach ( $info['ParserTestFiles'] as $path ) {
284 $this->globals['wgParserTestFiles'][] = "$dir/$path";
285 }
286 }
287 }
288
289 /**
290 * @param string $name
291 * @param mixed $value
292 * @param array &$array
293 */
294 protected function storeToArray( $name, $value, &$array ) {
295 if ( isset( $array[$name] ) ) {
296 $array[$name] = array_merge_recursive( $array[$name], $value );
297 } else {
298 $array[$name] = $value;
299 }
300 }
301 }