MediaWiki  1.34.0
Installer.php
Go to the documentation of this file.
1 <?php
30 
46 abstract class Installer {
47 
54  const MINIMUM_PCRE_VERSION = '7.2';
55 
59  protected $settings;
60 
66  protected $compiledDBs;
67 
73  protected $dbInstallers = [];
74 
80  protected $minMemorySize = 50;
81 
87  protected $parserTitle;
88 
94  protected $parserOptions;
95 
105  protected static $dbTypes = [
106  'mysql',
107  'postgres',
108  'sqlite',
109  ];
110 
122  protected $envChecks = [
123  'envCheckDB',
124  'envCheckBrokenXML',
125  'envCheckPCRE',
126  'envCheckMemory',
127  'envCheckCache',
128  'envCheckModSecurity',
129  'envCheckDiff3',
130  'envCheckGraphics',
131  'envCheckGit',
132  'envCheckServer',
133  'envCheckPath',
134  'envCheckShellLocale',
135  'envCheckUploadsDirectory',
136  'envCheckLibicu',
137  'envCheckSuhosinMaxValueLength',
138  'envCheck64Bit',
139  ];
140 
146  protected $envPreps = [
147  'envPrepServer',
148  'envPrepPath',
149  ];
150 
158  protected $defaultVarNames = [
159  'wgSitename',
160  'wgPasswordSender',
161  'wgLanguageCode',
162  'wgRightsIcon',
163  'wgRightsText',
164  'wgRightsUrl',
165  'wgEnableEmail',
166  'wgEnableUserEmail',
167  'wgEnotifUserTalk',
168  'wgEnotifWatchlist',
169  'wgEmailAuthentication',
170  'wgDBname',
171  'wgDBtype',
172  'wgDiff3',
173  'wgImageMagickConvertCommand',
174  'wgGitBin',
175  'IP',
176  'wgScriptPath',
177  'wgMetaNamespace',
178  'wgDeletedDirectory',
179  'wgEnableUploads',
180  'wgShellLocale',
181  'wgSecretKey',
182  'wgUseInstantCommons',
183  'wgUpgradeKey',
184  'wgDefaultSkin',
185  'wgPingback',
186  ];
187 
195  protected $internalDefaults = [
196  '_UserLang' => 'en',
197  '_Environment' => false,
198  '_RaiseMemory' => false,
199  '_UpgradeDone' => false,
200  '_InstallDone' => false,
201  '_Caches' => [],
202  '_InstallPassword' => '',
203  '_SameAccount' => true,
204  '_CreateDBAccount' => false,
205  '_NamespaceType' => 'site-name',
206  '_AdminName' => '', // will be set later, when the user selects language
207  '_AdminPassword' => '',
208  '_AdminPasswordConfirm' => '',
209  '_AdminEmail' => '',
210  '_Subscribe' => false,
211  '_SkipOptional' => 'continue',
212  '_RightsProfile' => 'wiki',
213  '_LicenseCode' => 'none',
214  '_CCDone' => false,
215  '_Extensions' => [],
216  '_Skins' => [],
217  '_MemCachedServers' => '',
218  '_UpgradeKeySupplied' => false,
219  '_ExistingDBSettings' => false,
220 
221  // $wgLogo is probably wrong (T50084); set something that will work.
222  // Single quotes work fine here, as LocalSettingsGenerator outputs this unescaped.
223  'wgLogo' => '$wgResourceBasePath/resources/assets/wiki.png',
224  'wgAuthenticationTokenVersion' => 1,
225  ];
226 
232  private $installSteps = [];
233 
239  protected $extraInstallSteps = [];
240 
246  protected $objectCaches = [
247  'apc' => 'apc_fetch',
248  'apcu' => 'apcu_fetch',
249  'wincache' => 'wincache_ucache_get'
250  ];
251 
257  public $rightsProfiles = [
258  'wiki' => [],
259  'no-anon' => [
260  '*' => [ 'edit' => false ]
261  ],
262  'fishbowl' => [
263  '*' => [
264  'createaccount' => false,
265  'edit' => false,
266  ],
267  ],
268  'private' => [
269  '*' => [
270  'createaccount' => false,
271  'edit' => false,
272  'read' => false,
273  ],
274  ],
275  ];
276 
282  public $licenses = [
283  'cc-by' => [
284  'url' => 'https://creativecommons.org/licenses/by/4.0/',
285  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by.png',
286  ],
287  'cc-by-sa' => [
288  'url' => 'https://creativecommons.org/licenses/by-sa/4.0/',
289  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-sa.png',
290  ],
291  'cc-by-nc-sa' => [
292  'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/',
293  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png',
294  ],
295  'cc-0' => [
296  'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
297  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-0.png',
298  ],
299  'gfdl' => [
300  'url' => 'https://www.gnu.org/copyleft/fdl.html',
301  'icon' => '$wgResourceBasePath/resources/assets/licenses/gnu-fdl.png',
302  ],
303  'none' => [
304  'url' => '',
305  'icon' => '',
306  'text' => ''
307  ],
308  'cc-choose' => [
309  // Details will be filled in by the selector.
310  'url' => '',
311  'icon' => '',
312  'text' => '',
313  ],
314  ];
315 
320  'https://lists.wikimedia.org/mailman/subscribe/mediawiki-announce';
321 
326  'ca', 'cs', 'da', 'de', 'en', 'es', 'et', 'eu', 'fi', 'fr', 'hr', 'hu',
327  'it', 'ja', 'ko', 'lt', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru',
328  'sl', 'sr', 'sv', 'tr', 'uk'
329  ];
330 
339  abstract public function showMessage( $msg, ...$params );
340 
346  abstract public function showError( $msg, ...$params );
347 
352  abstract public function showStatusMessage( Status $status );
353 
364  public static function getInstallerConfig( Config $baseConfig ) {
365  $configOverrides = new HashConfig();
366 
367  // disable (problematic) object cache types explicitly, preserving all other (working) ones
368  // bug T113843
369  $emptyCache = [ 'class' => EmptyBagOStuff::class ];
370 
371  $objectCaches = [
372  CACHE_NONE => $emptyCache,
373  CACHE_DB => $emptyCache,
374  CACHE_ANYTHING => $emptyCache,
375  CACHE_MEMCACHED => $emptyCache,
376  ] + $baseConfig->get( 'ObjectCaches' );
377 
378  $configOverrides->set( 'ObjectCaches', $objectCaches );
379 
380  // Load the installer's i18n.
381  $messageDirs = $baseConfig->get( 'MessagesDirs' );
382  $messageDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
383 
384  $configOverrides->set( 'MessagesDirs', $messageDirs );
385 
386  $installerConfig = new MultiConfig( [ $configOverrides, $baseConfig ] );
387 
388  // make sure we use the installer config as the main config
389  $configRegistry = $baseConfig->get( 'ConfigRegistry' );
390  $configRegistry['main'] = function () use ( $installerConfig ) {
391  return $installerConfig;
392  };
393 
394  $configOverrides->set( 'ConfigRegistry', $configRegistry );
395 
396  return $installerConfig;
397  }
398 
402  public function __construct() {
403  global $wgMemc, $wgUser, $wgObjectCaches;
404 
405  $defaultConfig = new GlobalVarConfig(); // all the stuff from DefaultSettings.php
406  $installerConfig = self::getInstallerConfig( $defaultConfig );
407 
408  // Reset all services and inject config overrides
409  MediaWikiServices::resetGlobalInstance( $installerConfig );
410 
411  // Don't attempt to load user language options (T126177)
412  // This will be overridden in the web installer with the user-specified language
413  RequestContext::getMain()->setLanguage( 'en' );
414 
415  // Disable all global services, since we don't have any configuration yet!
416  MediaWikiServices::disableStorageBackend();
417 
418  $mwServices = MediaWikiServices::getInstance();
419 
420  // Disable i18n cache
421  $mwServices->getLocalisationCache()->disableBackend();
422 
423  // Clear language cache so the old i18n cache doesn't sneak back in
425 
426  // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and
427  // SqlBagOStuff will then throw since we just disabled wfGetDB)
428  $wgObjectCaches = $mwServices->getMainConfig()->get( 'ObjectCaches' );
430 
431  // Disable interwiki lookup, to avoid database access during parses
432  $mwServices->redefineService( 'InterwikiLookup', function () {
433  return new NullInterwikiLookup();
434  } );
435 
436  // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
437  $wgUser = User::newFromId( 0 );
438  RequestContext::getMain()->setUser( $wgUser );
439 
440  $this->settings = $this->internalDefaults;
441 
442  foreach ( $this->defaultVarNames as $var ) {
443  $this->settings[$var] = $GLOBALS[$var];
444  }
445 
446  $this->doEnvironmentPreps();
447 
448  $this->compiledDBs = [];
449  foreach ( self::getDBTypes() as $type ) {
450  $installer = $this->getDBInstaller( $type );
451 
452  if ( !$installer->isCompiled() ) {
453  continue;
454  }
455  $this->compiledDBs[] = $type;
456  }
457 
458  $this->parserTitle = Title::newFromText( 'Installer' );
459  $this->parserOptions = new ParserOptions( $wgUser ); // language will be wrong :(
460  $this->parserOptions->setTidy( true );
461  // Don't try to access DB before user language is initialised
462  $this->setParserLanguage( Language::factory( 'en' ) );
463  }
464 
470  public static function getDBTypes() {
471  return self::$dbTypes;
472  }
473 
487  public function doEnvironmentChecks() {
488  // Php version has already been checked by entry scripts
489  // Show message here for information purposes
490  if ( wfIsHHVM() ) {
491  $this->showMessage( 'config-env-hhvm', HHVM_VERSION );
492  } else {
493  $this->showMessage( 'config-env-php', PHP_VERSION );
494  }
495 
496  $good = true;
497  // Must go here because an old version of PCRE can prevent other checks from completing
498  $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
499  if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
500  $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
501  $good = false;
502  } else {
503  foreach ( $this->envChecks as $check ) {
504  $status = $this->$check();
505  if ( $status === false ) {
506  $good = false;
507  }
508  }
509  }
510 
511  $this->setVar( '_Environment', $good );
512 
513  return $good ? Status::newGood() : Status::newFatal( 'config-env-bad' );
514  }
515 
516  public function doEnvironmentPreps() {
517  foreach ( $this->envPreps as $prep ) {
518  $this->$prep();
519  }
520  }
521 
528  public function setVar( $name, $value ) {
529  $this->settings[$name] = $value;
530  }
531 
542  public function getVar( $name, $default = null ) {
543  return $this->settings[$name] ?? $default;
544  }
545 
551  public function getCompiledDBs() {
552  return $this->compiledDBs;
553  }
554 
562  public static function getDBInstallerClass( $type ) {
563  return ucfirst( $type ) . 'Installer';
564  }
565 
573  public function getDBInstaller( $type = false ) {
574  if ( !$type ) {
575  $type = $this->getVar( 'wgDBtype' );
576  }
577 
578  $type = strtolower( $type );
579 
580  if ( !isset( $this->dbInstallers[$type] ) ) {
581  $class = self::getDBInstallerClass( $type );
582  $this->dbInstallers[$type] = new $class( $this );
583  }
584 
585  return $this->dbInstallers[$type];
586  }
587 
593  public static function getExistingLocalSettings() {
594  global $IP;
595 
596  // You might be wondering why this is here. Well if you don't do this
597  // then some poorly-formed extensions try to call their own classes
598  // after immediately registering them. We really need to get extension
599  // registration out of the global scope and into a real format.
600  // @see https://phabricator.wikimedia.org/T69440
601  global $wgAutoloadClasses;
602  $wgAutoloadClasses = [];
603 
604  // LocalSettings.php should not call functions, except wfLoadSkin/wfLoadExtensions
605  // Define the required globals here, to ensure, the functions can do it work correctly.
606  // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
608 
609  Wikimedia\suppressWarnings();
610  $_lsExists = file_exists( "$IP/LocalSettings.php" );
611  Wikimedia\restoreWarnings();
612 
613  if ( !$_lsExists ) {
614  return false;
615  }
616  unset( $_lsExists );
617 
618  require "$IP/includes/DefaultSettings.php";
619  require "$IP/LocalSettings.php";
620 
621  return get_defined_vars();
622  }
623 
633  public function getFakePassword( $realPassword ) {
634  return str_repeat( '*', strlen( $realPassword ) );
635  }
636 
644  public function setPassword( $name, $value ) {
645  if ( !preg_match( '/^\*+$/', $value ) ) {
646  $this->setVar( $name, $value );
647  }
648  }
649 
661  public static function maybeGetWebserverPrimaryGroup() {
662  if ( !function_exists( 'posix_getegid' ) || !function_exists( 'posix_getpwuid' ) ) {
663  # I don't know this, this isn't UNIX.
664  return null;
665  }
666 
667  # posix_getegid() *not* getmygid() because we want the group of the webserver,
668  # not whoever owns the current script.
669  $gid = posix_getegid();
670  $group = posix_getpwuid( $gid )['name'];
671 
672  return $group;
673  }
674 
691  public function parse( $text, $lineStart = false ) {
692  $parser = MediaWikiServices::getInstance()->getParser();
693 
694  try {
695  $out = $parser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
696  $html = $out->getText( [
697  'enableSectionEditLinks' => false,
698  'unwrap' => true,
699  ] );
700  $html = Parser::stripOuterParagraph( $html );
701  } catch ( Wikimedia\Services\ServiceDisabledException $e ) {
702  $html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
703  }
704 
705  return $html;
706  }
707 
711  public function getParserOptions() {
712  return $this->parserOptions;
713  }
714 
715  public function disableLinkPopups() {
716  $this->parserOptions->setExternalLinkTarget( false );
717  }
718 
719  public function restoreLinkPopups() {
720  global $wgExternalLinkTarget;
721  $this->parserOptions->setExternalLinkTarget( $wgExternalLinkTarget );
722  }
723 
732  public function populateSiteStats( DatabaseInstaller $installer ) {
733  $status = $installer->getConnection();
734  if ( !$status->isOK() ) {
735  return $status;
736  }
737  // @phan-suppress-next-line PhanUndeclaredMethod
738  $status->value->insert(
739  'site_stats',
740  [
741  'ss_row_id' => 1,
742  'ss_total_edits' => 0,
743  'ss_good_articles' => 0,
744  'ss_total_pages' => 0,
745  'ss_users' => 0,
746  'ss_active_users' => 0,
747  'ss_images' => 0
748  ],
749  __METHOD__, 'IGNORE'
750  );
751 
752  return Status::newGood();
753  }
754 
759  protected function envCheckDB() {
760  global $wgLang;
762  $dbType = $this->getVar( 'wgDBtype' );
763 
764  $allNames = [];
765 
766  // Messages: config-type-mysql, config-type-postgres, config-type-sqlite
767  foreach ( self::getDBTypes() as $name ) {
768  $allNames[] = wfMessage( "config-type-$name" )->text();
769  }
770 
771  $databases = $this->getCompiledDBs();
772 
773  $databases = array_flip( $databases );
774  $ok = true;
775  foreach ( array_keys( $databases ) as $db ) {
776  $installer = $this->getDBInstaller( $db );
777  $status = $installer->checkPrerequisites();
778  if ( !$status->isGood() ) {
779  if ( !$this instanceof WebInstaller && $db === $dbType ) {
780  // Strictly check the key database type instead of just outputting message
781  // Note: No perform this check run from the web installer, since this method always called by
782  // the welcome page under web installation, so $dbType will always be 'mysql'
783  $ok = false;
784  }
785  $this->showStatusMessage( $status );
786  unset( $databases[$db] );
787  }
788  }
789  $databases = array_flip( $databases );
790  if ( !$databases ) {
791  $this->showError( 'config-no-db', $wgLang->commaList( $allNames ), count( $allNames ) );
792  return false;
793  }
794  return $ok;
795  }
796 
801  protected function envCheckBrokenXML() {
802  $test = new PhpXmlBugTester();
803  if ( !$test->ok ) {
804  $this->showError( 'config-brokenlibxml' );
805 
806  return false;
807  }
808 
809  return true;
810  }
811 
820  protected function envCheckPCRE() {
821  Wikimedia\suppressWarnings();
822  $regexd = preg_replace( '/[\x{0430}-\x{04FF}]/iu', '', '-АБВГД-' );
823  // Need to check for \p support too, as PCRE can be compiled
824  // with utf8 support, but not unicode property support.
825  // check that \p{Zs} (space separators) matches
826  // U+3000 (Ideographic space)
827  $regexprop = preg_replace( '/\p{Zs}/u', '', "-\u{3000}-" );
828  Wikimedia\restoreWarnings();
829  if ( $regexd != '--' || $regexprop != '--' ) {
830  $this->showError( 'config-pcre-no-utf8' );
831 
832  return false;
833  }
834 
835  return true;
836  }
837 
842  protected function envCheckMemory() {
843  $limit = ini_get( 'memory_limit' );
844 
845  if ( !$limit || $limit == -1 ) {
846  return true;
847  }
848 
849  $n = wfShorthandToInteger( $limit );
850 
851  if ( $n < $this->minMemorySize * 1024 * 1024 ) {
852  $newLimit = "{$this->minMemorySize}M";
853 
854  if ( ini_set( "memory_limit", $newLimit ) === false ) {
855  $this->showMessage( 'config-memory-bad', $limit );
856  } else {
857  $this->showMessage( 'config-memory-raised', $limit, $newLimit );
858  $this->setVar( '_RaiseMemory', true );
859  }
860  }
861 
862  return true;
863  }
864 
868  protected function envCheckCache() {
869  $caches = [];
870  foreach ( $this->objectCaches as $name => $function ) {
871  if ( function_exists( $function ) ) {
872  $caches[$name] = true;
873  }
874  }
875 
876  if ( !$caches ) {
877  $this->showMessage( 'config-no-cache-apcu' );
878  }
879 
880  $this->setVar( '_Caches', $caches );
881  }
882 
887  protected function envCheckModSecurity() {
888  if ( self::apacheModulePresent( 'mod_security' )
889  || self::apacheModulePresent( 'mod_security2' ) ) {
890  $this->showMessage( 'config-mod-security' );
891  }
892 
893  return true;
894  }
895 
900  protected function envCheckDiff3() {
901  $names = [ "gdiff3", "diff3" ];
902  if ( wfIsWindows() ) {
903  $names[] = 'diff3.exe';
904  }
905  $versionInfo = [ '--version', 'GNU diffutils' ];
906 
907  $diff3 = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
908 
909  if ( $diff3 ) {
910  $this->setVar( 'wgDiff3', $diff3 );
911  } else {
912  $this->setVar( 'wgDiff3', false );
913  $this->showMessage( 'config-diff3-bad' );
914  }
915 
916  return true;
917  }
918 
923  protected function envCheckGraphics() {
924  $names = wfIsWindows() ? 'convert.exe' : 'convert';
925  $versionInfo = [ '-version', 'ImageMagick' ];
926  $convert = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
927 
928  $this->setVar( 'wgImageMagickConvertCommand', '' );
929  if ( $convert ) {
930  $this->setVar( 'wgImageMagickConvertCommand', $convert );
931  $this->showMessage( 'config-imagemagick', $convert );
932 
933  return true;
934  } elseif ( function_exists( 'imagejpeg' ) ) {
935  $this->showMessage( 'config-gd' );
936  } else {
937  $this->showMessage( 'config-no-scaling' );
938  }
939 
940  return true;
941  }
942 
949  protected function envCheckGit() {
950  $names = wfIsWindows() ? 'git.exe' : 'git';
951  $versionInfo = [ '--version', 'git version' ];
952 
953  $git = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
954 
955  if ( $git ) {
956  $this->setVar( 'wgGitBin', $git );
957  $this->showMessage( 'config-git', $git );
958  } else {
959  $this->setVar( 'wgGitBin', false );
960  $this->showMessage( 'config-git-bad' );
961  }
962 
963  return true;
964  }
965 
971  protected function envCheckServer() {
972  $server = $this->envGetDefaultServer();
973  if ( $server !== null ) {
974  $this->showMessage( 'config-using-server', $server );
975  }
976  return true;
977  }
978 
984  protected function envCheckPath() {
985  $this->showMessage(
986  'config-using-uri',
987  $this->getVar( 'wgServer' ),
988  $this->getVar( 'wgScriptPath' )
989  );
990  return true;
991  }
992 
997  protected function envCheckShellLocale() {
998  $os = php_uname( 's' );
999  $supported = [ 'Linux', 'SunOS', 'HP-UX', 'Darwin' ]; # Tested these
1000 
1001  if ( !in_array( $os, $supported ) ) {
1002  return true;
1003  }
1004 
1005  if ( Shell::isDisabled() ) {
1006  return true;
1007  }
1008 
1009  # Get a list of available locales.
1010  $result = Shell::command( '/usr/bin/locale', '-a' )
1011  ->execute();
1012 
1013  if ( $result->getExitCode() != 0 ) {
1014  return true;
1015  }
1016 
1017  $lines = $result->getStdout();
1018  $lines = array_map( 'trim', explode( "\n", $lines ) );
1019  $candidatesByLocale = [];
1020  $candidatesByLang = [];
1021  foreach ( $lines as $line ) {
1022  if ( $line === '' ) {
1023  continue;
1024  }
1025 
1026  if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
1027  continue;
1028  }
1029 
1030  list( , $lang, , , ) = $m;
1031 
1032  $candidatesByLocale[$m[0]] = $m;
1033  $candidatesByLang[$lang][] = $m;
1034  }
1035 
1036  # Try the current value of LANG.
1037  if ( isset( $candidatesByLocale[getenv( 'LANG' )] ) ) {
1038  $this->setVar( 'wgShellLocale', getenv( 'LANG' ) );
1039 
1040  return true;
1041  }
1042 
1043  # Try the most common ones.
1044  $commonLocales = [ 'C.UTF-8', 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' ];
1045  foreach ( $commonLocales as $commonLocale ) {
1046  if ( isset( $candidatesByLocale[$commonLocale] ) ) {
1047  $this->setVar( 'wgShellLocale', $commonLocale );
1048 
1049  return true;
1050  }
1051  }
1052 
1053  # Is there an available locale in the Wiki's language?
1054  $wikiLang = $this->getVar( 'wgLanguageCode' );
1055 
1056  if ( isset( $candidatesByLang[$wikiLang] ) ) {
1057  $m = reset( $candidatesByLang[$wikiLang] );
1058  $this->setVar( 'wgShellLocale', $m[0] );
1059 
1060  return true;
1061  }
1062 
1063  # Are there any at all?
1064  if ( count( $candidatesByLocale ) ) {
1065  $m = reset( $candidatesByLocale );
1066  $this->setVar( 'wgShellLocale', $m[0] );
1067 
1068  return true;
1069  }
1070 
1071  # Give up.
1072  return true;
1073  }
1074 
1079  protected function envCheckUploadsDirectory() {
1080  global $IP;
1081 
1082  $dir = $IP . '/images/';
1083  $url = $this->getVar( 'wgServer' ) . $this->getVar( 'wgScriptPath' ) . '/images/';
1084  $safe = !$this->dirIsExecutable( $dir, $url );
1085 
1086  if ( !$safe ) {
1087  $this->showMessage( 'config-uploads-not-safe', $dir );
1088  }
1089 
1090  return true;
1091  }
1092 
1098  protected function envCheckSuhosinMaxValueLength() {
1099  $currentValue = ini_get( 'suhosin.get.max_value_length' );
1100  $minRequired = 2000;
1101  $recommended = 5000;
1102  if ( $currentValue > 0 && $currentValue < $minRequired ) {
1103  $this->showError( 'config-suhosin-max-value-length', $currentValue, $minRequired, $recommended );
1104  return false;
1105  }
1106 
1107  return true;
1108  }
1109 
1116  protected function envCheck64Bit() {
1117  if ( PHP_INT_SIZE == 4 ) {
1118  $this->showMessage( 'config-using-32bit' );
1119  }
1120 
1121  return true;
1122  }
1123 
1127  protected function envCheckLibicu() {
1135  $not_normal_c = "\u{FA6C}";
1136  $normal_c = "\u{242EE}";
1137 
1138  $useNormalizer = 'php';
1139  $needsUpdate = false;
1140 
1141  if ( function_exists( 'normalizer_normalize' ) ) {
1142  $useNormalizer = 'intl';
1143  $intl = normalizer_normalize( $not_normal_c, Normalizer::FORM_C );
1144  if ( $intl !== $normal_c ) {
1145  $needsUpdate = true;
1146  }
1147  }
1148 
1149  // Uses messages 'config-unicode-using-php' and 'config-unicode-using-intl'
1150  if ( $useNormalizer === 'php' ) {
1151  $this->showMessage( 'config-unicode-pure-php-warning' );
1152  } else {
1153  $this->showMessage( 'config-unicode-using-' . $useNormalizer );
1154  if ( $needsUpdate ) {
1155  $this->showMessage( 'config-unicode-update-warning' );
1156  }
1157  }
1158  }
1159 
1163  protected function envPrepServer() {
1164  $server = $this->envGetDefaultServer();
1165  if ( $server !== null ) {
1166  $this->setVar( 'wgServer', $server );
1167  }
1168  }
1169 
1174  abstract protected function envGetDefaultServer();
1175 
1179  protected function envPrepPath() {
1180  global $IP;
1181  $IP = dirname( dirname( __DIR__ ) );
1182  $this->setVar( 'IP', $IP );
1183  }
1184 
1193  public function dirIsExecutable( $dir, $url ) {
1194  $scriptTypes = [
1195  'php' => [
1196  "<?php echo 'exec';",
1197  "#!/var/env php\n<?php echo 'exec';",
1198  ],
1199  ];
1200 
1201  // it would be good to check other popular languages here, but it'll be slow.
1202 
1203  Wikimedia\suppressWarnings();
1204 
1205  foreach ( $scriptTypes as $ext => $contents ) {
1206  foreach ( $contents as $source ) {
1207  $file = 'exectest.' . $ext;
1208 
1209  if ( !file_put_contents( $dir . $file, $source ) ) {
1210  break;
1211  }
1212 
1213  try {
1214  $text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
1215  get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
1216  } catch ( Exception $e ) {
1217  // HttpRequestFactory::get can throw with allow_url_fopen = false and no curl
1218  // extension.
1219  $text = null;
1220  }
1221  unlink( $dir . $file );
1222 
1223  if ( $text == 'exec' ) {
1224  Wikimedia\restoreWarnings();
1225 
1226  return $ext;
1227  }
1228  }
1229  }
1230 
1231  Wikimedia\restoreWarnings();
1232 
1233  return false;
1234  }
1235 
1242  public static function apacheModulePresent( $moduleName ) {
1243  if ( function_exists( 'apache_get_modules' ) && in_array( $moduleName, apache_get_modules() ) ) {
1244  return true;
1245  }
1246  // try it the hard way
1247  ob_start();
1248  phpinfo( INFO_MODULES );
1249  $info = ob_get_clean();
1250 
1251  return strpos( $info, $moduleName ) !== false;
1252  }
1253 
1259  public function setParserLanguage( $lang ) {
1260  $this->parserOptions->setTargetLanguage( $lang );
1261  $this->parserOptions->setUserLang( $lang );
1262  }
1263 
1269  protected function getDocUrl( $page ) {
1270  return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
1271  }
1272 
1282  public function findExtensions( $directory = 'extensions' ) {
1283  switch ( $directory ) {
1284  case 'extensions':
1285  return $this->findExtensionsByType( 'extension', 'extensions' );
1286  case 'skins':
1287  return $this->findExtensionsByType( 'skin', 'skins' );
1288  default:
1289  throw new InvalidArgumentException( "Invalid extension type" );
1290  }
1291  }
1292 
1302  protected function findExtensionsByType( $type = 'extension', $directory = 'extensions' ) {
1303  if ( $this->getVar( 'IP' ) === null ) {
1304  return Status::newGood( [] );
1305  }
1306 
1307  $extDir = $this->getVar( 'IP' ) . '/' . $directory;
1308  if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
1309  return Status::newGood( [] );
1310  }
1311 
1312  $dh = opendir( $extDir );
1313  $exts = [];
1314  $status = new Status;
1315  while ( ( $file = readdir( $dh ) ) !== false ) {
1316  // skip non-dirs and hidden directories
1317  if ( !is_dir( "$extDir/$file" ) || $file[0] === '.' ) {
1318  continue;
1319  }
1320  $extStatus = $this->getExtensionInfo( $type, $directory, $file );
1321  if ( $extStatus->isOK() ) {
1322  $exts[$file] = $extStatus->value;
1323  } elseif ( $extStatus->hasMessage( 'config-extension-not-found' ) ) {
1324  // (T225512) The directory is not actually an extension. Downgrade to warning.
1325  $status->warning( 'config-extension-not-found', $file );
1326  } else {
1327  $status->merge( $extStatus );
1328  }
1329  }
1330  closedir( $dh );
1331  uksort( $exts, 'strnatcasecmp' );
1332 
1333  $status->value = $exts;
1334 
1335  return $status;
1336  }
1337 
1345  protected function getExtensionInfo( $type, $parentRelPath, $name ) {
1346  if ( $this->getVar( 'IP' ) === null ) {
1347  throw new Exception( 'Cannot find extensions since the IP variable is not yet set' );
1348  }
1349  if ( $type !== 'extension' && $type !== 'skin' ) {
1350  throw new InvalidArgumentException( "Invalid extension type" );
1351  }
1352  $absDir = $this->getVar( 'IP' ) . "/$parentRelPath/$name";
1353  $relDir = "../$parentRelPath/$name";
1354  if ( !is_dir( $absDir ) ) {
1355  return Status::newFatal( 'config-extension-not-found', $name );
1356  }
1357  $jsonFile = $type . '.json';
1358  $fullJsonFile = "$absDir/$jsonFile";
1359  $isJson = file_exists( $fullJsonFile );
1360  $isPhp = false;
1361  if ( !$isJson ) {
1362  // Only fallback to PHP file if JSON doesn't exist
1363  $fullPhpFile = "$absDir/$name.php";
1364  $isPhp = file_exists( $fullPhpFile );
1365  }
1366  if ( !$isJson && !$isPhp ) {
1367  return Status::newFatal( 'config-extension-not-found', $name );
1368  }
1369 
1370  // Extension exists. Now see if there are screenshots
1371  $info = [];
1372  if ( is_dir( "$absDir/screenshots" ) ) {
1373  $paths = glob( "$absDir/screenshots/*.png" );
1374  foreach ( $paths as $path ) {
1375  $info['screenshots'][] = str_replace( $absDir, $relDir, $path );
1376  }
1377  }
1378 
1379  if ( $isJson ) {
1380  $jsonStatus = $this->readExtension( $fullJsonFile );
1381  if ( !$jsonStatus->isOK() ) {
1382  return $jsonStatus;
1383  }
1384  $info += $jsonStatus->value;
1385  }
1386 
1387  return Status::newGood( $info );
1388  }
1389 
1398  private function readExtension( $fullJsonFile, $extDeps = [], $skinDeps = [] ) {
1399  $load = [
1400  $fullJsonFile => 1
1401  ];
1402  if ( $extDeps ) {
1403  $extDir = $this->getVar( 'IP' ) . '/extensions';
1404  foreach ( $extDeps as $dep ) {
1405  $fname = "$extDir/$dep/extension.json";
1406  if ( !file_exists( $fname ) ) {
1407  return Status::newFatal( 'config-extension-not-found', $dep );
1408  }
1409  $load[$fname] = 1;
1410  }
1411  }
1412  if ( $skinDeps ) {
1413  $skinDir = $this->getVar( 'IP' ) . '/skins';
1414  foreach ( $skinDeps as $dep ) {
1415  $fname = "$skinDir/$dep/skin.json";
1416  if ( !file_exists( $fname ) ) {
1417  return Status::newFatal( 'config-extension-not-found', $dep );
1418  }
1419  $load[$fname] = 1;
1420  }
1421  }
1422  $registry = new ExtensionRegistry();
1423  try {
1424  $info = $registry->readFromQueue( $load );
1425  } catch ( ExtensionDependencyError $e ) {
1426  if ( $e->incompatibleCore || $e->incompatibleSkins
1427  || $e->incompatibleExtensions
1428  ) {
1429  // If something is incompatible with a dependency, we have no real
1430  // option besides skipping it
1431  return Status::newFatal( 'config-extension-dependency',
1432  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1433  } elseif ( $e->missingExtensions || $e->missingSkins ) {
1434  // There's an extension missing in the dependency tree,
1435  // so add those to the dependency list and try again
1436  $status = $this->readExtension(
1437  $fullJsonFile,
1438  array_merge( $extDeps, $e->missingExtensions ),
1439  array_merge( $skinDeps, $e->missingSkins )
1440  );
1441  if ( !$status->isOK() && !$status->hasMessage( 'config-extension-dependency' ) ) {
1442  $status = Status::newFatal( 'config-extension-dependency',
1443  basename( dirname( $fullJsonFile ) ), $status->getMessage() );
1444  }
1445  return $status;
1446  }
1447  // Some other kind of dependency error?
1448  return Status::newFatal( 'config-extension-dependency',
1449  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1450  }
1451  $ret = [];
1452  // The order of credits will be the order of $load,
1453  // so the first extension is the one we want to load,
1454  // everything else is a dependency
1455  $i = 0;
1456  foreach ( $info['credits'] as $name => $credit ) {
1457  $i++;
1458  if ( $i == 1 ) {
1459  // Extension we want to load
1460  continue;
1461  }
1462  $type = basename( $credit['path'] ) === 'skin.json' ? 'skins' : 'extensions';
1463  $ret['requires'][$type][] = $credit['name'];
1464  }
1465  $credits = array_values( $info['credits'] )[0];
1466  if ( isset( $credits['url'] ) ) {
1467  $ret['url'] = $credits['url'];
1468  }
1469  $ret['type'] = $credits['type'];
1470 
1471  return Status::newGood( $ret );
1472  }
1473 
1482  public function getDefaultSkin( array $skinNames ) {
1483  $defaultSkin = $GLOBALS['wgDefaultSkin'];
1484  if ( !$skinNames || in_array( $defaultSkin, $skinNames ) ) {
1485  return $defaultSkin;
1486  } else {
1487  return $skinNames[0];
1488  }
1489  }
1490 
1497  protected function includeExtensions() {
1498  global $IP;
1499  $exts = $this->getVar( '_Extensions' );
1500  $IP = $this->getVar( 'IP' );
1501 
1502  // Marker for DatabaseUpdater::loadExtensions so we don't
1503  // double load extensions
1504  define( 'MW_EXTENSIONS_LOADED', true );
1505 
1514  global $wgAutoloadClasses;
1515  $wgAutoloadClasses = [];
1516  $queue = [];
1517 
1518  require "$IP/includes/DefaultSettings.php";
1519 
1520  foreach ( $exts as $e ) {
1521  if ( file_exists( "$IP/extensions/$e/extension.json" ) ) {
1522  $queue["$IP/extensions/$e/extension.json"] = 1;
1523  } else {
1524  require_once "$IP/extensions/$e/$e.php";
1525  }
1526  }
1527 
1528  $registry = new ExtensionRegistry();
1529  $data = $registry->readFromQueue( $queue );
1530  $wgAutoloadClasses += $data['autoload'];
1531 
1532  // @phan-suppress-next-line PhanUndeclaredVariable $wgHooks is set by DefaultSettings
1533  $hooksWeWant = $wgHooks['LoadExtensionSchemaUpdates'] ?? [];
1534 
1535  if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
1536  $hooksWeWant = array_merge_recursive(
1537  $hooksWeWant,
1538  $data['globals']['wgHooks']['LoadExtensionSchemaUpdates']
1539  );
1540  }
1541  // Unset everyone else's hooks. Lord knows what someone might be doing
1542  // in ParserFirstCallInit (see T29171)
1543  $GLOBALS['wgHooks'] = [ 'LoadExtensionSchemaUpdates' => $hooksWeWant ];
1544 
1545  return Status::newGood();
1546  }
1547 
1560  protected function getInstallSteps( DatabaseInstaller $installer ) {
1561  $coreInstallSteps = [
1562  [ 'name' => 'database', 'callback' => [ $installer, 'setupDatabase' ] ],
1563  [ 'name' => 'tables', 'callback' => [ $installer, 'createTables' ] ],
1564  [ 'name' => 'interwiki', 'callback' => [ $installer, 'populateInterwikiTable' ] ],
1565  [ 'name' => 'stats', 'callback' => [ $this, 'populateSiteStats' ] ],
1566  [ 'name' => 'keys', 'callback' => [ $this, 'generateKeys' ] ],
1567  [ 'name' => 'updates', 'callback' => [ $installer, 'insertUpdateKeys' ] ],
1568  [ 'name' => 'sysop', 'callback' => [ $this, 'createSysop' ] ],
1569  [ 'name' => 'mainpage', 'callback' => [ $this, 'createMainpage' ] ],
1570  ];
1571 
1572  // Build the array of install steps starting from the core install list,
1573  // then adding any callbacks that wanted to attach after a given step
1574  foreach ( $coreInstallSteps as $step ) {
1575  $this->installSteps[] = $step;
1576  if ( isset( $this->extraInstallSteps[$step['name']] ) ) {
1577  $this->installSteps = array_merge(
1578  $this->installSteps,
1579  $this->extraInstallSteps[$step['name']]
1580  );
1581  }
1582  }
1583 
1584  // Prepend any steps that want to be at the beginning
1585  if ( isset( $this->extraInstallSteps['BEGINNING'] ) ) {
1586  $this->installSteps = array_merge(
1587  $this->extraInstallSteps['BEGINNING'],
1588  $this->installSteps
1589  );
1590  }
1591 
1592  // Extensions should always go first, chance to tie into hooks and such
1593  if ( count( $this->getVar( '_Extensions' ) ) ) {
1594  array_unshift( $this->installSteps,
1595  [ 'name' => 'extensions', 'callback' => [ $this, 'includeExtensions' ] ]
1596  );
1597  $this->installSteps[] = [
1598  'name' => 'extension-tables',
1599  'callback' => [ $installer, 'createExtensionTables' ]
1600  ];
1601  }
1602 
1603  return $this->installSteps;
1604  }
1605 
1614  public function performInstallation( $startCB, $endCB ) {
1615  $installResults = [];
1616  $installer = $this->getDBInstaller();
1617  $installer->preInstall();
1618  $steps = $this->getInstallSteps( $installer );
1619  foreach ( $steps as $stepObj ) {
1620  $name = $stepObj['name'];
1621  call_user_func_array( $startCB, [ $name ] );
1622 
1623  // Perform the callback step
1624  $status = call_user_func( $stepObj['callback'], $installer );
1625 
1626  // Output and save the results
1627  call_user_func( $endCB, $name, $status );
1628  $installResults[$name] = $status;
1629 
1630  // If we've hit some sort of fatal, we need to bail.
1631  // Callback already had a chance to do output above.
1632  if ( !$status->isOK() ) {
1633  break;
1634  }
1635  }
1636  if ( $status->isOK() ) {
1637  $this->showMessage(
1638  'config-install-db-success'
1639  );
1640  $this->setVar( '_InstallDone', true );
1641  }
1642 
1643  return $installResults;
1644  }
1645 
1651  public function generateKeys() {
1652  $keys = [ 'wgSecretKey' => 64 ];
1653  if ( strval( $this->getVar( 'wgUpgradeKey' ) ) === '' ) {
1654  $keys['wgUpgradeKey'] = 16;
1655  }
1656 
1657  return $this->doGenerateKeys( $keys );
1658  }
1659 
1666  protected function doGenerateKeys( $keys ) {
1668 
1669  foreach ( $keys as $name => $length ) {
1670  $secretKey = MWCryptRand::generateHex( $length );
1671  $this->setVar( $name, $secretKey );
1672  }
1673 
1674  return $status;
1675  }
1676 
1682  protected function createSysop() {
1683  $name = $this->getVar( '_AdminName' );
1684  $user = User::newFromName( $name );
1685 
1686  if ( !$user ) {
1687  // We should've validated this earlier anyway!
1688  return Status::newFatal( 'config-admin-error-user', $name );
1689  }
1690 
1691  if ( $user->idForName() == 0 ) {
1692  $user->addToDatabase();
1693 
1694  try {
1695  $user->setPassword( $this->getVar( '_AdminPassword' ) );
1696  } catch ( PasswordError $pwe ) {
1697  return Status::newFatal( 'config-admin-error-password', $name, $pwe->getMessage() );
1698  }
1699 
1700  $user->addGroup( 'sysop' );
1701  $user->addGroup( 'bureaucrat' );
1702  $user->addGroup( 'interface-admin' );
1703  if ( $this->getVar( '_AdminEmail' ) ) {
1704  $user->setEmail( $this->getVar( '_AdminEmail' ) );
1705  }
1706  $user->saveSettings();
1707 
1708  // Update user count
1709  $ssUpdate = SiteStatsUpdate::factory( [ 'users' => 1 ] );
1710  $ssUpdate->doUpdate();
1711  }
1713 
1714  if ( $this->getVar( '_Subscribe' ) && $this->getVar( '_AdminEmail' ) ) {
1716  }
1717 
1718  return $status;
1719  }
1720 
1725  $params = [
1726  'email' => $this->getVar( '_AdminEmail' ),
1727  'language' => 'en',
1728  'digest' => 0
1729  ];
1730 
1731  // Mailman doesn't support as many languages as we do, so check to make
1732  // sure their selected language is available
1733  $myLang = $this->getVar( '_UserLang' );
1734  if ( in_array( $myLang, $this->mediaWikiAnnounceLanguages ) ) {
1735  $myLang = $myLang == 'pt-br' ? 'pt_BR' : $myLang; // rewrite to Mailman's pt_BR
1736  $params['language'] = $myLang;
1737  }
1738 
1740  $res = MWHttpRequest::factory( $this->mediaWikiAnnounceUrl,
1741  [ 'method' => 'POST', 'postData' => $params ], __METHOD__ )->execute();
1742  if ( !$res->isOK() ) {
1743  $s->warning( 'config-install-subscribe-fail', $res->getMessage() );
1744  }
1745  } else {
1746  $s->warning( 'config-install-subscribe-notpossible' );
1747  }
1748  }
1749 
1756  protected function createMainpage( DatabaseInstaller $installer ) {
1759  if ( $title->exists() ) {
1760  $status->warning( 'config-install-mainpage-exists' );
1761  return $status;
1762  }
1763  try {
1764  $page = WikiPage::factory( $title );
1765  $content = new WikitextContent(
1766  wfMessage( 'mainpagetext' )->inContentLanguage()->text() . "\n\n" .
1767  wfMessage( 'mainpagedocfooter' )->inContentLanguage()->text()
1768  );
1769 
1770  $status = $page->doEditContent( $content,
1771  '',
1772  EDIT_NEW,
1773  false,
1774  User::newFromName( 'MediaWiki default' )
1775  );
1776  } catch ( Exception $e ) {
1777  // using raw, because $wgShowExceptionDetails can not be set yet
1778  $status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
1779  }
1780 
1781  return $status;
1782  }
1783 
1787  public static function overrideConfig() {
1788  // Use PHP's built-in session handling, since MediaWiki's
1789  // SessionHandler can't work before we have an object cache set up.
1790  if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
1791  define( 'MW_NO_SESSION_HANDLER', 1 );
1792  }
1793 
1794  // Don't access the database
1795  $GLOBALS['wgUseDatabaseMessages'] = false;
1796  // Don't cache langconv tables
1797  $GLOBALS['wgLanguageConverterCacheType'] = CACHE_NONE;
1798  // Debug-friendly
1799  $GLOBALS['wgShowExceptionDetails'] = true;
1800  $GLOBALS['wgShowHostnames'] = true;
1801  // Don't break forms
1802  $GLOBALS['wgExternalLinkTarget'] = '_blank';
1803 
1804  // Allow multiple ob_flush() calls
1805  $GLOBALS['wgDisableOutputCompression'] = true;
1806 
1807  // Use a sensible cookie prefix (not my_wiki)
1808  $GLOBALS['wgCookiePrefix'] = 'mw_installer';
1809 
1810  // Some of the environment checks make shell requests, remove limits
1811  $GLOBALS['wgMaxShellMemory'] = 0;
1812 
1813  // Override the default CookieSessionProvider with a dummy
1814  // implementation that won't stomp on PHP's cookies.
1815  $GLOBALS['wgSessionProviders'] = [
1816  [
1817  'class' => InstallerSessionProvider::class,
1818  'args' => [ [
1819  'priority' => 1,
1820  ] ]
1821  ]
1822  ];
1823 
1824  // Don't try to use any object cache for SessionManager either.
1825  $GLOBALS['wgSessionCacheType'] = CACHE_NONE;
1826 
1827  // Set a dummy $wgServer to bypass the check in Setup.php, the
1828  // web installer will automatically detect it and not use this value.
1829  $GLOBALS['wgServer'] = 'https://🌻.invalid';
1830  }
1831 
1839  public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
1840  $this->extraInstallSteps[$findStep][] = $callback;
1841  }
1842 
1847  protected function disableTimeLimit() {
1848  Wikimedia\suppressWarnings();
1849  set_time_limit( 0 );
1850  Wikimedia\restoreWarnings();
1851  }
1852 }
Installer\envCheckBrokenXML
envCheckBrokenXML()
Some versions of libxml+PHP break < and > encoding horribly.
Definition: Installer.php:801
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:42
MediaWiki\Shell\Shell
Executes shell commands.
Definition: Shell.php:44
Installer\__construct
__construct()
Constructor, always call this from child classes.
Definition: Installer.php:402
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:539
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:316
Language\clearCaches
static clearCaches()
Intended for tests that may change configuration in a way that invalidates caches.
Definition: Language.php:287
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
Installer\createMainpage
createMainpage(DatabaseInstaller $installer)
Insert Main Page with default content.
Definition: Installer.php:1756
Installer\parse
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
Definition: Installer.php:691
ExtensionDependencyError
Copyright (C) 2018 Kunal Mehta legoktm@member.fsf.org
Definition: ExtensionDependencyError.php:24
MultiConfig
Provides a fallback sequence for Config objects.
Definition: MultiConfig.php:28
$wgAutoloadClasses
$wgAutoloadClasses['ReplaceTextHooks']
Definition: ReplaceText.php:61
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:117
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
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:1193
CACHE_NONE
const CACHE_NONE
Definition: Defines.php:82
Installer\envCheckLibicu
envCheckLibicu()
Check the libicu version.
Definition: Installer.php:1127
ExtensionRegistry
ExtensionRegistry class.
Definition: ExtensionRegistry.php:18
CACHE_MEMCACHED
const CACHE_MEMCACHED
Definition: Defines.php:84
Installer\populateSiteStats
populateSiteStats(DatabaseInstaller $installer)
Install step which adds a row to the site_stats table with appropriate initial values.
Definition: Installer.php:732
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:239
DatabaseInstaller\getConnection
getConnection()
Connect to the database using the administrative user/password currently defined in the session.
Definition: DatabaseInstaller.php:182
Installer\$rightsProfiles
array $rightsProfiles
User rights profiles.
Definition: Installer.php:257
Installer\envCheckShellLocale
envCheckShellLocale()
Environment check for preferred locale in shell.
Definition: Installer.php:997
Installer\envCheckUploadsDirectory
envCheckUploadsDirectory()
Environment check for the permissions of the uploads directory.
Definition: Installer.php:1079
Installer\$settings
array $settings
Definition: Installer.php:59
Installer\envPrepServer
envPrepServer()
Environment prep for the server hostname.
Definition: Installer.php:1163
$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:1614
Installer\$mediaWikiAnnounceLanguages
$mediaWikiAnnounceLanguages
Supported language codes for Mailman.
Definition: Installer.php:325
PasswordError
Show an error when any operation involving passwords fails to run.
Definition: PasswordError.php:26
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:515
$wgHooks
$wgHooks['AdminLinks'][]
Definition: ReplaceText.php:58
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1264
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:185
Installer\$dbInstallers
array $dbInstallers
Cached DB installer instances, access using getDBInstaller().
Definition: Installer.php:73
Installer\setParserLanguage
setParserLanguage( $lang)
ParserOptions are constructed before we determined the language, so fix it.
Definition: Installer.php:1259
Title\newMainPage
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:649
Installer\addInstallStep
addInstallStep( $callback, $findStep='BEGINNING')
Add an installation step following the given step.
Definition: Installer.php:1839
Installer\$internalDefaults
array $internalDefaults
Variables that are stored alongside globals, and are used for any configuration of the installation p...
Definition: Installer.php:195
$res
$res
Definition: testCompression.php:52
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:644
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:528
Installer\$parserTitle
Title $parserTitle
Cached Title, used by parse().
Definition: Installer.php:87
Installer\$objectCaches
array $objectCaches
Known object cache types and the functions used to test for their existence.
Definition: Installer.php:246
$wgMemc
$wgMemc
Definition: Setup.php:791
Installer\$minMemorySize
int $minMemorySize
Minimum memory size in MB.
Definition: Installer.php:80
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:40
Installer\overrideConfig
static overrideConfig()
Override the necessary bits of the config to run an installation.
Definition: Installer.php:1787
Installer\createSysop
createSysop()
Create the first user account, grant it sysop, bureaucrat and interface-admin rights.
Definition: Installer.php:1682
Installer\getFakePassword
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:633
Config
Interface for configuration instances.
Definition: Config.php:28
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:1098
Installer\envPrepPath
envPrepPath()
Environment prep for setting $IP and $wgScriptPath.
Definition: Installer.php:1179
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:142
Installer\envCheckDiff3
envCheckDiff3()
Search for GNU diff3.
Definition: Installer.php:900
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Installer\generateKeys
generateKeys()
Generate $wgSecretKey.
Definition: Installer.php:1651
Installer\envCheckMemory
envCheckMemory()
Environment check for available memory.
Definition: Installer.php:842
$wgLang
$wgLang
Definition: Setup.php:881
$IP
$IP
Definition: update.php:3
$wgObjectCaches
$wgObjectCaches
Advanced object cache configuration.
Definition: DefaultSettings.php:2393
Installer\getCompiledDBs
getCompiledDBs()
Get a list of DBs supported by current PHP setup.
Definition: Installer.php:551
ObjectCache\getInstance
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:80
$queue
$queue
Definition: mergeMessageFileList.php:157
Installer\envCheckCache
envCheckCache()
Environment check for compiled object cache types.
Definition: Installer.php:868
Installer\getExistingLocalSettings
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
Definition: Installer.php:593
Installer\envCheckPath
envCheckPath()
Environment check to inform user which paths we've assumed.
Definition: Installer.php:984
Installer\doGenerateKeys
doGenerateKeys( $keys)
Generate a secret value for variables using a secure generator.
Definition: Installer.php:1666
$lines
$lines
Definition: router.php:61
Installer\$parserOptions
ParserOptions $parserOptions
Cached ParserOptions, used by parse().
Definition: Installer.php:94
$title
$title
Definition: testCompression.php:34
SiteStatsUpdate\factory
static factory(array $deltas)
Definition: SiteStatsUpdate.php:71
GlobalVarConfig
Accesses configuration settings from $GLOBALS.
Definition: GlobalVarConfig.php:28
$wgExternalLinkTarget
$wgExternalLinkTarget
Set a default target for external links, e.g.
Definition: DefaultSettings.php:4276
Installer\$dbTypes
static array $dbTypes
Known database types.
Definition: Installer.php:105
Installer\getVar
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:542
WikitextContent
Content object for wiki text pages.
Definition: WikitextContent.php:36
Installer\restoreLinkPopups
restoreLinkPopups()
Definition: Installer.php:719
Installer\getDefaultSkin
getDefaultSkin(array $skinNames)
Returns a default value to be used for $wgDefaultSkin: normally the one set in DefaultSettings,...
Definition: Installer.php:1482
Installer\findExtensions
findExtensions( $directory='extensions')
Find extensions or skins in a subdirectory of $IP.
Definition: Installer.php:1282
Installer\getInstallerConfig
static getInstallerConfig(Config $baseConfig)
Constructs a Config object that contains configuration settings that should be overwritten for the in...
Definition: Installer.php:364
$line
$line
Definition: cdb.php:59
$content
$content
Definition: router.php:78
Installer\$envPreps
array $envPreps
A list of environment preparation methods called by doEnvironmentPreps().
Definition: Installer.php:146
$wgExtensionDirectory
$wgExtensionDirectory
Filesystem extensions directory.
Definition: DefaultSettings.php:229
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
Installer\$installSteps
array $installSteps
The actual list of installation steps.
Definition: Installer.php:232
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:1907
Installer\doEnvironmentPreps
doEnvironmentPreps()
Definition: Installer.php:516
Installer\readExtension
readExtension( $fullJsonFile, $extDeps=[], $skinDeps=[])
Definition: Installer.php:1398
CACHE_ANYTHING
const CACHE_ANYTHING
Definition: Defines.php:81
Installer\getDBInstaller
getDBInstaller( $type=false)
Get an instance of DatabaseInstaller for the specified DB type.
Definition: Installer.php:573
DatabaseInstaller
Base class for DBMS-specific installation helper classes.
Definition: DatabaseInstaller.php:37
Installer\envCheckDB
envCheckDB()
Environment check for DB types.
Definition: Installer.php:759
Installer\getInstallSteps
getInstallSteps(DatabaseInstaller $installer)
Get an array of install steps.
Definition: Installer.php:1560
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:431
Installer\$compiledDBs
array $compiledDBs
List of detected DBs, access using getCompiledDBs().
Definition: Installer.php:66
Installer\doEnvironmentChecks
doEnvironmentChecks()
Do initial checks of the PHP environment.
Definition: Installer.php:487
EDIT_NEW
const EDIT_NEW
Definition: Defines.php:132
Installer\envCheckGraphics
envCheckGraphics()
Environment check for ImageMagick and GD.
Definition: Installer.php:923
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:2817
Installer\apacheModulePresent
static apacheModulePresent( $moduleName)
Checks for presence of an Apache module.
Definition: Installer.php:1242
PhpXmlBugTester
Test for PHP+libxml2 bug which breaks XML input subtly with certain versions.
Definition: PhpXmlBugTester.php:32
Title
Represents a title within MediaWiki.
Definition: Title.php:42
$status
return $status
Definition: SyntaxHighlight.php:347
Installer\envCheckPCRE
envCheckPCRE()
Environment check for the PCRE module.
Definition: Installer.php:820
Installer\getParserOptions
getParserOptions()
Definition: Installer.php:711
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:175
$path
$path
Definition: NoLocalSettings.php:25
Installer\envCheck64Bit
envCheck64Bit()
Checks if we're running on 64 bit or not.
Definition: Installer.php:1116
Installer\$licenses
array $licenses
License types.
Definition: Installer.php:282
Installer\disableTimeLimit
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:1847
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:67
$source
$source
Definition: mwdoc-filter.php:34
Installer\envCheckServer
envCheckServer()
Environment check to inform user which server we've assumed.
Definition: Installer.php:971
Installer
Base installer class.
Definition: Installer.php:46
$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:54
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:217
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:1302
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:470
Installer\disableLinkPopups
disableLinkPopups()
Definition: Installer.php:715
Installer\$mediaWikiAnnounceUrl
$mediaWikiAnnounceUrl
URL to mediawiki-announce subscription.
Definition: Installer.php:319
wfIsHHVM
wfIsHHVM()
Check if we are running under HHVM.
Definition: GlobalFunctions.php:1921
Installer\includeExtensions
includeExtensions()
Installs the auto-detected extensions.
Definition: Installer.php:1497
$wgStyleDirectory
$wgStyleDirectory
Filesystem stylesheets directory.
Definition: DefaultSettings.php:236
Installer\envCheckGit
envCheckGit()
Search for git.
Definition: Installer.php:949
Installer\getDocUrl
getDocUrl( $page)
Overridden by WebInstaller to provide lastPage parameters.
Definition: Installer.php:1269
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6
Installer\subscribeToMediaWikiAnnounce
subscribeToMediaWikiAnnounce(Status $s)
Definition: Installer.php:1724
CACHE_DB
const CACHE_DB
Definition: Defines.php:83
MWHttpRequest\factory
static factory( $url, array $options=null, $caller=__METHOD__)
Generate a new request object.
Definition: MWHttpRequest.php:189
Installer\maybeGetWebserverPrimaryGroup
static maybeGetWebserverPrimaryGroup()
On POSIX systems return the primary group of the webserver we're running under.
Definition: Installer.php:661
Installer\getExtensionInfo
getExtensionInfo( $type, $parentRelPath, $name)
Definition: Installer.php:1345
Installer\$defaultVarNames
array $defaultVarNames
MediaWiki configuration globals that will eventually be passed through to LocalSettings....
Definition: Installer.php:158
Installer\getDBInstallerClass
static getDBInstallerClass( $type)
Get the DatabaseInstaller class name for this type.
Definition: Installer.php:562
Installer\$envChecks
array $envChecks
A list of environment check methods called by doEnvironmentChecks().
Definition: Installer.php:122
$type
$type
Definition: testCompression.php:48
Installer\envCheckModSecurity
envCheckModSecurity()
Scare user to death if they have mod_security or mod_security2.
Definition: Installer.php:887