Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 71 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
FixDefaultJsonContentPages | |
0.00% |
0 / 68 |
|
0.00% |
0 / 4 |
90 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getUpdateKey | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
doDBUpdates | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
12 | |||
handleRow | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | /** |
3 | * Fix instances of pre-existing JSON pages |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @ingroup Maintenance |
22 | */ |
23 | |
24 | use MediaWiki\Revision\RevisionRecord; |
25 | use MediaWiki\Revision\SlotRecord; |
26 | use MediaWiki\Title\Title; |
27 | use Wikimedia\Rdbms\IExpression; |
28 | use Wikimedia\Rdbms\LikeValue; |
29 | |
30 | require_once __DIR__ . '/Maintenance.php'; |
31 | |
32 | /** |
33 | * Usage: |
34 | * fixDefaultJsonContentPages.php |
35 | * |
36 | * It is automatically run by update.php |
37 | */ |
38 | class FixDefaultJsonContentPages extends LoggedUpdateMaintenance { |
39 | public function __construct() { |
40 | parent::__construct(); |
41 | $this->addDescription( |
42 | 'Fix instances of JSON pages prior to them being the ContentHandler default' ); |
43 | $this->setBatchSize( 100 ); |
44 | } |
45 | |
46 | protected function getUpdateKey() { |
47 | return __CLASS__; |
48 | } |
49 | |
50 | protected function doDBUpdates() { |
51 | $dbr = $this->getReplicaDB(); |
52 | $namespaces = [ |
53 | NS_MEDIAWIKI => $dbr->expr( |
54 | 'page_title', |
55 | IExpression::LIKE, |
56 | new LikeValue( $dbr->anyString(), '.json' ) |
57 | ), |
58 | NS_USER => $dbr->expr( |
59 | 'page_title', |
60 | IExpression::LIKE, |
61 | new LikeValue( $dbr->anyString(), '/', $dbr->anyString(), '.json' ) |
62 | ), |
63 | ]; |
64 | foreach ( $namespaces as $ns => $likeExpr ) { |
65 | $lastPage = 0; |
66 | do { |
67 | $rows = $dbr->newSelectQueryBuilder() |
68 | ->select( [ 'page_id', 'page_title', 'page_namespace', 'page_content_model' ] ) |
69 | ->from( 'page' ) |
70 | ->where( [ |
71 | 'page_namespace' => $ns, |
72 | $likeExpr, |
73 | $dbr->expr( 'page_id', '>', $lastPage ), |
74 | ] ) |
75 | ->orderBy( 'page_id' ) |
76 | ->limit( $this->getBatchSize() ) |
77 | ->caller( __METHOD__ )->fetchResultSet(); |
78 | foreach ( $rows as $row ) { |
79 | $this->handleRow( $row ); |
80 | $lastPage = $row->page_id; |
81 | } |
82 | } while ( $rows->numRows() >= $this->getBatchSize() ); |
83 | } |
84 | |
85 | return true; |
86 | } |
87 | |
88 | protected function handleRow( stdClass $row ) { |
89 | $title = Title::makeTitle( $row->page_namespace, $row->page_title ); |
90 | $this->output( "Processing {$title} ({$row->page_id})...\n" ); |
91 | $rev = $this->getServiceContainer() |
92 | ->getRevisionLookup() |
93 | ->getRevisionByTitle( $title ); |
94 | $content = $rev->getContent( SlotRecord::MAIN, RevisionRecord::RAW ); |
95 | $dbw = $this->getPrimaryDB(); |
96 | if ( $content instanceof JsonContent ) { |
97 | if ( $content->isValid() ) { |
98 | // Yay, actually JSON. We need to just change the |
99 | // page_content_model because revision will automatically |
100 | // use the default, which is *now* JSON. |
101 | $this->output( "Setting page_content_model to json..." ); |
102 | $dbw->newUpdateQueryBuilder() |
103 | ->update( 'page' ) |
104 | ->set( [ 'page_content_model' => CONTENT_MODEL_JSON ] ) |
105 | ->where( [ 'page_id' => $row->page_id ] ) |
106 | ->caller( __METHOD__ )->execute(); |
107 | |
108 | $this->output( "done.\n" ); |
109 | $this->waitForReplication(); |
110 | } else { |
111 | // Not JSON...force it to wikitext. We need to update the |
112 | // revision table so that these revisions are always processed |
113 | // as wikitext in the future. page_content_model is already |
114 | // set to "wikitext". |
115 | $this->output( "Setting rev_content_model to wikitext..." ); |
116 | // Grab all the ids for batching |
117 | $ids = $dbw->newSelectQueryBuilder() |
118 | ->select( 'rev_id' ) |
119 | ->from( 'revision' ) |
120 | ->where( [ 'rev_page' => $row->page_id ] ) |
121 | ->caller( __METHOD__ )->fetchFieldValues(); |
122 | foreach ( array_chunk( $ids, 50 ) as $chunk ) { |
123 | $dbw->newUpdateQueryBuilder() |
124 | ->update( 'revision' ) |
125 | ->set( [ 'rev_content_model' => CONTENT_MODEL_WIKITEXT ] ) |
126 | ->where( [ 'rev_page' => $row->page_id, 'rev_id' => $chunk ] ) |
127 | ->caller( __METHOD__ )->execute(); |
128 | |
129 | $this->waitForReplication(); |
130 | } |
131 | $this->output( "done.\n" ); |
132 | } |
133 | } else { |
134 | $this->output( "not a JSON page? Skipping\n" ); |
135 | } |
136 | } |
137 | } |
138 | |
139 | $maintClass = FixDefaultJsonContentPages::class; |
140 | require_once RUN_MAINTENANCE_IF_MAIN; |