MediaWiki  1.29.2
DatabaseUpdater.php
Go to the documentation of this file.
1 <?php
26 
27 require_once __DIR__ . '/../../maintenance/Maintenance.php';
28 
36 abstract class DatabaseUpdater {
42  protected $updates = [];
43 
49  protected $updatesSkipped = [];
50 
55  protected $extensionUpdates = [];
56 
62  protected $db;
63 
67  protected $maintenance;
68 
69  protected $shared = false;
70 
86  ];
87 
93  protected $fileHandle = null;
94 
100  protected $skipSchema = false;
101 
105  protected $holdContentHandlerUseDB = true;
106 
114  protected function __construct( Database &$db, $shared, Maintenance $maintenance = null ) {
115  $this->db = $db;
116  $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files
117  $this->shared = $shared;
118  if ( $maintenance ) {
119  $this->maintenance = $maintenance;
120  $this->fileHandle = $maintenance->fileHandle;
121  } else {
122  $this->maintenance = new FakeMaintenance;
123  }
124  $this->maintenance->setDB( $db );
125  $this->initOldGlobals();
126  $this->loadExtensions();
127  Hooks::run( 'LoadExtensionSchemaUpdates', [ $this ] );
128  }
129 
134  private function initOldGlobals() {
135  global $wgExtNewTables, $wgExtNewFields, $wgExtPGNewFields,
136  $wgExtPGAlteredFields, $wgExtNewIndexes, $wgExtModifiedFields;
137 
138  # For extensions only, should be populated via hooks
139  # $wgDBtype should be checked to specifiy the proper file
140  $wgExtNewTables = []; // table, dir
141  $wgExtNewFields = []; // table, column, dir
142  $wgExtPGNewFields = []; // table, column, column attributes; for PostgreSQL
143  $wgExtPGAlteredFields = []; // table, column, new type, conversion method; for PostgreSQL
144  $wgExtNewIndexes = []; // table, index, dir
145  $wgExtModifiedFields = []; // table, index, dir
146  }
147 
152  private function loadExtensions() {
153  if ( !defined( 'MEDIAWIKI_INSTALL' ) ) {
154  return; // already loaded
155  }
157 
158  $registry = ExtensionRegistry::getInstance();
159  $queue = $registry->getQueue();
160  // Don't accidentally load extensions in the future
161  $registry->clearQueue();
162 
163  // This will automatically add "AutoloadClasses" to $wgAutoloadClasses
164  $data = $registry->readFromQueue( $queue );
165  $hooks = [ 'wgHooks' => [ 'LoadExtensionSchemaUpdates' => [] ] ];
166  if ( isset( $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
167  $hooks = $data['globals']['wgHooks']['LoadExtensionSchemaUpdates'];
168  }
169  if ( $vars && isset( $vars['wgHooks']['LoadExtensionSchemaUpdates'] ) ) {
170  $hooks = array_merge_recursive( $hooks, $vars['wgHooks']['LoadExtensionSchemaUpdates'] );
171  }
173  $wgHooks['LoadExtensionSchemaUpdates'] = $hooks;
174  if ( $vars && isset( $vars['wgAutoloadClasses'] ) ) {
175  $wgAutoloadClasses += $vars['wgAutoloadClasses'];
176  }
177  }
178 
187  public static function newForDB( Database $db, $shared = false, $maintenance = null ) {
188  $type = $db->getType();
189  if ( in_array( $type, Installer::getDBTypes() ) ) {
190  $class = ucfirst( $type ) . 'Updater';
191 
192  return new $class( $db, $shared, $maintenance );
193  } else {
194  throw new MWException( __METHOD__ . ' called for unsupported $wgDBtype' );
195  }
196  }
197 
203  public function getDB() {
204  return $this->db;
205  }
206 
212  public function output( $str ) {
213  if ( $this->maintenance->isQuiet() ) {
214  return;
215  }
217  if ( !$wgCommandLineMode ) {
218  $str = htmlspecialchars( $str );
219  }
220  echo $str;
221  flush();
222  }
223 
236  public function addExtensionUpdate( array $update ) {
237  $this->extensionUpdates[] = $update;
238  }
239 
249  public function addExtensionTable( $tableName, $sqlPath ) {
250  $this->extensionUpdates[] = [ 'addTable', $tableName, $sqlPath, true ];
251  }
252 
260  public function addExtensionIndex( $tableName, $indexName, $sqlPath ) {
261  $this->extensionUpdates[] = [ 'addIndex', $tableName, $indexName, $sqlPath, true ];
262  }
263 
272  public function addExtensionField( $tableName, $columnName, $sqlPath ) {
273  $this->extensionUpdates[] = [ 'addField', $tableName, $columnName, $sqlPath, true ];
274  }
275 
284  public function dropExtensionField( $tableName, $columnName, $sqlPath ) {
285  $this->extensionUpdates[] = [ 'dropField', $tableName, $columnName, $sqlPath, true ];
286  }
287 
297  public function dropExtensionIndex( $tableName, $indexName, $sqlPath ) {
298  $this->extensionUpdates[] = [ 'dropIndex', $tableName, $indexName, $sqlPath, true ];
299  }
300 
308  public function dropExtensionTable( $tableName, $sqlPath ) {
309  $this->extensionUpdates[] = [ 'dropTable', $tableName, $sqlPath, true ];
310  }
311 
324  public function renameExtensionIndex( $tableName, $oldIndexName, $newIndexName,
325  $sqlPath, $skipBothIndexExistWarning = false
326  ) {
327  $this->extensionUpdates[] = [
328  'renameIndex',
329  $tableName,
330  $oldIndexName,
331  $newIndexName,
332  $skipBothIndexExistWarning,
333  $sqlPath,
334  true
335  ];
336  }
337 
345  public function modifyExtensionField( $tableName, $fieldName, $sqlPath ) {
346  $this->extensionUpdates[] = [ 'modifyField', $tableName, $fieldName, $sqlPath, true ];
347  }
348 
356  public function tableExists( $tableName ) {
357  return ( $this->db->tableExists( $tableName, __METHOD__ ) );
358  }
359 
369  public function addPostDatabaseUpdateMaintenance( $class ) {
370  $this->postDatabaseUpdateMaintenance[] = $class;
371  }
372 
378  protected function getExtensionUpdates() {
380  }
381 
389  }
390 
397  private function writeSchemaUpdateFile( array $schemaUpdate = [] ) {
399  $this->updatesSkipped = [];
400 
401  foreach ( $updates as $funcList ) {
402  $func = $funcList[0];
403  $arg = $funcList[1];
404  $origParams = $funcList[2];
405  call_user_func_array( $func, $arg );
406  flush();
407  $this->updatesSkipped[] = $origParams;
408  }
409  }
410 
421  public function getSchemaVars() {
422  return []; // DB-type specific
423  }
424 
430  public function doUpdates( array $what = [ 'core', 'extensions', 'stats' ] ) {
431  $this->db->setSchemaVars( $this->getSchemaVars() );
432 
433  $what = array_flip( $what );
434  $this->skipSchema = isset( $what['noschema'] ) || $this->fileHandle !== null;
435  if ( isset( $what['core'] ) ) {
436  $this->runUpdates( $this->getCoreUpdateList(), false );
437  }
438  if ( isset( $what['extensions'] ) ) {
439  $this->runUpdates( $this->getOldGlobalUpdates(), false );
440  $this->runUpdates( $this->getExtensionUpdates(), true );
441  }
442 
443  if ( isset( $what['stats'] ) ) {
444  $this->checkStats();
445  }
446 
447  if ( $this->fileHandle ) {
448  $this->skipSchema = false;
449  $this->writeSchemaUpdateFile();
450  }
451  }
452 
459  private function runUpdates( array $updates, $passSelf ) {
460  $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
461 
462  $updatesDone = [];
463  $updatesSkipped = [];
464  foreach ( $updates as $params ) {
465  $origParams = $params;
466  $func = array_shift( $params );
467  if ( !is_array( $func ) && method_exists( $this, $func ) ) {
468  $func = [ $this, $func ];
469  } elseif ( $passSelf ) {
470  array_unshift( $params, $this );
471  }
472  $ret = call_user_func_array( $func, $params );
473  flush();
474  if ( $ret !== false ) {
475  $updatesDone[] = $origParams;
476  $lbFactory->waitForReplication();
477  } else {
478  $updatesSkipped[] = [ $func, $params, $origParams ];
479  }
480  }
481  $this->updatesSkipped = array_merge( $this->updatesSkipped, $updatesSkipped );
482  $this->updates = array_merge( $this->updates, $updatesDone );
483  }
484 
492  public function updateRowExists( $key ) {
493  $row = $this->db->selectRow(
494  'updatelog',
495  # T67813
496  '1 AS X',
497  [ 'ul_key' => $key ],
498  __METHOD__
499  );
500 
501  return (bool)$row;
502  }
503 
511  public function insertUpdateRow( $key, $val = null ) {
512  $this->db->clearFlag( DBO_DDLMODE );
513  $values = [ 'ul_key' => $key ];
514  if ( $val && $this->canUseNewUpdatelog() ) {
515  $values['ul_value'] = $val;
516  }
517  $this->db->insert( 'updatelog', $values, __METHOD__, 'IGNORE' );
518  $this->db->setFlag( DBO_DDLMODE );
519  }
520 
529  protected function canUseNewUpdatelog() {
530  return $this->db->tableExists( 'updatelog', __METHOD__ ) &&
531  $this->db->fieldExists( 'updatelog', 'ul_value', __METHOD__ );
532  }
533 
542  protected function doTable( $name ) {
544 
545  // Don't bother to check $wgSharedTables if there isn't a shared database
546  // or the user actually also wants to do updates on the shared database.
547  if ( $wgSharedDB === null || $this->shared ) {
548  return true;
549  }
550 
551  if ( in_array( $name, $wgSharedTables ) ) {
552  $this->output( "...skipping update to shared table $name.\n" );
553  return false;
554  } else {
555  return true;
556  }
557  }
558 
567  protected function getOldGlobalUpdates() {
568  global $wgExtNewFields, $wgExtNewTables, $wgExtModifiedFields,
569  $wgExtNewIndexes;
570 
571  $updates = [];
572 
573  foreach ( $wgExtNewTables as $tableRecord ) {
574  $updates[] = [
575  'addTable', $tableRecord[0], $tableRecord[1], true
576  ];
577  }
578 
579  foreach ( $wgExtNewFields as $fieldRecord ) {
580  $updates[] = [
581  'addField', $fieldRecord[0], $fieldRecord[1],
582  $fieldRecord[2], true
583  ];
584  }
585 
586  foreach ( $wgExtNewIndexes as $fieldRecord ) {
587  $updates[] = [
588  'addIndex', $fieldRecord[0], $fieldRecord[1],
589  $fieldRecord[2], true
590  ];
591  }
592 
593  foreach ( $wgExtModifiedFields as $fieldRecord ) {
594  $updates[] = [
595  'modifyField', $fieldRecord[0], $fieldRecord[1],
596  $fieldRecord[2], true
597  ];
598  }
599 
600  return $updates;
601  }
602 
611  abstract protected function getCoreUpdateList();
612 
618  public function copyFile( $filename ) {
619  $this->db->sourceFile(
620  $filename,
621  null,
622  null,
623  __METHOD__,
624  [ $this, 'appendLine' ]
625  );
626  }
627 
638  public function appendLine( $line ) {
639  $line = rtrim( $line ) . ";\n";
640  if ( fwrite( $this->fileHandle, $line ) === false ) {
641  throw new MWException( "trouble writing file" );
642  }
643 
644  return false;
645  }
646 
655  protected function applyPatch( $path, $isFullPath = false, $msg = null ) {
656  if ( $msg === null ) {
657  $msg = "Applying $path patch";
658  }
659  if ( $this->skipSchema ) {
660  $this->output( "...skipping schema change ($msg).\n" );
661 
662  return false;
663  }
664 
665  $this->output( "$msg ..." );
666 
667  if ( !$isFullPath ) {
668  $path = $this->patchPath( $this->db, $path );
669  }
670  if ( $this->fileHandle !== null ) {
671  $this->copyFile( $path );
672  } else {
673  $this->db->sourceFile( $path );
674  }
675  $this->output( "done.\n" );
676 
677  return true;
678  }
679 
689  public function patchPath( IDatabase $db, $patch ) {
690  global $IP;
691 
692  $dbType = $db->getType();
693  if ( file_exists( "$IP/maintenance/$dbType/archives/$patch" ) ) {
694  return "$IP/maintenance/$dbType/archives/$patch";
695  } else {
696  return "$IP/maintenance/archives/$patch";
697  }
698  }
699 
708  protected function addTable( $name, $patch, $fullpath = false ) {
709  if ( !$this->doTable( $name ) ) {
710  return true;
711  }
712 
713  if ( $this->db->tableExists( $name, __METHOD__ ) ) {
714  $this->output( "...$name table already exists.\n" );
715  } else {
716  return $this->applyPatch( $patch, $fullpath, "Creating $name table" );
717  }
718 
719  return true;
720  }
721 
731  protected function addField( $table, $field, $patch, $fullpath = false ) {
732  if ( !$this->doTable( $table ) ) {
733  return true;
734  }
735 
736  if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
737  $this->output( "...$table table does not exist, skipping new field patch.\n" );
738  } elseif ( $this->db->fieldExists( $table, $field, __METHOD__ ) ) {
739  $this->output( "...have $field field in $table table.\n" );
740  } else {
741  return $this->applyPatch( $patch, $fullpath, "Adding $field field to table $table" );
742  }
743 
744  return true;
745  }
746 
756  protected function addIndex( $table, $index, $patch, $fullpath = false ) {
757  if ( !$this->doTable( $table ) ) {
758  return true;
759  }
760 
761  if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
762  $this->output( "...skipping: '$table' table doesn't exist yet.\n" );
763  } elseif ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
764  $this->output( "...index $index already set on $table table.\n" );
765  } else {
766  return $this->applyPatch( $patch, $fullpath, "Adding index $index to table $table" );
767  }
768 
769  return true;
770  }
771 
781  protected function dropField( $table, $field, $patch, $fullpath = false ) {
782  if ( !$this->doTable( $table ) ) {
783  return true;
784  }
785 
786  if ( $this->db->fieldExists( $table, $field, __METHOD__ ) ) {
787  return $this->applyPatch( $patch, $fullpath, "Table $table contains $field field. Dropping" );
788  } else {
789  $this->output( "...$table table does not contain $field field.\n" );
790  }
791 
792  return true;
793  }
794 
804  protected function dropIndex( $table, $index, $patch, $fullpath = false ) {
805  if ( !$this->doTable( $table ) ) {
806  return true;
807  }
808 
809  if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
810  return $this->applyPatch( $patch, $fullpath, "Dropping $index index from table $table" );
811  } else {
812  $this->output( "...$index key doesn't exist.\n" );
813  }
814 
815  return true;
816  }
817 
830  protected function renameIndex( $table, $oldIndex, $newIndex,
831  $skipBothIndexExistWarning, $patch, $fullpath = false
832  ) {
833  if ( !$this->doTable( $table ) ) {
834  return true;
835  }
836 
837  // First requirement: the table must exist
838  if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
839  $this->output( "...skipping: '$table' table doesn't exist yet.\n" );
840 
841  return true;
842  }
843 
844  // Second requirement: the new index must be missing
845  if ( $this->db->indexExists( $table, $newIndex, __METHOD__ ) ) {
846  $this->output( "...index $newIndex already set on $table table.\n" );
847  if ( !$skipBothIndexExistWarning &&
848  $this->db->indexExists( $table, $oldIndex, __METHOD__ )
849  ) {
850  $this->output( "...WARNING: $oldIndex still exists, despite it has " .
851  "been renamed into $newIndex (which also exists).\n" .
852  " $oldIndex should be manually removed if not needed anymore.\n" );
853  }
854 
855  return true;
856  }
857 
858  // Third requirement: the old index must exist
859  if ( !$this->db->indexExists( $table, $oldIndex, __METHOD__ ) ) {
860  $this->output( "...skipping: index $oldIndex doesn't exist.\n" );
861 
862  return true;
863  }
864 
865  // Requirements have been satisfied, patch can be applied
866  return $this->applyPatch(
867  $patch,
868  $fullpath,
869  "Renaming index $oldIndex into $newIndex to table $table"
870  );
871  }
872 
884  public function dropTable( $table, $patch = false, $fullpath = false ) {
885  if ( !$this->doTable( $table ) ) {
886  return true;
887  }
888 
889  if ( $this->db->tableExists( $table, __METHOD__ ) ) {
890  $msg = "Dropping table $table";
891 
892  if ( $patch === false ) {
893  $this->output( "$msg ..." );
894  $this->db->dropTable( $table, __METHOD__ );
895  $this->output( "done.\n" );
896  } else {
897  return $this->applyPatch( $patch, $fullpath, $msg );
898  }
899  } else {
900  $this->output( "...$table doesn't exist.\n" );
901  }
902 
903  return true;
904  }
905 
915  public function modifyField( $table, $field, $patch, $fullpath = false ) {
916  if ( !$this->doTable( $table ) ) {
917  return true;
918  }
919 
920  $updateKey = "$table-$field-$patch";
921  if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
922  $this->output( "...$table table does not exist, skipping modify field patch.\n" );
923  } elseif ( !$this->db->fieldExists( $table, $field, __METHOD__ ) ) {
924  $this->output( "...$field field does not exist in $table table, " .
925  "skipping modify field patch.\n" );
926  } elseif ( $this->updateRowExists( $updateKey ) ) {
927  $this->output( "...$field in table $table already modified by patch $patch.\n" );
928  } else {
929  $this->insertUpdateRow( $updateKey );
930 
931  return $this->applyPatch( $patch, $fullpath, "Modifying $field field of table $table" );
932  }
933 
934  return true;
935  }
936 
942  public function setFileAccess() {
943  $repo = RepoGroup::singleton()->getLocalRepo();
944  $zonePath = $repo->getZonePath( 'temp' );
945  if ( $repo->getBackend()->directoryExists( [ 'dir' => $zonePath ] ) ) {
946  // If the directory was never made, then it will have the right ACLs when it is made
947  $status = $repo->getBackend()->secure( [
948  'dir' => $zonePath,
949  'noAccess' => true,
950  'noListing' => true
951  ] );
952  if ( $status->isOK() ) {
953  $this->output( "Set the local repo temp zone container to be private.\n" );
954  } else {
955  $this->output( "Failed to set the local repo temp zone container to be private.\n" );
956  }
957  }
958  }
959 
963  public function purgeCache() {
965  # We can't guarantee that the user will be able to use TRUNCATE,
966  # but we know that DELETE is available to us
967  $this->output( "Purging caches..." );
968  $this->db->delete( 'objectcache', '*', __METHOD__ );
969  if ( $wgLocalisationCacheConf['manualRecache'] ) {
970  $this->rebuildLocalisationCache();
971  }
972  $blobStore = new MessageBlobStore();
973  $blobStore->clear();
974  $this->db->delete( 'module_deps', '*', __METHOD__ );
975  $this->output( "done.\n" );
976  }
977 
981  protected function checkStats() {
982  $this->output( "...site_stats is populated..." );
983  $row = $this->db->selectRow( 'site_stats', '*', [ 'ss_row_id' => 1 ], __METHOD__ );
984  if ( $row === false ) {
985  $this->output( "data is missing! rebuilding...\n" );
986  } elseif ( isset( $row->site_stats ) && $row->ss_total_pages == -1 ) {
987  $this->output( "missing ss_total_pages, rebuilding...\n" );
988  } else {
989  $this->output( "done.\n" );
990 
991  return;
992  }
993  SiteStatsInit::doAllAndCommit( $this->db );
994  }
995 
996  # Common updater functions
997 
1001  protected function doActiveUsersInit() {
1002  $activeUsers = $this->db->selectField( 'site_stats', 'ss_active_users', false, __METHOD__ );
1003  if ( $activeUsers == -1 ) {
1004  $activeUsers = $this->db->selectField( 'recentchanges',
1005  'COUNT( DISTINCT rc_user_text )',
1006  [ 'rc_user != 0', 'rc_bot' => 0, "rc_log_type != 'newusers'" ], __METHOD__
1007  );
1008  $this->db->update( 'site_stats',
1009  [ 'ss_active_users' => intval( $activeUsers ) ],
1010  [ 'ss_row_id' => 1 ], __METHOD__, [ 'LIMIT' => 1 ]
1011  );
1012  }
1013  $this->output( "...ss_active_users user count set...\n" );
1014  }
1015 
1019  protected function doLogUsertextPopulation() {
1020  if ( !$this->updateRowExists( 'populate log_usertext' ) ) {
1021  $this->output(
1022  "Populating log_user_text field, printing progress markers. For large\n" .
1023  "databases, you may want to hit Ctrl-C and do this manually with\n" .
1024  "maintenance/populateLogUsertext.php.\n"
1025  );
1026 
1027  $task = $this->maintenance->runChild( 'PopulateLogUsertext' );
1028  $task->execute();
1029  $this->output( "done.\n" );
1030  }
1031  }
1032 
1036  protected function doLogSearchPopulation() {
1037  if ( !$this->updateRowExists( 'populate log_search' ) ) {
1038  $this->output(
1039  "Populating log_search table, printing progress markers. For large\n" .
1040  "databases, you may want to hit Ctrl-C and do this manually with\n" .
1041  "maintenance/populateLogSearch.php.\n" );
1042 
1043  $task = $this->maintenance->runChild( 'PopulateLogSearch' );
1044  $task->execute();
1045  $this->output( "done.\n" );
1046  }
1047  }
1048 
1053  protected function doUpdateTranscacheField() {
1054  if ( $this->updateRowExists( 'convert transcache field' ) ) {
1055  $this->output( "...transcache tc_time already converted.\n" );
1056 
1057  return true;
1058  }
1059 
1060  return $this->applyPatch( 'patch-tc-timestamp.sql', false,
1061  "Converting tc_time from UNIX epoch to MediaWiki timestamp" );
1062  }
1063 
1067  protected function doCollationUpdate() {
1068  global $wgCategoryCollation;
1069  if ( $this->db->fieldExists( 'categorylinks', 'cl_collation', __METHOD__ ) ) {
1070  if ( $this->db->selectField(
1071  'categorylinks',
1072  'COUNT(*)',
1073  'cl_collation != ' . $this->db->addQuotes( $wgCategoryCollation ),
1074  __METHOD__
1075  ) == 0
1076  ) {
1077  $this->output( "...collations up-to-date.\n" );
1078 
1079  return;
1080  }
1081 
1082  $this->output( "Updating category collations..." );
1083  $task = $this->maintenance->runChild( 'UpdateCollation' );
1084  $task->execute();
1085  $this->output( "...done.\n" );
1086  }
1087  }
1088 
1092  protected function doMigrateUserOptions() {
1093  if ( $this->db->tableExists( 'user_properties' ) ) {
1094  $cl = $this->maintenance->runChild( 'ConvertUserOptions', 'convertUserOptions.php' );
1095  $cl->execute();
1096  $this->output( "done.\n" );
1097  }
1098  }
1099 
1103  protected function doEnableProfiling() {
1105 
1106  if ( !$this->doTable( 'profiling' ) ) {
1107  return;
1108  }
1109 
1110  $profileToDb = false;
1111  if ( isset( $wgProfiler['output'] ) ) {
1112  $out = $wgProfiler['output'];
1113  if ( $out === 'db' ) {
1114  $profileToDb = true;
1115  } elseif ( is_array( $out ) && in_array( 'db', $out ) ) {
1116  $profileToDb = true;
1117  }
1118  }
1119 
1120  if ( $profileToDb && !$this->db->tableExists( 'profiling', __METHOD__ ) ) {
1121  $this->applyPatch( 'patch-profiling.sql', false, 'Add profiling table' );
1122  }
1123  }
1124 
1128  protected function rebuildLocalisationCache() {
1132  $cl = $this->maintenance->runChild( 'RebuildLocalisationCache', 'rebuildLocalisationCache.php' );
1133  $this->output( "Rebuilding localisation cache...\n" );
1134  $cl->setForce();
1135  $cl->execute();
1136  $this->output( "done.\n" );
1137  }
1138 
1143  protected function disableContentHandlerUseDB() {
1144  global $wgContentHandlerUseDB;
1145 
1146  if ( $wgContentHandlerUseDB ) {
1147  $this->output( "Turning off Content Handler DB fields for this part of upgrade.\n" );
1148  $this->holdContentHandlerUseDB = $wgContentHandlerUseDB;
1149  $wgContentHandlerUseDB = false;
1150  }
1151  }
1152 
1156  protected function enableContentHandlerUseDB() {
1157  global $wgContentHandlerUseDB;
1158 
1159  if ( $this->holdContentHandlerUseDB ) {
1160  $this->output( "Content Handler DB fields should be usable now.\n" );
1161  $wgContentHandlerUseDB = $this->holdContentHandlerUseDB;
1162  }
1163  }
1164 }
DatabaseUpdater\output
output( $str)
Output some text.
Definition: DatabaseUpdater.php:212
DatabaseUpdater\dropIndex
dropIndex( $table, $index, $patch, $fullpath=false)
Drop an index from an existing table.
Definition: DatabaseUpdater.php:804
DatabaseUpdater\dropTable
dropTable( $table, $patch=false, $fullpath=false)
If the specified table exists, drop it, or execute the patch if one is provided.
Definition: DatabaseUpdater.php:884
DatabaseUpdater\copyFile
copyFile( $filename)
Append an SQL fragment to the open file handle.
Definition: DatabaseUpdater.php:618
DatabaseUpdater\$updatesSkipped
array $updatesSkipped
Array of updates that were skipped.
Definition: DatabaseUpdater.php:49
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:45
RepoGroup\singleton
static singleton()
Get a RepoGroup instance.
Definition: RepoGroup.php:59
DatabaseUpdater\applyPatch
applyPatch( $path, $isFullPath=false, $msg=null)
Applies a SQL patch.
Definition: DatabaseUpdater.php:655
DatabaseUpdater\doCollationUpdate
doCollationUpdate()
Update CategoryLinks collation.
Definition: DatabaseUpdater.php:1067
SiteStatsInit\doAllAndCommit
static doAllAndCommit( $database, array $options=[])
Do all updates and commit them.
Definition: SiteStats.php:386
$wgSharedTables
$wgSharedTables
Definition: DefaultSettings.php:1887
DatabaseUpdater
Class for handling database updates.
Definition: DatabaseUpdater.php:36
$wgAutoloadClasses
global $wgAutoloadClasses
Definition: TestsAutoLoader.php:24
DatabaseUpdater\addPostDatabaseUpdateMaintenance
addPostDatabaseUpdateMaintenance( $class)
Add a maintenance script to be run after the database updates are complete.
Definition: DatabaseUpdater.php:369
DatabaseUpdater\checkStats
checkStats()
Check the site_stats table is not properly populated.
Definition: DatabaseUpdater.php:981
$wgSharedDB
$wgSharedDB
Shared database for multiple wikis.
Definition: DefaultSettings.php:1877
DatabaseUpdater\getCoreUpdateList
getCoreUpdateList()
Get an array of updates to perform on the database.
DatabaseUpdater\doMigrateUserOptions
doMigrateUserOptions()
Migrates user options from the user table blob to user_properties.
Definition: DatabaseUpdater.php:1092
$status
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition: hooks.txt:1049
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
DatabaseUpdater\dropField
dropField( $table, $field, $patch, $fullpath=false)
Drop a field from an existing table.
Definition: DatabaseUpdater.php:781
DatabaseUpdater\enableContentHandlerUseDB
enableContentHandlerUseDB()
Turns content handler fields back on.
Definition: DatabaseUpdater.php:1156
DatabaseUpdater\addField
addField( $table, $field, $patch, $fullpath=false)
Add a new field to an existing table.
Definition: DatabaseUpdater.php:731
DatabaseUpdater\doTable
doTable( $name)
Returns whether updates should be executed on the database table $name.
Definition: DatabaseUpdater.php:542
$params
$params
Definition: styleTest.css.php:40
DatabaseUpdater\getPostDatabaseUpdateMaintenance
getPostDatabaseUpdateMaintenance()
Definition: DatabaseUpdater.php:387
Maintenance\setDB
setDB(IDatabase $db)
Sets database object to be returned by getDB().
Definition: Maintenance.php:1264
DatabaseUpdater\appendLine
appendLine( $line)
Append a line to the open filehandle.
Definition: DatabaseUpdater.php:638
$name
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:304
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: maintenance.txt:39
DatabaseUpdater\patchPath
patchPath(IDatabase $db, $patch)
Get the full path of a patch file.
Definition: DatabaseUpdater.php:689
$type
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
Definition: hooks.txt:2536
DatabaseUpdater\getSchemaVars
getSchemaVars()
Get appropriate schema variables in the current database connection.
Definition: DatabaseUpdater.php:421
$lbFactory
$lbFactory
Definition: doMaintenance.php:117
DatabaseUpdater\addExtensionIndex
addExtensionIndex( $tableName, $indexName, $sqlPath)
Definition: DatabaseUpdater.php:260
DatabaseUpdater\$db
Database $db
Handle to the database subclass.
Definition: DatabaseUpdater.php:62
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:40
DatabaseUpdater\doActiveUsersInit
doActiveUsersInit()
Sets the number of active users in the site_stats table.
Definition: DatabaseUpdater.php:1001
DatabaseUpdater\dropExtensionIndex
dropExtensionIndex( $tableName, $indexName, $sqlPath)
Drop an index from an extension table.
Definition: DatabaseUpdater.php:297
DatabaseUpdater\$updates
array $updates
Array of updates to perform on the database.
Definition: DatabaseUpdater.php:42
DatabaseUpdater\doEnableProfiling
doEnableProfiling()
Enable profiling table when it's turned on.
Definition: DatabaseUpdater.php:1103
ExtensionRegistry\getInstance
static getInstance()
Definition: ExtensionRegistry.php:80
DatabaseUpdater\addExtensionUpdate
addExtensionUpdate(array $update)
Add a new update coming from an extension.
Definition: DatabaseUpdater.php:236
updates
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these updates(as a Java servelet could)
DatabaseUpdater\setFileAccess
setFileAccess()
Set any .htaccess files or equivilent for storage repos.
Definition: DatabaseUpdater.php:942
MWException
MediaWiki exception.
Definition: MWException.php:26
DatabaseUpdater\renameIndex
renameIndex( $table, $oldIndex, $newIndex, $skipBothIndexExistWarning, $patch, $fullpath=false)
Rename an index from an existing table.
Definition: DatabaseUpdater.php:830
DatabaseUpdater\getExtensionUpdates
getExtensionUpdates()
Get the list of extension-defined updates.
Definition: DatabaseUpdater.php:378
DatabaseUpdater\$maintenance
Maintenance $maintenance
Definition: DatabaseUpdater.php:67
$wgCommandLineMode
global $wgCommandLineMode
Definition: Setup.php:503
Wikimedia\Rdbms\Database\setFlag
setFlag( $flag, $remember=self::REMEMBER_NOTHING)
Set a flag for this connection.
Definition: Database.php:602
$IP
$IP
Definition: update.php:3
DatabaseUpdater\modifyExtensionField
modifyExtensionField( $tableName, $fieldName, $sqlPath)
Definition: DatabaseUpdater.php:345
DatabaseUpdater\rebuildLocalisationCache
rebuildLocalisationCache()
Rebuilds the localisation cache.
Definition: DatabaseUpdater.php:1128
$queue
$queue
Definition: mergeMessageFileList.php:161
Installer\getExistingLocalSettings
static getExistingLocalSettings()
Determine if LocalSettings.php exists.
Definition: Installer.php:574
DatabaseUpdater\getDB
getDB()
Get a database connection to run updates.
Definition: DatabaseUpdater.php:203
$wgLocalisationCacheConf
$wgLocalisationCacheConf
Localisation cache configuration.
Definition: DefaultSettings.php:2489
DatabaseUpdater\runUpdates
runUpdates(array $updates, $passSelf)
Helper function for doUpdates()
Definition: DatabaseUpdater.php:459
DatabaseUpdater\doUpdates
doUpdates(array $what=[ 'core', 'extensions', 'stats'])
Do all the updates.
Definition: DatabaseUpdater.php:430
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
$vars
static configuration should be added through ResourceLoaderGetConfigVars instead & $vars
Definition: hooks.txt:2179
FakeMaintenance
Fake maintenance wrapper, mostly used for the web installer/updater.
Definition: Maintenance.php:1550
DatabaseUpdater\updateRowExists
updateRowExists( $key)
Helper function: check if the given key is present in the updatelog table.
Definition: DatabaseUpdater.php:492
DatabaseUpdater\disableContentHandlerUseDB
disableContentHandlerUseDB()
Turns off content handler fields during parts of the upgrade where they aren't available.
Definition: DatabaseUpdater.php:1143
DatabaseUpdater\doLogSearchPopulation
doLogSearchPopulation()
Migrate log params to new table and index for searching.
Definition: DatabaseUpdater.php:1036
$line
$line
Definition: cdb.php:58
DatabaseUpdater\doUpdateTranscacheField
doUpdateTranscacheField()
Updates the timestamps in the transcache table.
Definition: DatabaseUpdater.php:1053
DatabaseUpdater\newForDB
static newForDB(Database $db, $shared=false, $maintenance=null)
Definition: DatabaseUpdater.php:187
DBO_DDLMODE
const DBO_DDLMODE
Definition: defines.php:16
DatabaseUpdater\__construct
__construct(Database &$db, $shared, Maintenance $maintenance=null)
Constructor.
Definition: DatabaseUpdater.php:114
DatabaseUpdater\canUseNewUpdatelog
canUseNewUpdatelog()
Updatelog was changed in 1.17 to have a ul_value column so we can record more information about what ...
Definition: DatabaseUpdater.php:529
DatabaseUpdater\$fileHandle
resource $fileHandle
File handle for SQL output.
Definition: DatabaseUpdater.php:93
$ret
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1956
DatabaseUpdater\getOldGlobalUpdates
getOldGlobalUpdates()
Before 1.17, we used to handle updates via stuff like $wgExtNewTables/Fields/Indexes.
Definition: DatabaseUpdater.php:567
DatabaseUpdater\doLogUsertextPopulation
doLogUsertextPopulation()
Populates the log_user_text field in the logging table.
Definition: DatabaseUpdater.php:1019
DatabaseUpdater\tableExists
tableExists( $tableName)
Definition: DatabaseUpdater.php:356
DatabaseUpdater\addExtensionField
addExtensionField( $tableName, $columnName, $sqlPath)
Definition: DatabaseUpdater.php:272
DatabaseUpdater\modifyField
modifyField( $table, $field, $patch, $fullpath=false)
Modify an existing field.
Definition: DatabaseUpdater.php:915
DatabaseUpdater\writeSchemaUpdateFile
writeSchemaUpdateFile(array $schemaUpdate=[])
Definition: DatabaseUpdater.php:397
$wgHooks
$wgHooks['ArticleShow'][]
Definition: hooks.txt:110
DatabaseUpdater\loadExtensions
loadExtensions()
Loads LocalSettings.php, if needed, and initialises everything needed for LoadExtensionSchemaUpdates ...
Definition: DatabaseUpdater.php:152
$path
$path
Definition: NoLocalSettings.php:26
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
DatabaseUpdater\renameExtensionIndex
renameExtensionIndex( $tableName, $oldIndexName, $newIndexName, $sqlPath, $skipBothIndexExistWarning=false)
Rename an index on an extension table.
Definition: DatabaseUpdater.php:324
DatabaseUpdater\addTable
addTable( $name, $patch, $fullpath=false)
Add a new table to the database.
Definition: DatabaseUpdater.php:708
DatabaseUpdater\$shared
$shared
Definition: DatabaseUpdater.php:69
$wgProfiler
$wgProfiler
Definition: WebStart.php:73
MessageBlobStore
This class generates message blobs for use by ResourceLoader modules.
Definition: MessageBlobStore.php:37
Wikimedia\Rdbms\IDatabase\getType
getType()
Get the type of the DBMS, as it appears in $wgDBtype.
DatabaseUpdater\dropExtensionField
dropExtensionField( $tableName, $columnName, $sqlPath)
Definition: DatabaseUpdater.php:284
DatabaseUpdater\purgeCache
purgeCache()
Purge the objectcache table.
Definition: DatabaseUpdater.php:963
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:1956
DatabaseUpdater\$skipSchema
bool $skipSchema
Flag specifying whether or not to skip schema (e.g.
Definition: DatabaseUpdater.php:100
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
DatabaseUpdater\addExtensionTable
addExtensionTable( $tableName, $sqlPath)
Convenience wrapper for addExtensionUpdate() when adding a new table (which is the most common usage ...
Definition: DatabaseUpdater.php:249
Installer\getDBTypes
static getDBTypes()
Get a list of known DB types.
Definition: Installer.php:458
MediaWikiServices
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency MediaWikiServices
Definition: injection.txt:23
DatabaseUpdater\initOldGlobals
initOldGlobals()
Initialize all of the old globals.
Definition: DatabaseUpdater.php:134
DatabaseUpdater\addIndex
addIndex( $table, $index, $patch, $fullpath=false)
Add a new index to an existing table.
Definition: DatabaseUpdater.php:756
DatabaseUpdater\$extensionUpdates
array $extensionUpdates
List of extension-provided database updates.
Definition: DatabaseUpdater.php:55
DatabaseUpdater\insertUpdateRow
insertUpdateRow( $key, $val=null)
Helper function: Add a key to the updatelog table Obviously, only use this for updates that occur aft...
Definition: DatabaseUpdater.php:511
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:131
DatabaseUpdater\$postDatabaseUpdateMaintenance
string[] $postDatabaseUpdateMaintenance
Scripts to run after database update Should be a subclass of LoggedUpdateMaintenance.
Definition: DatabaseUpdater.php:75
DatabaseUpdater\dropExtensionTable
dropExtensionTable( $tableName, $sqlPath)
Definition: DatabaseUpdater.php:308
array
the array() calling protocol came about after MediaWiki 1.4rc1.
DatabaseUpdater\$holdContentHandlerUseDB
$holdContentHandlerUseDB
Hold the value of $wgContentHandlerUseDB during the upgrade.
Definition: DatabaseUpdater.php:105
$out
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
Definition: hooks.txt:783