MediaWiki  master
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 
233  private $installSteps = [];
234 
240  protected $extraInstallSteps = [];
241 
247  protected $objectCaches = [
248  'apc' => 'apc_fetch',
249  'apcu' => 'apcu_fetch',
250  'wincache' => 'wincache_ucache_get'
251  ];
252 
258  public $rightsProfiles = [
259  'wiki' => [],
260  'no-anon' => [
261  '*' => [ 'edit' => false ]
262  ],
263  'fishbowl' => [
264  '*' => [
265  'createaccount' => false,
266  'edit' => false,
267  ],
268  ],
269  'private' => [
270  '*' => [
271  'createaccount' => false,
272  'edit' => false,
273  'read' => false,
274  ],
275  ],
276  ];
277 
283  public $licenses = [
284  'cc-by' => [
285  'url' => 'https://creativecommons.org/licenses/by/4.0/',
286  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by.png',
287  ],
288  'cc-by-sa' => [
289  'url' => 'https://creativecommons.org/licenses/by-sa/4.0/',
290  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-sa.png',
291  ],
292  'cc-by-nc-sa' => [
293  'url' => 'https://creativecommons.org/licenses/by-nc-sa/4.0/',
294  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-by-nc-sa.png',
295  ],
296  'cc-0' => [
297  'url' => 'https://creativecommons.org/publicdomain/zero/1.0/',
298  'icon' => '$wgResourceBasePath/resources/assets/licenses/cc-0.png',
299  ],
300  'gfdl' => [
301  'url' => 'https://www.gnu.org/copyleft/fdl.html',
302  'icon' => '$wgResourceBasePath/resources/assets/licenses/gnu-fdl.png',
303  ],
304  'none' => [
305  'url' => '',
306  'icon' => '',
307  'text' => ''
308  ],
309  'cc-choose' => [
310  // Details will be filled in by the selector.
311  'url' => '',
312  'icon' => '',
313  'text' => '',
314  ],
315  ];
316 
321  'https://lists.wikimedia.org/mailman/subscribe/mediawiki-announce';
322 
327  'ca', 'cs', 'da', 'de', 'en', 'es', 'et', 'eu', 'fi', 'fr', 'hr', 'hu',
328  'it', 'ja', 'ko', 'lt', 'nl', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru',
329  'sl', 'sr', 'sv', 'tr', 'uk'
330  ];
331 
340  abstract public function showMessage( $msg, ...$params );
341 
347  abstract public function showError( $msg, ...$params );
348 
353  abstract public function showStatusMessage( Status $status );
354 
365  public static function getInstallerConfig( Config $baseConfig ) {
366  $configOverrides = new HashConfig();
367 
368  // disable (problematic) object cache types explicitly, preserving all other (working) ones
369  // bug T113843
370  $emptyCache = [ 'class' => EmptyBagOStuff::class ];
371 
372  $objectCaches = [
373  CACHE_NONE => $emptyCache,
374  CACHE_DB => $emptyCache,
375  CACHE_ANYTHING => $emptyCache,
376  CACHE_MEMCACHED => $emptyCache,
377  ] + $baseConfig->get( 'ObjectCaches' );
378 
379  $configOverrides->set( 'ObjectCaches', $objectCaches );
380 
381  // Load the installer's i18n.
382  $messageDirs = $baseConfig->get( 'MessagesDirs' );
383  $messageDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
384 
385  $configOverrides->set( 'MessagesDirs', $messageDirs );
386 
387  $installerConfig = new MultiConfig( [ $configOverrides, $baseConfig ] );
388 
389  // make sure we use the installer config as the main config
390  $configRegistry = $baseConfig->get( 'ConfigRegistry' );
391  $configRegistry['main'] = function () use ( $installerConfig ) {
392  return $installerConfig;
393  };
394 
395  $configOverrides->set( 'ConfigRegistry', $configRegistry );
396 
397  return $installerConfig;
398  }
399 
403  public function __construct() {
404  global $wgMemc, $wgUser, $wgObjectCaches;
405 
406  $defaultConfig = new GlobalVarConfig(); // all the stuff from DefaultSettings.php
407  $installerConfig = self::getInstallerConfig( $defaultConfig );
408 
409  // Reset all services and inject config overrides
410  MediaWikiServices::resetGlobalInstance( $installerConfig );
411 
412  // Don't attempt to load user language options (T126177)
413  // This will be overridden in the web installer with the user-specified language
414  RequestContext::getMain()->setLanguage( 'en' );
415 
416  // Disable all global services, since we don't have any configuration yet!
417  MediaWikiServices::disableStorageBackend();
418 
419  $mwServices = MediaWikiServices::getInstance();
420 
421  // Disable i18n cache
422  $mwServices->getLocalisationCache()->disableBackend();
423 
424  // Clear language cache so the old i18n cache doesn't sneak back in
426 
427  // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and
428  // SqlBagOStuff will then throw since we just disabled wfGetDB)
429  $wgObjectCaches = $mwServices->getMainConfig()->get( 'ObjectCaches' );
431 
432  // Disable interwiki lookup, to avoid database access during parses
433  $mwServices->redefineService( 'InterwikiLookup', function () {
434  return new NullInterwikiLookup();
435  } );
436 
437  // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
438  $wgUser = User::newFromId( 0 );
439  RequestContext::getMain()->setUser( $wgUser );
440 
441  $this->settings = $this->internalDefaults;
442 
443  foreach ( $this->defaultVarNames as $var ) {
444  $this->settings[$var] = $GLOBALS[$var];
445  }
446 
447  $this->doEnvironmentPreps();
448 
449  $this->compiledDBs = [];
450  foreach ( self::getDBTypes() as $type ) {
451  $installer = $this->getDBInstaller( $type );
452 
453  if ( !$installer->isCompiled() ) {
454  continue;
455  }
456  $this->compiledDBs[] = $type;
457  }
458 
459  $this->parserTitle = Title::newFromText( 'Installer' );
460  $this->parserOptions = new ParserOptions( $wgUser ); // language will be wrong :(
461  $this->parserOptions->setTidy( true );
462  // Don't try to access DB before user language is initialised
463  $this->setParserLanguage( Language::factory( 'en' ) );
464  }
465 
471  public static function getDBTypes() {
472  return self::$dbTypes;
473  }
474 
488  public function doEnvironmentChecks() {
489  // PHP version has already been checked by entry scripts
490  // Show message here for information purposes
491  $this->showMessage( 'config-env-php', PHP_VERSION );
492 
493  $good = true;
494  // Must go here because an old version of PCRE can prevent other checks from completing
495  $pcreVersion = explode( ' ', PCRE_VERSION, 2 )[0];
496  if ( version_compare( $pcreVersion, self::MINIMUM_PCRE_VERSION, '<' ) ) {
497  $this->showError( 'config-pcre-old', self::MINIMUM_PCRE_VERSION, $pcreVersion );
498  $good = false;
499  } else {
500  foreach ( $this->envChecks as $check ) {
501  $status = $this->$check();
502  if ( $status === false ) {
503  $good = false;
504  }
505  }
506  }
507 
508  $this->setVar( '_Environment', $good );
509 
510  return $good ? Status::newGood() : Status::newFatal( 'config-env-bad' );
511  }
512 
513  public function doEnvironmentPreps() {
514  foreach ( $this->envPreps as $prep ) {
515  $this->$prep();
516  }
517  }
518 
525  public function setVar( $name, $value ) {
526  $this->settings[$name] = $value;
527  }
528 
539  public function getVar( $name, $default = null ) {
540  return $this->settings[$name] ?? $default;
541  }
542 
548  public function getCompiledDBs() {
549  return $this->compiledDBs;
550  }
551 
559  public static function getDBInstallerClass( $type ) {
560  return ucfirst( $type ) . 'Installer';
561  }
562 
570  public function getDBInstaller( $type = false ) {
571  if ( !$type ) {
572  $type = $this->getVar( 'wgDBtype' );
573  }
574 
575  $type = strtolower( $type );
576 
577  if ( !isset( $this->dbInstallers[$type] ) ) {
578  $class = self::getDBInstallerClass( $type );
579  $this->dbInstallers[$type] = new $class( $this );
580  }
581 
582  return $this->dbInstallers[$type];
583  }
584 
590  public static function getExistingLocalSettings() {
591  global $IP;
592 
593  // You might be wondering why this is here. Well if you don't do this
594  // then some poorly-formed extensions try to call their own classes
595  // after immediately registering them. We really need to get extension
596  // registration out of the global scope and into a real format.
597  // @see https://phabricator.wikimedia.org/T69440
598  global $wgAutoloadClasses;
599  $wgAutoloadClasses = [];
600 
601  // LocalSettings.php should not call functions, except wfLoadSkin/wfLoadExtensions
602  // Define the required globals here, to ensure, the functions can do it work correctly.
603  // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
605 
606  Wikimedia\suppressWarnings();
607  $_lsExists = file_exists( "$IP/LocalSettings.php" );
608  Wikimedia\restoreWarnings();
609 
610  if ( !$_lsExists ) {
611  return false;
612  }
613  unset( $_lsExists );
614 
615  require "$IP/includes/DefaultSettings.php";
616  require "$IP/LocalSettings.php";
617 
618  return get_defined_vars();
619  }
620 
630  public function getFakePassword( $realPassword ) {
631  return str_repeat( '*', strlen( $realPassword ) );
632  }
633 
641  public function setPassword( $name, $value ) {
642  if ( !preg_match( '/^\*+$/', $value ) ) {
643  $this->setVar( $name, $value );
644  }
645  }
646 
658  public static function maybeGetWebserverPrimaryGroup() {
659  if ( !function_exists( 'posix_getegid' ) || !function_exists( 'posix_getpwuid' ) ) {
660  # I don't know this, this isn't UNIX.
661  return null;
662  }
663 
664  # posix_getegid() *not* getmygid() because we want the group of the webserver,
665  # not whoever owns the current script.
666  $gid = posix_getegid();
667  $group = posix_getpwuid( $gid )['name'];
668 
669  return $group;
670  }
671 
688  public function parse( $text, $lineStart = false ) {
689  $parser = MediaWikiServices::getInstance()->getParser();
690 
691  try {
692  $out = $parser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart );
693  $html = $out->getText( [
694  'enableSectionEditLinks' => false,
695  'unwrap' => true,
696  ] );
697  $html = Parser::stripOuterParagraph( $html );
698  } catch ( Wikimedia\Services\ServiceDisabledException $e ) {
699  $html = '<!--DB access attempted during parse--> ' . htmlspecialchars( $text );
700  }
701 
702  return $html;
703  }
704 
708  public function getParserOptions() {
709  return $this->parserOptions;
710  }
711 
712  public function disableLinkPopups() {
713  $this->parserOptions->setExternalLinkTarget( false );
714  }
715 
716  public function restoreLinkPopups() {
717  global $wgExternalLinkTarget;
718  $this->parserOptions->setExternalLinkTarget( $wgExternalLinkTarget );
719  }
720 
729  public function populateSiteStats( DatabaseInstaller $installer ) {
730  $status = $installer->getConnection();
731  if ( !$status->isOK() ) {
732  return $status;
733  }
734  // @phan-suppress-next-line PhanUndeclaredMethod
735  $status->value->insert(
736  'site_stats',
737  [
738  'ss_row_id' => 1,
739  'ss_total_edits' => 0,
740  'ss_good_articles' => 0,
741  'ss_total_pages' => 0,
742  'ss_users' => 0,
743  'ss_active_users' => 0,
744  'ss_images' => 0
745  ],
746  __METHOD__, 'IGNORE'
747  );
748 
749  return Status::newGood();
750  }
751 
756  protected function envCheckDB() {
757  global $wgLang;
759  $dbType = $this->getVar( 'wgDBtype' );
760 
761  $allNames = [];
762 
763  // Messages: config-type-mysql, config-type-postgres, config-type-sqlite
764  foreach ( self::getDBTypes() as $name ) {
765  $allNames[] = wfMessage( "config-type-$name" )->text();
766  }
767 
768  $databases = $this->getCompiledDBs();
769 
770  $databases = array_flip( $databases );
771  $ok = true;
772  foreach ( array_keys( $databases ) as $db ) {
773  $installer = $this->getDBInstaller( $db );
774  $status = $installer->checkPrerequisites();
775  if ( !$status->isGood() ) {
776  if ( !$this instanceof WebInstaller && $db === $dbType ) {
777  // Strictly check the key database type instead of just outputting message
778  // Note: No perform this check run from the web installer, since this method always called by
779  // the welcome page under web installation, so $dbType will always be 'mysql'
780  $ok = false;
781  }
782  $this->showStatusMessage( $status );
783  unset( $databases[$db] );
784  }
785  }
786  $databases = array_flip( $databases );
787  if ( !$databases ) {
788  $this->showError( 'config-no-db', $wgLang->commaList( $allNames ), count( $allNames ) );
789  return false;
790  }
791  return $ok;
792  }
793 
798  protected function envCheckBrokenXML() {
799  $test = new PhpXmlBugTester();
800  if ( !$test->ok ) {
801  $this->showError( 'config-brokenlibxml' );
802 
803  return false;
804  }
805 
806  return true;
807  }
808 
817  protected function envCheckPCRE() {
818  Wikimedia\suppressWarnings();
819  $regexd = preg_replace( '/[\x{0430}-\x{04FF}]/iu', '', '-АБВГД-' );
820  // Need to check for \p support too, as PCRE can be compiled
821  // with utf8 support, but not unicode property support.
822  // check that \p{Zs} (space separators) matches
823  // U+3000 (Ideographic space)
824  $regexprop = preg_replace( '/\p{Zs}/u', '', "-\u{3000}-" );
825  Wikimedia\restoreWarnings();
826  if ( $regexd != '--' || $regexprop != '--' ) {
827  $this->showError( 'config-pcre-no-utf8' );
828 
829  return false;
830  }
831 
832  return true;
833  }
834 
839  protected function envCheckMemory() {
840  $limit = ini_get( 'memory_limit' );
841 
842  if ( !$limit || $limit == -1 ) {
843  return true;
844  }
845 
846  $n = wfShorthandToInteger( $limit );
847 
848  if ( $n < $this->minMemorySize * 1024 * 1024 ) {
849  $newLimit = "{$this->minMemorySize}M";
850 
851  if ( ini_set( "memory_limit", $newLimit ) === false ) {
852  $this->showMessage( 'config-memory-bad', $limit );
853  } else {
854  $this->showMessage( 'config-memory-raised', $limit, $newLimit );
855  $this->setVar( '_RaiseMemory', true );
856  }
857  }
858 
859  return true;
860  }
861 
865  protected function envCheckCache() {
866  $caches = [];
867  foreach ( $this->objectCaches as $name => $function ) {
868  if ( function_exists( $function ) ) {
869  $caches[$name] = true;
870  }
871  }
872 
873  if ( !$caches ) {
874  $this->showMessage( 'config-no-cache-apcu' );
875  }
876 
877  $this->setVar( '_Caches', $caches );
878  }
879 
884  protected function envCheckModSecurity() {
885  if ( self::apacheModulePresent( 'mod_security' )
886  || self::apacheModulePresent( 'mod_security2' ) ) {
887  $this->showMessage( 'config-mod-security' );
888  }
889 
890  return true;
891  }
892 
897  protected function envCheckDiff3() {
898  $names = [ "gdiff3", "diff3" ];
899  if ( wfIsWindows() ) {
900  $names[] = 'diff3.exe';
901  }
902  $versionInfo = [ '--version', 'GNU diffutils' ];
903 
904  $diff3 = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
905 
906  if ( $diff3 ) {
907  $this->setVar( 'wgDiff3', $diff3 );
908  } else {
909  $this->setVar( 'wgDiff3', false );
910  $this->showMessage( 'config-diff3-bad' );
911  }
912 
913  return true;
914  }
915 
920  protected function envCheckGraphics() {
921  $names = wfIsWindows() ? 'convert.exe' : 'convert';
922  $versionInfo = [ '-version', 'ImageMagick' ];
923  $convert = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
924 
925  $this->setVar( 'wgImageMagickConvertCommand', '' );
926  if ( $convert ) {
927  $this->setVar( 'wgImageMagickConvertCommand', $convert );
928  $this->showMessage( 'config-imagemagick', $convert );
929 
930  return true;
931  } elseif ( function_exists( 'imagejpeg' ) ) {
932  $this->showMessage( 'config-gd' );
933  } else {
934  $this->showMessage( 'config-no-scaling' );
935  }
936 
937  return true;
938  }
939 
946  protected function envCheckGit() {
947  $names = wfIsWindows() ? 'git.exe' : 'git';
948  $versionInfo = [ '--version', 'git version' ];
949 
950  $git = ExecutableFinder::findInDefaultPaths( $names, $versionInfo );
951 
952  if ( $git ) {
953  $this->setVar( 'wgGitBin', $git );
954  $this->showMessage( 'config-git', $git );
955  } else {
956  $this->setVar( 'wgGitBin', false );
957  $this->showMessage( 'config-git-bad' );
958  }
959 
960  return true;
961  }
962 
968  protected function envCheckServer() {
969  $server = $this->envGetDefaultServer();
970  if ( $server !== null ) {
971  $this->showMessage( 'config-using-server', $server );
972  }
973  return true;
974  }
975 
981  protected function envCheckPath() {
982  $this->showMessage(
983  'config-using-uri',
984  $this->getVar( 'wgServer' ),
985  $this->getVar( 'wgScriptPath' )
986  );
987  return true;
988  }
989 
994  protected function envCheckShellLocale() {
995  $os = php_uname( 's' );
996  $supported = [ 'Linux', 'SunOS', 'HP-UX', 'Darwin' ]; # Tested these
997 
998  if ( !in_array( $os, $supported ) ) {
999  return true;
1000  }
1001 
1002  if ( Shell::isDisabled() ) {
1003  return true;
1004  }
1005 
1006  # Get a list of available locales.
1007  $result = Shell::command( '/usr/bin/locale', '-a' )
1008  ->execute();
1009 
1010  if ( $result->getExitCode() != 0 ) {
1011  return true;
1012  }
1013 
1014  $lines = $result->getStdout();
1015  $lines = array_map( 'trim', explode( "\n", $lines ) );
1016  $candidatesByLocale = [];
1017  $candidatesByLang = [];
1018  foreach ( $lines as $line ) {
1019  if ( $line === '' ) {
1020  continue;
1021  }
1022 
1023  if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
1024  continue;
1025  }
1026 
1027  list( , $lang, , , ) = $m;
1028 
1029  $candidatesByLocale[$m[0]] = $m;
1030  $candidatesByLang[$lang][] = $m;
1031  }
1032 
1033  # Try the current value of LANG.
1034  if ( isset( $candidatesByLocale[getenv( 'LANG' )] ) ) {
1035  $this->setVar( 'wgShellLocale', getenv( 'LANG' ) );
1036 
1037  return true;
1038  }
1039 
1040  # Try the most common ones.
1041  $commonLocales = [ 'C.UTF-8', 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' ];
1042  foreach ( $commonLocales as $commonLocale ) {
1043  if ( isset( $candidatesByLocale[$commonLocale] ) ) {
1044  $this->setVar( 'wgShellLocale', $commonLocale );
1045 
1046  return true;
1047  }
1048  }
1049 
1050  # Is there an available locale in the Wiki's language?
1051  $wikiLang = $this->getVar( 'wgLanguageCode' );
1052 
1053  if ( isset( $candidatesByLang[$wikiLang] ) ) {
1054  $m = reset( $candidatesByLang[$wikiLang] );
1055  $this->setVar( 'wgShellLocale', $m[0] );
1056 
1057  return true;
1058  }
1059 
1060  # Are there any at all?
1061  if ( count( $candidatesByLocale ) ) {
1062  $m = reset( $candidatesByLocale );
1063  $this->setVar( 'wgShellLocale', $m[0] );
1064 
1065  return true;
1066  }
1067 
1068  # Give up.
1069  return true;
1070  }
1071 
1076  protected function envCheckUploadsDirectory() {
1077  global $IP;
1078 
1079  $dir = $IP . '/images/';
1080  $url = $this->getVar( 'wgServer' ) . $this->getVar( 'wgScriptPath' ) . '/images/';
1081  $safe = !$this->dirIsExecutable( $dir, $url );
1082 
1083  if ( !$safe ) {
1084  $this->showMessage( 'config-uploads-not-safe', $dir );
1085  }
1086 
1087  return true;
1088  }
1089 
1095  protected function envCheckSuhosinMaxValueLength() {
1096  $currentValue = ini_get( 'suhosin.get.max_value_length' );
1097  $minRequired = 2000;
1098  $recommended = 5000;
1099  if ( $currentValue > 0 && $currentValue < $minRequired ) {
1100  $this->showError( 'config-suhosin-max-value-length', $currentValue, $minRequired, $recommended );
1101  return false;
1102  }
1103 
1104  return true;
1105  }
1106 
1113  protected function envCheck64Bit() {
1114  if ( PHP_INT_SIZE == 4 ) {
1115  $this->showMessage( 'config-using-32bit' );
1116  }
1117 
1118  return true;
1119  }
1120 
1124  protected function envCheckLibicu() {
1132  $not_normal_c = "\u{FA6C}";
1133  $normal_c = "\u{242EE}";
1134 
1135  $useNormalizer = 'php';
1136  $needsUpdate = false;
1137 
1138  if ( function_exists( 'normalizer_normalize' ) ) {
1139  $useNormalizer = 'intl';
1140  $intl = normalizer_normalize( $not_normal_c, Normalizer::FORM_C );
1141  if ( $intl !== $normal_c ) {
1142  $needsUpdate = true;
1143  }
1144  }
1145 
1146  // Uses messages 'config-unicode-using-php' and 'config-unicode-using-intl'
1147  if ( $useNormalizer === 'php' ) {
1148  $this->showMessage( 'config-unicode-pure-php-warning' );
1149  } else {
1150  $this->showMessage( 'config-unicode-using-' . $useNormalizer );
1151  if ( $needsUpdate ) {
1152  $this->showMessage( 'config-unicode-update-warning' );
1153  }
1154  }
1155  }
1156 
1160  protected function envPrepServer() {
1161  $server = $this->envGetDefaultServer();
1162  if ( $server !== null ) {
1163  $this->setVar( 'wgServer', $server );
1164  }
1165  }
1166 
1171  abstract protected function envGetDefaultServer();
1172 
1176  protected function envPrepPath() {
1177  global $IP;
1178  $IP = dirname( dirname( __DIR__ ) );
1179  $this->setVar( 'IP', $IP );
1180  }
1181 
1190  public function dirIsExecutable( $dir, $url ) {
1191  $scriptTypes = [
1192  'php' => [
1193  "<?php echo 'exec';",
1194  "#!/var/env php\n<?php echo 'exec';",
1195  ],
1196  ];
1197 
1198  // it would be good to check other popular languages here, but it'll be slow.
1199 
1200  Wikimedia\suppressWarnings();
1201 
1202  foreach ( $scriptTypes as $ext => $contents ) {
1203  foreach ( $contents as $source ) {
1204  $file = 'exectest.' . $ext;
1205 
1206  if ( !file_put_contents( $dir . $file, $source ) ) {
1207  break;
1208  }
1209 
1210  try {
1211  $text = MediaWikiServices::getInstance()->getHttpRequestFactory()->
1212  get( $url . $file, [ 'timeout' => 3 ], __METHOD__ );
1213  } catch ( Exception $e ) {
1214  // HttpRequestFactory::get can throw with allow_url_fopen = false and no curl
1215  // extension.
1216  $text = null;
1217  }
1218  unlink( $dir . $file );
1219 
1220  if ( $text == 'exec' ) {
1221  Wikimedia\restoreWarnings();
1222 
1223  return $ext;
1224  }
1225  }
1226  }
1227 
1228  Wikimedia\restoreWarnings();
1229 
1230  return false;
1231  }
1232 
1239  public static function apacheModulePresent( $moduleName ) {
1240  if ( function_exists( 'apache_get_modules' ) && in_array( $moduleName, apache_get_modules() ) ) {
1241  return true;
1242  }
1243  // try it the hard way
1244  ob_start();
1245  phpinfo( INFO_MODULES );
1246  $info = ob_get_clean();
1247 
1248  return strpos( $info, $moduleName ) !== false;
1249  }
1250 
1256  public function setParserLanguage( $lang ) {
1257  $this->parserOptions->setTargetLanguage( $lang );
1258  $this->parserOptions->setUserLang( $lang );
1259  }
1260 
1266  protected function getDocUrl( $page ) {
1267  return "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
1268  }
1269 
1279  public function findExtensions( $directory = 'extensions' ) {
1280  switch ( $directory ) {
1281  case 'extensions':
1282  return $this->findExtensionsByType( 'extension', 'extensions' );
1283  case 'skins':
1284  return $this->findExtensionsByType( 'skin', 'skins' );
1285  default:
1286  throw new InvalidArgumentException( "Invalid extension type" );
1287  }
1288  }
1289 
1299  protected function findExtensionsByType( $type = 'extension', $directory = 'extensions' ) {
1300  if ( $this->getVar( 'IP' ) === null ) {
1301  return Status::newGood( [] );
1302  }
1303 
1304  $extDir = $this->getVar( 'IP' ) . '/' . $directory;
1305  if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
1306  return Status::newGood( [] );
1307  }
1308 
1309  $dh = opendir( $extDir );
1310  $exts = [];
1311  $status = new Status;
1312  while ( ( $file = readdir( $dh ) ) !== false ) {
1313  // skip non-dirs and hidden directories
1314  if ( !is_dir( "$extDir/$file" ) || $file[0] === '.' ) {
1315  continue;
1316  }
1317  $extStatus = $this->getExtensionInfo( $type, $directory, $file );
1318  if ( $extStatus->isOK() ) {
1319  $exts[$file] = $extStatus->value;
1320  } elseif ( $extStatus->hasMessage( 'config-extension-not-found' ) ) {
1321  // (T225512) The directory is not actually an extension. Downgrade to warning.
1322  $status->warning( 'config-extension-not-found', $file );
1323  } else {
1324  $status->merge( $extStatus );
1325  }
1326  }
1327  closedir( $dh );
1328  uksort( $exts, 'strnatcasecmp' );
1329 
1330  $status->value = $exts;
1331 
1332  return $status;
1333  }
1334 
1342  protected function getExtensionInfo( $type, $parentRelPath, $name ) {
1343  if ( $this->getVar( 'IP' ) === null ) {
1344  throw new Exception( 'Cannot find extensions since the IP variable is not yet set' );
1345  }
1346  if ( $type !== 'extension' && $type !== 'skin' ) {
1347  throw new InvalidArgumentException( "Invalid extension type" );
1348  }
1349  $absDir = $this->getVar( 'IP' ) . "/$parentRelPath/$name";
1350  $relDir = "../$parentRelPath/$name";
1351  if ( !is_dir( $absDir ) ) {
1352  return Status::newFatal( 'config-extension-not-found', $name );
1353  }
1354  $jsonFile = $type . '.json';
1355  $fullJsonFile = "$absDir/$jsonFile";
1356  $isJson = file_exists( $fullJsonFile );
1357  $isPhp = false;
1358  if ( !$isJson ) {
1359  // Only fallback to PHP file if JSON doesn't exist
1360  $fullPhpFile = "$absDir/$name.php";
1361  $isPhp = file_exists( $fullPhpFile );
1362  }
1363  if ( !$isJson && !$isPhp ) {
1364  return Status::newFatal( 'config-extension-not-found', $name );
1365  }
1366 
1367  // Extension exists. Now see if there are screenshots
1368  $info = [];
1369  if ( is_dir( "$absDir/screenshots" ) ) {
1370  $paths = glob( "$absDir/screenshots/*.png" );
1371  foreach ( $paths as $path ) {
1372  $info['screenshots'][] = str_replace( $absDir, $relDir, $path );
1373  }
1374  }
1375 
1376  if ( $isJson ) {
1377  $jsonStatus = $this->readExtension( $fullJsonFile );
1378  if ( !$jsonStatus->isOK() ) {
1379  return $jsonStatus;
1380  }
1381  $info += $jsonStatus->value;
1382  }
1383 
1384  return Status::newGood( $info );
1385  }
1386 
1395  private function readExtension( $fullJsonFile, $extDeps = [], $skinDeps = [] ) {
1396  $load = [
1397  $fullJsonFile => 1
1398  ];
1399  if ( $extDeps ) {
1400  $extDir = $this->getVar( 'IP' ) . '/extensions';
1401  foreach ( $extDeps as $dep ) {
1402  $fname = "$extDir/$dep/extension.json";
1403  if ( !file_exists( $fname ) ) {
1404  return Status::newFatal( 'config-extension-not-found', $dep );
1405  }
1406  $load[$fname] = 1;
1407  }
1408  }
1409  if ( $skinDeps ) {
1410  $skinDir = $this->getVar( 'IP' ) . '/skins';
1411  foreach ( $skinDeps as $dep ) {
1412  $fname = "$skinDir/$dep/skin.json";
1413  if ( !file_exists( $fname ) ) {
1414  return Status::newFatal( 'config-extension-not-found', $dep );
1415  }
1416  $load[$fname] = 1;
1417  }
1418  }
1419  $registry = new ExtensionRegistry();
1420  try {
1421  $info = $registry->readFromQueue( $load );
1422  } catch ( ExtensionDependencyError $e ) {
1423  if ( $e->incompatibleCore || $e->incompatibleSkins
1424  || $e->incompatibleExtensions
1425  ) {
1426  // If something is incompatible with a dependency, we have no real
1427  // option besides skipping it
1428  return Status::newFatal( 'config-extension-dependency',
1429  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1430  } elseif ( $e->missingExtensions || $e->missingSkins ) {
1431  // There's an extension missing in the dependency tree,
1432  // so add those to the dependency list and try again
1433  $status = $this->readExtension(
1434  $fullJsonFile,
1435  array_merge( $extDeps, $e->missingExtensions ),
1436  array_merge( $skinDeps, $e->missingSkins )
1437  );
1438  if ( !$status->isOK() && !$status->hasMessage( 'config-extension-dependency' ) ) {
1439  $status = Status::newFatal( 'config-extension-dependency',
1440  basename( dirname( $fullJsonFile ) ), $status->getMessage() );
1441  }
1442  return $status;
1443  }
1444  // Some other kind of dependency error?
1445  return Status::newFatal( 'config-extension-dependency',
1446  basename( dirname( $fullJsonFile ) ), $e->getMessage() );
1447  }
1448  $ret = [];
1449  // The order of credits will be the order of $load,
1450  // so the first extension is the one we want to load,
1451  // everything else is a dependency
1452  $i = 0;
1453  foreach ( $info['credits'] as $name => $credit ) {
1454  $i++;
1455  if ( $i == 1 ) {
1456  // Extension we want to load
1457  continue;
1458  }
1459  $type = basename( $credit['path'] ) === 'skin.json' ? 'skins' : 'extensions';
1460  $ret['requires'][$type][] = $credit['name'];
1461  }
1462  $credits = array_values( $info['credits'] )[0];
1463  if ( isset( $credits['url'] ) ) {
1464  $ret['url'] = $credits['url'];
1465  }
1466  $ret['type'] = $credits['type'];
1467 
1468  return Status::newGood( $ret );
1469  }
1470 
1479  public function getDefaultSkin( array $skinNames ) {
1480  $defaultSkin = $GLOBALS['wgDefaultSkin'];
1481  if ( !$skinNames || in_array( $defaultSkin, $skinNames ) ) {
1482  return $defaultSkin;
1483  } else {
1484  return $skinNames[0];
1485  }
1486  }
1487 
1494  protected function includeExtensions() {
1495  global $IP;
1496  $exts = $this->getVar( '_Extensions' );
1497  $IP = $this->getVar( 'IP' );
1498 
1499  // Marker for DatabaseUpdater::loadExtensions so we don't
1500  // double load extensions
1501  define( 'MW_EXTENSIONS_LOADED', true );
1502 
1511  global $wgAutoloadClasses;
1512  $wgAutoloadClasses = [];
1513  $queue = [];
1514 
1515  require "$IP/includes/DefaultSettings.php";
1516 
1517  foreach ( $exts as $e ) {
1518  if ( file_exists( "$IP/extensions/$e/extension.json" ) ) {
1519  $queue["$IP/extensions/$e/extension.json"] = 1;
1520  } else {
1521  require_once "$IP/extensions/$e/$e.php";
1522  }
1523  }
1524 
1525  $registry = new ExtensionRegistry();
1526  $data = $registry->readFromQueue( $queue );
1527  $wgAutoloadClasses += $data['autoload'];
1528 
1529  // @phan-suppress-next-line PhanUndeclaredVariable $wgHooks is set by DefaultSettings
1530  $hooksWeWant = $wgHooks['LoadExtensionSchemaUpdates'] ?? [];
1531 
1532  if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
1533  $hooksWeWant = array_merge_recursive(
1534  $hooksWeWant,
1535  $data['globals']['wgHooks']['LoadExtensionSchemaUpdates']
1536  );
1537  }
1538  // Unset everyone else's hooks. Lord knows what someone might be doing
1539  // in ParserFirstCallInit (see T29171)
1540  $GLOBALS['wgHooks'] = [ 'LoadExtensionSchemaUpdates' => $hooksWeWant ];
1541 
1542  return Status::newGood();
1543  }
1544 
1558  protected function getInstallSteps( DatabaseInstaller $installer ) {
1559  $coreInstallSteps = [
1560  [ 'name' => 'database', 'callback' => [ $installer, 'setupDatabase' ] ],
1561  [ 'name' => 'tables', 'callback' => [ $installer, 'createTables' ] ],
1562  [ 'name' => 'interwiki', 'callback' => [ $installer, 'populateInterwikiTable' ] ],
1563  [ 'name' => 'stats', 'callback' => [ $this, 'populateSiteStats' ] ],
1564  [ 'name' => 'keys', 'callback' => [ $this, 'generateKeys' ] ],
1565  [ 'name' => 'updates', 'callback' => [ $installer, 'insertUpdateKeys' ] ],
1566  [ 'name' => 'sysop', 'callback' => [ $this, 'createSysop' ] ],
1567  [ 'name' => 'mainpage', 'callback' => [ $this, 'createMainpage' ] ],
1568  ];
1569 
1570  // Build the array of install steps starting from the core install list,
1571  // then adding any callbacks that wanted to attach after a given step
1572  foreach ( $coreInstallSteps as $step ) {
1573  $this->installSteps[] = $step;
1574  if ( isset( $this->extraInstallSteps[$step['name']] ) ) {
1575  $this->installSteps = array_merge(
1576  $this->installSteps,
1577  $this->extraInstallSteps[$step['name']]
1578  );
1579  }
1580  }
1581 
1582  // Prepend any steps that want to be at the beginning
1583  if ( isset( $this->extraInstallSteps['BEGINNING'] ) ) {
1584  $this->installSteps = array_merge(
1585  $this->extraInstallSteps['BEGINNING'],
1586  $this->installSteps
1587  );
1588  }
1589 
1590  // Extensions should always go first, chance to tie into hooks and such
1591  if ( count( $this->getVar( '_Extensions' ) ) ) {
1592  array_unshift( $this->installSteps,
1593  [ 'name' => 'extensions', 'callback' => [ $this, 'includeExtensions' ] ]
1594  );
1595  $this->installSteps[] = [
1596  'name' => 'extension-tables',
1597  'callback' => [ $installer, 'createExtensionTables' ]
1598  ];
1599  }
1600 
1601  return $this->installSteps;
1602  }
1603 
1612  public function performInstallation( $startCB, $endCB ) {
1613  $installResults = [];
1614  $installer = $this->getDBInstaller();
1615  $installer->preInstall();
1616  $steps = $this->getInstallSteps( $installer );
1617  foreach ( $steps as $stepObj ) {
1618  $name = $stepObj['name'];
1619  call_user_func_array( $startCB, [ $name ] );
1620 
1621  // Perform the callback step
1622  $status = call_user_func( $stepObj['callback'], $installer );
1623 
1624  // Output and save the results
1625  call_user_func( $endCB, $name, $status );
1626  $installResults[$name] = $status;
1627 
1628  // If we've hit some sort of fatal, we need to bail.
1629  // Callback already had a chance to do output above.
1630  if ( !$status->isOK() ) {
1631  break;
1632  }
1633  }
1634  if ( $status->isOK() ) {
1635  $this->showMessage(
1636  'config-install-db-success'
1637  );
1638  $this->setVar( '_InstallDone', true );
1639  }
1640 
1641  return $installResults;
1642  }
1643 
1649  public function generateKeys() {
1650  $keys = [ 'wgSecretKey' => 64 ];
1651  if ( strval( $this->getVar( 'wgUpgradeKey' ) ) === '' ) {
1652  $keys['wgUpgradeKey'] = 16;
1653  }
1654 
1655  return $this->doGenerateKeys( $keys );
1656  }
1657 
1664  protected function doGenerateKeys( $keys ) {
1665  $status = Status::newGood();
1666 
1667  foreach ( $keys as $name => $length ) {
1668  $secretKey = MWCryptRand::generateHex( $length );
1669  $this->setVar( $name, $secretKey );
1670  }
1671 
1672  return $status;
1673  }
1674 
1680  protected function createSysop() {
1681  $name = $this->getVar( '_AdminName' );
1682  $user = User::newFromName( $name );
1683 
1684  if ( !$user ) {
1685  // We should've validated this earlier anyway!
1686  return Status::newFatal( 'config-admin-error-user', $name );
1687  }
1688 
1689  if ( $user->idForName() == 0 ) {
1690  $user->addToDatabase();
1691 
1692  try {
1693  $user->setPassword( $this->getVar( '_AdminPassword' ) );
1694  } catch ( PasswordError $pwe ) {
1695  return Status::newFatal( 'config-admin-error-password', $name, $pwe->getMessage() );
1696  }
1697 
1698  $user->addGroup( 'sysop' );
1699  $user->addGroup( 'bureaucrat' );
1700  $user->addGroup( 'interface-admin' );
1701  if ( $this->getVar( '_AdminEmail' ) ) {
1702  $user->setEmail( $this->getVar( '_AdminEmail' ) );
1703  }
1704  $user->saveSettings();
1705 
1706  // Update user count
1707  $ssUpdate = SiteStatsUpdate::factory( [ 'users' => 1 ] );
1708  $ssUpdate->doUpdate();
1709  }
1710  $status = Status::newGood();
1711 
1712  if ( $this->getVar( '_Subscribe' ) && $this->getVar( '_AdminEmail' ) ) {
1713  $this->subscribeToMediaWikiAnnounce( $status );
1714  }
1715 
1716  return $status;
1717  }
1718 
1723  $params = [
1724  'email' => $this->getVar( '_AdminEmail' ),
1725  'language' => 'en',
1726  'digest' => 0
1727  ];
1728 
1729  // Mailman doesn't support as many languages as we do, so check to make
1730  // sure their selected language is available
1731  $myLang = $this->getVar( '_UserLang' );
1732  if ( in_array( $myLang, $this->mediaWikiAnnounceLanguages ) ) {
1733  $myLang = $myLang == 'pt-br' ? 'pt_BR' : $myLang; // rewrite to Mailman's pt_BR
1734  $params['language'] = $myLang;
1735  }
1736 
1738  $res = MWHttpRequest::factory( $this->mediaWikiAnnounceUrl,
1739  [ 'method' => 'POST', 'postData' => $params ], __METHOD__ )->execute();
1740  if ( !$res->isOK() ) {
1741  $s->warning( 'config-install-subscribe-fail', $res->getMessage() );
1742  }
1743  } else {
1744  $s->warning( 'config-install-subscribe-notpossible' );
1745  }
1746  }
1747 
1754  protected function createMainpage( DatabaseInstaller $installer ) {
1755  $status = Status::newGood();
1757  if ( $title->exists() ) {
1758  $status->warning( 'config-install-mainpage-exists' );
1759  return $status;
1760  }
1761  try {
1762  $page = WikiPage::factory( $title );
1763  $content = new WikitextContent(
1764  wfMessage( 'mainpagetext' )->inContentLanguage()->text() . "\n\n" .
1765  wfMessage( 'mainpagedocfooter' )->inContentLanguage()->text()
1766  );
1767 
1768  $status = $page->doEditContent( $content,
1769  '',
1770  EDIT_NEW,
1771  false,
1772  User::newFromName( 'MediaWiki default' )
1773  );
1774  } catch ( Exception $e ) {
1775  // using raw, because $wgShowExceptionDetails can not be set yet
1776  $status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
1777  }
1778 
1779  return $status;
1780  }
1781 
1785  public static function overrideConfig() {
1786  // Use PHP's built-in session handling, since MediaWiki's
1787  // SessionHandler can't work before we have an object cache set up.
1788  if ( !defined( 'MW_NO_SESSION_HANDLER' ) ) {
1789  define( 'MW_NO_SESSION_HANDLER', 1 );
1790  }
1791 
1792  // Don't access the database
1793  $GLOBALS['wgUseDatabaseMessages'] = false;
1794  // Don't cache langconv tables
1795  $GLOBALS['wgLanguageConverterCacheType'] = CACHE_NONE;
1796  // Debug-friendly
1797  $GLOBALS['wgShowExceptionDetails'] = true;
1798  $GLOBALS['wgShowHostnames'] = true;
1799  // Don't break forms
1800  $GLOBALS['wgExternalLinkTarget'] = '_blank';
1801 
1802  // Allow multiple ob_flush() calls
1803  $GLOBALS['wgDisableOutputCompression'] = true;
1804 
1805  // Use a sensible cookie prefix (not my_wiki)
1806  $GLOBALS['wgCookiePrefix'] = 'mw_installer';
1807 
1808  // Some of the environment checks make shell requests, remove limits
1809  $GLOBALS['wgMaxShellMemory'] = 0;
1810 
1811  // Override the default CookieSessionProvider with a dummy
1812  // implementation that won't stomp on PHP's cookies.
1813  $GLOBALS['wgSessionProviders'] = [
1814  [
1815  'class' => InstallerSessionProvider::class,
1816  'args' => [ [
1817  'priority' => 1,
1818  ] ]
1819  ]
1820  ];
1821 
1822  // Don't try to use any object cache for SessionManager either.
1823  $GLOBALS['wgSessionCacheType'] = CACHE_NONE;
1824  }
1825 
1833  public function addInstallStep( $callback, $findStep = 'BEGINNING' ) {
1834  $this->extraInstallSteps[$findStep][] = $callback;
1835  }
1836 
1841  protected function disableTimeLimit() {
1842  Wikimedia\suppressWarnings();
1843  set_time_limit( 0 );
1844  Wikimedia\restoreWarnings();
1845  }
1846 }
static getDBInstallerClass( $type)
Get the DatabaseInstaller class name for this type.
Definition: Installer.php:559
static factory(Title $title)
Create a WikiPage object of the appropriate class for the given title.
Definition: WikiPage.php:142
envCheckServer()
Environment check to inform user which server we&#39;ve assumed.
Definition: Installer.php:968
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
array $internalDefaults
Variables that are stored alongside globals, and are used for any configuration of the installation p...
Definition: Installer.php:195
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
envCheckBrokenXML()
Some versions of libxml+PHP break < and > encoding horribly.
Definition: Installer.php:798
static factory( $url, array $options=null, $caller=__METHOD__)
Generate a new request object.
Title $parserTitle
Cached Title, used by parse().
Definition: Installer.php:87
array $dbInstallers
Cached DB installer instances, access using getDBInstaller().
Definition: Installer.php:73
restoreLinkPopups()
Definition: Installer.php:716
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:648
$IP
Definition: WebStart.php:41
Copyright (C) 2018 Kunal Mehta legoktm@member.fsf.org
envPrepPath()
Environment prep for setting $IP and $wgScriptPath.
Definition: Installer.php:1176
static getInstallerConfig(Config $baseConfig)
Constructs a Config object that contains configuration settings that should be overwritten for the in...
Definition: Installer.php:365
if(!isset( $args[0])) $lang
envCheckShellLocale()
Environment check for preferred locale in shell.
Definition: Installer.php:994
includeExtensions()
Installs the auto-detected extensions.
Definition: Installer.php:1494
envCheckGraphics()
Environment check for ImageMagick and GD.
Definition: Installer.php:920
Class for the core installer web interface.
$source
doEnvironmentPreps()
Definition: Installer.php:513
envCheckGit()
Search for git.
Definition: Installer.php:946
static getInstance( $id)
Get a cached instance of the specified type of cache object.
Definition: ObjectCache.php:78
array $settings
Definition: Installer.php:59
envCheckDiff3()
Search for GNU diff3.
Definition: Installer.php:897
ParserOptions $parserOptions
Cached ParserOptions, used by parse().
Definition: Installer.php:94
envCheckModSecurity()
Scare user to death if they have mod_security or mod_security2.
Definition: Installer.php:884
warning( $message,... $parameters)
Add a new warning.
An interwiki lookup that has no data, intended for use in the installer.
wfIsWindows()
Check if the operating system is Windows.
static canMakeRequests()
Simple function to test if we can make any sort of requests at all, using cURL or fopen() ...
$wgMemc
Definition: Setup.php:767
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:641
get( $name)
Get a configuration variable such as "Sitename" or "UploadMaintenance.".
dirIsExecutable( $dir, $url)
Checks if scripts located in the given directory can be executed via the given URL.
Definition: Installer.php:1190
const CACHE_MEMCACHED
Definition: Defines.php:84
getConnection()
Connect to the database using the administrative user/password currently defined in the session...
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6502
array $objectCaches
Known object cache types and the functions used to test for their existence.
Definition: Installer.php:247
envCheck64Bit()
Checks if we&#39;re running on 64 bit or not.
Definition: Installer.php:1113
showMessage( $msg,... $params)
UI interface for displaying a short message The parameters are like parameters to wfMessage()...
$wgExtensionDirectory
Filesystem extensions directory.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
showStatusMessage(Status $status)
Show a message to the installing user by using a Status object.
envCheckSuhosinMaxValueLength()
Checks if suhosin.get.max_value_length is set, and if so generate a warning because it is incompatibl...
Definition: Installer.php:1095
$mediaWikiAnnounceLanguages
Supported language codes for Mailman.
Definition: Installer.php:326
$wgLang
Definition: Setup.php:857
static getMain()
Get the RequestContext object associated with the main request.
generateKeys()
Generate $wgSecretKey.
Definition: Installer.php:1649
Interface for configuration instances.
Definition: Config.php:28
static maybeGetWebserverPrimaryGroup()
On POSIX systems return the primary group of the webserver we&#39;re running under.
Definition: Installer.php:658
getExtensionInfo( $type, $parentRelPath, $name)
Definition: Installer.php:1342
setParserLanguage( $lang)
ParserOptions are constructed before we determined the language, so fix it.
Definition: Installer.php:1256
array $envPreps
A list of environment preparation methods called by doEnvironmentPreps().
Definition: Installer.php:146
array $envChecks
A list of environment check methods called by doEnvironmentChecks().
Definition: Installer.php:122
addInstallStep( $callback, $findStep='BEGINNING')
Add an installation step following the given step.
Definition: Installer.php:1833
static factory(array $deltas)
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
getDBInstaller( $type=false)
Get an instance of DatabaseInstaller for the specified DB type.
Definition: Installer.php:570
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
Definition: Installer.php:590
doGenerateKeys( $keys)
Generate a secret value for variables using a secure generator.
Definition: Installer.php:1664
int $minMemorySize
Minimum memory size in MB.
Definition: Installer.php:80
getInstallSteps(DatabaseInstaller $installer)
Get an array of install steps.
Definition: Installer.php:1558
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:630
array $compiledDBs
List of detected DBs, access using getCompiledDBs().
Definition: Installer.php:66
getParserOptions()
Definition: Installer.php:708
static generateHex( $chars)
Generate a run of cryptographically random data and return it in hexadecimal string format...
Definition: MWCryptRand.php:36
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:539
findExtensions( $directory='extensions')
Find extensions or skins in a subdirectory of $IP.
Definition: Installer.php:1279
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:212
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:1841
static apacheModulePresent( $moduleName)
Checks for presence of an Apache module.
Definition: Installer.php:1239
$GLOBALS['IP']
Content object for wiki text pages.
Test for PHP+libxml2 bug which breaks XML input subtly with certain versions.
Provides a fallback sequence for Config objects.
Definition: MultiConfig.php:28
$wgHooks
Global list of hooks.
array array $rightsProfiles
User rights profiles.
Definition: Installer.php:258
createMainpage(DatabaseInstaller $installer)
Insert Main Page with default content.
Definition: Installer.php:1754
static findInDefaultPaths( $names, $versionInfo=false)
Same as locateExecutable(), but checks in getPossibleBinPaths() by default.
disableLinkPopups()
Definition: Installer.php:712
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
Definition: Installer.php:688
envCheckCache()
Environment check for compiled object cache types.
Definition: Installer.php:865
envCheckUploadsDirectory()
Environment check for the permissions of the uploads directory.
Definition: Installer.php:1076
performInstallation( $startCB, $endCB)
Actually perform the installation.
Definition: Installer.php:1612
const MINIMUM_PCRE_VERSION
The oldest version of PCRE we can support.
Definition: Installer.php:54
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:539
envCheckDB()
Environment check for DB types.
Definition: Installer.php:756
showError( $msg,... $params)
Same as showMessage(), but for displaying errors.
$lines
Definition: router.php:61
getDocUrl( $page)
Overridden by WebInstaller to provide lastPage parameters.
Definition: Installer.php:1266
populateSiteStats(DatabaseInstaller $installer)
Install step which adds a row to the site_stats table with appropriate initial values.
Definition: Installer.php:729
Show an error when any operation involving passwords fails to run.
array $extraInstallSteps
Extra steps for installation, for things like DatabaseInstallers to modify.
Definition: Installer.php:240
getCompiledDBs()
Get a list of DBs supported by current PHP setup.
Definition: Installer.php:548
const EDIT_NEW
Definition: Defines.php:132
array array array $licenses
License types.
Definition: Installer.php:283
envGetDefaultServer()
Helper function to be called from envPrepServer()
envCheckPCRE()
Environment check for the PCRE module.
Definition: Installer.php:817
envCheckPath()
Environment check to inform user which paths we&#39;ve assumed.
Definition: Installer.php:981
$line
Definition: cdb.php:59
const CACHE_ANYTHING
Definition: Defines.php:81
__construct()
Constructor, always call this from child classes.
Definition: Installer.php:403
$wgStyleDirectory
Filesystem stylesheets directory.
static array $dbTypes
Known database types.
Definition: Installer.php:105
if(!is_readable( $file)) $ext
Definition: router.php:48
Base class for DBMS-specific installation helper classes.
static overrideConfig()
Override the necessary bits of the config to run an installation.
Definition: Installer.php:1785
Base installer class.
Definition: Installer.php:46
static clearCaches()
Intended for tests that may change configuration in a way that invalidates caches.
Definition: Language.php:282
$wgObjectCaches
Advanced object cache configuration.
$content
Definition: router.php:78
static getDBTypes()
Get a list of known DB types.
Definition: Installer.php:471
$wgAutoloadClasses
Array mapping class names to filenames, for autoloading.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:525
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:515
findExtensionsByType( $type='extension', $directory='extensions')
Find extensions or skins, and return an array containing the value for &#39;Name&#39; for each found extensio...
Definition: Installer.php:1299
const CACHE_NONE
Definition: Defines.php:82
envCheckLibicu()
Check the libicu version.
Definition: Installer.php:1124
$wgExternalLinkTarget
Set a default target for external links, e.g.
envCheckMemory()
Environment check for available memory.
Definition: Installer.php:839
doEnvironmentChecks()
Do initial checks of the PHP environment.
Definition: Installer.php:488
createSysop()
Create the first user account, grant it sysop, bureaucrat and interface-admin rights.
Definition: Installer.php:1680
A Config instance which stores all settings as a member variable.
Definition: HashConfig.php:28
readExtension( $fullJsonFile, $extDeps=[], $skinDeps=[])
Definition: Installer.php:1395
envPrepServer()
Environment prep for the server hostname.
Definition: Installer.php:1160
wfShorthandToInteger( $string='', $default=-1)
Converts shorthand byte notation to integer form.
array array array $mediaWikiAnnounceUrl
URL to mediawiki-announce subscription.
Definition: Installer.php:320
array $defaultVarNames
MediaWiki configuration globals that will eventually be passed through to LocalSettings.php.
Definition: Installer.php:158
const CACHE_DB
Definition: Defines.php:83
subscribeToMediaWikiAnnounce(Status $s)
Definition: Installer.php:1722
array array [] $installSteps
The actual list of installation steps.
Definition: Installer.php:233
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319
getDefaultSkin(array $skinNames)
Returns a default value to be used for $wgDefaultSkin: normally the one set in DefaultSettings, but will fall back to another if the default skin is missing and some other one is present instead.
Definition: Installer.php:1479