~vcs-imports/stellarium-website/trunk

« back to all changes in this revision

Viewing changes to wiki/maintenance/namespaceDupes.php

  • Committer: Matthew Gates
  • Date: 2010-12-24 21:26:07 UTC
  • Revision ID: matthewg42@gmail.com-20101224212607-rjlt7qam0160puxb
added wiki directory but without LocalSettings.php; added util directory w/ 2 scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Check for articles to fix after adding/deleting namespaces
 
4
 *
 
5
 * Copyright (C) 2005-2007 Brion Vibber <brion@pobox.com>
 
6
 * http://www.mediawiki.org/
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
16
 * GNU General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU General Public License along
 
19
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
20
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
21
 * http://www.gnu.org/copyleft/gpl.html
 
22
 *
 
23
 * @ingroup Maintenance
 
24
 */
 
25
 
 
26
require_once( dirname(__FILE__) . '/Maintenance.php' );
 
27
 
 
28
class NamespaceConflictChecker extends Maintenance {
 
29
        public function __construct() {
 
30
                parent::__construct();
 
31
                $this->mDescription = "";
 
32
                $this->addOption( 'fix', 'Attempt to automatically fix errors' );
 
33
                $this->addOption( 'suffix', "Dupes will be renamed with correct namespace with\n" .
 
34
                                                                        "\t\t<text> Appended after the article name", false, true );
 
35
                $this->addOption( 'prefix', "Do an explicit check for the given title prefix\n" .
 
36
                                                                        "\t\tappended after the article name", false, true );
 
37
        }
 
38
 
 
39
        public function execute() {
 
40
                global $wgTitle;
 
41
 
 
42
                $this->db = wfGetDB( DB_MASTER );
 
43
                $wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' );
 
44
 
 
45
                $fix = $this->hasOption( 'fix' );
 
46
                $suffix = $this->getOption( 'suffix', '' );
 
47
                $prefix = $this->getOption( 'prefix', '' );
 
48
                $key = intval( $this->getOption( 'key', 0 ) );
 
49
 
 
50
                if( $prefix ) {
 
51
                        $retval = $this->checkPrefix( $key, $prefix, $fix, $suffix );
 
52
                } else {
 
53
                        $retval = $this->checkAll( $fix, $suffix );
 
54
                }
 
55
        
 
56
                if( $retval ) {
 
57
                        $this->output( "\nLooks good!\n" );
 
58
                } else {
 
59
                        $this->output( "\nOh noeees\n" );
 
60
                }
 
61
        }
 
62
 
 
63
        /**
 
64
         * @todo Document
 
65
         * @param $fix bool Whether or not to fix broken entries
 
66
         * @param $suffix String Suffix to append to renamed articles
 
67
         */
 
68
        private function checkAll( $fix, $suffix = '' ) {
 
69
                global $wgContLang, $wgNamespaceAliases, $wgCanonicalNamespaceNames;
 
70
                global $wgCapitalLinks;
 
71
                
 
72
                $spaces = array();
 
73
                
 
74
                // List interwikis first, so they'll be overridden
 
75
                // by any conflicting local namespaces.
 
76
                foreach( $this->getInterwikiList() as $prefix ) {
 
77
                        $name = $wgContLang->ucfirst( $prefix );
 
78
                        $spaces[$name] = 0;
 
79
                }
 
80
 
 
81
                // Now pull in all canonical and alias namespaces...
 
82
                foreach( $wgCanonicalNamespaceNames as $ns => $name ) {
 
83
                        // This includes $wgExtraNamespaces
 
84
                        if( $name !== '' ) {
 
85
                                $spaces[$name] = $ns;
 
86
                        }
 
87
                }
 
88
                foreach( $wgContLang->getNamespaces() as $ns => $name ) {
 
89
                        if( $name !== '' ) {
 
90
                                $spaces[$name] = $ns;
 
91
                        }
 
92
                }
 
93
                foreach( $wgNamespaceAliases as $name => $ns ) {
 
94
                        $spaces[$name] = $ns;
 
95
                }
 
96
                foreach( $wgContLang->getNamespaceAliases() as $name => $ns ) {
 
97
                        $spaces[$name] = $ns;
 
98
                }
 
99
                
 
100
                // We'll need to check for lowercase keys as well,
 
101
                // since we're doing case-sensitive searches in the db.
 
102
                foreach( $spaces as $name => $ns ) {
 
103
                        $moreNames = array();
 
104
                        $moreNames[] = $wgContLang->uc( $name );
 
105
                        $moreNames[] = $wgContLang->ucfirst( $wgContLang->lc( $name ) );
 
106
                        $moreNames[] = $wgContLang->ucwords( $name );
 
107
                        $moreNames[] = $wgContLang->ucwords( $wgContLang->lc( $name ) );
 
108
                        $moreNames[] = $wgContLang->ucwordbreaks( $name );
 
109
                        $moreNames[] = $wgContLang->ucwordbreaks( $wgContLang->lc( $name ) );
 
110
                        if( !$wgCapitalLinks ) {
 
111
                                foreach( $moreNames as $altName ) {
 
112
                                        $moreNames[] = $wgContLang->lcfirst( $altName );
 
113
                                }
 
114
                                $moreNames[] = $wgContLang->lcfirst( $name );
 
115
                        }
 
116
                        foreach( array_unique( $moreNames ) as $altName ) {
 
117
                                if( $altName !== $name ) {
 
118
                                        $spaces[$altName] = $ns;
 
119
                                }
 
120
                        }
 
121
                }
 
122
                
 
123
                ksort( $spaces );
 
124
                asort( $spaces );
 
125
                
 
126
                $ok = true;
 
127
                foreach( $spaces as $name => $ns ) {
 
128
                        $ok = $this->checkNamespace( $ns, $name, $fix, $suffix ) && $ok;
 
129
                }
 
130
                return $ok;
 
131
        }
 
132
 
 
133
        /**
 
134
         * Get the interwiki list
 
135
         * @todo Needs to respect interwiki cache!
 
136
         * @return array
 
137
         */
 
138
        private function getInterwikiList() {
 
139
                $result = $this->db->select( 'interwiki', array( 'iw_prefix' ) );
 
140
                $prefixes = array();
 
141
                foreach( $result as $row ) {
 
142
                        $prefixes[] = $row->iw_prefix;
 
143
                }
 
144
                $this->db->freeResult( $result );
 
145
                return $prefixes;
 
146
        }
 
147
 
 
148
        /**
 
149
         * @todo Document
 
150
         * @param $ns int A namespace id
 
151
         * @param $name String
 
152
         * @param $fix bool Whether to fix broken entries
 
153
         * @param $suffix String Suffix to append to renamed articles
 
154
         */
 
155
        private function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
 
156
                $conflicts = $this->getConflicts( $ns, $name );
 
157
                $count = count( $conflicts );
 
158
                if( $count == 0 ) {
 
159
                        return true;
 
160
                }
 
161
 
 
162
                $ok = true;
 
163
                foreach( $conflicts as $row ) {
 
164
                        $resolvable = $this->reportConflict( $row, $suffix );
 
165
                        $ok = $ok && $resolvable;
 
166
                        if( $fix && ( $resolvable || $suffix != '' ) ) {
 
167
                                $ok = $this->resolveConflict( $row, $resolvable, $suffix ) && $ok;
 
168
                        }
 
169
                }
 
170
                return $ok;
 
171
        }
 
