MediaWiki  master
Installer.php
Go to the documentation of this file.
1 <?php
30 
52 abstract class Installer {
53 
60  public const MINIMUM_PCRE_VERSION = '7.2';
61 
65  protected $settings;
66 
72  protected $compiledDBs;
73 
79  protected $dbInstallers = [];
80 
86  protected $minMemorySize = 50;
87 
93  protected $parserTitle;
94 
100  protected $parserOptions;
101 
111  protected static $dbTypes = [
112  'mysql',
113  'postgres',
114  'sqlite',
115  ];
116 
128  protected $envChecks = [
129  'envCheckDB',
130  'envCheckPCRE',
131  'envCheckMemory',
132  'envCheckCache',
133  'envCheckModSecurity',
134  'envCheckDiff3',
135  'envCheckGraphics',
136  'envCheckGit',
137  'envCheckServer',
138  'envCheckPath',
139  'envCheckShellLocale',
140  'envCheckUploadsDirectory',
141  'envCheckLibicu',
142  'envCheckSuhosinMaxValueLength',
143  'envCheck64Bit',
144  ];
145 
151  protected $envPreps = [
152  'envPrepServer',
153  'envPrepPath',
154  ];
155 
163  protected $defaultVarNames = [
164  'wgSitename',
165  'wgPasswordSender',
166  'wgLanguageCode',
167  'wgRightsIcon',
168  'wgRightsText',
169  'wgRightsUrl',
170  'wgEnableEmail',
171  'wgEnableUserEmail',
172  'wgEnotifUserTalk',
173  'wgEnotifWatchlist',
174  'wgEmailAuthentication',
175  'wgDBname',
176  'wgDBtype',
177  'wgDiff3',
178  'wgImageMagickConvertCommand',
179  'wgGitBin',
180  'IP',
181  'wgScriptPath',
182  'wgMetaNamespace',
183  'wgDeletedDirectory',
184  'wgEnableUploads',
185  'wgShellLocale',
186  'wgSecretKey',
187  'wgUseInstantCommons',
188  'wgUpgradeKey',
189  'wgDefaultSkin',
190  'wgPingback',
191  ];
192 
200  protected $internalDefaults = [
201  '_UserLang' => 'en',
202  '_Environment' => false,
203  '_RaiseMemory' => false,
204  '_UpgradeDone' => false,
205  '_InstallDone' => false,
206  '_Caches' => [],
207  '_InstallPassword' => '',
208  '_SameAccount' => true,
209  '_CreateDBAccount' => false,
210  '_NamespaceType' => 'site-name',
211  '_AdminName' => '', // will be set later, when the user selects language
212  '_AdminPassword' => '',
213  '_AdminPasswordConfirm' => '',
214  '_AdminEmail' => '',
215  '_Subscribe' => false,
216  '_SkipOptional' => 'continue',
217  '_RightsProfile' => 'wiki',
218  '_LicenseCode' => 'none',
219  '_CCDone' => false,
220  '_Extensions' => [],
221  '_Skins' => [],
222  '_MemCachedServers' => '',
223  '_UpgradeKeySupplied' => false,
224  '_ExistingDBSettings' => false,
225  // Single quotes are intentional, LocalSettingsGenerator must output this unescaped.
226  '_Logo' => '$wgResourceBasePath/resources/assets/wiki.png',
227 
228  'wgAuthenticationTokenVersion' => 1,
229  ];
230 
237  private $installSteps = [];
238 
244  protected $extraInstallSteps = [];
245 
251  protected $objectCaches = [
252  'apcu' => 'apcu_fetch',
253  'wincache' => 'wincache_ucache_get'
254  ];
255 
261  public $rightsProfiles = [
262  'wiki' => [],
263  'no-anon' => [
264  '*' => [ 'edit' => false ]
265  ],
266  'fishbowl' => [
267  '*' => [
268  'createaccount' => false,
269  'edit' => false,
270  ],
271  ],
272  'private' => [
273  '*' => [
274  'createaccount' => false,
275  'edit' => false,
276  'read' => false,
277  ],
278  ],
279  ];
280 
286  public $licenses = [
287  'cc-by' => [
288  'url' => 'https://creativecommons.org/licenses/by/4.0/',
289  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by.png',
290  ],
291  'cc-by-sa' => [
292  'url' => 'https://creativecommons.org/licenses/by-sa/4.0/',
293  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-sa.png',
294  ],
295  'cc-by-nc-sa' => [
296  'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/',
297  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png',
298  ],
299  'cc-0' => [
300  'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
301  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-0.png',
302  ],
303  'gfdl' => [
304  'url' => 'https://www.gnu.org/copyleft/fdl.html',
305  'icon' => '$wgResourceBasePath/resources/assets/licenses/gnu-fdl.png',
306  ],
307  'none' => [
308  'url' => '',
309  'icon' => '',
310  'text' => ''
311  ],
312  'cc-choose' => [
313  // Details will be filled in by the selector.
314  'url' => '',
315  'icon' => '',
316  'text' => '',
317  ],
318  ];
319 
324  'https://lists.wikimedia.org/mailman/subscribe/mediawiki-announce';
325 
330  'ca', 'cs', 'da', 'de', 'en', 'es', 'et', 'eu', 'fi', 'fr', 'hr', 'hu',
331  'it', 'ja', 'ko', 'lt', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru',
332  'sl', 'sr', 'sv', 'tr', 'uk'
333  ];
334 
343  abstract public function showMessage( $msg, ...$params );
344 
350  abstract public function showError( $msg, ...$params );
351 
356  abstract public function showStatusMessage( Status $status );
357 
368  public static function getInstallerConfig( Config $baseConfig ) {
369  $configOverrides = new HashConfig();
370 
371  // disable (problematic) object cache types explicitly, preserving all other (working) ones
372  // bug T113843
373  $emptyCache = [ 'class' => EmptyBagOStuff::class ];
374 
375  $objectCaches = [
376  CACHE_NONE => $emptyCache,
377  CACHE_DB => $emptyCache,
378  CACHE_ANYTHING => $emptyCache,
379  CACHE_MEMCACHED => $emptyCache,
380  ] + $baseConfig->get( 'ObjectCaches' );
381 
382  $configOverrides->set( 'ObjectCaches', $objectCaches );
383 
384  // Load the installer's i18n.
385  $messageDirs = $baseConfig->get( 'MessagesDirs' );
386  $messageDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
387 
388  $configOverrides->set( 'MessagesDirs', $messageDirs );
389 
390  $installerConfig = new MultiConfig( [ $configOverrides, $baseConfig ] );
391 
392  // make sure we use the installer config as the main config
393  $configRegistry = $baseConfig->get( 'ConfigRegistry' );
394  $configRegistry['main'] = function () use ( $installerConfig ) {
395  return $installerConfig;
396  };
397 
398  $configOverrides->set( 'ConfigRegistry', $configRegistry );
399 
400  return $installerConfig;
401  }
402 
406  public function __construct() {
407  $defaultConfig = new GlobalVarConfig(); // all the stuff from DefaultSettings.php
408  $installerConfig = self::getInstallerConfig( $defaultConfig );
409 
410  $this->resetMediaWikiServices( $installerConfig );
411 
412  // Disable all storage services, since we don't have any configuration yet!
413  MediaWikiServices::disableStorageBackend();
414 
415  $this->settings = $this->internalDefaults;
416 
417  foreach ( $this->defaultVarNames as $var ) {
418  $this->settings[$var] = $GLOBALS[$var];
419  }
420 
421  $this->doEnvironmentPreps();
422 
423  $this->compiledDBs = [];
424  foreach ( self::getDBTypes() as $type ) {
425  $installer = $this->getDBInstaller( $type );
426 
427  if ( !$installer->isCompiled() ) {
428  continue;
429  }
430  $this->compiledDBs[] = $type;
431  }
432 
433  $this->parserTitle = Title::newFromText( 'Installer' );
434  }
435 
450  public function resetMediaWikiServices( Config $installerConfig = null, $serviceOverrides = [] ) {
451  global $wgUser, $wgObjectCaches, $wgLang;
452 
453  $serviceOverrides += [
454  // Disable interwiki lookup, to avoid database access during parses
455  'InterwikiLookup' => function () {
456  return new NullInterwikiLookup();
457  },
458 
459  // Disable user options database fetching, only rely on default options.
460  'UserOptionsLookup' => function ( MediaWikiServices $services ) {
461  return $services->get( '_DefaultOptionsLookup' );
462  }
463  ];
464 
465  $lang = $this->getVar( '_UserLang', 'en' );
466 
467  // Reset all services and inject config overrides
468  MediaWikiServices::resetGlobalInstance( $installerConfig );
469 
470  $mwServices = MediaWikiServices::getInstance();
471 
472  foreach ( $serviceOverrides as $name => $callback ) {
473  // Skip if the caller set $callback to null
474  // to suppress default overrides.
475  if ( $callback ) {
476  $mwServices->redefineService( $name, $callback );
477  }
478  }
479 
480  // Disable i18n cache
481  $mwServices->getLocalisationCache()->disableBackend();
482 
483  // Clear language cache so the old i18n cache doesn't sneak back in
485 
486  // Set a fake user.
487  // Note that this will reset the context's language,
488  // so set the user before setting the language.
489  $user = User::newFromId( 0 );
490  $wgUser = $user;
491 
492  RequestContext::getMain()->setUser( $user );
493 
494  // Don't attempt to load user language options (T126177)
495  // This will be overridden in the web installer with the user-specified language
496  // Ensure $wgLang does not have a reference to a stale LocalisationCache instance
497  // (T241638, T261081)
498  RequestContext::getMain()->setLanguage( $lang );
499  $wgLang = RequestContext::getMain()->getLanguage();
500 
501  // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and
502  // SqlBagOStuff will then throw since we just disabled wfGetDB)
503  $wgObjectCaches = $mwServices->getMainConfig()->get( 'ObjectCaches' );
504 
505  $this->parserOptions = new ParserOptions( $user ); // language will be wrong :(
506  // Don't try to access DB before user language is initialised
507  $this->setParserLanguage( $mwServices->getLanguageFactory()->getLanguage( 'en' ) );
508 
509  return $mwServices;
510  }
511 
517  public static function getDBTypes() {
518  return self::$dbTypes;
519  }
520 
534  public function doEnvironmentChecks() {
535  // PHP version has already been checked by entry scripts
536  // Show message here for information purposes
537  $this->showMessage( 'config-env-php', PHP_VERSION );
538 
539  $good = true;
540  // Must go here because an old version of PCRE can prevent other checks from completing
541  $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
542  if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
543  $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
544  $good = false;
545  } else {
546  foreach ( $this->envChecks as $check ) {
547  $status = $this->$check();
548  if ( $status === false ) {
549  $good = false;
550  }
551  }
552  }
553 
554  $this->setVar( '_Environment', $good );
555 
556  return $good ? Status::newGood() : Status::newFatal( 'config-env-bad' );
557  }
558 
559  public function doEnvironmentPreps() {
560  foreach ( $this->envPreps as $prep ) {
561  $this->$prep();
562  }
563  }
564 
571  public function setVar( $name, $value ) {
572  $this->settings[$name] = $value;
573  }
574 
585  public function getVar( $name, $default = null ) {
586  return $this->settings[$name] ?? $default;
587  }
588 
594  public function getCompiledDBs() {
595  return $this->compiledDBs;
596  }
597 
605  public static function getDBInstallerClass( $type ) {
606  return ucfirst( $type ) . 'Installer';
607  }
608 
616  public function getDBInstaller( $type = false ) {
617  if ( !$type ) {
618  $type = $this->getVar( 'wgDBtype' );
619  }
620 
621  $type = strtolower( $type );
622 
623  if ( !isset( $this->dbInstallers[$type] ) ) {
624  $class = self::getDBInstallerClass( $type );
625  $this->dbInstallers[$type] = new $class( $this );
626  }
627 
628  return $this->dbInstallers[$type];
629  }
630 
636  public static function getExistingLocalSettings() {
637  global $IP;
638 
639  // You might be wondering why this is here. Well if you don't do this
640  // then some poorly-formed extensions try to call their own classes
641  // after immediately registering them. We really need to get extension
642  // registration out of the global scope and into a real format.
643  // @see https://phabricator.wikimedia.org/T69440
644  global $wgAutoloadClasses;
645  $wgAutoloadClasses = [];
646 
647  // LocalSettings.php should not call functions, except wfLoadSkin/wfLoadExtensions
648  // Define the required globals here, to ensure, the functions can do it work correctly.
649  // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
651 
652  Wikimedia\suppressWarnings();
653  $_lsExists = file_exists( "$IP/LocalSettings.php" );
654  Wikimedia\restoreWarnings();
655 
656  if ( !$_lsExists ) {
657  return false;
658  }
659  unset( $_lsExists );
660 
661  require "$IP/includes/DefaultSettings.php";
662  require "$IP/LocalSettings.php";
663 
664  return get_defined_vars();
665  }
666 
676  public function getFakePassword( $realPassword ) {
677  return str_repeat( '*', strlen( $realPassword ) );
678  }
679 
687  public function setPassword( $name, $value ) {
688  if ( !preg_match( '/^\*+$/', $value ) ) {
689  $this->setVar( $name, $value );
690  }
691  }
692 
704  public static function maybeGetWebserverPrimaryGroup() {
705  if ( !function_exists( 'posix_getegid' ) || !function_exists( 'posix_getpwuid' ) ) {
706  # I don't know this, this isn't UNIX.
707  return null;
708  }
709 
710  # posix_getegid() *not* getmygid() because we want the group of the webserver,
711  # not whoever owns the current script.
712  $gid = posix_getegid();
713  return posix_getpwuid( $gid )['name'] ?? null;
714  }
715 
732  public function parse( $text, $lineStart = false ) {
733  $parser = MediaWikiServices::getInstance()->getParser();
734 
735  try {
736  $out = $parser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
737  $html = $out->getText( [
738  'enableSectionEditLinks' => false,
739  'unwrap' => true,
740  ] );
741  $html = Parser::stripOuterParagraph( $html );
742  } catch ( Wikimedia\Services\ServiceDisabledException $e ) {
743  $html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
744  }
745 
746  return $html;
747  }
748 
752  public function getParserOptions() {
753  return $this->parserOptions;
754  }
755 
756  public function disableLinkPopups() {
757  $this->parserOptions->setExternalLinkTarget( false );
758  }
759 
760  public function restoreLinkPopups() {
761  global $wgExternalLinkTarget;
762  $this->parserOptions->setExternalLinkTarget( $wgExternalLinkTarget );
763  }
764 
773  public function populateSiteStats( DatabaseInstaller $installer ) {
774  $status = $installer->getConnection();
775  if ( !$status->isOK() ) {
776  return $status;
777  }
778  // @phan-suppress-next-line PhanUndeclaredMethod
779  $status->value->insert(
780  'site_stats',
781  [
782  'ss_row_id' => 1,
783  'ss_total_edits' => 0,
784  'ss_good_articles' => 0,
785  'ss_total_pages' => 0,
786  'ss_users' => 0,
787  'ss_active_users' => 0,
788  'ss_images' => 0
789  ],
790  __METHOD__, 'IGNORE'
791  );
792 
793  return Status::newGood();
794  }
795 
800  protected function envCheckDB() {
801  global $wgLang;
803  $dbType = $this->getVar( 'wgDBtype' );
804 
805  $allNames = [];
806 
807  // Messages: config-type-mysql, config-type-postgres, config-type-sqlite
808  foreach ( self::getDBTypes() as $name ) {
809  $allNames[] = wfMessage( "config-type-$name" )->text();
810  }
811 
812  $databases = $this->getCompiledDBs();
813 
814  $databases = array_flip( $databases );
815  $ok = true;
816  foreach ( array_keys( $databases ) as $db ) {
817  $installer = $this->getDBInstaller( $db );
818  $status = $installer->checkPrerequisites();
819  if ( !$status->isGood() ) {
820  if ( !$this instanceof WebInstaller && $db === $dbType ) {
821  // Strictly check the key database type instead of just outputting message
822  // Note: No perform this check run from the web installer, since this method always called by
823  // the welcome page under web installation, so $dbType will always be 'mysql'
824  $ok = false;
825  }
826  $this->showStatusMessage( $status );
827  unset( $databases[$db] );
828  }
829  }
830  $databases = array_flip( $databases );
831  if ( !$databases ) {
832  $this->showError( 'config-no-db', $wgLang->commaList( $allNames ), count( $allNames ) );
833  return false;
834  }
835  return $ok;
836  }
837 
846  protected function envCheckPCRE() {
847  Wikimedia\suppressWarnings();
848  $regexd = preg_replace( '/[\x{0430}-\x{04FF}]/iu', '', '-АБВГД-' );
849  // Need to check for \p support too, as PCRE can be compiled
850  // with utf8 support, but not unicode property support.
851  // check that \p{Zs} (space separators) matches
852  // U+3000 (Ideographic space)
853  $regexprop = preg_replace( '/\p{Zs}/u', '', "-\u{3000}-" );
854  Wikimedia\restoreWarnings();
855  if ( $regexd != '--' || $regexprop != '--' ) {
856  $this->showError( 'config-pcre-no-utf8' );
857 
858  return false;
859  }
860 
861  return true;
862  }
863 
868  protected function envCheckMemory() {
869  $limit = ini_get( 'memory_limit' );
870 
871  if ( !$limit || $limit == -1 ) {
872  return true;
873  }
874 
875  $n = wfShorthandToInteger( $limit );
876 
877  if ( $n < $this->minMemorySize * 1024 * 1024 ) {
878  $newLimit = "{$this->minMemorySize}M";
879 
880  if ( ini_set( "memory_limit", $newLimit ) === false ) {
881  $this->showMessage( 'config-memory-bad', $limit );
882  } else {
883  $this->showMessage( 'config-memory-raised', $limit, $newLimit );
884  $this->setVar( '_RaiseMemory', true );
885  }
886  }
887 
888  return true;
889  }
890 
894  protected function envCheckCache() {
895  $caches = [];
896  foreach ( $this->objectCaches as $name => $function ) {
897  if ( function_exists( $function ) ) {
898  $caches[$name] = true;
899  }
900  }
901 
902  if ( !$caches ) {
903  $this->showMessage( 'config-no-cache-apcu' );
904  }
905 
906  $this->setVar( '_Caches', $caches );
907  }
908 
913  protected function envCheckModSecurity() {
914  if ( self::apacheModulePresent( 'mod_security' )
915  || self::apacheModulePresent( 'mod_security2' ) ) {
916  $this->showMessage( 'config-mod-security' );
917  }
918 
919  return true;
920  }
921 
926  protected function envCheckDiff3() {
927  $names = [ "gdiff3", "diff3" ];
928  if ( wfIsWindows() ) {
929  $names[] = 'diff3.exe';
930  }
931  $versionInfo = [ '--version', 'GNU diffutils' ];
932 
933  $diff3 = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
934 
935  if ( $diff3 ) {
936  $this->setVar( 'wgDiff3', $diff3 );
937  } else {
938  $this->setVar( 'wgDiff3', false );
939  $this->showMessage( 'config-diff3-bad' );
940  }
941 
942  return true;
943  }
944 
949  protected function envCheckGraphics() {
950  $names = wfIsWindows() ? 'convert.exe' : 'convert';
951  $versionInfo = [ '-version', 'ImageMagick' ];
952  $convert = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
953 
954  $this->setVar( 'wgImageMagickConvertCommand', '' );
955  if ( $convert ) {
956  $this->setVar( 'wgImageMagickConvertCommand', $convert );
957  $this->showMessage( 'config-imagemagick', $convert );
958 
959  return true;
960  } elseif ( function_exists( 'imagejpeg' ) ) {
961  $this->showMessage( 'config-gd' );
962  } else {
963  $this->showMessage( 'config-no-scaling' );
964  }
965 
966  return true;
967  }
968 
975  protected function envCheckGit() {
976  $names = wfIsWindows() ? 'git.exe' : 'git';
977  $versionInfo = [ '--version', 'git version' ];
978 
979  $git = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
980 
981  if ( $git ) {
982  $this->setVar( 'wgGitBin', $git );
983  $this->showMessage( 'config-git', $git );
984  } else {
985  $this->setVar( 'wgGitBin', false );
986  $this->showMessage( 'config-git-bad' );
987  }
988 
989  return true;
990  }
991 
997  protected function envCheckServer() {
998  $server = $this->envGetDefaultServer();
999  if ( $server !== null ) {
1000  $this->showMessage( 'config-using-server', $server );
1001  }
1002  return true;
1003  }
1004 
1010  protected function envCheckPath() {
1011  $this->showMessage(
1012  'config-using-uri',
1013  $this->getVar( 'wgServer' ),
1014  $this->getVar( 'wgScriptPath' )
1015  );
1016  return true;
1017  }
1018 
1023  protected function envCheckShellLocale() {
1024  $os = php_uname( 's' );
1025  $supported = [ 'Linux', 'SunOS', 'HP-UX', 'Darwin' ]; # Tested these
1026 
1027  if ( !in_array( $os, $supported ) ) {
1028  return true;
1029  }
1030 
1031  if ( Shell::isDisabled() ) {
1032  return true;
1033  }
1034 
1035  # Get a list of available locales.
1036  $result = Shell::command( '/usr/bin/locale', '-a' )
1037  ->execute();
1038 
1039  if ( $result->getExitCode() != 0 ) {
1040  return true;
1041  }
1042 
1043  $lines = $result->getStdout();
1044  $lines = array_map( 'trim', explode( "\n", $lines ) );
1045  $candidatesByLocale = [];
1046  $candidatesByLang = [];
1047  foreach ( $lines as $line ) {
1048  if ( $line === '' ) {
1049  continue;
1050  }
1051 
1052  if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
1053  continue;
1054  }
1055 
1056  list( , $lang, , , ) = $m;
1057 
1058  $candidatesByLocale[$m[0]] = $m;
1059  $candidatesByLang[$lang][] = $m;
1060  }
1061 
1062  # Try the current value of LANG.
1063  if ( isset( $candidatesByLocale[getenv( 'LANG' )] ) ) {
1064  $this->setVar( 'wgShellLocale', getenv( 'LANG' ) );
1065 
1066  return true;
1067  }
1068 
1069  # Try the most common ones.
1070  $commonLocales = [ 'C.UTF-8', 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' ];
1071  foreach ( $commonLocales as $commonLocale ) {
1072  if ( isset( $candidatesByLocale[$commonLocale] ) ) {
1073  $this->setVar( 'wgShellLocale', $commonLocale );
1074 
1075  return true;
1076  }
1077  }
1078 
1079  # Is there an available locale in the Wiki's language?
1080  $wikiLang = $this->getVar( 'wgLanguageCode' );
1081 
1082  if ( isset( $candidatesByLang[$wikiLang] ) ) {
1083  $m = reset( $candidatesByLang[$wikiLang] );
1084  $this->setVar( 'wgShellLocale', $m[0] );
1085 
1086  return true;
1087  }
1088 
1089  # Are there any at all?
1090  if ( count( $candidatesByLocale ) ) {
1091  $m = reset( $candidatesByLocale );
1092  $this->setVar( 'wgShellLocale', $m[0] );
1093 
1094  return true;
1095  }
1096 
1097  # Give up.
1098  return true;
1099  }
1100 
1105  protected function envCheckUploadsDirectory() {
1106  global $IP;
1107 
1108  $dir = $IP . '/images/';
1109  $url = $this->getVar( 'wgServer' ) . $this->getVar( 'wgScriptPath' ) . '/images/';
1110  $safe = !$this->dirIsExecutable( $dir, $url );
1111 
1112  if ( !$safe ) {
1113  $this->showMessage( 'config-uploads-not-safe', $dir );
1114  }
1115 
1116  return true;
1117  }
1118 
1124  protected function envCheckSuhosinMaxValueLength() {
1125  $currentValue = ini_get( 'suhosin.get.max_value_length' );
1126  $minRequired = 2000;
1127  $recommended = 5000;
1128  if ( $currentValue > 0 && $currentValue < $minRequired ) {
1129  $this->showError( 'config-suhosin-max-value-length', $currentValue, $minRequired, $recommended );
1130  return false;
1131  }
1132 
1133  return true;
1134  }
1135 
1142  protected function envCheck64Bit() {
1143  if ( PHP_INT_SIZE == 4 ) {
1144  $this->showMessage( 'config-using-32bit' );
1145  }
1146 
1147  return true;
1148  }
1149 
1153  protected function envCheckLibicu() {
1161  $not_normal_c = "\u{FA6C}";
1162  $normal_c = "\u{242EE}";
1163 
1164  $useNormalizer = 'php';
1165  $needsUpdate = false;
1166 
1167  if ( function_exists( 'normalizer_normalize' ) ) {
1168  $useNormalizer = 'intl';
1169  $intl = normalizer_normalize( $not_normal_c, Normalizer::FORM_C );
1170  if ( $intl !== $normal_c ) {
1171  $needsUpdate = true;
1172  }
1173  }
1174 
1175  // Uses messages 'config-unicode-using-php' and 'config-unicode-using-intl'
1176  if ( $useNormalizer === 'php' ) {
1177  $this->showMessage( 'config-unicode-pure-php-warning' );
1178  } else {
1179  $this->showMessage( 'config-unicode-using-' . $useNormalizer );
1180  if ( $needsUpdate ) {
1181  $this->showMessage( 'config-unicode-update-warning' );
1182  }
1183  }
1184  }
1185 
1189  protected function envPrepServer() {
1190  $server = $this->envGetDefaultServer();
1191  if ( $server !== null ) {
1192  $this->setVar( 'wgServer', $server );
1193  }
1194  }
1195 
1200  abstract protected function envGetDefaultServer();
1201 
1205  protected function envPrepPath() {
1206  global $IP;
1207  $IP = dirname( dirname( __DIR__ ) );
1208  $this->setVar( 'IP', $IP );
1209  }
1210 
1219  public function dirIsExecutable( $dir, $url ) {
1220  $scriptTypes = [
1221  'php' => [
1222  "<?php echo 'exec';",
1223  "#!/var/env php\n<?php echo 'exec';",
1224  ],
1225  ];
1226 
1227  // it would be good to check other popular languages here, but it'll be slow.
1228 
1229  Wikimedia\suppressWarnings();
1230 
1231  foreach ( $scriptTypes as $ext => $contents ) {
1232  foreach ( $contents as $source ) {
1233  $file = 'exectest.' . $ext;
1234 
1235  if ( !file_put_contents( $dir . $file, $source ) ) {
1236  break;
1237  }
1238 
1239  try {
1240  $text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
1241  get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
1242  } catch ( Exception $e ) {
1243  // HttpRequestFactory::get can throw with allow_url_fopen = false and no curl
1244  // extension.
1245  $text = null;
1246  }
1247  unlink( $dir . $file );
1248 
1249  if ( $text == 'exec' ) {
1250  Wikimedia\restoreWarnings();
1251 
1252  return $ext;
1253  }
1254  }
1255  }
1256 
1257  Wikimedia\restoreWarnings();
1258 
1259  return false;
1260  }
1261 
1268  public static function apacheModulePresent( $moduleName ) {
1269  if ( function_exists( 'apache_get_modules' ) && in_array( $moduleName, apache_get_modules() ) ) {
1270  return true;
1271  }
1272  // try it the hard way
1273  ob_start();
1274  phpinfo( INFO_MODULES );
1275  $info = ob_get_clean();
1276 
1277  return strpos( $info, $moduleName ) !== false;
1278  }
1279 
1285  public function setParserLanguage( $lang ) {
1286  $this->parserOptions->setTargetLanguage( $lang );
1287  $this->parserOptions->setUserLang( $lang );
1288  }
1289 
1295  protected function getDocUrl( $page ) {
1296  return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
1297  }
1298 
1308  public function findExtensions( $directory = 'extensions' ) {
1309  switch ( $directory ) {
1310  case 'extensions':
1311  return $this->findExtensionsByType( 'extension', 'extensions' );
1312  case 'skins':
1313  return $this->findExtensionsByType( 'skin', 'skins' );
1314  default:
1315  throw new InvalidArgumentException( "Invalid extension type" );
1316  }
1317  }
1318 
1328  protected function findExtensionsByType( $type = 'extension', $directory = 'extensions' ) {
1329  if ( $this->getVar( 'IP' ) === null ) {
1330  return Status::newGood( [] );
1331  }
1332 
1333  $extDir = $this->getVar( 'IP' ) . '/' . $directory;
1334  if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
1335  return Status::newGood( [] );
1336  }
1337 
1338  $dh = opendir( $extDir );
1339  $exts = [];
1340  $status = new Status;
1341  while ( ( $file = readdir( $dh ) ) !== false ) {
1342  // skip non-dirs and hidden directories
1343  if ( !is_dir( "$extDir/$file" ) || $file[0] === '.' ) {
1344  continue;
1345  }
1346  $extStatus = $this->getExtensionInfo( $type, $directory, $file );
1347  if ( $extStatus->isOK() ) {
1348  $exts[$file] = $extStatus->value;
1349  } elseif ( $extStatus->hasMessage( 'config-extension-not-found' ) ) {
1350  // (T225512) The directory is not actually an extension. Downgrade to warning.
1351  $status->warning( 'config-extension-not-found', $file );
1352  } else {
1353  $status->merge( $extStatus );
1354  }
1355  }
1356  closedir( $dh );
1357  uksort( $exts, 'strnatcasecmp' );
1358 
1359  $status->value = $exts;
1360 
1361  return $status;
1362  }
1363 
1371  protected function getExtensionInfo( $type, $parentRelPath, $name ) {
1372  if ( $this->getVar( 'IP' ) === null ) {
1373  throw new Exception( 'Cannot find extensions since the IP variable is not yet set' );
1374  }
1375  if ( $type !== 'extension' && $type !== 'skin' ) {
1376  throw new InvalidArgumentException( "Invalid extension type" );
1377  }
1378  $absDir = $this->getVar( 'IP' ) . "/$parentRelPath/$name";
1379  $relDir = "../$parentRelPath/$name";
1380  if ( !is_dir( $absDir ) ) {
1381  return Status::newFatal( 'config-extension-not-found', $name );
1382  }
1383  $jsonFile = $type . '.json';
1384  $fullJsonFile = "$absDir/$jsonFile";
1385  $isJson = file_exists( $fullJsonFile );
1386  $isPhp = false;
1387  if ( !$isJson ) {
1388  // Only fallback to PHP file if JSON doesn't exist
1389  $fullPhpFile = "$absDir/$name.php";
1390  $isPhp = file_exists( $fullPhpFile );
1391  }
1392  if ( !$isJson && !$isPhp ) {
1393  return Status::newFatal( 'config-extension-not-found', $name );
1394  }
1395 
1396  // Extension exists. Now see if there are screenshots
1397  $info = [];
1398  if ( is_dir( "$absDir/screenshots" ) ) {
1399  $paths = glob( "$absDir/screenshots/*.png" );
1400  foreach ( $paths as $path ) {
1401  $info['screenshots'][] = str_replace( $absDir, $relDir, $path );
1402  }
1403  }
1404 
1405  if ( $isJson ) {
1406  $jsonStatus = $this->readExtension( $fullJsonFile );
1407  if ( !$jsonStatus->isOK() ) {
1408  return $jsonStatus;
1409  }
1410  $info += $jsonStatus->value;
1411  }
1412 
1413  return Status::newGood( $info );
1414  }
1415 
1424  private function readExtension( $fullJsonFile, $extDeps = [], $skinDeps = [] ) {
1425  $load = [
1426  $fullJsonFile => 1
1427  ];
1428  if ( $extDeps ) {
1429  $extDir = $this->getVar( 'IP' ) . '/extensions';
1430  foreach ( $extDeps as $dep ) {
1431  $fname = "$extDir/$dep/extension.json";
1432  if ( !file_exists( $fname ) ) {
1433  return Status::newFatal( 'config-extension-not-found', $dep );
1434  }
1435  $load[$fname] = 1;
1436  }
1437  }
1438  if ( $skinDeps ) {
1439  $skinDir = $this->getVar( 'IP' ) . '/skins';
1440  foreach ( $skinDeps as $dep ) {
1441  $fname = "$skinDir/$dep/skin.json";
1442  if ( !file_exists( $fname ) ) {
1443  return Status::newFatal( 'config-extension-not-found', $dep );
1444  }
1445  $load[$fname] = 1;
1446  }
1447  }
1448  $registry = new ExtensionRegistry();
1449  try {
1450  $info = $registry->readFromQueue( $load );
1451  } catch ( ExtensionDependencyError $e ) {
1452  if ( $e->incompatibleCore || $e->incompatibleSkins
1453  || $e->incompatibleExtensions
1454  ) {
1455  // If something is incompatible with a dependency, we have no real
1456  // option besides skipping it
1457  return Status::newFatal( 'config-extension-dependency',
1458  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1459  } elseif ( $e->missingExtensions || $e->missingSkins ) {
1460  // There's an extension missing in the dependency tree,
1461  // so add those to the dependency list and try again
1462  $status = $this->readExtension(
1463  $fullJsonFile,
1464  array_merge( $extDeps, $e->missingExtensions ),
1465  array_merge( $skinDeps, $e->missingSkins )
1466  );
1467  if ( !$status->isOK() && !$status->hasMessage( 'config-extension-dependency' ) ) {
1468  $status = Status::newFatal( 'config-extension-dependency',
1469  basename( dirname( $fullJsonFile ) ), $status->getMessage() );
1470  }
1471  return $status;
1472  }
1473  // Some other kind of dependency error?
1474  return Status::newFatal( 'config-extension-dependency',
1475  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1476  }
1477  $ret = [];
1478  // The order of credits will be the order of $load,
1479  // so the first extension is the one we want to load,
1480  // everything else is a dependency
1481  $i = 0;
1482  foreach ( $info['credits'] as $name => $credit ) {
1483  $i++;
1484  if ( $i == 1 ) {
1485  // Extension we want to load
1486  continue;
1487  }
1488  $type = basename( $credit['path'] ) === 'skin.json' ? 'skins' : 'extensions';
1489  $ret['requires'][$type][] = $credit['name'];
1490  }
1491  $credits = array_values( $info['credits'] )[0];
1492  if ( isset( $credits['url'] ) ) {
1493  $ret['url'] = $credits['url'];
1494  }
1495  $ret['type'] = $credits['type'];
1496 
1497  return Status::newGood( $ret );
1498  }
1499 
1508  public function getDefaultSkin( array $skinNames ) {
1509  $defaultSkin = $GLOBALS['wgDefaultSkin'];
1510  if ( !$skinNames || in_array( $defaultSkin, $skinNames ) ) {
1511  return $defaultSkin;
1512  } else {
1513  return $skinNames[0];
1514  }
1515  }
1516 
1523  protected function includeExtensions() {
1524  global $IP;
1525  $exts = $this->getVar( '_Extensions' );
1526  $IP = $this->getVar( 'IP' );
1527 
1528  // Marker for DatabaseUpdater::loadExtensions so we don't
1529  // double load extensions
1530  define( 'MW_EXTENSIONS_LOADED', true );
1531 
1540  global $wgAutoloadClasses;
1541  $wgAutoloadClasses = [];
1542  $queue = [];
1543 
1544  require "$IP/includes/DefaultSettings.php";
1545 
1546  foreach ( $exts as $e ) {
1547  if ( file_exists( "$IP/extensions/$e/extension.json" ) ) {
1548  $queue["$IP/extensions/$e/extension.json"] = 1;
1549  } else {
1550  require_once "$IP/extensions/$e/$e.php";
1551  }
1552  }
1553 
1554  $registry = new ExtensionRegistry();
1555  $data = $registry->readFromQueue( $queue );
1556  $wgAutoloadClasses += $data['globals']['wgAutoloadClasses'];
1557 
1558  // @phan-suppress-next-line PhanUndeclaredVariable,PhanCoalescingAlwaysNull $wgHooks is set by DefaultSettings
1559  $hooksWeWant = $wgHooks['LoadExtensionSchemaUpdates'] ?? [];
1560 
1561  if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
1562  $hooksWeWant = array_merge_recursive(
1563  $hooksWeWant,
1564  $data['globals']['wgHooks']['LoadExtensionSchemaUpdates']
1565  );
1566  }
1567  // Unset everyone else's hooks. Lord knows what someone might be doing
1568  // in ParserFirstCallInit (see T29171)
1569  $GLOBALS['wgHooks'] = [ 'LoadExtensionSchemaUpdates' => $hooksWeWant ];
1570 
1571  return Status::newGood();
1572  }
1573 
1587  protected function getInstallSteps( DatabaseInstaller $installer ) {
1588  $coreInstallSteps = [
1589  [ 'name' => 'database', 'callback' => [ $installer, 'setupDatabase' ] ],
1590  [ 'name' => 'tables', 'callback' => [ $installer, 'createTables' ] ],
1591  [ 'name' => 'tables-manual', 'callback' => [ $installer, 'createManualTables' ] ],
1592  [ 'name' => 'interwiki', 'callback' => [ $installer, 'populateInterwikiTable' ] ],
1593  [ 'name' => 'stats', 'callback' => [ $this, 'populateSiteStats' ] ],
1594  [ 'name' => 'keys', 'callback' => [ $this, 'generateKeys' ] ],
1595  [ 'name' => 'updates', 'callback' => [ $installer, 'insertUpdateKeys' ] ],
1596  [ 'name' => 'restore-services', 'callback' => [ $this, 'restoreServices' ] ],
1597  [ 'name' => 'sysop', 'callback' => [ $this, 'createSysop' ] ],
1598  [ 'name' => 'mainpage', 'callback' => [ $this, 'createMainpage' ] ],
1599  ];
1600 
1601  // Build the array of install steps starting from the core install list,
1602  // then adding any callbacks that wanted to attach after a given step
1603  foreach ( $coreInstallSteps as $step ) {
1604  $this->installSteps[] = $step;
1605  if ( isset( $this->extraInstallSteps[$step['name']] ) ) {
1606  $this->installSteps = array_merge(
1607  $this->installSteps,
1608  $this->extraInstallSteps[$step['name']]
1609  );
1610  }
1611  }
1612 
1613  // Prepend any steps that want to be at the beginning
1614  if ( isset( $this->extraInstallSteps['BEGINNING'] ) ) {
1615  $this->installSteps = array_merge(
1616  $this->extraInstallSteps['BEGINNING'],
1617  $this->installSteps
1618  );
1619  }
1620 
1621  // Extensions should always go first, chance to tie into hooks and such
1622  if ( count( $this->getVar( '_Extensions' ) ) ) {
1623  array_unshift( $this->installSteps,
1624  [ 'name' => 'extensions', 'callback' => [ $this, 'includeExtensions' ] ]
1625  );
1626  $this->installSteps[] = [
1627  'name' => 'extension-tables',
1628  'callback' => [ $installer, 'createExtensionTables' ]
1629  ];
1630  }
1631 
1632  return $this->installSteps;
1633  }
1634 
1643  public function performInstallation( $startCB, $endCB ) {
1644  $installResults = [];
1645  $installer = $this->getDBInstaller();
1646  $installer->preInstall();
1647  $steps = $this->getInstallSteps( $installer );
1648  foreach ( $steps as $stepObj ) {
1649  $name = $stepObj['name'];
1650  call_user_func_array( $startCB, [ $name ] );
1651 
1652  // Perform the callback step
1653  $status = call_user_func( $stepObj['callback'], $installer );
1654 
1655  // Output and save the results
1656  call_user_func( $endCB, $name, $status );
1657  $installResults[$name] = $status;
1658 
1659  // If we've hit some sort of fatal, we need to bail.
1660  // Callback already had a chance to do output above.
1661  if ( !$status->isOK() ) {
1662  break;
1663  }
1664  }
1665  if ( $status->isOK() ) {
1666  $this->showMessage(
1667  'config-install-db-success'
1668  );
1669  $this->setVar( '_InstallDone', true );
1670  }
1671 
1672  return $installResults;
1673  }
1674 
1680  public function generateKeys() {
1681  $keys = [ 'wgSecretKey' => 64 ];
1682  if ( strval( $this->getVar( 'wgUpgradeKey' ) ) === '' ) {
1683  $keys['wgUpgradeKey'] = 16;
1684  }
1685 
1686  return $this->doGenerateKeys( $keys );
1687  }
1688 
1693  public function restoreServices() {
1694  $this->resetMediaWikiServices( null, [
1695  'UserOptionsLookup' => function ( MediaWikiServices $services ) {
1696  return $services->get( 'UserOptionsManager' );
1697  }
1698  ] );
1699  return Status::newGood();
1700  }
1701 
1708  protected function doGenerateKeys( $keys ) {
1709  $status = Status::newGood();
1710 
1711  foreach ( $keys as $name => $length ) {
1712  $secretKey = MWCryptRand::generateHex( $length );
1713  $this->setVar( $name, $secretKey );
1714  }
1715 
1716  return $status;
1717  }
1718 
1724  protected function createSysop() {
1725  $name = $this->getVar( '_AdminName' );
1726  $user = User::newFromName( $name );
1727 
1728  if ( !$user ) {
1729  // We should've validated this earlier anyway!
1730  return Status::newFatal( 'config-admin-error-user', $name );
1731  }
1732 
1733  if ( $user->idForName() == 0 ) {
1734  $user->addToDatabase();
1735 
1736  $password = $this->getVar( '_AdminPassword' );
1737  $status = $user->changeAuthenticationData( [
1738  'username' => $user->getName(),
1739  'password' => $password,
1740  'retype' => $password,
1741  ] );
1742  if ( !$status->isGood() ) {
1743  return Status::newFatal( 'config-admin-error-password',
1744  $name, $status->getWikiText( null, null, $this->getVar( '_UserLang' ) ) );
1745  }
1746 
1747  $user->addGroup( 'sysop' );
1748  $user->addGroup( 'bureaucrat' );
1749  $user->addGroup( 'interface-admin' );
1750  if ( $this->getVar( '_AdminEmail' ) ) {
1751  $user->setEmail( $this->getVar( '_AdminEmail' ) );
1752  }
1753  $user->saveSettings();
1754 
1755  // Update user count
1756  $ssUpdate = SiteStatsUpdate::factory( [ 'users' => 1 ] );
1757  $ssUpdate->doUpdate();
1758  }
1759  $status = Status::newGood();
1760 
1761  if ( $this->getVar( '_Subscribe' ) && $this->getVar( '_AdminEmail' ) ) {
1762  $this->subscribeToMediaWikiAnnounce( $status );
1763  }
1764 
1765  return $status;
1766  }
1767 
1772  $params = [
1773  'email' => $this->getVar( '_AdminEmail' ),
1774  'language' => 'en',
1775  'digest' => 0
1776  ];
1777 
1778  // Mailman doesn't support as many languages as we do, so check to make
1779  // sure their selected language is available
1780  $myLang = $this->getVar( '_UserLang' );
1781  if ( in_array( $myLang, $this->mediaWikiAnnounceLanguages ) ) {
1782  $myLang = $myLang == 'pt-br' ? 'pt_BR' : $myLang; // rewrite to Mailman's pt_BR
1783  $params['language'] = $myLang;
1784  }
1785 
1787  $res = MWHttpRequest::factory( $this->mediaWikiAnnounceUrl,
1788  [ 'method' => 'POST', 'postData' => $params ], __METHOD__ )->execute();
1789  if ( !$res->isOK() ) {
1790  $s->warning( 'config-install-subscribe-fail', $res->getMessage() );
1791  }
1792  } else {
1793  $s->warning( 'config-install-subscribe-notpossible' );
1794  }
1795  }
1796 
1803  protected function createMainpage( DatabaseInstaller $installer ) {
1804  $status = Status::newGood();
1806  if ( $title->exists() ) {
1807  $status->warning( 'config-install-mainpage-exists' );
1808  return $status;
1809  }
1810  try {
1811  $page = WikiPage::factory( $title );
1812  $content = new WikitextContent(
1813  wfMessage( 'mainpagetext' )->inContentLanguage()->text() . "\n\n" .
1814  wfMessage( 'mainpagedocfooter' )->inContentLanguage()->text()
1815  );
1816 
1817  $status = $page->doEditContent( $content,
1818  '',
1819  EDIT_NEW,
1820  false,
1821  User::newSystemUser( 'MediaWiki default' )
1822  );
1823  } catch ( Exception $e ) {
1824  // using raw, because $wgShowExceptionDetails can not be set yet
1825  $status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
1826  }
1827 
1828  return $status;
1829  }
1830 
1834  public static function overrideConfig() {
1835  // Use PHP's built-in session handling, since MediaWiki's
1836  // SessionHandler can't work before we have an object cache set up.
1837  if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
1838  define( 'MW_NO_SESSION_HANDLER', 1 );
1839  }
1840 
1841  // Don't access the database
1842  $GLOBALS['wgUseDatabaseMessages'] = false;
1843  // Don't cache langconv tables
1844  $GLOBALS['wgLanguageConverterCacheType'] = CACHE_NONE;
1845  // Don't try to cache ResourceLoader dependencies in the database
1846  $GLOBALS['wgResourceLoaderUseObjectCacheForDeps'] = true;
1847  // Debug-friendly
1848  $GLOBALS['wgShowExceptionDetails'] = true;
1849  $GLOBALS['wgShowHostnames'] = true;
1850  // Don't break forms
1851  $GLOBALS['wgExternalLinkTarget'] = '_blank';
1852 
1853  // Allow multiple ob_flush() calls
1854  $GLOBALS['wgDisableOutputCompression'] = true;
1855 
1856  // Use a sensible cookie prefix (not my_wiki)
1857  $GLOBALS['wgCookiePrefix'] = 'mw_installer';
1858 
1859  // Some of the environment checks make shell requests, remove limits
1860  $GLOBALS['wgMaxShellMemory'] = 0;
1861 
1862  // Override the default CookieSessionProvider with a dummy
1863  // implementation that won't stomp on PHP's cookies.
1864  $GLOBALS['wgSessionProviders'] = [
1865  [
1866  'class' => InstallerSessionProvider::class,
1867  'args' => [ [
1868  'priority' => 1,
1869  ] ]
1870  ]
1871  ];
1872 
1873  // Don't use the DB as the main stash
1874  $GLOBALS['wgMainStash'] = CACHE_NONE;
1875 
1876  // Don't try to use any object cache for SessionManager either.
1877  $GLOBALS['wgSessionCacheType'] = CACHE_NONE;
1878 
1879  // Set a dummy $wgServer to bypass the check in Setup.php, the
1880  // web installer will automatically detect it and not use this value.
1881  $GLOBALS['wgServer'] = 'https://🌻.invalid';
1882  }
1883 
1891  public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
1892  $this->extraInstallSteps[$findStep][] = $callback;
1893  }
1894 
1899  protected function disableTimeLimit() {
1900  Wikimedia\suppressWarnings();
1901  set_time_limit( 0 );
1902  Wikimedia\restoreWarnings();
1903  }
1904 }
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:44
MediaWiki\Shell\Shell
Executes shell commands.
Definition: Shell.php:44
Installer\__construct
__construct()
Constructor, always call this from child classes.
Definition: Installer.php:406
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:579
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:328
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:70
Installer\createMainpage
createMainpage(DatabaseInstaller $installer)
Insert Main Page with default content.
Definition: Installer.php:1803
Installer\parse
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
Definition: Installer.php:732
ExtensionDependencyError
Copyright (C) 2018 Kunal Mehta legoktm@member.fsf.org
Definition: ExtensionDependencyError.php:25
MultiConfig
Provides a fallback sequence for Config objects.
Definition: MultiConfig.php:28
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:160
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
HashConfig
A Config instance which stores all settings as a member variable.
Definition: HashConfig.php:28
Installer\showStatusMessage
showStatusMessage(Status $status)
Show a message to the installing user by using a Status object.
Installer\dirIsExecutable
dirIsExecutable( $dir, $url)
Checks if scripts located in the given directory can be executed via the given URL.
Definition: Installer.php:1219
CACHE_NONE
const CACHE_NONE
Definition: Defines.php:91
Installer\envCheckLibicu
envCheckLibicu()
Check the libicu version.
Definition: Installer.php:1153
ExtensionRegistry
ExtensionRegistry class.
Definition: ExtensionRegistry.php:17
CACHE_MEMCACHED
const CACHE_MEMCACHED
Definition: Defines.php:93
Installer\populateSiteStats
populateSiteStats(DatabaseInstaller $installer)
Install step which adds a row to the site_stats table with appropriate initial values.
Definition: Installer.php:773
WebInstaller
Class for the core installer web interface.
Definition: WebInstaller.php:32
Installer\$extraInstallSteps
array $extraInstallSteps
Extra steps for installation, for things like DatabaseInstallers to modify.
Definition: Installer.php:244
DatabaseInstaller\getConnection
getConnection()
Connect to the database using the administrative user/password currently defined in the session.
Definition: DatabaseInstaller.php:186
Installer\$rightsProfiles
array $rightsProfiles
User rights profiles.
Definition: Installer.php:261
Installer\envCheckShellLocale
envCheckShellLocale()
Environment check for preferred locale in shell.
Definition: Installer.php:1023
Installer\envCheckUploadsDirectory
envCheckUploadsDirectory()
Environment check for the permissions of the uploads directory.
Definition: Installer.php:1105
Installer\$settings
array $settings
Definition: Installer.php:65
Installer\envPrepServer
envPrepServer()
Environment prep for the server hostname.
Definition: Installer.php:1189
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
Installer\performInstallation
performInstallation( $startCB, $endCB)
Actually perform the installation.
Definition: Installer.php:1643
Installer\$mediaWikiAnnounceLanguages
$mediaWikiAnnounceLanguages
Supported language codes for Mailman.
Definition: Installer.php:329
User\newFromName
static newFromName( $name, $validate='valid')
Definition: User.php:542
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1220
MediaWiki\Interwiki\NullInterwikiLookup
An interwiki lookup that has no data, intended for use in the installer.
Definition: NullInterwikiLookup.php:29
$s
$s
Definition: mergeMessageFileList.php:184
Installer\$dbInstallers
array $dbInstallers
Cached DB installer instances, access using getDBInstaller().
Definition: Installer.php:79
Installer\setParserLanguage
setParserLanguage( $lang)
ParserOptions are constructed before we determined the language, so fix it.
Definition: Installer.php:1285
Title\newMainPage
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:653
Installer\addInstallStep
addInstallStep( $callback, $findStep='BEGINNING')
Add an installation step following the given step.
Definition: Installer.php:1891
Installer\$internalDefaults
array $internalDefaults
Variables that are stored alongside globals, and are used for any configuration of the installation p...
Definition: Installer.php:200
$res
$res
Definition: testCompression.php:57
Installer\setPassword
setPassword( $name, $value)
Set a variable which stores a password, except if the new value is a fake password in which case leav...
Definition: Installer.php:687
Installer\envGetDefaultServer
envGetDefaultServer()
Helper function to be called from envPrepServer()
Installer\setVar
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:571
Installer\restoreServices
restoreServices()
Restore services that have been redefined in the early stage of installation.
Definition: Installer.php:1693
Installer\$parserTitle
Title $parserTitle
Cached Title, used by parse().
Definition: Installer.php:93
Installer\$objectCaches
array $objectCaches
Known object cache types and the functions used to test for their existence.
Definition: Installer.php:251
Installer\$minMemorySize
int $minMemorySize
Minimum memory size in MB.
Definition: Installer.php:86
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:44
User\newSystemUser
static newSystemUser( $name, $options=[])
Static factory method for creation of a "system" user from username.
Definition: User.php:772
Installer\overrideConfig
static overrideConfig()
Override the necessary bits of the config to run an installation.
Definition: Installer.php:1834
Installer\createSysop
createSysop()
Create the first user account, grant it sysop, bureaucrat and interface-admin rights.
Definition: Installer.php:1724
Installer\getFakePassword
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:676
Config
Interface for configuration instances.
Definition: Config.php:30
Installer\showMessage
showMessage( $msg,... $params)
UI interface for displaying a short message The parameters are like parameters to wfMessage().
Installer\envCheckSuhosinMaxValueLength
envCheckSuhosinMaxValueLength()
Checks if suhosin.get.max_value_length is set, and if so generate a warning because it is incompatibl...
Definition: Installer.php:1124
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7929
Installer\envPrepPath
envPrepPath()
Environment prep for setting $IP and $wgScriptPath.
Definition: Installer.php:1205
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:159
Installer\envCheckDiff3
envCheckDiff3()
Search for GNU diff3.
Definition: Installer.php:926
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Installer\generateKeys
generateKeys()
Generate $wgSecretKey.
Definition: Installer.php:1680
Installer\envCheckMemory
envCheckMemory()
Environment check for available memory.
Definition: Installer.php:868
$wgLang
$wgLang
Definition: Setup.php:776
$wgObjectCaches
$wgObjectCaches
Advanced object cache configuration.
Definition: DefaultSettings.php:2496
Installer\getCompiledDBs
getCompiledDBs()
Get a list of DBs supported by current PHP setup.
Definition: Installer.php:594
$queue
$queue
Definition: mergeMessageFileList.php:156
Installer\envCheckCache
envCheckCache()
Environment check for compiled object cache types.
Definition: Installer.php:894
Installer\getExistingLocalSettings
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
Definition: Installer.php:636
Installer\envCheckPath
envCheckPath()
Environment check to inform user which paths we've assumed.
Definition: Installer.php:1010
Installer\doGenerateKeys
doGenerateKeys( $keys)
Generate a secret value for variables using a secure generator.
Definition: Installer.php:1708
Installer\$parserOptions
ParserOptions $parserOptions
Cached ParserOptions, used by parse().
Definition: Installer.php:100
$title
$title
Definition: testCompression.php:38
SiteStatsUpdate\factory
static factory(array $deltas)
Definition: SiteStatsUpdate.php:71
GlobalVarConfig
Accesses configuration settings from $GLOBALS.
Definition: GlobalVarConfig.php:29
$wgExternalLinkTarget
$wgExternalLinkTarget
Set a default target for external links, e.g.
Definition: DefaultSettings.php:4663
Installer\$dbTypes
static array $dbTypes
Known database types.
Definition: Installer.php:111
Installer\getVar
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:585
WikitextContent
Content object for wiki text pages.
Definition: WikitextContent.php:37
Installer\restoreLinkPopups
restoreLinkPopups()
Definition: Installer.php:760
Installer\getDefaultSkin
getDefaultSkin(array $skinNames)
Returns a default value to be used for $wgDefaultSkin: normally the one set in DefaultSettings,...
Definition: Installer.php:1508
Installer\findExtensions
findExtensions( $directory='extensions')
Find extensions or skins in a subdirectory of $IP.
Definition: Installer.php:1308
Installer\getInstallerConfig
static getInstallerConfig(Config $baseConfig)
Constructs a Config object that contains configuration settings that should be overwritten for the in...
Definition: Installer.php:368
$content
$content
Definition: router.php:76
Installer\$envPreps
array $envPreps
A list of environment preparation methods called by doEnvironmentPreps().
Definition: Installer.php:151
$wgExtensionDirectory
$wgExtensionDirectory
Filesystem extensions directory.
Definition: DefaultSettings.php:251
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:1853
$line
$line
Definition: mcc.php:119
Installer\doEnvironmentPreps
doEnvironmentPreps()
Definition: Installer.php:559
Installer\resetMediaWikiServices
resetMediaWikiServices(Config $installerConfig=null, $serviceOverrides=[])
Reset the global service container and associated global state to accommodate different stages of the...
Definition: Installer.php:450
Installer\readExtension
readExtension( $fullJsonFile, $extDeps=[], $skinDeps=[])
Definition: Installer.php:1424
CACHE_ANYTHING
const CACHE_ANYTHING
Definition: Defines.php:90
Installer\getDBInstaller
getDBInstaller( $type=false)
Get an instance of DatabaseInstaller for the specified DB type.
Definition: Installer.php:616
DatabaseInstaller
Base class for DBMS-specific installation helper classes.
Definition: DatabaseInstaller.php:37
Installer\envCheckDB
envCheckDB()
Environment check for DB types.
Definition: Installer.php:800
Installer\getInstallSteps
getInstallSteps(DatabaseInstaller $installer)
Get an array of install steps.
Definition: Installer.php:1587
MWCryptRand\generateHex
static generateHex( $chars)
Generate a run of cryptographically random data and return it in hexadecimal string format.
Definition: MWCryptRand.php:36
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:454
$wgAutoloadClasses
$wgAutoloadClasses
Array mapping class names to filenames, for autoloading.
Definition: DefaultSettings.php:7824
Installer\$compiledDBs
array $compiledDBs
List of detected DBs, access using getCompiledDBs().
Definition: Installer.php:72
$lines
if(!file_exists( $CREDITS)) $lines
Definition: updateCredits.php:49
Installer\doEnvironmentChecks
doEnvironmentChecks()
Do initial checks of the PHP environment.
Definition: Installer.php:534
Language\$mLangObjCache
static array $mLangObjCache
Definition: Language.php:144
EDIT_NEW
const EDIT_NEW
Definition: Defines.php:141
Installer\envCheckGraphics
envCheckGraphics()
Environment check for ImageMagick and GD.
Definition: Installer.php:949
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:2671
Installer\apacheModulePresent
static apacheModulePresent( $moduleName)
Checks for presence of an Apache module.
Definition: Installer.php:1268
Title
Represents a title within MediaWiki.
Definition: Title.php:41
Installer\envCheckPCRE
envCheckPCRE()
Environment check for the PCRE module.
Definition: Installer.php:846
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6231
Installer\getParserOptions
getParserOptions()
Definition: Installer.php:752
MWHttpRequest\canMakeRequests
static canMakeRequests()
Simple function to test if we can make any sort of requests at all, using cURL or fopen()
Definition: MWHttpRequest.php:181
$path
$path
Definition: NoLocalSettings.php:25
Installer\envCheck64Bit
envCheck64Bit()
Checks if we're running on 64 bit or not.
Definition: Installer.php:1142
Installer\$licenses
array $licenses
License types.
Definition: Installer.php:286
Installer\disableTimeLimit
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:1899
Wikimedia
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
$keys
$keys
Definition: testCompression.php:72
$source
$source
Definition: mwdoc-filter.php:34
Installer\envCheckServer
envCheckServer()
Environment check to inform user which server we've assumed.
Definition: Installer.php:997
Installer
Base installer class.
Definition: Installer.php:52
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
Installer\MINIMUM_PCRE_VERSION
const MINIMUM_PCRE_VERSION
The oldest version of PCRE we can support.
Definition: Installer.php:60
Installer\findExtensionsByType
findExtensionsByType( $type='extension', $directory='extensions')
Find extensions or skins, and return an array containing the value for 'Name' for each found extensio...
Definition: Installer.php:1328
Installer\showError
showError( $msg,... $params)
Same as showMessage(), but for displaying errors.
ExecutableFinder\findInDefaultPaths
static findInDefaultPaths( $names, $versionInfo=false)
Same as locateExecutable(), but checks in getPossibleBinPaths() by default.
Definition: ExecutableFinder.php:96
Installer\getDBTypes
static getDBTypes()
Get a list of known DB types.
Definition: Installer.php:517
Installer\disableLinkPopups
disableLinkPopups()
Definition: Installer.php:756
Installer\$installSteps
array[] $installSteps
The actual list of installation steps.
Definition: Installer.php:237
Installer\$mediaWikiAnnounceUrl
$mediaWikiAnnounceUrl
URL to mediawiki-announce subscription.
Definition: Installer.php:323
$IP
$IP
Definition: WebStart.php:49
Installer\includeExtensions
includeExtensions()
Installs the auto-detected extensions.
Definition: Installer.php:1523
$wgStyleDirectory
$wgStyleDirectory
Filesystem stylesheets directory.
Definition: DefaultSettings.php:258
Installer\envCheckGit
envCheckGit()
Search for git.
Definition: Installer.php:975
Installer\getDocUrl
getDocUrl( $page)
Overridden by WebInstaller to provide lastPage parameters.
Definition: Installer.php:1295
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6
Installer\subscribeToMediaWikiAnnounce
subscribeToMediaWikiAnnounce(Status $s)
Definition: Installer.php:1771
CACHE_DB
const CACHE_DB
Definition: Defines.php:92
MWHttpRequest\factory
static factory( $url, array $options=null, $caller=__METHOD__)
Generate a new request object.
Definition: MWHttpRequest.php:195
Installer\maybeGetWebserverPrimaryGroup
static maybeGetWebserverPrimaryGroup()
On POSIX systems return the primary group of the webserver we're running under.
Definition: Installer.php:704
Installer\getExtensionInfo
getExtensionInfo( $type, $parentRelPath, $name)
Definition: Installer.php:1371
Installer\$defaultVarNames
array $defaultVarNames
MediaWiki configuration globals that will eventually be passed through to LocalSettings....
Definition: Installer.php:163
Installer\getDBInstallerClass
static getDBInstallerClass( $type)
Get the DatabaseInstaller class name for this type.
Definition: Installer.php:605
Installer\$envChecks
array $envChecks
A list of environment check methods called by doEnvironmentChecks().
Definition: Installer.php:128
$type
$type
Definition: testCompression.php:52
Installer\envCheckModSecurity
envCheckModSecurity()
Scare user to death if they have mod_security or mod_security2.
Definition: Installer.php:913