MediaWiki  master
Installer.php
Go to the documentation of this file.
1 <?php
31 
53 abstract class Installer {
54 
61  public const MINIMUM_PCRE_VERSION = '7.2';
62 
66  protected $settings;
67 
73  protected $compiledDBs;
74 
80  protected $dbInstallers = [];
81 
87  protected $minMemorySize = 50;
88 
94  protected $parserTitle;
95 
101  protected $parserOptions;
102 
107 
119  protected $envChecks = [
120  'envCheckDB',
121  'envCheckPCRE',
122  'envCheckMemory',
123  'envCheckCache',
124  'envCheckModSecurity',
125  'envCheckDiff3',
126  'envCheckGraphics',
127  'envCheckGit',
128  'envCheckServer',
129  'envCheckPath',
130  'envCheckShellLocale',
131  'envCheckUploadsDirectory',
132  'envCheckLibicu',
133  'envCheckSuhosinMaxValueLength',
134  'envCheck64Bit',
135  ];
136 
142  protected $envPreps = [
143  'envPrepServer',
144  'envPrepPath',
145  ];
146 
154  protected $defaultVarNames = [
155  'wgSitename',
156  'wgPasswordSender',
157  'wgLanguageCode',
158  'wgRightsIcon',
159  'wgRightsText',
160  'wgRightsUrl',
161  'wgEnableEmail',
162  'wgEnableUserEmail',
163  'wgEnotifUserTalk',
164  'wgEnotifWatchlist',
165  'wgEmailAuthentication',
166  'wgDBname',
167  'wgDBtype',
168  'wgDiff3',
169  'wgImageMagickConvertCommand',
170  'wgGitBin',
171  'IP',
172  'wgScriptPath',
173  'wgMetaNamespace',
174  'wgDeletedDirectory',
175  'wgEnableUploads',
176  'wgShellLocale',
177  'wgSecretKey',
178  'wgUseInstantCommons',
179  'wgUpgradeKey',
180  'wgDefaultSkin',
181  'wgPingback',
182  ];
183 
191  protected $internalDefaults = [
192  '_UserLang' => 'en',
193  '_Environment' => false,
194  '_RaiseMemory' => false,
195  '_UpgradeDone' => false,
196  '_InstallDone' => false,
197  '_Caches' => [],
198  '_InstallPassword' => '',
199  '_SameAccount' => true,
200  '_CreateDBAccount' => false,
201  '_NamespaceType' => 'site-name',
202  '_AdminName' => '', // will be set later, when the user selects language
203  '_AdminPassword' => '',
204  '_AdminPasswordConfirm' => '',
205  '_AdminEmail' => '',
206  '_Subscribe' => false,
207  '_SkipOptional' => 'continue',
208  '_RightsProfile' => 'wiki',
209  '_LicenseCode' => 'none',
210  '_CCDone' => false,
211  '_Extensions' => [],
212  '_Skins' => [],
213  '_MemCachedServers' => '',
214  '_UpgradeKeySupplied' => false,
215  '_ExistingDBSettings' => false,
216 
217  // $wgLogo is probably wrong (T50084); set something that will work.
218  // Single quotes work fine here, as LocalSettingsGenerator outputs this unescaped.
219  'wgLogo' => '$wgResourceBasePath/resources/assets/wiki.png',
220  'wgAuthenticationTokenVersion' => 1,
221  ];
222 
229  private $installSteps = [];
230 
236  protected $extraInstallSteps = [];
237 
243  protected $objectCaches = [
244  'apcu' => 'apcu_fetch',
245  'wincache' => 'wincache_ucache_get'
246  ];
247 
253  public $rightsProfiles = [
254  'wiki' => [],
255  'no-anon' => [
256  '*' => [ 'edit' => false ]
257  ],
258  'fishbowl' => [
259  '*' => [
260  'createaccount' => false,
261  'edit' => false,
262  ],
263  ],
264  'private' => [
265  '*' => [
266  'createaccount' => false,
267  'edit' => false,
268  'read' => false,
269  ],
270  ],
271  ];
272 
278  public $licenses = [
279  'cc-by' => [
280  'url' => 'https://creativecommons.org/licenses/by/4.0/',
281  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by.png',
282  ],
283  'cc-by-sa' => [
284  'url' => 'https://creativecommons.org/licenses/by-sa/4.0/',
285  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-sa.png',
286  ],
287  'cc-by-nc-sa' => [
288  'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/',
289  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png',
290  ],
291  'cc-0' => [
292  'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
293  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-0.png',
294  ],
295  'gfdl' => [
296  'url' => 'https://www.gnu.org/copyleft/fdl.html',
297  'icon' => '$wgResourceBasePath/resources/assets/licenses/gnu-fdl.png',
298  ],
299  'none' => [
300  'url' => '',
301  'icon' => '',
302  'text' => ''
303  ],
304  'cc-choose' => [
305  // Details will be filled in by the selector.
306  'url' => '',
307  'icon' => '',
308  'text' => '',
309  ],
310  ];
311 
316  'https://lists.wikimedia.org/mailman/subscribe/mediawiki-announce';
317 
322  'ca', 'cs', 'da', 'de', 'en', 'es', 'et', 'eu', 'fi', 'fr', 'hr', 'hu',
323  'it', 'ja', 'ko', 'lt', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru',
324  'sl', 'sr', 'sv', 'tr', 'uk'
325  ];
326 
335  abstract public function showMessage( $msg, ...$params );
336 
342  abstract public function showError( $msg, ...$params );
343 
348  abstract public function showStatusMessage( Status $status );
349 
360  public static function getInstallerConfig( Config $baseConfig ) {
361  $configOverrides = new HashConfig();
362 
363  // disable (problematic) object cache types explicitly, preserving all other (working) ones
364  // bug T113843
365  $emptyCache = [ 'class' => EmptyBagOStuff::class ];
366 
367  $objectCaches = [
368  CACHE_NONE => $emptyCache,
369  CACHE_DB => $emptyCache,
370  CACHE_ANYTHING => $emptyCache,
371  CACHE_MEMCACHED => $emptyCache,
372  ] + $baseConfig->get( 'ObjectCaches' );
373 
374  $configOverrides->set( 'ObjectCaches', $objectCaches );
375 
376  // Load the installer's i18n.
377  $messageDirs = $baseConfig->get( 'MessagesDirs' );
378  $messageDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
379 
380  $configOverrides->set( 'MessagesDirs', $messageDirs );
381 
382  $installerConfig = new MultiConfig( [ $configOverrides, $baseConfig ] );
383 
384  // make sure we use the installer config as the main config
385  $configRegistry = $baseConfig->get( 'ConfigRegistry' );
386  $configRegistry['main'] = function () use ( $installerConfig ) {
387  return $installerConfig;
388  };
389 
390  $configOverrides->set( 'ConfigRegistry', $configRegistry );
391 
392  return $installerConfig;
393  }
394 
398  public function __construct() {
399  global $wgMemc, $wgUser, $wgObjectCaches;
400  $defaultConfig = new GlobalVarConfig(); // all the stuff from DefaultSettings.php
401  $installerConfig = self::getInstallerConfig( $defaultConfig );
402 
403  // Reset all services and inject config overrides
404  MediaWikiServices::resetGlobalInstance( $installerConfig );
405 
406  // Don't attempt to load user language options (T126177)
407  // This will be overridden in the web installer with the user-specified language
408  RequestContext::getMain()->setLanguage( 'en' );
409 
410  // Disable all global services, since we don't have any configuration yet!
411  MediaWikiServices::disableStorageBackend();
412 
413  $mwServices = MediaWikiServices::getInstance();
414 
415  // Disable i18n cache
416  $mwServices->getLocalisationCache()->disableBackend();
417 
418  // Clear language cache so the old i18n cache doesn't sneak back in
420 
421  // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and
422  // SqlBagOStuff will then throw since we just disabled wfGetDB)
423  $wgObjectCaches = $mwServices->getMainConfig()->get( 'ObjectCaches' );
425 
426  // Disable interwiki lookup, to avoid database access during parses
427  $mwServices->redefineService( 'InterwikiLookup', function () {
428  return new NullInterwikiLookup();
429  } );
430  // Disable user options database fetching, only rely on default options.
431  $mwServices->redefineService(
432  'UserOptionsLookup',
433  function ( MediaWikiServices $services ) {
434  return $services->get( '_DefaultOptionsLookup' );
435  }
436  );
437 
438  $user = User::newFromId( 0 );
439  $wgUser = $user;
440  RequestContext::getMain()->setUser( $user );
441 
442  $this->settings = $this->internalDefaults;
443 
444  foreach ( $this->defaultVarNames as $var ) {
445  $this->settings[$var] = $GLOBALS[$var];
446  }
447 
448  $this->doEnvironmentPreps();
449 
450  $this->compiledDBs = [];
451  $this->installerDbSupport = InstallerDBSupport::getInstance();
452 
453  foreach ( $this->installerDbSupport->getDatabases() as $type ) {
454  $installer = $this->getDBInstaller( $type );
455 
456  if ( !$installer->isCompiled() ) {
457  continue;
458  }
459  $this->compiledDBs[] = $type;
460  }
461 
462  $this->parserTitle = Title::newFromText( 'Installer' );
463  $this->parserOptions = new ParserOptions( $user ); // language will be wrong :(
464  // Don't try to access DB before user language is initialised
465  $this->setParserLanguage( $mwServices->getLanguageFactory()->getLanguage( 'en' ) );
466  }
467 
474  public static function getDBTypes() {
475  wfDeprecated( __METHOD__, '1.35' );
476  return InstallerDBSupport::getInstance()->getDatabases();
477  }
478 
492  public function doEnvironmentChecks() {
493  // PHP version has already been checked by entry scripts
494  // Show message here for information purposes
495  $this->showMessage( 'config-env-php', PHP_VERSION );
496 
497  $good = true;
498  // Must go here because an old version of PCRE can prevent other checks from completing
499  $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
500  if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
501  $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
502  $good = false;
503  } else {
504  foreach ( $this->envChecks as $check ) {
505  $status = $this->$check();
506  if ( $status === false ) {
507  $good = false;
508  }
509  }
510  }
511 
512  $this->setVar( '_Environment', $good );
513 
514  return $good ? Status::newGood() : Status::newFatal( 'config-env-bad' );
515  }
516 
517  public function doEnvironmentPreps() {
518  foreach ( $this->envPreps as $prep ) {
519  $this->$prep();
520  }
521  }
522 
529  public function setVar( $name, $value ) {
530  $this->settings[$name] = $value;
531  }
532 
543  public function getVar( $name, $default = null ) {
544  return $this->settings[$name] ?? $default;
545  }
546 
552  public function getCompiledDBs() {
553  return $this->compiledDBs;
554  }
555 
564  public static function getDBInstallerClass( $type ) {
565  wfDeprecated( __METHOD__, '1.35' );
566 
567  return InstallerDBSupport::getInstance()->getDBInstallerClass( $type );
568  }
569 
577  public function getDBInstaller( $type = false ) {
578  if ( !$type ) {
579  $type = $this->getVar( 'wgDBtype' );
580  }
581 
582  if ( !isset( $this->dbInstallers[$type] ) ) {
583  $class = $this->installerDbSupport->getDBInstallerClass( $type );
584  $this->dbInstallers[$type] = new $class( $this );
585  }
586 
587  return $this->dbInstallers[$type];
588  }
589 
595  public static function getExistingLocalSettings() {
596  global $IP;
597 
598  // You might be wondering why this is here. Well if you don't do this
599  // then some poorly-formed extensions try to call their own classes
600  // after immediately registering them. We really need to get extension
601  // registration out of the global scope and into a real format.
602  // @see https://phabricator.wikimedia.org/T69440
603  global $wgAutoloadClasses;
604  $wgAutoloadClasses = [];
605 
606  // LocalSettings.php should not call functions, except wfLoadSkin/wfLoadExtensions
607  // Define the required globals here, to ensure, the functions can do it work correctly.
608  // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
610 
611  Wikimedia\suppressWarnings();
612  $_lsExists = file_exists( "$IP/LocalSettings.php" );
613  Wikimedia\restoreWarnings();
614 
615  if ( !$_lsExists ) {
616  return false;
617  }
618  unset( $_lsExists );
619 
620  require "$IP/includes/DefaultSettings.php";
621  require "$IP/LocalSettings.php";
622 
623  return get_defined_vars();
624  }
625 
635  public function getFakePassword( $realPassword ) {
636  return str_repeat( '*', strlen( $realPassword ) );
637  }
638 
646  public function setPassword( $name, $value ) {
647  if ( !preg_match( '/^\*+$/', $value ) ) {
648  $this->setVar( $name, $value );
649  }
650  }
651 
663  public static function maybeGetWebserverPrimaryGroup() {
664  if ( !function_exists( 'posix_getegid' ) || !function_exists( 'posix_getpwuid' ) ) {
665  # I don't know this, this isn't UNIX.
666  return null;
667  }
668 
669  # posix_getegid() *not* getmygid() because we want the group of the webserver,
670  # not whoever owns the current script.
671  $gid = posix_getegid();
672  return posix_getpwuid( $gid )['name'] ?? null;
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 ( $this->installerDbSupport->getDatabases() 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 
805  protected function envCheckPCRE() {
806  Wikimedia\suppressWarnings();
807  $regexd = preg_replace( '/[\x{0430}-\x{04FF}]/iu', '', '-АБВГД-' );
808  // Need to check for \p support too, as PCRE can be compiled
809  // with utf8 support, but not unicode property support.
810  // check that \p{Zs} (space separators) matches
811  // U+3000 (Ideographic space)
812  $regexprop = preg_replace( '/\p{Zs}/u', '', "-\u{3000}-" );
813  Wikimedia\restoreWarnings();
814  if ( $regexd != '--' || $regexprop != '--' ) {
815  $this->showError( 'config-pcre-no-utf8' );
816 
817  return false;
818  }
819 
820  return true;
821  }
822 
827  protected function envCheckMemory() {
828  $limit = ini_get( 'memory_limit' );
829 
830  if ( !$limit || $limit == -1 ) {
831  return true;
832  }
833 
834  $n = wfShorthandToInteger( $limit );
835 
836  if ( $n < $this->minMemorySize * 1024 * 1024 ) {
837  $newLimit = "{$this->minMemorySize}M";
838 
839  if ( ini_set( "memory_limit", $newLimit ) === false ) {
840  $this->showMessage( 'config-memory-bad', $limit );
841  } else {
842  $this->showMessage( 'config-memory-raised', $limit, $newLimit );
843  $this->setVar( '_RaiseMemory', true );
844  }
845  }
846 
847  return true;
848  }
849 
853  protected function envCheckCache() {
854  $caches = [];
855  foreach ( $this->objectCaches as $name => $function ) {
856  if ( function_exists( $function ) ) {
857  $caches[$name] = true;
858  }
859  }
860 
861  if ( !$caches ) {
862  $this->showMessage( 'config-no-cache-apcu' );
863  }
864 
865  $this->setVar( '_Caches', $caches );
866  }
867 
872  protected function envCheckModSecurity() {
873  if ( self::apacheModulePresent( 'mod_security' )
874  || self::apacheModulePresent( 'mod_security2' ) ) {
875  $this->showMessage( 'config-mod-security' );
876  }
877 
878  return true;
879  }
880 
885  protected function envCheckDiff3() {
886  $names = [ "gdiff3", "diff3" ];
887  if ( wfIsWindows() ) {
888  $names[] = 'diff3.exe';
889  }
890  $versionInfo = [ '--version', 'GNU diffutils' ];
891 
892  $diff3 = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
893 
894  if ( $diff3 ) {
895  $this->setVar( 'wgDiff3', $diff3 );
896  } else {
897  $this->setVar( 'wgDiff3', false );
898  $this->showMessage( 'config-diff3-bad' );
899  }
900 
901  return true;
902  }
903 
908  protected function envCheckGraphics() {
909  $names = wfIsWindows() ? 'convert.exe' : 'convert';
910  $versionInfo = [ '-version', 'ImageMagick' ];
911  $convert = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
912 
913  $this->setVar( 'wgImageMagickConvertCommand', '' );
914  if ( $convert ) {
915  $this->setVar( 'wgImageMagickConvertCommand', $convert );
916  $this->showMessage( 'config-imagemagick', $convert );
917 
918  return true;
919  } elseif ( function_exists( 'imagejpeg' ) ) {
920  $this->showMessage( 'config-gd' );
921  } else {
922  $this->showMessage( 'config-no-scaling' );
923  }
924 
925  return true;
926  }
927 
934  protected function envCheckGit() {
935  $names = wfIsWindows() ? 'git.exe' : 'git';
936  $versionInfo = [ '--version', 'git version' ];
937 
938  $git = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
939 
940  if ( $git ) {
941  $this->setVar( 'wgGitBin', $git );
942  $this->showMessage( 'config-git', $git );
943  } else {
944  $this->setVar( 'wgGitBin', false );
945  $this->showMessage( 'config-git-bad' );
946  }
947 
948  return true;
949  }
950 
956  protected function envCheckServer() {
957  $server = $this->envGetDefaultServer();
958  if ( $server !== null ) {
959  $this->showMessage( 'config-using-server', $server );
960  }
961  return true;
962  }
963 
969  protected function envCheckPath() {
970  $this->showMessage(
971  'config-using-uri',
972  $this->getVar( 'wgServer' ),
973  $this->getVar( 'wgScriptPath' )
974  );
975  return true;
976  }
977 
982  protected function envCheckShellLocale() {
983  $os = php_uname( 's' );
984  $supported = [ 'Linux', 'SunOS', 'HP-UX', 'Darwin' ]; # Tested these
985 
986  if ( !in_array( $os, $supported ) ) {
987  return true;
988  }
989 
990  if ( Shell::isDisabled() ) {
991  return true;
992  }
993 
994  # Get a list of available locales.
995  $result = Shell::command( '/usr/bin/locale', '-a' )
996  ->execute();
997 
998  if ( $result->getExitCode() != 0 ) {
999  return true;
1000  }
1001 
1002  $lines = $result->getStdout();
1003  $lines = array_map( 'trim', explode( "\n", $lines ) );
1004  $candidatesByLocale = [];
1005  $candidatesByLang = [];
1006  foreach ( $lines as $line ) {
1007  if ( $line === '' ) {
1008  continue;
1009  }
1010 
1011  if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
1012  continue;
1013  }
1014 
1015  list( , $lang, , , ) = $m;
1016 
1017  $candidatesByLocale[$m[0]] = $m;
1018  $candidatesByLang[$lang][] = $m;
1019  }
1020 
1021  # Try the current value of LANG.
1022  if ( isset( $candidatesByLocale[getenv( 'LANG' )] ) ) {
1023  $this->setVar( 'wgShellLocale', getenv( 'LANG' ) );
1024 
1025  return true;
1026  }
1027 
1028  # Try the most common ones.
1029  $commonLocales = [ 'C.UTF-8', 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' ];
1030  foreach ( $commonLocales as $commonLocale ) {
1031  if ( isset( $candidatesByLocale[$commonLocale] ) ) {
1032  $this->setVar( 'wgShellLocale', $commonLocale );
1033 
1034  return true;
1035  }
1036  }
1037 
1038  # Is there an available locale in the Wiki's language?
1039  $wikiLang = $this->getVar( 'wgLanguageCode' );
1040 
1041  if ( isset( $candidatesByLang[$wikiLang] ) ) {
1042  $m = reset( $candidatesByLang[$wikiLang] );
1043  $this->setVar( 'wgShellLocale', $m[0] );
1044 
1045  return true;
1046  }
1047 
1048  # Are there any at all?
1049  if ( count( $candidatesByLocale ) ) {
1050  $m = reset( $candidatesByLocale );
1051  $this->setVar( 'wgShellLocale', $m[0] );
1052 
1053  return true;
1054  }
1055 
1056  # Give up.
1057  return true;
1058  }
1059 
1064  protected function envCheckUploadsDirectory() {
1065  global $IP;
1066 
1067  $dir = $IP . '/images/';
1068  $url = $this->getVar( 'wgServer' ) . $this->getVar( 'wgScriptPath' ) . '/images/';
1069  $safe = !$this->dirIsExecutable( $dir, $url );
1070 
1071  if ( !$safe ) {
1072  $this->showMessage( 'config-uploads-not-safe', $dir );
1073  }
1074 
1075  return true;
1076  }
1077 
1083  protected function envCheckSuhosinMaxValueLength() {
1084  $currentValue = ini_get( 'suhosin.get.max_value_length' );
1085  $minRequired = 2000;
1086  $recommended = 5000;
1087  if ( $currentValue > 0 && $currentValue < $minRequired ) {
1088  $this->showError( 'config-suhosin-max-value-length', $currentValue, $minRequired, $recommended );
1089  return false;
1090  }
1091 
1092  return true;
1093  }
1094 
1101  protected function envCheck64Bit() {
1102  if ( PHP_INT_SIZE == 4 ) {
1103  $this->showMessage( 'config-using-32bit' );
1104  }
1105 
1106  return true;
1107  }
1108 
1112  protected function envCheckLibicu() {
1120  $not_normal_c = "\u{FA6C}";
1121  $normal_c = "\u{242EE}";
1122 
1123  $useNormalizer = 'php';
1124  $needsUpdate = false;
1125 
1126  if ( function_exists( 'normalizer_normalize' ) ) {
1127  $useNormalizer = 'intl';
1128  $intl = normalizer_normalize( $not_normal_c, Normalizer::FORM_C );
1129  if ( $intl !== $normal_c ) {
1130  $needsUpdate = true;
1131  }
1132  }
1133 
1134  // Uses messages 'config-unicode-using-php' and 'config-unicode-using-intl'
1135  if ( $useNormalizer === 'php' ) {
1136  $this->showMessage( 'config-unicode-pure-php-warning' );
1137  } else {
1138  $this->showMessage( 'config-unicode-using-' . $useNormalizer );
1139  if ( $needsUpdate ) {
1140  $this->showMessage( 'config-unicode-update-warning' );
1141  }
1142  }
1143  }
1144 
1148  protected function envPrepServer() {
1149  $server = $this->envGetDefaultServer();
1150  if ( $server !== null ) {
1151  $this->setVar( 'wgServer', $server );
1152  }
1153  }
1154 
1159  abstract protected function envGetDefaultServer();
1160 
1164  protected function envPrepPath() {
1165  global $IP;
1166  $IP = dirname( dirname( __DIR__ ) );
1167  $this->setVar( 'IP', $IP );
1168  }
1169 
1178  public function dirIsExecutable( $dir, $url ) {
1179  $scriptTypes = [
1180  'php' => [
1181  "<?php echo 'exec';",
1182  "#!/var/env php\n<?php echo 'exec';",
1183  ],
1184  ];
1185 
1186  // it would be good to check other popular languages here, but it'll be slow.
1187 
1188  Wikimedia\suppressWarnings();
1189 
1190  foreach ( $scriptTypes as $ext => $contents ) {
1191  foreach ( $contents as $source ) {
1192  $file = 'exectest.' . $ext;
1193 
1194  if ( !file_put_contents( $dir . $file, $source ) ) {
1195  break;
1196  }
1197 
1198  try {
1199  $text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
1200  get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
1201  } catch ( Exception $e ) {
1202  // HttpRequestFactory::get can throw with allow_url_fopen = false and no curl
1203  // extension.
1204  $text = null;
1205  }
1206  unlink( $dir . $file );
1207 
1208  if ( $text == 'exec' ) {
1209  Wikimedia\restoreWarnings();
1210 
1211  return $ext;
1212  }
1213  }
1214  }
1215 
1216  Wikimedia\restoreWarnings();
1217 
1218  return false;
1219  }
1220 
1227  public static function apacheModulePresent( $moduleName ) {
1228  if ( function_exists( 'apache_get_modules' ) && in_array( $moduleName, apache_get_modules() ) ) {
1229  return true;
1230  }
1231  // try it the hard way
1232  ob_start();
1233  phpinfo( INFO_MODULES );
1234  $info = ob_get_clean();
1235 
1236  return strpos( $info, $moduleName ) !== false;
1237  }
1238 
1244  public function setParserLanguage( $lang ) {
1245  $this->parserOptions->setTargetLanguage( $lang );
1246  $this->parserOptions->setUserLang( $lang );
1247  }
1248 
1254  protected function getDocUrl( $page ) {
1255  return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
1256  }
1257 
1267  public function findExtensions( $directory = 'extensions' ) {
1268  switch ( $directory ) {
1269  case 'extensions':
1270  return $this->findExtensionsByType( 'extension', 'extensions' );
1271  case 'skins':
1272  return $this->findExtensionsByType( 'skin', 'skins' );
1273  default:
1274  throw new InvalidArgumentException( "Invalid extension type" );
1275  }
1276  }
1277 
1287  protected function findExtensionsByType( $type = 'extension', $directory = 'extensions' ) {
1288  if ( $this->getVar( 'IP' ) === null ) {
1289  return Status::newGood( [] );
1290  }
1291 
1292  $extDir = $this->getVar( 'IP' ) . '/' . $directory;
1293  if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
1294  return Status::newGood( [] );
1295  }
1296 
1297  $dh = opendir( $extDir );
1298  $exts = [];
1299  $status = new Status;
1300  while ( ( $file = readdir( $dh ) ) !== false ) {
1301  // skip non-dirs and hidden directories
1302  if ( !is_dir( "$extDir/$file" ) || $file[0] === '.' ) {
1303  continue;
1304  }
1305  $extStatus = $this->getExtensionInfo( $type, $directory, $file );
1306  if ( $extStatus->isOK() ) {
1307  $exts[$file] = $extStatus->value;
1308  } elseif ( $extStatus->hasMessage( 'config-extension-not-found' ) ) {
1309  // (T225512) The directory is not actually an extension. Downgrade to warning.
1310  $status->warning( 'config-extension-not-found', $file );
1311  } else {
1312  $status->merge( $extStatus );
1313  }
1314  }
1315  closedir( $dh );
1316  uksort( $exts, 'strnatcasecmp' );
1317 
1318  $status->value = $exts;
1319 
1320  return $status;
1321  }
1322 
1330  protected function getExtensionInfo( $type, $parentRelPath, $name ) {
1331  if ( $this->getVar( 'IP' ) === null ) {
1332  throw new Exception( 'Cannot find extensions since the IP variable is not yet set' );
1333  }
1334  if ( $type !== 'extension' && $type !== 'skin' ) {
1335  throw new InvalidArgumentException( "Invalid extension type" );
1336  }
1337  $absDir = $this->getVar( 'IP' ) . "/$parentRelPath/$name";
1338  $relDir = "../$parentRelPath/$name";
1339  if ( !is_dir( $absDir ) ) {
1340  return Status::newFatal( 'config-extension-not-found', $name );
1341  }
1342  $jsonFile = $type . '.json';
1343  $fullJsonFile = "$absDir/$jsonFile";
1344  $isJson = file_exists( $fullJsonFile );
1345  $isPhp = false;
1346  if ( !$isJson ) {
1347  // Only fallback to PHP file if JSON doesn't exist
1348  $fullPhpFile = "$absDir/$name.php";
1349  $isPhp = file_exists( $fullPhpFile );
1350  }
1351  if ( !$isJson && !$isPhp ) {
1352  return Status::newFatal( 'config-extension-not-found', $name );
1353  }
1354 
1355  // Extension exists. Now see if there are screenshots
1356  $info = [];
1357  if ( is_dir( "$absDir/screenshots" ) ) {
1358  $paths = glob( "$absDir/screenshots/*.png" );
1359  foreach ( $paths as $path ) {
1360  $info['screenshots'][] = str_replace( $absDir, $relDir, $path );
1361  }
1362  }
1363 
1364  if ( $isJson ) {
1365  $jsonStatus = $this->readExtension( $fullJsonFile );
1366  if ( !$jsonStatus->isOK() ) {
1367  return $jsonStatus;
1368  }
1369  $info += $jsonStatus->value;
1370  }
1371 
1372  return Status::newGood( $info );
1373  }
1374 
1383  private function readExtension( $fullJsonFile, $extDeps = [], $skinDeps = [] ) {
1384  $load = [
1385  $fullJsonFile => 1
1386  ];
1387  if ( $extDeps ) {
1388  $extDir = $this->getVar( 'IP' ) . '/extensions';
1389  foreach ( $extDeps as $dep ) {
1390  $fname = "$extDir/$dep/extension.json";
1391  if ( !file_exists( $fname ) ) {
1392  return Status::newFatal( 'config-extension-not-found', $dep );
1393  }
1394  $load[$fname] = 1;
1395  }
1396  }
1397  if ( $skinDeps ) {
1398  $skinDir = $this->getVar( 'IP' ) . '/skins';
1399  foreach ( $skinDeps as $dep ) {
1400  $fname = "$skinDir/$dep/skin.json";
1401  if ( !file_exists( $fname ) ) {
1402  return Status::newFatal( 'config-extension-not-found', $dep );
1403  }
1404  $load[$fname] = 1;
1405  }
1406  }
1407  $registry = new ExtensionRegistry();
1408  try {
1409  $info = $registry->readFromQueue( $load );
1410  } catch ( ExtensionDependencyError $e ) {
1411  if ( $e->incompatibleCore || $e->incompatibleSkins
1412  || $e->incompatibleExtensions
1413  ) {
1414  // If something is incompatible with a dependency, we have no real
1415  // option besides skipping it
1416  return Status::newFatal( 'config-extension-dependency',
1417  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1418  } elseif ( $e->missingExtensions || $e->missingSkins ) {
1419  // There's an extension missing in the dependency tree,
1420  // so add those to the dependency list and try again
1421  $status = $this->readExtension(
1422  $fullJsonFile,
1423  array_merge( $extDeps, $e->missingExtensions ),
1424  array_merge( $skinDeps, $e->missingSkins )
1425  );
1426  if ( !$status->isOK() && !$status->hasMessage( 'config-extension-dependency' ) ) {
1427  $status = Status::newFatal( 'config-extension-dependency',
1428  basename( dirname( $fullJsonFile ) ), $status->getMessage() );
1429  }
1430  return $status;
1431  }
1432  // Some other kind of dependency error?
1433  return Status::newFatal( 'config-extension-dependency',
1434  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1435  }
1436  $ret = [];
1437  // The order of credits will be the order of $load,
1438  // so the first extension is the one we want to load,
1439  // everything else is a dependency
1440  $i = 0;
1441  foreach ( $info['credits'] as $name => $credit ) {
1442  $i++;
1443  if ( $i == 1 ) {
1444  // Extension we want to load
1445  continue;
1446  }
1447  $type = basename( $credit['path'] ) === 'skin.json' ? 'skins' : 'extensions';
1448  $ret['requires'][$type][] = $credit['name'];
1449  }
1450  $credits = array_values( $info['credits'] )[0];
1451  if ( isset( $credits['url'] ) ) {
1452  $ret['url'] = $credits['url'];
1453  }
1454  $ret['type'] = $credits['type'];
1455 
1456  return Status::newGood( $ret );
1457  }
1458 
1467  public function getDefaultSkin( array $skinNames ) {
1468  $defaultSkin = $GLOBALS['wgDefaultSkin'];
1469  if ( !$skinNames || in_array( $defaultSkin, $skinNames ) ) {
1470  return $defaultSkin;
1471  } else {
1472  return $skinNames[0];
1473  }
1474  }
1475 
1482  protected function includeExtensions() {
1483  global $IP;
1484  $exts = $this->getVar( '_Extensions' );
1485  $IP = $this->getVar( 'IP' );
1486 
1487  // Marker for DatabaseUpdater::loadExtensions so we don't
1488  // double load extensions
1489  define( 'MW_EXTENSIONS_LOADED', true );
1490 
1499  global $wgAutoloadClasses;
1500  $wgAutoloadClasses = [];
1501  $queue = [];
1502 
1503  require "$IP/includes/DefaultSettings.php";
1504 
1505  foreach ( $exts as $e ) {
1506  if ( file_exists( "$IP/extensions/$e/extension.json" ) ) {
1507  $queue["$IP/extensions/$e/extension.json"] = 1;
1508  } else {
1509  require_once "$IP/extensions/$e/$e.php";
1510  }
1511  }
1512 
1513  $registry = new ExtensionRegistry();
1514  $data = $registry->readFromQueue( $queue );
1515  $wgAutoloadClasses += $data['globals']['wgAutoloadClasses'];
1516 
1517  // @phan-suppress-next-line PhanUndeclaredVariable,PhanCoalescingAlwaysNull $wgHooks is set by DefaultSettings
1518  $hooksWeWant = $wgHooks['LoadExtensionSchemaUpdates'] ?? [];
1519 
1520  if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
1521  $hooksWeWant = array_merge_recursive(
1522  $hooksWeWant,
1523  $data['globals']['wgHooks']['LoadExtensionSchemaUpdates']
1524  );
1525  }
1526  // Unset everyone else's hooks. Lord knows what someone might be doing
1527  // in ParserFirstCallInit (see T29171)
1528  $GLOBALS['wgHooks'] = [ 'LoadExtensionSchemaUpdates' => $hooksWeWant ];
1529 
1530  return Status::newGood();
1531  }
1532 
1546  protected function getInstallSteps( DatabaseInstaller $installer ) {
1547  $coreInstallSteps = [
1548  [ 'name' => 'database', 'callback' => [ $installer, 'setupDatabase' ] ],
1549  [ 'name' => 'tables', 'callback' => [ $installer, 'createTables' ] ],
1550  [ 'name' => 'tables-manual', 'callback' => [ $installer, 'createManualTables' ] ],
1551  [ 'name' => 'interwiki', 'callback' => [ $installer, 'populateInterwikiTable' ] ],
1552  [ 'name' => 'stats', 'callback' => [ $this, 'populateSiteStats' ] ],
1553  [ 'name' => 'keys', 'callback' => [ $this, 'generateKeys' ] ],
1554  [ 'name' => 'updates', 'callback' => [ $installer, 'insertUpdateKeys' ] ],
1555  [ 'name' => 'restore-services', 'callback' => [ $this, 'restoreServices' ] ],
1556  [ 'name' => 'sysop', 'callback' => [ $this, 'createSysop' ] ],
1557  [ 'name' => 'mainpage', 'callback' => [ $this, 'createMainpage' ] ],
1558  ];
1559 
1560  // Build the array of install steps starting from the core install list,
1561  // then adding any callbacks that wanted to attach after a given step
1562  foreach ( $coreInstallSteps as $step ) {
1563  $this->installSteps[] = $step;
1564  if ( isset( $this->extraInstallSteps[$step['name']] ) ) {
1565  $this->installSteps = array_merge(
1566  $this->installSteps,
1567  $this->extraInstallSteps[$step['name']]
1568  );
1569  }
1570  }
1571 
1572  // Prepend any steps that want to be at the beginning
1573  if ( isset( $this->extraInstallSteps['BEGINNING'] ) ) {
1574  $this->installSteps = array_merge(
1575  $this->extraInstallSteps['BEGINNING'],
1576  $this->installSteps
1577  );
1578  }
1579 
1580  // Extensions should always go first, chance to tie into hooks and such
1581  if ( count( $this->getVar( '_Extensions' ) ) ) {
1582  array_unshift( $this->installSteps,
1583  [ 'name' => 'extensions', 'callback' => [ $this, 'includeExtensions' ] ]
1584  );
1585  $this->installSteps[] = [
1586  'name' => 'extension-tables',
1587  'callback' => [ $installer, 'createExtensionTables' ]
1588  ];
1589  }
1590 
1591  return $this->installSteps;
1592  }
1593 
1602  public function performInstallation( $startCB, $endCB ) {
1603  $installResults = [];
1604  $installer = $this->getDBInstaller();
1605  $installer->preInstall();
1606  $steps = $this->getInstallSteps( $installer );
1607  foreach ( $steps as $stepObj ) {
1608  $name = $stepObj['name'];
1609  call_user_func_array( $startCB, [ $name ] );
1610 
1611  // Perform the callback step
1612  $status = call_user_func( $stepObj['callback'], $installer );
1613 
1614  // Output and save the results
1615  call_user_func( $endCB, $name, $status );
1616  $installResults[$name] = $status;
1617 
1618  // If we've hit some sort of fatal, we need to bail.
1619  // Callback already had a chance to do output above.
1620  if ( !$status->isOK() ) {
1621  break;
1622  }
1623  }
1624  if ( $status->isOK() ) {
1625  $this->showMessage(
1626  'config-install-db-success'
1627  );
1628  $this->setVar( '_InstallDone', true );
1629  }
1630 
1631  return $installResults;
1632  }
1633 
1639  public function generateKeys() {
1640  $keys = [ 'wgSecretKey' => 64 ];
1641  if ( strval( $this->getVar( 'wgUpgradeKey' ) ) === '' ) {
1642  $keys['wgUpgradeKey'] = 16;
1643  }
1644 
1645  return $this->doGenerateKeys( $keys );
1646  }
1647 
1652  public function restoreServices() {
1653  MediaWikiServices::resetGlobalInstance();
1654  MediaWikiServices::getInstance()->redefineService(
1655  'UserOptionsLookup',
1656  function ( MediaWikiServices $services ) {
1657  return $services->get( 'UserOptionsManager' );
1658  }
1659  );
1660  return Status::newGood();
1661  }
1662 
1669  protected function doGenerateKeys( $keys ) {
1670  $status = Status::newGood();
1671 
1672  foreach ( $keys as $name => $length ) {
1673  $secretKey = MWCryptRand::generateHex( $length );
1674  $this->setVar( $name, $secretKey );
1675  }
1676 
1677  return $status;
1678  }
1679 
1685  protected function createSysop() {
1686  $name = $this->getVar( '_AdminName' );
1687  $user = User::newFromName( $name );
1688 
1689  if ( !$user ) {
1690  // We should've validated this earlier anyway!
1691  return Status::newFatal( 'config-admin-error-user', $name );
1692  }
1693 
1694  if ( $user->idForName() == 0 ) {
1695  $user->addToDatabase();
1696 
1697  $password = $this->getVar( '_AdminPassword' );
1698  $status = $user->changeAuthenticationData( [
1699  'username' => $user->getName(),
1700  'password' => $password,
1701  'retype' => $password,
1702  ] );
1703  if ( !$status->isGood() ) {
1704  return Status::newFatal( 'config-admin-error-password',
1705  $name, $status->getWikiText( null, null, $this->getVar( '_UserLang' ) ) );
1706  }
1707 
1708  $user->addGroup( 'sysop' );
1709  $user->addGroup( 'bureaucrat' );
1710  $user->addGroup( 'interface-admin' );
1711  if ( $this->getVar( '_AdminEmail' ) ) {
1712  $user->setEmail( $this->getVar( '_AdminEmail' ) );
1713  }
1714  $user->saveSettings();
1715 
1716  // Update user count
1717  $ssUpdate = SiteStatsUpdate::factory( [ 'users' => 1 ] );
1718  $ssUpdate->doUpdate();
1719  }
1720  $status = Status::newGood();
1721 
1722  if ( $this->getVar( '_Subscribe' ) && $this->getVar( '_AdminEmail' ) ) {
1723  $this->subscribeToMediaWikiAnnounce( $status );
1724  }
1725 
1726  return $status;
1727  }
1728 
1733  $params = [
1734  'email' => $this->getVar( '_AdminEmail' ),
1735  'language' => 'en',
1736  'digest' => 0
1737  ];
1738 
1739  // Mailman doesn't support as many languages as we do, so check to make
1740  // sure their selected language is available
1741  $myLang = $this->getVar( '_UserLang' );
1742  if ( in_array( $myLang, $this->mediaWikiAnnounceLanguages ) ) {
1743  $myLang = $myLang == 'pt-br' ? 'pt_BR' : $myLang; // rewrite to Mailman's pt_BR
1744  $params['language'] = $myLang;
1745  }
1746 
1748  $res = MWHttpRequest::factory( $this->mediaWikiAnnounceUrl,
1749  [ 'method' => 'POST', 'postData' => $params ], __METHOD__ )->execute();
1750  if ( !$res->isOK() ) {
1751  $s->warning( 'config-install-subscribe-fail', $res->getMessage() );
1752  }
1753  } else {
1754  $s->warning( 'config-install-subscribe-notpossible' );
1755  }
1756  }
1757 
1764  protected function createMainpage( DatabaseInstaller $installer ) {
1765  $status = Status::newGood();
1767  if ( $title->exists() ) {
1768  $status->warning( 'config-install-mainpage-exists' );
1769  return $status;
1770  }
1771  try {
1772  $page = WikiPage::factory( $title );
1773  $content = new WikitextContent(
1774  wfMessage( 'mainpagetext' )->inContentLanguage()->text() . "\n\n" .
1775  wfMessage( 'mainpagedocfooter' )->inContentLanguage()->text()
1776  );
1777 
1778  $status = $page->doEditContent( $content,
1779  '',
1780  EDIT_NEW,
1781  false,
1782  User::newSystemUser( 'MediaWiki default' )
1783  );
1784  } catch ( Exception $e ) {
1785  // using raw, because $wgShowExceptionDetails can not be set yet
1786  $status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
1787  }
1788 
1789  return $status;
1790  }
1791 
1795  public static function overrideConfig() {
1796  // Use PHP's built-in session handling, since MediaWiki's
1797  // SessionHandler can't work before we have an object cache set up.
1798  if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
1799  define( 'MW_NO_SESSION_HANDLER', 1 );
1800  }
1801 
1802  // Don't access the database
1803  $GLOBALS['wgUseDatabaseMessages'] = false;
1804  // Don't cache langconv tables
1805  $GLOBALS['wgLanguageConverterCacheType'] = CACHE_NONE;
1806  // Don't try to cache ResourceLoader dependencies in the database
1807  $GLOBALS['wgResourceLoaderUseObjectCacheForDeps'] = true;
1808  // Debug-friendly
1809  $GLOBALS['wgShowExceptionDetails'] = true;
1810  $GLOBALS['wgShowHostnames'] = true;
1811  // Don't break forms
1812  $GLOBALS['wgExternalLinkTarget'] = '_blank';
1813 
1814  // Allow multiple ob_flush() calls
1815  $GLOBALS['wgDisableOutputCompression'] = true;
1816 
1817  // Use a sensible cookie prefix (not my_wiki)
1818  $GLOBALS['wgCookiePrefix'] = 'mw_installer';
1819 
1820  // Some of the environment checks make shell requests, remove limits
1821  $GLOBALS['wgMaxShellMemory'] = 0;
1822 
1823  // Override the default CookieSessionProvider with a dummy
1824  // implementation that won't stomp on PHP's cookies.
1825  $GLOBALS['wgSessionProviders'] = [
1826  [
1827  'class' => InstallerSessionProvider::class,
1828  'args' => [ [
1829  'priority' => 1,
1830  ] ]
1831  ]
1832  ];
1833 
1834  // Don't use the DB as the main stash
1835  $GLOBALS['wgMainStash'] = CACHE_NONE;
1836 
1837  // Don't try to use any object cache for SessionManager either.
1838  $GLOBALS['wgSessionCacheType'] = CACHE_NONE;
1839 
1840  // Set a dummy $wgServer to bypass the check in Setup.php, the
1841  // web installer will automatically detect it and not use this value.
1842  $GLOBALS['wgServer'] = 'https://🌻.invalid';
1843  }
1844 
1852  public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
1853  $this->extraInstallSteps[$findStep][] = $callback;
1854  }
1855 
1860  protected function disableTimeLimit() {
1861  Wikimedia\suppressWarnings();
1862  set_time_limit( 0 );
1863  Wikimedia\restoreWarnings();
1864  }
1865 
1872  public function getUsedExtensionName() : ?string {
1873  if ( empty( $this->settings['wgDBtype'] ) ) {
1874  return null;
1875  }
1876  return $this->installerDbSupport
1877  ->getExtensionNameForDatabase( $this->settings['wgDBtype'] );
1878  }
1879 }
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:398
User\newFromId
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:557
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:329
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:1764
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
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:152
$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:1178
CACHE_NONE
const CACHE_NONE
Definition: Defines.php:91
Installer\envCheckLibicu
envCheckLibicu()
Check the libicu version.
Definition: Installer.php:1112
ExtensionRegistry
ExtensionRegistry class.
Definition: ExtensionRegistry.php:18
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: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:236
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:253
Installer\envCheckShellLocale
envCheckShellLocale()
Environment check for preferred locale in shell.
Definition: Installer.php:982
Installer\envCheckUploadsDirectory
envCheckUploadsDirectory()
Environment check for the permissions of the uploads directory.
Definition: Installer.php:1064
Installer\$settings
array $settings
Definition: Installer.php:66
Installer\envPrepServer
envPrepServer()
Environment prep for the server hostname.
Definition: Installer.php:1148
Installer\getUsedExtensionName
getUsedExtensionName()
Return the name of the extension selected to provide the database or null if the database is provided...
Definition: Installer.php:1872
$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:1602
Installer\$mediaWikiAnnounceLanguages
$mediaWikiAnnounceLanguages
Supported language codes for Mailman.
Definition: Installer.php:321
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:533
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1222
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:80
Installer\setParserLanguage
setParserLanguage( $lang)
ParserOptions are constructed before we determined the language, so fix it.
Definition: Installer.php:1244
Title\newMainPage
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:654
Installer\addInstallStep
addInstallStep( $callback, $findStep='BEGINNING')
Add an installation step following the given step.
Definition: Installer.php:1852
Installer\$internalDefaults
array $internalDefaults
Variables that are stored alongside globals, and are used for any configuration of the installation p...
Definition: Installer.php:191
$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:646
Installer\envGetDefaultServer
envGetDefaultServer()
Helper function to be called from envPrepServer()
$wgMemc
$wgMemc
Definition: Setup.php:692
Installer\setVar
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:529
Installer\restoreServices
restoreServices()
Restore services that have been redefined in the early stage of installation.
Definition: Installer.php:1652
Installer\$parserTitle
Title $parserTitle
Cached Title, used by parse().
Definition: Installer.php:94
Installer\$objectCaches
array $objectCaches
Known object cache types and the functions used to test for their existence.
Definition: Installer.php:243
Installer\$minMemorySize
int $minMemorySize
Minimum memory size in MB.
Definition: Installer.php:87
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:42
User\newSystemUser
static newSystemUser( $name, $options=[])
Static factory method for creation of a "system" user from username.
Definition: User.php:750
Installer\overrideConfig
static overrideConfig()
Override the necessary bits of the config to run an installation.
Definition: Installer.php:1795
Installer\createSysop
createSysop()
Create the first user account, grant it sysop, bureaucrat and interface-admin rights.
Definition: Installer.php:1685
Installer\getFakePassword
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:635
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:1083
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7921
Installer\envPrepPath
envPrepPath()
Environment prep for setting $IP and $wgScriptPath.
Definition: Installer.php:1164
WikiPage\factory
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:154
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1029
Installer\envCheckDiff3
envCheckDiff3()
Search for GNU diff3.
Definition: Installer.php:885
Config\get
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
Installer\generateKeys
generateKeys()
Generate $wgSecretKey.
Definition: Installer.php:1639
Installer\envCheckMemory
envCheckMemory()
Environment check for available memory.
Definition: Installer.php:827
$wgLang
$wgLang
Definition: Setup.php:782
$wgObjectCaches
$wgObjectCaches
Advanced object cache configuration.
Definition: DefaultSettings.php:2501
Installer\getCompiledDBs
getCompiledDBs()
Get a list of DBs supported by current PHP setup.
Definition: Installer.php:552
ObjectCache\getInstance
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:78
$queue
$queue
Definition: mergeMessageFileList.php:157
Installer\envCheckCache
envCheckCache()
Environment check for compiled object cache types.
Definition: Installer.php:853
Installer\getExistingLocalSettings
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
Definition: Installer.php:595
Installer\envCheckPath
envCheckPath()
Environment check to inform user which paths we've assumed.
Definition: Installer.php:969
Installer\doGenerateKeys
doGenerateKeys( $keys)
Generate a secret value for variables using a secure generator.
Definition: Installer.php:1669
Installer\$parserOptions
ParserOptions $parserOptions
Cached ParserOptions, used by parse().
Definition: Installer.php:101
$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:28
$wgExternalLinkTarget
$wgExternalLinkTarget
Set a default target for external links, e.g.
Definition: DefaultSettings.php:4669
Installer\getVar
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:543
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:1467
Installer\findExtensions
findExtensions( $directory='extensions')
Find extensions or skins in a subdirectory of $IP.
Definition: Installer.php:1267
Installer\getInstallerConfig
static getInstallerConfig(Config $baseConfig)
Constructs a Config object that contains configuration settings that should be overwritten for the in...
Definition: Installer.php:360
$content
$content
Definition: router.php:76
Installer\$envPreps
array $envPreps
A list of environment preparation methods called by doEnvironmentPreps().
Definition: Installer.php:142
$wgExtensionDirectory
$wgExtensionDirectory
Filesystem extensions directory.
Definition: DefaultSettings.php:251
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
wfIsWindows
wfIsWindows()
Check if the operating system is Windows.
Definition: GlobalFunctions.php:1849
$line
$line
Definition: mcc.php:119
Installer\doEnvironmentPreps
doEnvironmentPreps()
Definition: Installer.php:517
Installer\readExtension
readExtension( $fullJsonFile, $extDeps=[], $skinDeps=[])
Definition: Installer.php:1383
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:577
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:1546
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:451
$wgAutoloadClasses
$wgAutoloadClasses
Array mapping class names to filenames, for autoloading.
Definition: DefaultSettings.php:7816
Installer\$compiledDBs
array $compiledDBs
List of detected DBs, access using getCompiledDBs().
Definition: Installer.php:73
$lines
if(!file_exists( $CREDITS)) $lines
Definition: updateCredits.php:49
MediaWiki\Installer\Services\InstallerDBSupport
Definition: InstallerDBSupport.php:48
Installer\doEnvironmentChecks
doEnvironmentChecks()
Do initial checks of the PHP environment.
Definition: Installer.php:492
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:908
wfShorthandToInteger
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
Definition: GlobalFunctions.php:2710
Installer\apacheModulePresent
static apacheModulePresent( $moduleName)
Checks for presence of an Apache module.
Definition: Installer.php:1227
Title
Represents a title within MediaWiki.
Definition: Title.php:42
Installer\envCheckPCRE
envCheckPCRE()
Environment check for the PCRE module.
Definition: Installer.php:805
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6263
Installer\$installerDbSupport
InstallerDBSupport $installerDbSupport
Definition: Installer.php:106
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:181
$path
$path
Definition: NoLocalSettings.php:25
Installer\envCheck64Bit
envCheck64Bit()
Checks if we're running on 64 bit or not.
Definition: Installer.php:1101
Installer\$licenses
array $licenses
License types.
Definition: Installer.php:278
Installer\disableTimeLimit
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:1860
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:956
Installer
Base installer class.
Definition: Installer.php:53
$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:61
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:1287
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:474
Installer\disableLinkPopups
disableLinkPopups()
Definition: Installer.php:715
Installer\$installSteps
array[] $installSteps
The actual list of installation steps.
Definition: Installer.php:229
Installer\$mediaWikiAnnounceUrl
$mediaWikiAnnounceUrl
URL to mediawiki-announce subscription.
Definition: Installer.php:315
$IP
$IP
Definition: WebStart.php:49
Installer\includeExtensions
includeExtensions()
Installs the auto-detected extensions.
Definition: Installer.php:1482
$wgStyleDirectory
$wgStyleDirectory
Filesystem stylesheets directory.
Definition: DefaultSettings.php:258
Installer\envCheckGit
envCheckGit()
Search for git.
Definition: Installer.php:934
Installer\getDocUrl
getDocUrl( $page)
Overridden by WebInstaller to provide lastPage parameters.
Definition: Installer.php:1254
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6
Installer\subscribeToMediaWikiAnnounce
subscribeToMediaWikiAnnounce(Status $s)
Definition: Installer.php:1732
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:663
Installer\getExtensionInfo
getExtensionInfo( $type, $parentRelPath, $name)
Definition: Installer.php:1330
Installer\$defaultVarNames
array $defaultVarNames
MediaWiki configuration globals that will eventually be passed through to LocalSettings....
Definition: Installer.php:154
Installer\getDBInstallerClass
static getDBInstallerClass( $type)
Get the DatabaseInstaller class name for this type.
Definition: Installer.php:564
Installer\$envChecks
array $envChecks
A list of environment check methods called by doEnvironmentChecks().
Definition: Installer.php:119
$type
$type
Definition: testCompression.php:52
Installer\envCheckModSecurity
envCheckModSecurity()
Scare user to death if they have mod_security or mod_security2.
Definition: Installer.php:872