172
        
 
173
        /**
 
174
         * @todo: do this for reals
 
175
         */
 
176
        private function checkPrefix( $key, $prefix, $fix, $suffix = '' ) {
 
177
                $this->output( "Checking prefix \"$prefix\" vs namespace $key\n" );
 
178
                return $this->checkNamespace( $key, $prefix, $fix, $suffix );
 
179
        }
 
180
 
 
181
        /**
 
182
         * Find pages in mainspace that have a prefix of the new namespace
 
183
         * so we know titles that will need migrating
 
184
         * @param $ns int Namespace id (id for new namespace?)
 
185
         * @param $name String Prefix that is being made a namespace
 
186
         */
 
187
        private function getConflicts( $ns, $name ) {
 
188
                $page  = 'page';
 
189
                $table = $this->db->tableName( $page );
 
190
 
 
191
                $prefix     = $this->db->strencode( $name );
 
192
                $encNamespace = $this->db->addQuotes( $ns );
 
193
 
 
194
                $titleSql = "TRIM(LEADING '$prefix:' FROM {$page}_title)";
 
195
                if( $ns == 0 ) {
 
196
                        // An interwiki; try an alternate encoding with '-' for ':'
 
197
                        $titleSql = $this->db->buildConcat( array( "'$prefix-'", $titleSql ) );
 
198
                }
 
199
                                     
 
200
                $sql = "SELECT {$page}_id    AS id,
 
201
                               {$page}_title AS oldtitle,
 
202
                               $encNamespace AS namespace,
 
203
                               $titleSql     AS title
 
204
                          FROM {$table}
 
205
                         WHERE {$page}_namespace=0
 
206
                           AND {$page}_title " . $this->db->buildLike( $name . ':', $this->db->anyString() );
 
207
 
 
208
                $result = $this->db->query( $sql, __METHOD__ );
 
209
 
 
210
                $set = array();
 
211
                foreach( $result as $row ) {
 
212
                        $set[] = $row;
 
213
                }
 
214
                $this->db->freeResult( $result );
 
215
 
 
216
                return $set;
 
217
        }
 
