Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 91 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
CleanCNTranslateMetadata | |
0.00% |
0 / 85 |
|
0.00% |
0 / 5 |
90 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
cleanDuplicates | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
12 | |||
populateIDs | |
0.00% |
0 / 28 |
|
0.00% |
0 / 1 |
6 | |||
deleteOrphans | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | $IP = getenv( 'MW_INSTALL_PATH' ); |
4 | if ( $IP === false ) { |
5 | $IP = __DIR__ . '/../../..'; |
6 | } |
7 | require_once "$IP/maintenance/Maintenance.php"; |
8 | |
9 | /** |
10 | * Cleans up the Revision Tag table which is where CentralNotice stores |
11 | * metadata required for the Translate extension. |
12 | * |
13 | * So far this class: |
14 | * * Removes duplicate revision entries (there should be only one per banner) |
15 | * * Associates entries with a banner by name |
16 | * * Removes entries that have no banner object |
17 | */ |
18 | class CleanCNTranslateMetadata extends Maintenance { |
19 | /** @var string|null */ |
20 | private $ttag; |
21 | |
22 | public function __construct() { |
23 | parent::__construct(); |
24 | $this->requireExtension( 'CentralNotice' ); |
25 | } |
26 | |
27 | public function execute() { |
28 | $this->ttag = Banner::TRANSLATE_BANNER_TAG; |
29 | |
30 | $this->cleanDuplicates(); |
31 | $this->populateIDs(); |
32 | $this->deleteOrphans(); |
33 | |
34 | ChoiceDataProvider::invalidateCache(); |
35 | } |
36 | |
37 | /** |
38 | * Remove duplicated revtags |
39 | */ |
40 | private function cleanDuplicates() { |
41 | $this->output( "Cleaning duplicates\n" ); |
42 | |
43 | $db = CNDatabase::getDb( DB_PRIMARY ); |
44 | |
45 | $res = $db->newSelectQueryBuilder() |
46 | ->select( [ |
47 | 'rt_page', |
48 | 'maxrev' => 'MAX(rt_revision)', |
49 | 'count' => 'COUNT(*)' |
50 | ] ) |
51 | ->from( 'revtag' ) |
52 | ->where( [ 'rt_type' => $this->ttag ] ) |
53 | ->groupBy( 'rt_page' ) |
54 | ->caller( __METHOD__ ) |
55 | ->fetchResultSet(); |
56 | |
57 | foreach ( $res as $row ) { |
58 | if ( (int)$row->count === 1 ) { |
59 | continue; |
60 | } |
61 | |
62 | $maxRev = (int)$row->maxrev; |
63 | $db->newDeleteQueryBuilder() |
64 | ->deleteFrom( 'revtag' ) |
65 | ->where( [ |
66 | 'rt_type' => $this->ttag, |
67 | 'rt_page' => $row->rt_page, |
68 | $db->expr( 'rt_revision', '!=', $maxRev ), |
69 | ] ) |
70 | ->caller( __METHOD__ ) |
71 | ->execute(); |
72 | $numRows = $db->affectedRows(); |
73 | $this->output( |
74 | " -- Deleted {$numRows} rows for banner with page id {$row->rt_page}\n" |
75 | ); |
76 | } |
77 | } |
78 | |
79 | /** |
80 | * Attach a banner ID with a orphan metadata line |
81 | */ |
82 | private function populateIDs() { |
83 | $this->output( "Associating metadata with banner ids\n" ); |
84 | |
85 | $db = CNDatabase::getDb( DB_PRIMARY ); |
86 | |
87 | $res = $db->newSelectQueryBuilder() |
88 | ->select( [ 'rt_page', 'rt_revision', 'page_title', 'tmp_id' ] ) |
89 | ->from( 'revtag' ) |
90 | ->join( 'page', null, 'rt_page=page_id' ) |
91 | ->join( 'cn_templates', null, [ |
92 | # Length of "centralnotice-template-" |
93 | 'tmp_name=substr(page_title, 24)' |
94 | ] ) |
95 | ->where( [ |
96 | 'rt_type' => $this->ttag, |
97 | 'rt_value' => null, |
98 | ] ) |
99 | ->caller( __METHOD__ ) |
100 | ->fetchResultSet(); |
101 | |
102 | foreach ( $res as $row ) { |
103 | $this->output( " -- Associating banner id {$row->tmp_id} " . |
104 | "with revtag with page id {$row->rt_page}\n" ); |
105 | $db->newUpdateQueryBuilder() |
106 | ->update( 'revtag' ) |
107 | ->set( [ 'rt_value' => $row->tmp_id ] ) |
108 | ->where( [ |
109 | 'rt_type' => $this->ttag, |
110 | 'rt_page' => $row->rt_page, |
111 | 'rt_value' => null, |
112 | ] ) |
113 | ->caller( __METHOD__ ) |
114 | ->execute(); |
115 | } |
116 | } |
117 | |
118 | /** |
119 | * Delete rows that have no banner ID associated with them |
120 | */ |
121 | private function deleteOrphans() { |
122 | $db = CNDatabase::getDb( DB_PRIMARY ); |
123 | $this->output( "Preparing to delete orphaned rows\n" ); |
124 | |
125 | $res = $db->newSelectQueryBuilder() |
126 | ->select( [ 'rt_page', 'rt_revision' ] ) |
127 | ->from( 'revtag' ) |
128 | ->where( [ 'rt_type' => $this->ttag, 'rt_value' => null ] ) |
129 | ->caller( __METHOD__ ) |
130 | ->fetchResultSet(); |
131 | |
132 | foreach ( $res as $row ) { |
133 | $this->output( " -- Deleting orphan row {$row->rt_page}:{$row->rt_revision}\n" ); |
134 | $db->newDeleteQueryBuilder() |
135 | ->deleteFrom( 'revtag' ) |
136 | ->where( [ |
137 | 'rt_type' => $this->ttag, |
138 | 'rt_page' => $row->rt_page, |
139 | 'rt_revision' => $row->rt_revision, |
140 | 'rt_value' => null, // Just in case something updated it |
141 | ] ) |
142 | ->caller( __METHOD__ ) |
143 | ->execute(); |
144 | } |
145 | } |
146 | } |
147 | |
148 | $maintClass = CleanCNTranslateMetadata::class; |
149 | require_once RUN_MAINTENANCE_IF_MAIN; |