MediaWiki  master
ExtensionProcessor.php
Go to the documentation of this file.
1 <?php
2 
3 class ExtensionProcessor implements Processor {
4 
10  protected static $globalSettings = [
11  'ActionFilteredLogs',
12  'Actions',
13  'AddGroups',
14  'APIFormatModules',
15  'APIListModules',
16  'APIMetaModules',
17  'APIModules',
18  'APIPropModules',
19  'AuthManagerAutoConfig',
20  'AvailableRights',
21  'CentralIdLookupProviders',
22  'ChangeCredentialsBlacklist',
23  'ConfigRegistry',
24  'ContentHandlers',
25  'DefaultUserOptions',
26  'ExtensionEntryPointListFiles',
27  'ExtensionFunctions',
28  'FeedClasses',
29  'FileExtensions',
30  'FilterLogTypes',
31  'GrantPermissionGroups',
32  'GrantPermissions',
33  'GroupPermissions',
34  'GroupsAddToSelf',
35  'GroupsRemoveFromSelf',
36  'HiddenPrefs',
37  'ImplicitGroups',
38  'JobClasses',
39  'LogActions',
40  'LogActionsHandlers',
41  'LogHeaders',
42  'LogNames',
43  'LogRestrictions',
44  'LogTypes',
45  'MediaHandlers',
46  'PasswordPolicy',
47  'RateLimits',
48  'RawHtmlMessages',
49  'ReauthenticateTime',
50  'RecentChangesFlags',
51  'RemoveCredentialsBlacklist',
52  'RemoveGroups',
53  'ResourceLoaderSources',
54  'RevokePermissions',
55  'SessionProviders',
56  'SpecialPages'
57  ];
58 
64  protected const CORE_ATTRIBS = [
65  'ParsoidModules',
66  'RestRoutes',
67  'SkinOOUIThemes',
68  'SearchMappings',
69  'TrackingCategories',
70  ];
71 
79  protected const MERGE_STRATEGIES = [
80  'wgAuthManagerAutoConfig' => 'array_plus_2d',
81  'wgCapitalLinkOverrides' => 'array_plus',
82  'wgExtraGenderNamespaces' => 'array_plus',
83  'wgGrantPermissions' => 'array_plus_2d',
84  'wgGroupPermissions' => 'array_plus_2d',
85  'wgHooks' => 'array_merge_recursive',
86  'wgNamespaceContentModels' => 'array_plus',
87  'wgNamespaceProtection' => 'array_plus',
88  'wgNamespacesWithSubpages' => 'array_plus',
89  'wgPasswordPolicy' => 'array_merge_recursive',
90  'wgRateLimits' => 'array_plus_2d',
91  'wgRevokePermissions' => 'array_plus_2d',
92  ];
93 
99  protected const CREDIT_ATTRIBS = [
100  'type',
101  'author',
102  'description',
103  'descriptionmsg',
104  'license-name',
105  'name',
106  'namemsg',
107  'url',
108  'version',
109  ];
110 
117  protected const NOT_ATTRIBS = [
118  'callback',
119  'config',
120  'config_prefix',
121  'load_composer_autoloader',
122  'manifest_version',
123  'namespaces',
124  'requires',
125  'AutoloadClasses',
126  'ExtensionMessagesFiles',
127  'Hooks',
128  'MessagePosterModule',
129  'MessagesDirs',
130  'OOUIThemePaths',
131  'ParserTestFiles',
132  'QUnitTestModule',
133  'ResourceFileModulePaths',
134  'ResourceModuleSkinStyles',
135  'ResourceModules',
136  'ServiceWiringFiles',
137  ];
138 
146  protected $globals = [
147  'wgExtensionMessagesFiles' => [],
148  'wgMessagesDirs' => [],
149  ];
150 
156  protected $defines = [];
157 
164  protected $callbacks = [];
165 
169  protected $credits = [];
170 
177  protected $attributes = [];
178 
185  protected $extAttributes = [];
186 
192  public function extractInfo( $path, array $info, $version ) {
193  $dir = dirname( $path );
194  $this->extractHooks( $info, $path );
195  $this->extractExtensionMessagesFiles( $dir, $info );
196  $this->extractMessagesDirs( $dir, $info );
197  $this->extractSkins( $dir, $info );
198  $this->extractSkinImportPaths( $dir, $info );
199  $this->extractNamespaces( $info );
200  $this->extractResourceLoaderModules( $dir, $info );
201  if ( isset( $info['ServiceWiringFiles'] ) ) {
202  $this->extractPathBasedGlobal(
203  'wgServiceWiringFiles',
204  $dir,
205  $info['ServiceWiringFiles']
206  );
207  }
208  if ( isset( $info['ParserTestFiles'] ) ) {
209  $this->extractPathBasedGlobal(
210  'wgParserTestFiles',
211  $dir,
212  $info['ParserTestFiles']
213  );
214  }
215  $name = $this->extractCredits( $path, $info );
216  if ( isset( $info['callback'] ) ) {
217  $this->callbacks[$name] = $info['callback'];
218  }
219 
220  // config should be after all core globals are extracted,
221  // so duplicate setting detection will work fully
222  if ( $version >= 2 ) {
223  $this->extractConfig2( $info, $dir );
224  } else {
225  // $version === 1
226  $this->extractConfig1( $info );
227  }
228 
229  // Record the extension name in the ParsoidModules property
230  if ( isset( $info['ParsoidModules'] ) ) {
231  foreach ( $info['ParsoidModules'] as &$module ) {
232  $module['name'] = $name;
233  }
234  }
235 
236  if ( $version >= 2 ) {
237  $this->extractAttributes( $path, $info );
238  }
239 
240  foreach ( $info as $key => $val ) {
241  // If it's a global setting,
242  if ( in_array( $key, self::$globalSettings ) ) {
243  $this->storeToArrayRecursive( $path, "wg$key", $val, $this->globals );
244  continue;
245  }
246  // Ignore anything that starts with a @
247  if ( $key[0] === '@' ) {
248  continue;
249  }
250 
251  if ( $version >= 2 ) {
252  // Only allowed attributes are set
253  if ( in_array( $key, self::CORE_ATTRIBS ) ) {
254  $this->storeToArray( $path, $key, $val, $this->attributes );
255  }
256  } else {
257  // version === 1
258  if ( !in_array( $key, self::NOT_ATTRIBS )
259  && !in_array( $key, self::CREDIT_ATTRIBS )
260  ) {
261  // If it's not disallowed, it's an attribute
262  $this->storeToArrayRecursive( $path, $key, $val, $this->attributes );
263  }
264  }
265  }
266  }
267 
272  protected function extractAttributes( $path, array $info ) {
273  if ( isset( $info['attributes'] ) ) {
274  foreach ( $info['attributes'] as $extName => $value ) {
275  $this->storeToArrayRecursive( $path, $extName, $value, $this->extAttributes );
276  }
277  }
278  }
279 
280  public function getExtractedInfo() {
281  // Make sure the merge strategies are set
282  foreach ( $this->globals as $key => $val ) {
283  if ( isset( self::MERGE_STRATEGIES[$key] ) ) {
284  $this->globals[$key][ExtensionRegistry::MERGE_STRATEGY] = self::MERGE_STRATEGIES[$key];
285  }
286  }
287 
288  // Merge $this->extAttributes into $this->attributes depending on what is loaded
289  foreach ( $this->extAttributes as $extName => $value ) {
290  // Only set the attribute if $extName is loaded (and hence present in credits)
291  if ( isset( $this->credits[$extName] ) ) {
292  foreach ( $value as $attrName => $attrValue ) {
293  $this->storeToArrayRecursive(
294  '', // Don't provide a path since it's impossible to generate an error here
295  $extName . $attrName,
296  $attrValue,
297  $this->attributes
298  );
299  }
300  unset( $this->extAttributes[$extName] );
301  }
302  }
303 
304  return [
305  'globals' => $this->globals,
306  'defines' => $this->defines,
307  'callbacks' => $this->callbacks,
308  'credits' => $this->credits,
309  'attributes' => $this->attributes,
310  ];
311  }
312 
313  public function getRequirements( array $info, $includeDev ) {
314  // Quick shortcuts
315  if ( !$includeDev || !isset( $info['dev-requires'] ) ) {
316  return $info['requires'] ?? [];
317  }
318 
319  if ( !isset( $info['requires'] ) ) {
320  return $info['dev-requires'] ?? [];
321  }
322 
323  // OK, we actually have to merge everything
324  $merged = [];
325 
326  // Helper that combines version requirements by
327  // picking the non-null if one is, or combines
328  // the two. Note that it is not possible for
329  // both inputs to be null.
330  $pick = static function ( $a, $b ) {
331  if ( $a === null ) {
332  return $b;
333  } elseif ( $b === null ) {
334  return $a;
335  } else {
336  return "$a $b";
337  }
338  };
339 
340  $req = $info['requires'];
341  $dev = $info['dev-requires'];
342  if ( isset( $req['MediaWiki'] ) || isset( $dev['MediaWiki'] ) ) {
343  $merged['MediaWiki'] = $pick(
344  $req['MediaWiki'] ?? null,
345  $dev['MediaWiki'] ?? null
346  );
347  }
348 
349  $platform = array_merge(
350  array_keys( $req['platform'] ?? [] ),
351  array_keys( $dev['platform'] ?? [] )
352  );
353  if ( $platform ) {
354  foreach ( $platform as $pkey ) {
355  if ( $pkey === 'php' ) {
356  $value = $pick(
357  $req['platform']['php'] ?? null,
358  $dev['platform']['php'] ?? null
359  );
360  } else {
361  // Prefer dev value, but these should be constant
362  // anyways (ext-* and ability-*)
363  $value = $dev['platform'][$pkey] ?? $req['platform'][$pkey];
364  }
365  $merged['platform'][$pkey] = $value;
366  }
367  }
368 
369  foreach ( [ 'extensions', 'skins' ] as $thing ) {
370  $things = array_merge(
371  array_keys( $req[$thing] ?? [] ),
372  array_keys( $dev[$thing] ?? [] )
373  );
374  foreach ( $things as $name ) {
375  $merged[$thing][$name] = $pick(
376  $req[$thing][$name] ?? null,
377  $dev[$thing][$name] ?? null
378  );
379  }
380  }
381  return $merged;
382  }
383 
395  private function setArrayHookHandler(
396  array $callback,
397  array $hookHandlersAttr,
398  string $name,
399  string $path
400  ) {
401  if ( isset( $callback['handler'] ) ) {
402  $handlerName = $callback['handler'];
403  $handlerDefinition = $hookHandlersAttr[$handlerName] ?? false;
404  if ( !$handlerDefinition ) {
405  throw new UnexpectedValueException(
406  "Missing handler definition for $name in HookHandlers attribute in $path"
407  );
408  }
409  $callback['handler'] = $handlerDefinition;
410  $callback['extensionPath'] = $path;
411  $this->attributes['Hooks'][$name][] = $callback;
412  } else {
413  foreach ( $callback as $callable ) {
414  if ( is_array( $callable ) ) {
415  if ( isset( $callable['handler'] ) ) { // Non-legacy style handler
416  $this->setArrayHookHandler( $callable, $hookHandlersAttr, $name, $path );
417  } else { // Legacy style handler array
418  $this->globals['wgHooks'][$name][] = $callable;
419  }
420  } elseif ( is_string( $callable ) ) {
421  $this->setStringHookHandler( $callable, $hookHandlersAttr, $name, $path );
422  }
423  }
424  }
425  }
426 
437  private function setStringHookHandler(
438  string $callback,
439  array $hookHandlersAttr,
440  string $name,
441  string $path
442  ) {
443  if ( isset( $hookHandlersAttr[$callback] ) ) {
444  $handler = [
445  'handler' => $hookHandlersAttr[$callback],
446  'extensionPath' => $path
447  ];
448  $this->attributes['Hooks'][$name][] = $handler;
449  } else { // legacy style handler
450  $this->globals['wgHooks'][$name][] = $callback;
451  }
452  }
453 
462  protected function extractHooks( array $info, string $path ) {
463  $extName = $info['name'];
464  if ( isset( $info['Hooks'] ) ) {
465  $hookHandlersAttr = [];
466  foreach ( $info['HookHandlers'] ?? [] as $name => $def ) {
467  $hookHandlersAttr[$name] = [ 'name' => "$extName-$name" ] + $def;
468  }
469  foreach ( $info['Hooks'] as $name => $callback ) {
470  if ( is_string( $callback ) ) {
471  $this->setStringHookHandler( $callback, $hookHandlersAttr, $name, $path );
472  } elseif ( is_array( $callback ) ) {
473  $this->setArrayHookHandler( $callback, $hookHandlersAttr, $name, $path );
474  }
475  }
476  }
477  if ( isset( $info['DeprecatedHooks'] ) ) {
478  $deprecatedHooks = [];
479  foreach ( $info['DeprecatedHooks'] as $name => $deprecatedHookInfo ) {
480  $deprecatedHookInfo += [ 'component' => $extName ];
481  $deprecatedHooks[$name] = $deprecatedHookInfo;
482  }
483  if ( isset( $this->attributes['DeprecatedHooks'] ) ) {
484  $this->attributes['DeprecatedHooks'] += $deprecatedHooks;
485  } else {
486  $this->attributes['DeprecatedHooks'] = $deprecatedHooks;
487  }
488  }
489  }
490 
496  protected function extractNamespaces( array $info ) {
497  if ( isset( $info['namespaces'] ) ) {
498  foreach ( $info['namespaces'] as $ns ) {
499  if ( defined( $ns['constant'] ) ) {
500  // If the namespace constant is already defined, use it.
501  // This allows namespace IDs to be overwritten locally.
502  $id = constant( $ns['constant'] );
503  } else {
504  $id = $ns['id'];
505  }
506  $this->defines[ $ns['constant'] ] = $id;
507 
508  if ( !( isset( $ns['conditional'] ) && $ns['conditional'] ) ) {
509  // If it is not conditional, register it
510  $this->attributes['ExtensionNamespaces'][$id] = $ns['name'];
511  }
512  if ( isset( $ns['movable'] ) && !$ns['movable'] ) {
513  $this->attributes['ImmovableNamespaces'][] = $id;
514  }
515  if ( isset( $ns['gender'] ) ) {
516  $this->globals['wgExtraGenderNamespaces'][$id] = $ns['gender'];
517  }
518  if ( isset( $ns['subpages'] ) && $ns['subpages'] ) {
519  $this->globals['wgNamespacesWithSubpages'][$id] = true;
520  }
521  if ( isset( $ns['content'] ) && $ns['content'] ) {
522  $this->globals['wgContentNamespaces'][] = $id;
523  }
524  if ( isset( $ns['defaultcontentmodel'] ) ) {
525  $this->globals['wgNamespaceContentModels'][$id] = $ns['defaultcontentmodel'];
526  }
527  if ( isset( $ns['protection'] ) ) {
528  $this->globals['wgNamespaceProtection'][$id] = $ns['protection'];
529  }
530  if ( isset( $ns['capitallinkoverride'] ) ) {
531  $this->globals['wgCapitalLinkOverrides'][$id] = $ns['capitallinkoverride'];
532  }
533  if ( isset( $ns['includable'] ) && !$ns['includable'] ) {
534  $this->globals['wgNonincludableNamespaces'][] = $id;
535  }
536  }
537  }
538  }
539 
540  protected function extractResourceLoaderModules( $dir, array $info ) {
541  $defaultPaths = $info['ResourceFileModulePaths'] ?? false;
542  if ( isset( $defaultPaths['localBasePath'] ) ) {
543  if ( $defaultPaths['localBasePath'] === '' ) {
544  // Avoid double slashes (e.g. /extensions/Example//path)
545  $defaultPaths['localBasePath'] = $dir;
546  } else {
547  $defaultPaths['localBasePath'] = "$dir/{$defaultPaths['localBasePath']}";
548  }
549  }
550 
551  foreach ( [ 'ResourceModules', 'ResourceModuleSkinStyles', 'OOUIThemePaths' ] as $setting ) {
552  if ( isset( $info[$setting] ) ) {
553  foreach ( $info[$setting] as $name => $data ) {
554  if ( isset( $data['localBasePath'] ) ) {
555  if ( $data['localBasePath'] === '' ) {
556  // Avoid double slashes (e.g. /extensions/Example//path)
557  $data['localBasePath'] = $dir;
558  } else {
559  $data['localBasePath'] = "$dir/{$data['localBasePath']}";
560  }
561  }
562  if ( $defaultPaths ) {
563  $data += $defaultPaths;
564  }
565  $this->attributes[$setting][$name] = $data;
566  }
567  }
568  }
569 
570  if ( isset( $info['QUnitTestModule'] ) ) {
571  $data = $info['QUnitTestModule'];
572  if ( isset( $data['localBasePath'] ) ) {
573  if ( $data['localBasePath'] === '' ) {
574  // Avoid double slashes (e.g. /extensions/Example//path)
575  $data['localBasePath'] = $dir;
576  } else {
577  $data['localBasePath'] = "$dir/{$data['localBasePath']}";
578  }
579  }
580  $this->attributes['QUnitTestModules']["test.{$info['name']}"] = $data;
581  }
582 
583  if ( isset( $info['MessagePosterModule'] ) ) {
584  $data = $info['MessagePosterModule'];
585  $basePath = $data['localBasePath'] ?? '';
586  $baseDir = $basePath === '' ? $dir : "$dir/$basePath";
587  foreach ( $data['scripts'] ?? [] as $scripts ) {
588  $this->attributes['MessagePosterModule']['scripts'][] =
589  new ResourceLoaderFilePath( $scripts, $baseDir );
590  }
591  foreach ( $data['dependencies'] ?? [] as $dependency ) {
592  $this->attributes['MessagePosterModule']['dependencies'][] = $dependency;
593  }
594  }
595  }
596 
597  protected function extractExtensionMessagesFiles( $dir, array $info ) {
598  if ( isset( $info['ExtensionMessagesFiles'] ) ) {
599  foreach ( $info['ExtensionMessagesFiles'] as &$file ) {
600  $file = "$dir/$file";
601  }
602  $this->globals["wgExtensionMessagesFiles"] += $info['ExtensionMessagesFiles'];
603  }
604  }
605 
613  protected function extractMessagesDirs( $dir, array $info ) {
614  if ( isset( $info['MessagesDirs'] ) ) {
615  foreach ( $info['MessagesDirs'] as $name => $files ) {
616  foreach ( (array)$files as $file ) {
617  $this->globals["wgMessagesDirs"][$name][] = "$dir/$file";
618  }
619  }
620  }
621  }
622 
629  protected function extractSkins( $dir, array $info ) {
630  if ( isset( $info['ValidSkinNames'] ) ) {
631  foreach ( $info['ValidSkinNames'] as $skinKey => $data ) {
632  if ( isset( $data['args'][0]['templateDirectory'] ) ) {
633  $templateDirectory = $data['args'][0]['templateDirectory'];
634  $correctedPath = $dir . '/' . $templateDirectory;
635  // Historically the template directory was relative to core
636  // but it really should've been relative to the skin directory.
637  // If the path exists relative to the skin directory, assume that
638  // is what was intended. Otherwise fall back on the previous behavior
639  // of having it relative to core.
640  if ( is_dir( $correctedPath ) ) {
641  $data['args'][0]['templateDirectory'] = $correctedPath;
642  } else {
643  $data['args'][0]['templateDirectory'] = $templateDirectory;
645  'Template directory should be relative to skin or omitted.',
646  '1.37'
647  );
648  }
649  } elseif ( isset( $data['args'][0] ) ) {
650  // If not set, we set a sensible default.
651  $data['args'][0]['templateDirectory'] = $dir . '/templates';
652  }
653  $this->globals['wgValidSkinNames'][$skinKey] = $data;
654  }
655  }
656  }
657 
662  protected function extractSkinImportPaths( $dir, array $info ) {
663  if ( isset( $info['SkinLessImportPaths'] ) ) {
664  foreach ( $info['SkinLessImportPaths'] as $skin => $subpath ) {
665  $this->attributes['SkinLessImportPaths'][$skin] = "$dir/$subpath";
666  }
667  }
668  }
669 
676  protected function extractCredits( $path, array $info ) {
677  $credits = [
678  'path' => $path,
679  'type' => 'other',
680  ];
681  foreach ( self::CREDIT_ATTRIBS as $attr ) {
682  if ( isset( $info[$attr] ) ) {
683  $credits[$attr] = $info[$attr];
684  }
685  }
686 
687  $name = $credits['name'];
688 
689  // If someone is loading the same thing twice, throw
690  // a nice error (T121493)
691  if ( isset( $this->credits[$name] ) ) {
692  $firstPath = $this->credits[$name]['path'];
693  $secondPath = $credits['path'];
694  throw new Exception( "It was attempted to load $name twice, from $firstPath and $secondPath." );
695  }
696 
697  $this->credits[$name] = $credits;
698 
699  return $name;
700  }
701 
708  protected function extractConfig1( array $info ) {
709  if ( isset( $info['config'] ) ) {
710  if ( isset( $info['config']['_prefix'] ) ) {
711  $prefix = $info['config']['_prefix'];
712  unset( $info['config']['_prefix'] );
713  } else {
714  $prefix = 'wg';
715  }
716  foreach ( $info['config'] as $key => $val ) {
717  if ( $key[0] !== '@' ) {
718  $this->addConfigGlobal( "$prefix$key", $val, $info['name'] );
719  }
720  }
721  }
722  }
723 
731  protected function extractConfig2( array $info, $dir ) {
732  $prefix = $info['config_prefix'] ?? 'wg';
733  if ( isset( $info['config'] ) ) {
734  foreach ( $info['config'] as $key => $data ) {
735  if ( !array_key_exists( 'value', $data ) ) {
736  throw new UnexpectedValueException( "Missing value for config $key" );
737  }
738 
739  $value = $data['value'];
740  if ( isset( $data['path'] ) && $data['path'] ) {
741  $callback = static function ( $value ) use ( $dir ) {
742  return "$dir/$value";
743  };
744  if ( is_array( $value ) ) {
745  $value = array_map( $callback, $value );
746  } else {
747  $value = $callback( $value );
748  }
749  }
750  if ( isset( $data['merge_strategy'] ) ) {
751  $value[ExtensionRegistry::MERGE_STRATEGY] = $data['merge_strategy'];
752  }
753  $this->addConfigGlobal( "$prefix$key", $value, $info['name'] );
754  $data['providedby'] = $info['name'];
755  if ( isset( $info['ConfigRegistry'][0] ) ) {
756  $data['configregistry'] = array_keys( $info['ConfigRegistry'] )[0];
757  }
758  }
759  }
760  }
761 
769  private function addConfigGlobal( $key, $value, $extName ) {
770  if ( array_key_exists( $key, $this->globals ) ) {
771  throw new RuntimeException(
772  "The configuration setting '$key' was already set by MediaWiki core or"
773  . " another extension, and cannot be set again by $extName." );
774  }
775  $this->globals[$key] = $value;
776  }
777 
778  protected function extractPathBasedGlobal( $global, $dir, $paths ) {
779  foreach ( $paths as $path ) {
780  $this->globals[$global][] = "$dir/$path";
781  }
782  }
783 
793  protected function storeToArrayRecursive( $path, $name, $value, &$array ) {
794  if ( !is_array( $value ) ) {
795  throw new InvalidArgumentException( "The value for '$name' should be an array (from $path)" );
796  }
797  if ( isset( $array[$name] ) ) {
798  $array[$name] = array_merge_recursive( $array[$name], $value );
799  } else {
800  $array[$name] = $value;
801  }
802  }
803 
813  protected function storeToArray( $path, $name, $value, &$array ) {
814  if ( !is_array( $value ) ) {
815  throw new InvalidArgumentException( "The value for '$name' should be an array (from $path)" );
816  }
817  if ( isset( $array[$name] ) ) {
818  $array[$name] = array_merge( $array[$name], $value );
819  } else {
820  $array[$name] = $value;
821  }
822  }
823 
824  public function getExtraAutoloaderPaths( $dir, array $info ) {
825  $paths = [];
826  if ( isset( $info['load_composer_autoloader'] ) && $info['load_composer_autoloader'] === true ) {
827  $paths[] = "$dir/vendor/autoload.php";
828  }
829  return $paths;
830  }
831 }
ExtensionProcessor\$callbacks
callable[] $callbacks
Things to be called once registration of these extensions are done keyed by the name of the extension...
Definition: ExtensionProcessor.php:164
ExtensionProcessor\extractResourceLoaderModules
extractResourceLoaderModules( $dir, array $info)
Definition: ExtensionProcessor.php:540
ResourceLoaderFilePath
An object to represent a path to a JavaScript/CSS file, along with a remote and local base path,...
Definition: ResourceLoaderFilePath.php:28
ExtensionProcessor\extractConfig1
extractConfig1(array $info)
Set configuration settings for manifest_version == 1.
Definition: ExtensionProcessor.php:708
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
ExtensionProcessor\storeToArray
storeToArray( $path, $name, $value, &$array)
Stores $value to $array; using array_merge() if $array already contains $name.
Definition: ExtensionProcessor.php:813
Processor
Processors read associated arrays and register whatever is required.
Definition: Processor.php:9
ExtensionProcessor\addConfigGlobal
addConfigGlobal( $key, $value, $extName)
Helper function to set a value to a specific global, if it isn't set already.
Definition: ExtensionProcessor.php:769
ExtensionProcessor\extractExtensionMessagesFiles
extractExtensionMessagesFiles( $dir, array $info)
Definition: ExtensionProcessor.php:597
ExtensionRegistry\MERGE_STRATEGY
const MERGE_STRATEGY
Special key that defines the merge strategy.
Definition: ExtensionRegistry.php:51
ExtensionProcessor\extractSkinImportPaths
extractSkinImportPaths( $dir, array $info)
Definition: ExtensionProcessor.php:662
ExtensionProcessor
Definition: ExtensionProcessor.php:3
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1028
ExtensionProcessor\extractPathBasedGlobal
extractPathBasedGlobal( $global, $dir, $paths)
Definition: ExtensionProcessor.php:778
ExtensionProcessor\setArrayHookHandler
setArrayHookHandler(array $callback, array $hookHandlersAttr, string $name, string $path)
When handler value is an array, set $wgHooks or Hooks attribute Could be legacy hook e....
Definition: ExtensionProcessor.php:395
ExtensionProcessor\extractConfig2
extractConfig2(array $info, $dir)
Set configuration settings for manifest_version == 2.
Definition: ExtensionProcessor.php:731
ExtensionProcessor\$globals
array $globals
Stuff that is going to be set to $GLOBALS.
Definition: ExtensionProcessor.php:146
ExtensionProcessor\getExtraAutoloaderPaths
getExtraAutoloaderPaths( $dir, array $info)
Get the path for additional autoloaders, e.g.
Definition: ExtensionProcessor.php:824
ExtensionProcessor\getRequirements
getRequirements(array $info, $includeDev)
Get the requirements for the provided info.
Definition: ExtensionProcessor.php:313
ExtensionProcessor\$credits
array $credits
Definition: ExtensionProcessor.php:169
ExtensionProcessor\extractNamespaces
extractNamespaces(array $info)
Register namespaces with the appropriate global settings.
Definition: ExtensionProcessor.php:496
ExtensionProcessor\getExtractedInfo
getExtractedInfo()
Definition: ExtensionProcessor.php:280
ExtensionProcessor\$extAttributes
array $extAttributes
Extension attributes, keyed by name => settings.
Definition: ExtensionProcessor.php:185
ExtensionProcessor\$globalSettings
static array $globalSettings
Keys that should be set to $GLOBALS.
Definition: ExtensionProcessor.php:10
ExtensionProcessor\extractAttributes
extractAttributes( $path, array $info)
Definition: ExtensionProcessor.php:272
ExtensionProcessor\extractCredits
extractCredits( $path, array $info)
Definition: ExtensionProcessor.php:676
$path
$path
Definition: NoLocalSettings.php:25
ExtensionProcessor\extractInfo
extractInfo( $path, array $info, $version)
Definition: ExtensionProcessor.php:192
ExtensionProcessor\$defines
array $defines
Things that should be define()'d.
Definition: ExtensionProcessor.php:156
ExtensionProcessor\extractSkins
extractSkins( $dir, array $info)
Extract skins and handle path correction for templateDirectory.
Definition: ExtensionProcessor.php:629
ExtensionProcessor\$attributes
array $attributes
Any thing else in the $info that hasn't already been processed.
Definition: ExtensionProcessor.php:177
ExtensionProcessor\setStringHookHandler
setStringHookHandler(string $callback, array $hookHandlersAttr, string $name, string $path)
When handler value is a string, set $wgHooks or Hooks attribute.
Definition: ExtensionProcessor.php:437
ExtensionProcessor\extractMessagesDirs
extractMessagesDirs( $dir, array $info)
Set message-related settings, which need to be expanded to use absolute paths.
Definition: ExtensionProcessor.php:613
ExtensionProcessor\extractHooks
extractHooks(array $info, string $path)
Extract hook information from Hooks and HookHandler attributes.
Definition: ExtensionProcessor.php:462
ExtensionProcessor\storeToArrayRecursive
storeToArrayRecursive( $path, $name, $value, &$array)
Stores $value to $array; using array_merge_recursive() if $array already contains $name.
Definition: ExtensionProcessor.php:793