218
 
 
219
        /**
 
220
         * Report any conflicts we find
 
221
         */
 
222
        private function reportConflict( $row, $suffix ) {
 
223
                $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
 
224
                if( is_null($newTitle) || !$newTitle->canExist() ) {
 
225
                        // Title is also an illegal title...
 
226
                        // For the moment we'll let these slide to cleanupTitles or whoever.
 
227
                        $this->output( sprintf( "... %d (0,\"%s\")\n",
 
228
                                $row->id,
 
229
                                $row->oldtitle ) );
 
230
                        $this->output( "...  *** cannot resolve automatically; illegal title ***\n" );
 
231
                        return false;
 
232
                }
 
233
 
 
234
                $this->output( sprintf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
 
235
                        $row->id,
 
236
                        $row->oldtitle,
 
237
                        $newTitle->getNamespace(),
 
238
                        $newTitle->getDBkey(),
 
239
                        $newTitle->getPrefixedText() ) );
 
240
 
 
241
                $id = $newTitle->getArticleId();
 
242
                if( $id ) {
 
243
                        $this->output( "...  *** cannot resolve automatically; page exists with ID $id ***\n" );
 
244
                        return false;
 
245
                } else {
 
246
                        return true;
 
247
                }
 
248
        }
 
249
 
 
250
        /**
 
251
         * Resolve any conflicts
 
252
         * @param $row Row from the page table to fix
 
253
         * @param $resolveable bool 
 
254
         * @param $suffix String Suffix to append to the fixed page
 
255
         */
 
256
        private function resolveConflict( $row, $resolvable, $suffix ) {
 
257
                if( !$resolvable ) {
 
258
                        $this->output( "...  *** old title {$row->title}\n" );
 
259
                        while( true ) {
 
260
                                $row->title .= $suffix;
 
261
                                $this->output( "...  *** new title {$row->title}\n" );
 
262
                                $title = Title::makeTitleSafe( $row->namespace, $row->title );
 
263
                                if ( ! $title ) {
 
264
                                        $this->output( "... !!! invalid title\n" );
 
265
                                        return false;
 
266
                                }
 
267
                                if ( $id = $title->getArticleId() ) {
 
268
                                        $this->output( "...  *** page exists with ID $id ***\n" );
 
269
                                } else {        
 
270
                                        break;
 
271
                                }
 
272
                        }
 
273
                        $this->output( "...  *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n" );
 
274
                }
 
275
                $this->resolveConflictOn( $row, 'page', 'page' );
 
276
                return true;
 
277
        }
 
278
 
 
279
        /**
 
280
         * Resolve a given conflict
 
281
         * @param $row Row from the old broken entry
 
282
         * @param $table String Table to update
 
283
         * @param $prefix String Prefix for column name, like page or ar
 
284
         */
 
285
        private function resolveConflictOn( $row, $table, $prefix ) {
 
286
                $this->output( "... resolving on $table... " );
 
287
                $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
 
288
                $this->db->update( $table,
 
289
                        array(
 
290
                                "{$prefix}_namespace" => $newTitle->getNamespace(),
 
291
                                "{$prefix}_title"     => $newTitle->getDBkey(),
 
292
                        ),
 
293
                        array(
 
294
                                "{$prefix}_namespace" => 0,
 
295
                                "{$prefix}_title"     => $row->oldtitle,
 
296
                        ),
 
297
                        __METHOD__ );
 
298
                $this->output( "ok.\n" );
 
299
                return true;
 
300
        }
 
301
}
 
302
 
 
303
$maintClass = "NamespaceConflictChecker";
 
304
require_once( DO_MAINTENANCE );