]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - maintenance/namespaceDupes.php
MediaWiki 1.11.0
[autoinstallsdev/mediawiki.git] / maintenance / namespaceDupes.php
1 <?php
2 # Copyright (C) 2005-2007 Brion Vibber <brion@pobox.com>
3 # http://www.mediawiki.org/
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 $options = array( 'fix', 'suffix', 'help' );
21
22 /** */
23 require_once( 'commandLine.inc' );
24
25 if(isset( $options['help'] ) ) {
26 print <<<END
27 usage: namespaceDupes.php [--fix] [--suffix=<text>] [--help]
28     --help          : this help message
29     --fix           : attempt to automatically fix errors
30     --suffix=<text> : dupes will be renamed with correct namespace with <text>
31                       appended after the article name.
32     --prefix=<text> : Do an explicit check for the given title prefix
33                       in place of the standard namespace list.
34     --verbose       : Display output for checked namespaces without conflicts
35
36 END;
37 die;
38 }
39
40 class NamespaceConflictChecker {
41         function NamespaceConflictChecker( $db, $verbose=false ) {
42                 $this->db = $db;
43                 $this->verbose = $verbose;
44         }
45
46         function checkAll( $fix, $suffix = '' ) {
47                 global $wgContLang, $wgNamespaceAliases, $wgCanonicalNamespaceNames;
48                 global $wgCapitalLinks;
49                 
50                 $spaces = array();
51                 
52                 // List interwikis first, so they'll be overridden
53                 // by any conflicting local namespaces.
54                 foreach( $this->getInterwikiList() as $prefix ) {
55                         $name = $wgContLang->ucfirst( $prefix );
56                         $spaces[$name] = 0;
57                 }
58
59                 // Now pull in all canonical and alias namespaces...
60                 foreach( $wgCanonicalNamespaceNames as $ns => $name ) {
61                         // This includes $wgExtraNamespaces
62                         if( $name !== '' ) {
63                                 $spaces[$name] = $ns;
64                         }
65                 }
66                 foreach( $wgContLang->getNamespaces() as $ns => $name ) {
67                         if( $name !== '' ) {
68                                 $spaces[$name] = $ns;
69                         }
70                 }
71                 foreach( $wgNamespaceAliases as $name => $ns ) {
72                         $spaces[$name] = $ns;
73                 }
74                 foreach( $wgContLang->namespaceAliases as $name => $ns ) {
75                         $spaces[$name] = $ns;
76                 }
77                 
78                 if( !$wgCapitalLinks ) {
79                         // We'll need to check for lowercase keys as well,
80                         // since we're doing case-sensitive searches in the db.
81                         foreach( array_values( $spaces ) as $name => $ns ) {
82                                 $lcname = $wgContLang->lcfirst( $name );
83                                 $spaces[$lcname] = $ns;
84                         }
85                 }
86                 ksort( $spaces );
87                 asort( $spaces );
88                 
89                 $ok = true;
90                 foreach( $spaces as $name => $ns ) {
91                         $ok = $this->checkNamespace( $ns, $name, $fix, $suffix ) && $ok;
92                 }
93                 return $ok;
94         }
95         
96         private function getInterwikiList() {
97                 $result = $this->db->select( 'interwiki', array( 'iw_prefix' ) );
98                 while( $row = $this->db->fetchObject( $result ) ) {
99                         $prefixes[] = $row->iw_prefix;
100                 }
101                 $this->db->freeResult( $result );
102                 return $prefixes;
103         }
104
105         function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
106                 if( $ns == 0 ) {
107                         $header = "Checking interwiki prefix: \"$name\"\n";
108                 } else {
109                         $header = "Checking namespace $ns: \"$name\"\n";
110                 }
111
112                 $conflicts = $this->getConflicts( $ns, $name );
113                 $count = count( $conflicts );
114                 if( $count == 0 ) {
115                         if( $this->verbose ) {
116                                 echo $header;
117                                 echo "... no conflicts detected!\n";
118                         }
119                         return true;
120                 }
121
122                 echo $header;
123                 echo "... $count conflicts detected:\n";
124                 $ok = true;
125                 foreach( $conflicts as $row ) {
126                         $resolvable = $this->reportConflict( $row, $suffix );
127                         $ok = $ok && $resolvable;
128                         if( $fix && ( $resolvable || $suffix != '' ) ) {
129                                 $ok = $this->resolveConflict( $row, $resolvable, $suffix ) && $ok;
130                         }
131                 }
132                 return $ok;
133         }
134         
135         /**
136          * @todo: do this for reals
137          */
138         function checkPrefix( $key, $prefix, $fix, $suffix = '' ) {
139                 echo "Checking prefix \"$prefix\" vs namespace $key\n";
140                 return $this->checkNamespace( $key, $prefix, $fix, $suffix );
141         }
142
143         function getConflicts( $ns, $name ) {
144                 $page  = 'page';
145                 $table = $this->db->tableName( $page );
146
147                 $prefix     = $this->db->strencode( $name );
148                 $likeprefix = str_replace( '_', '\\_', $prefix);
149                 $encNamespace = $this->db->addQuotes( $ns );
150
151                 $titleSql = "TRIM(LEADING '$prefix:' FROM {$page}_title)";
152                 if( $ns == 0 ) {
153                         // An interwiki; try an alternate encoding with '-' for ':'
154                         $titleSql = "CONCAT('$prefix-',$titleSql)";
155                 }
156                                      
157                 $sql = "SELECT {$page}_id    AS id,
158                                {$page}_title AS oldtitle,
159                                $encNamespace AS namespace,
160                                $titleSql     AS title
161                           FROM {$table}
162                          WHERE {$page}_namespace=0
163                            AND {$page}_title LIKE '$likeprefix:%'";
164
165                 $result = $this->db->query( $sql, 'NamespaceConflictChecker::getConflicts' );
166
167                 $set = array();
168                 while( $row = $this->db->fetchObject( $result ) ) {
169                         $set[] = $row;
170                 }
171                 $this->db->freeResult( $result );
172
173                 return $set;
174         }
175
176         function reportConflict( $row, $suffix ) {
177                 $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
178                 printf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
179                         $row->id,
180                         $row->oldtitle,
181                         $newTitle->getNamespace(),
182                         $newTitle->getDbKey(),
183                         $newTitle->getPrefixedText() );
184
185                 $id = $newTitle->getArticleId();
186                 if( $id ) {
187                         echo "...  *** cannot resolve automatically; page exists with ID $id ***\n";
188                         return false;
189                 } else {
190                         return true;
191                 }
192         }
193
194         function resolveConflict( $row, $resolvable, $suffix ) {
195                 if( !$resolvable ) {
196                         $row->title .= $suffix;
197                         $title = Title::makeTitleSafe( $row->namespace, $row->title );
198                         echo "...  *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n";
199                 }
200                 $tables = array( 'page' );
201                 foreach( $tables as $table ) {
202                         $this->resolveConflictOn( $row, $table );
203                 }
204                 return true;
205         }
206
207         function resolveConflictOn( $row, $table ) {
208                 $fname = 'NamespaceConflictChecker::resolveConflictOn';
209                 echo "... resolving on $table... ";
210                 $newTitle = Title::makeTitleSafe( $row->namespace, $row->title );
211                 $this->db->update( $table,
212                         array(
213                                 "{$table}_namespace" => $newTitle->getNamespace(),
214                                 "{$table}_title"     => $newTitle->getDbKey(),
215                         ),
216                         array(
217                                 "{$table}_namespace" => 0,
218                                 "{$table}_title"     => $row->oldtitle,
219                         ),
220                         $fname );
221                 echo "ok.\n";
222                 return true;
223         }
224 }
225
226
227
228
229 $wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' );
230
231 $verbose = isset( $options['verbose'] );
232 $fix = isset( $options['fix'] );
233 $suffix = isset( $options['suffix'] ) ? $options['suffix'] : '';
234 $prefix = isset( $options['prefix'] ) ? $options['prefix'] : '';
235 $key = isset( $options['key'] ) ? intval( $options['key'] ) : 0;
236
237 $dbw = wfGetDB( DB_MASTER );
238 $duper = new NamespaceConflictChecker( $dbw, $verbose );
239
240 if( $prefix ) {
241         $retval = $duper->checkPrefix( $key, $prefix, $fix, $suffix );
242 } else {
243         $retval = $duper->checkAll( $fix, $suffix );
244 }
245
246 if( $retval ) {
247         echo "\nLooks good!\n";
248         exit( 0 );
249 } else {
250         echo "\nOh noeees\n";
251         exit( -1 );
252 }
253
254