MediaWiki master
updateRestrictions.php
Go to the documentation of this file.
1<?php
13namespace MediaWiki\Maintenance;
14
15// @codeCoverageIgnoreStart
16require_once __DIR__ . '/Maintenance.php';
17// @codeCoverageIgnoreEnd
18
26 public function __construct() {
27 parent::__construct();
28 $this->addDescription( 'Updates page_restrictions table from old page_restriction column' );
29 $this->setBatchSize( 1000 );
30 }
31
33 public function doDBUpdates() {
34 $dbw = $this->getDB( DB_PRIMARY );
35 $batchSize = $this->getBatchSize();
36
37 if ( !$dbw->tableExists( 'page_restrictions', __METHOD__ ) ) {
38 $this->fatalError( "page_restrictions table does not exist" );
39 }
40
41 if ( !$dbw->fieldExists( 'page', 'page_restrictions', __METHOD__ ) ) {
42 $this->output( "Migration is not needed.\n" );
43 return true;
44 }
45
46 $encodedExpiry = $dbw->getInfinity();
47
48 $maxPageId = $dbw->newSelectQueryBuilder()
49 ->select( 'MAX(page_id)' )
50 ->from( 'page' )
51 ->caller( __METHOD__ )->fetchField();
52
53 $batchMinPageId = 0;
54
55 do {
56 $batchMaxPageId = $batchMinPageId + $batchSize;
57
58 $this->output( "...processing page IDs from $batchMinPageId to $batchMaxPageId.\n" );
59
60 $res = $dbw->newSelectQueryBuilder()
61 ->select( [ 'page_id', 'page_restrictions' ] )
62 ->from( 'page' )
63 ->where( [
64 $dbw->expr( 'page_restrictions', '!=', '' ),
65 $dbw->expr( 'page_id', '>', $batchMinPageId ),
66 $dbw->expr( 'page_id', '<=', $batchMaxPageId ),
67 ] )
68 ->caller( __METHOD__ )->fetchResultSet();
69
70 // No pages have legacy protection settings in the current batch
71 if ( !$res->numRows() ) {
72 $batchMinPageId = $batchMaxPageId;
73 continue;
74 }
75
76 $batch = [];
77 $pageIds = [];
78
79 foreach ( $res as $row ) {
80 $pageIds[] = $row->page_id;
81
82 $restrictionsByAction = $this->mapLegacyRestrictionBlob( $row->page_restrictions );
83
84 # Update restrictions table
85 foreach ( $restrictionsByAction as $action => $restrictions ) {
86 $batch[] = [
87 'pr_page' => $row->page_id,
88 'pr_type' => $action,
89 'pr_level' => $restrictions,
90 'pr_cascade' => 0,
91 'pr_expiry' => $encodedExpiry
92 ];
93 }
94 }
95
96 $this->beginTransactionRound( __METHOD__ );
97
98 // Insert new format protection settings for the pages in the current batch.
99 // Use INSERT IGNORE to ignore conflicts with new format settings that might exist for the page
100 $dbw->newInsertQueryBuilder()
101 ->insertInto( 'page_restrictions' )
102 ->ignore()
103 ->rows( $batch )
104 ->caller( __METHOD__ )->execute();
105
106 // Clear out the legacy page.page_restrictions blob for this batch
107 $dbw->newUpdateQueryBuilder()
108 ->update( 'page' )
109 ->set( [ 'page_restrictions' => '' ] )
110 ->where( [ 'page_id' => $pageIds ] )
111 ->caller( __METHOD__ )
112 ->execute();
113
114 $this->commitTransactionRound( __METHOD__ );
115
116 $batchMinPageId = $batchMaxPageId;
117 } while ( $batchMaxPageId < $maxPageId );
118
119 $this->output( "...Done!\n" );
120 return true;
121 }
122
131 private function mapLegacyRestrictionBlob( $legacyBlob ) {
132 $oldRestrictions = [];
133
134 foreach ( explode( ':', trim( $legacyBlob ) ) as $restrict ) {
135 $temp = explode( '=', trim( $restrict ) );
136
137 // Treat old old format without action name as edit/move restriction
138 if ( count( $temp ) == 1 ) {
139 $level = trim( $temp[0] );
140
141 $oldRestrictions['edit'] = $level;
142 $oldRestrictions['move'] = $level;
143 } else {
144 $restriction = trim( $temp[1] );
145 // Some old entries are empty
146 if ( $restriction != '' ) {
147 $oldRestrictions[$temp[0]] = $restriction;
148 }
149 }
150 }
151
152 return $oldRestrictions;
153 }
154
156 protected function getUpdateKey() {
157 return __CLASS__;
158 }
159}
160
161// @codeCoverageIgnoreStart
162$maintClass = UpdateRestrictions::class;
163require_once RUN_MAINTENANCE_IF_MAIN;
164// @codeCoverageIgnoreEnd
const DB_PRIMARY
Definition defines.php:28
Class for scripts that perform database maintenance and want to log the update in updatelog so we can...
getBatchSize()
Returns batch size.
output( $out, $channel=null)
Throw some output to the user.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
getDB( $db, $groups=[], $dbDomain=false)
Returns a database to be used by current maintenance script.
commitTransactionRound( $fname)
Commit a transactional batch of DB operations and wait for replica DB servers to catch up.
beginTransactionRound( $fname)
Start a transactional batch of DB operations.
addDescription( $text)
Set the description text.
Maintenance script that updates page_restrictions table from old page_restriction column.
doDBUpdates()
Do the actual work.All child classes will need to implement this. Return true to log the update as do...
getUpdateKey()
Get the update key name to go in the update log table.string
Update the CREDITS list by merging in the list of git commit authors.