/**
* @param Database &$db To perform updates on
* @param bool $shared Whether to perform updates on shared tables
- * @param Maintenance $maintenance Maintenance object which created us
+ * @param Maintenance|null $maintenance Maintenance object which created us
*/
protected function __construct( Database &$db, $shared, Maintenance $maintenance = null ) {
$this->db = $db;
* Output some text. If we're running from web, escape the text first.
*
* @param string $str Text to output
+ * @param-taint $str escapes_html
*/
public function output( $str ) {
if ( $this->maintenance->isQuiet() ) {
foreach ( $updates as $funcList ) {
$func = $funcList[0];
- $arg = $funcList[1];
+ $args = $funcList[1];
$origParams = $funcList[2];
- call_user_func_array( $func, $arg );
+ $func( ...$args );
flush();
$this->updatesSkipped[] = $origParams;
}
} elseif ( $passSelf ) {
array_unshift( $params, $this );
}
- $ret = call_user_func_array( $func, $params );
+ $ret = $func( ...$params );
flush();
if ( $ret !== false ) {
$updatesDone[] = $origParams;
* Obviously, only use this for updates that occur after the updatelog table was
* created!
* @param string $key Name of key to insert
- * @param string $val [optional] Value to insert along with the key
+ * @param string|null $val [optional] Value to insert along with the key
*/
public function insertUpdateRow( $key, $val = null ) {
$this->db->clearFlag( DBO_DDLMODE );
*
* @param string $path Path to the patch file
* @param bool $isFullPath Whether to treat $path as a relative or not
- * @param string $msg Description of the patch
+ * @param string|null $msg Description of the patch
* @return bool False if patch is skipped.
*/
protected function applyPatch( $path, $isFullPath = false, $msg = null ) {
return true;
}
+ /**
+ * Add a new index to an existing table if none of the given indexes exist
+ *
+ * @param string $table Name of the table to modify
+ * @param string[] $indexes Name of the indexes to check. $indexes[0] should
+ * be the one actually being added.
+ * @param string $patch Path to the patch file
+ * @param bool $fullpath Whether to treat $patch path as a relative or not
+ * @return bool False if this was skipped because schema changes are skipped
+ */
+ protected function addIndexIfNoneExist( $table, $indexes, $patch, $fullpath = false ) {
+ if ( !$this->doTable( $table ) ) {
+ return true;
+ }
+
+ if ( !$this->db->tableExists( $table, __METHOD__ ) ) {
+ $this->output( "...skipping: '$table' table doesn't exist yet.\n" );
+ return true;
+ }
+
+ $newIndex = $indexes[0];
+ foreach ( $indexes as $index ) {
+ if ( $this->db->indexExists( $table, $index, __METHOD__ ) ) {
+ $this->output(
+ "...skipping index $newIndex because index $index already set on $table table.\n"
+ );
+ return true;
+ }
+ }
+
+ return $this->applyPatch( $patch, $fullpath, "Adding index $index to table $table" );
+ }
+
/**
* Drop a field from an existing table
*
$this->output( "done.\n" );
}
}
+
+ /**
+ * Populates the MCR content tables
+ * @since 1.32
+ */
+ protected function populateContentTables() {
+ global $wgMultiContentRevisionSchemaMigrationStage;
+ if ( ( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) &&
+ !$this->updateRowExists( 'PopulateContentTables' )
+ ) {
+ $this->output(
+ "Migrating revision data to the MCR 'slot' and 'content' tables, printing progress markers.\n" .
+ "For large databases, you may want to hit Ctrl-C and do this manually with\n" .
+ "maintenance/populateContentTables.php.\n"
+ );
+ $task = $this->maintenance->runChild(
+ PopulateContentTables::class, 'populateContentTables.php'
+ );
+ $ok = $task->execute();
+ $this->output( $ok ? "done.\n" : "errors were encountered.\n" );
+ if ( $ok ) {
+ $this->insertUpdateRow( 'PopulateContentTables' );
+ }
+ }
+ }
}