Index: branches/wikidata/phase3/skins/monobook/main.css |
— | — | @@ -1349,6 +1349,12 @@ |
1350 | 1350 | padding: 1.5em 2em; |
1351 | 1351 | } |
1352 | 1352 | |
| 1353 | +div#fixPseudoNsForm { |
| 1354 | + margin-bottom: 1em; |
| 1355 | + border: 1px solid #aaa; |
| 1356 | + padding: 1.5em 2em; |
| 1357 | +} |
| 1358 | + |
1353 | 1359 | /* noarticletext */ |
1354 | 1360 | div.noarticletext { |
1355 | 1361 | border: 1px solid #ccc; |
Index: branches/wikidata/phase3/includes/Defines.php |
— | — | @@ -154,6 +154,12 @@ |
155 | 155 | /**#@-*/ |
156 | 156 | |
157 | 157 | /**#@+ |
| 158 | + * Pseudonamespace conversions |
| 159 | + */ |
| 160 | +define('NS_PSEUDO_NOT_FOUND',1); |
| 161 | +define('NS_PSEUDO_CONVERTED',2); |
| 162 | + |
| 163 | +/**#@+ |
158 | 164 | * Valid namespace names character class |
159 | 165 | */ |
160 | 166 | define('NS_CHAR','[ _0-9A-Za-z\x80-\xff]'); |
Index: branches/wikidata/phase3/includes/Title.php |
— | — | @@ -1194,6 +1194,9 @@ |
1195 | 1195 | if(array_key_exists($this->mNamespace,$wgNamespaces)) { |
1196 | 1196 | $p .= $wgNamespaces[$this->mNamespace]->getDefaultName() . ':'; |
1197 | 1197 | } else { |
| 1198 | + # The database refers to a namespace that |
| 1199 | + # no longer exists. We're using a pseudo-prefix, |
| 1200 | + # but the page is inaccessible for now. |
1198 | 1201 | $p = wfMsg('namespace_missing_prefix').'_'.$this->mNamespace.':'; |
1199 | 1202 | } |
1200 | 1203 | } |
Index: branches/wikidata/phase3/includes/Namespace.php |
— | — | @@ -889,7 +889,65 @@ |
890 | 890 | $dbr->freeResult( $res ); |
891 | 891 | } |
892 | 892 | |
| 893 | + /** |
| 894 | + * Convert a "pseudonamespace" (just prefixed titles) into a real |
| 895 | + * one. |
| 896 | + * |
| 897 | + * @param string $prefix - The pseudonamespace prefix string |
| 898 | + * @param Namespace $target - the target namespace object |
| 899 | + * @param Namespace $source - the source namespace object (should |
| 900 | + * usually be $wgNamespaces[NS_MAIN] or ..[NS_TALK]). This is the |
| 901 | + * one we expect the prefixed titles to be stored in. |
| 902 | + * |
| 903 | + * Why pass around Namespace objects? This saves us some validation, |
| 904 | + * since the indexes can be assumed to exist. |
| 905 | + * |
| 906 | + * @static |
| 907 | + */ |
| 908 | + function convertPseudonamespace($prefix,$target,$source) { |
| 909 | + $dbm =& wfGetDB(DB_MASTER); |
| 910 | + $dbs =& wfGetDB(DB_SLAVE); |
| 911 | + $fname="Namespace::convertPseudonamespace"; |
| 912 | + $table = $dbs->tableName( 'page' ); |
| 913 | + $eprefix = $dbs->strencode( $prefix ); |
| 914 | + $likeprefix = str_replace( '_', '\\_', $eprefix); |
| 915 | + $targetid=$target->getIndex(); |
| 916 | + $sourceid=$source->getIndex(); |
| 917 | + |
| 918 | + $sql = "SELECT page_id AS id, |
| 919 | + page_title AS oldtitle, |
| 920 | + TRIM(LEADING '$eprefix:' FROM page_title) AS title |
| 921 | + FROM {$table} |
| 922 | + WHERE page_namespace=$sourceid |
| 923 | + AND page_title LIKE '$likeprefix:%'"; |
| 924 | + |
| 925 | + $result = $dbs->query( $sql, $fname ); |
| 926 | + $set = array(); |
| 927 | + while( $row = $dbs->fetchObject( $result ) ) { |
| 928 | + $set[] = $row; |
| 929 | + } |
| 930 | + $dbs->freeResult( $result ); |
| 931 | + |
| 932 | + # TODO: Don't run this blindly - check for title dupes first |
| 933 | + if(!count($set)) { |
| 934 | + return NS_PSEUDO_NOT_FOUND; |
| 935 | + } else { |
| 936 | + foreach($set as $row) { |
| 937 | + $dbm->update( $table, |
| 938 | + array( |
| 939 | + "page_namespace" => $targetid, |
| 940 | + "page_title" => $row->title, |
| 941 | + ), |
| 942 | + array( |
| 943 | + "page_namespace" => $sourceid, |
| 944 | + "page_title" => $row->oldtitle, |
| 945 | + ), |
| 946 | + $fname ); |
| 947 | + } |
| 948 | + } |
| 949 | + return NS_PSEUDO_CONVERTED; |
893 | 950 | |
| 951 | + } |
894 | 952 | |
895 | 953 | } |
896 | 954 | |
Index: branches/wikidata/phase3/includes/DefaultSettings.php |
— | — | @@ -794,6 +794,7 @@ |
795 | 795 | |
796 | 796 | $wgGroupPermissions['bureaucrat']['userrights'] = true; |
797 | 797 | $wgGroupPermissions['bureaucrat']['namespaces'] = true; |
| 798 | +$wgGroupPermissions['bureaucrat']['fix_pseudonamespaces'] = true; |
798 | 799 | |
799 | 800 | /** |
800 | 801 | * The developer group is deprecated, but can be activated if need be |
Index: branches/wikidata/phase3/includes/SpecialNamespaces.php |
— | — | @@ -20,6 +20,8 @@ |
21 | 21 | $f->addNamespaces(); |
22 | 22 | } elseif($wgRequest->getText('nsAction')=='changenamespaces') { |
23 | 23 | $f->changeNamespaces(); |
| 24 | + } elseif($wgRequest->getText('nsAction')=='fixpseudonamespaces') { |
| 25 | + $f->fixPseudonamespaces(); |
24 | 26 | } |
25 | 27 | } elseif($action == 'delete') { |
26 | 28 | $f->deleteNamespace(); |
— | — | @@ -139,25 +141,12 @@ |
140 | 142 | $hidden = $ns->isHidden ? ' checked' : ''; |
141 | 143 | |
142 | 144 | $linkprefix = $ns->getTarget(); |
143 | | - $parentslot = $ns->getParentIndex(); |
144 | | - $namespaceselect = ''; |
145 | | - |
| 145 | + $parentslot = $ns->getParentIndex(); |
146 | 146 | # maybe make HTMLnamespaceselector more flexible and use |
147 | 147 | # it instead here |
148 | 148 | if( !$ns->isSpecial() ) { |
149 | | - foreach ( $name_array as $arr_index => $arr_name ) { |
150 | | - if( $arr_index < NS_MAIN && $arr_name!=$noparent ) |
151 | | - continue; |
152 | | - $list_option = ($arr_index == NS_MAIN ? wfMsg ( 'blanknamespace' ) : $arr_name); |
153 | | - if(is_null($parentslot)) { |
154 | | - $arr_name == $noparent ? $selected = ' selected ' : $selected=''; |
155 | | - } else { |
156 | | - $arr_index == $parentslot ? $selected = ' selected' : $selected=''; |
157 | | - } |
158 | | - $namespaceselect .= "\n<option value='$arr_index'$selected>$list_option</option>"; |
159 | | - } |
| 149 | + $namespaceselect=$this->getSelector($name_array,$parentslot); |
160 | 150 | |
161 | | - |
162 | 151 | // TODO : fix code below, maybe use HTMLForm ? |
163 | 152 | |
164 | 153 | $namespaceselect_html = <<<END |
— | — | @@ -315,14 +304,50 @@ |
316 | 305 | <<<END |
317 | 306 | <input type="submit" value="{$namespace_save_changes}" /> |
318 | 307 | </form> |
319 | | - |
| 308 | +<br/> |
320 | 309 | END; |
321 | 310 | |
| 311 | + |
322 | 312 | // Ouput the form |
323 | 313 | $wgOut->addHTML( $htmlform ); |
324 | 314 | |
| 315 | + // Pseudonamespace converter |
| 316 | + if(in_array( 'fix_pseudonamespaces', $wgUser->getRights())) { |
| 317 | + $all_name_array = Namespace::getFormattedDefaultNamespaces(); |
| 318 | + $pseudons_select=$this->getSelector($all_name_array); |
| 319 | + $wgOut->addWikiText( wfMsg( 'fix_pseudonamespaces_header' ) ); |
| 320 | + $phtmlform =' |
| 321 | +<div id="fixPseudoNsForm"> |
| 322 | +<form name="fixpseudonamepaces" method="post" action="'.$action.'"> |
| 323 | +<input type="hidden" name="nsAction" value="fixpseudonamespaces" /> |
| 324 | +<input type="hidden" name="wpEditToken" value="'.$token.'" /> |
| 325 | +<table> |
| 326 | + <tr valign="top"> |
| 327 | + <td>'.wfMsg('pseudonamespace_prefix').'</td> |
| 328 | + <td> |
| 329 | + <input type="text" name="nsPrefix" size="20" /> |
| 330 | + </td> |
| 331 | + </tr> |
| 332 | + <tr valign="top"> |
| 333 | + <td>'.wfMsg('pseudonamespace_target').'<br /></td> |
| 334 | + <td><select name="nsConvertTo" size="1">'.$pseudons_select.'</select></td> |
| 335 | + </tr> |
| 336 | + <tr> |
| 337 | + <td colspan="2"> |
| 338 | + <label> |
| 339 | + <input type="checkbox" name="nsConvertTalk" checked />'.wfMsg('pseudonamespace_converttalk').' |
| 340 | + </label> |
| 341 | + </td> |
| 342 | + </tr> |
| 343 | +</table> |
| 344 | +<input type="submit" value="'.wfMsg('pseudonamespace_convert').'" /> |
| 345 | +</form> |
| 346 | +</div>'; |
| 347 | + $wgOut->addHTML($phtmlform); |
325 | 348 | } |
326 | 349 | |
| 350 | +} |
| 351 | + |
327 | 352 | /** |
328 | 353 | * @todo Document |
329 | 354 | */ |
— | — | @@ -631,5 +656,66 @@ |
632 | 657 | return false; |
633 | 658 | } |
634 | 659 | } |
| 660 | + |
| 661 | + /** |
| 662 | + * Call Namespace::convertPseudonamespace with the correct |
| 663 | + * parameters and display the results. |
| 664 | + */ |
| 665 | + function fixPseudonamespaces() { |
| 666 | + |
| 667 | + global $wgOut, $wgRequest, $wgUser, $wgNamespaces; |
| 668 | + if(!in_array( 'fix_pseudonamespaces', $wgUser->getRights())) { |
| 669 | + $this->showForm( wfMsg('badaccess'), wfMsg('badaccesstext','[['.wfMsg('administrators').']]','fix_pseudonamespaces')); |
| 670 | + return false; |
| 671 | + } |
| 672 | + $prefix=$wgRequest->getText('nsPrefix'); |
| 673 | + $targetid=$wgRequest->getIntOrNull('nsConvertTo'); |
| 674 | + $converttalk = $wgRequest->getBool('nsConvertTalk'); |
| 675 | + if(empty($prefix) || is_null($targetid)) { |
| 676 | + $this->showForm (wfMsg('pseudonamespace_info_missing')); |
| 677 | + return false; |
| 678 | + |
| 679 | + } |
| 680 | + $rv=Namespace::convertPseudonamespace($prefix,$wgNamespaces[$targetid],$wgNamespaces[NS_MAIN]); |
| 681 | + if($rv==NS_PSEUDO_NOT_FOUND) { |
| 682 | + $this->showForm( wfMsg('pseudonamespace_not_found',$prefix)); |
| 683 | + return false; |
| 684 | + } else { |
| 685 | + $wgOut->addWikiText(wfMsg('pseudonamespace_converted', $prefix, $wgNamespaces[$targetid]->getDefaultName())); |
| 686 | + } |
| 687 | + if($converttalk) { |
| 688 | + # A pseudonamespace, by definition, exists in the |
| 689 | + # main (unprefixed) namespace - therefore its talk |
| 690 | + # pages are NS_TALK. |
| 691 | + |
| 692 | + # TODO: Don't assume we _have_ a talk namespace for the |
| 693 | + # target namespace. |
| 694 | + $trv=Namespace::convertPseudonamespace($prefix,$wgNamespaces[$wgNamespaces[$targetid]->getTalk()],$wgNamespaces[NS_TALK]); |
| 695 | + if($trv==NS_PSEUDO_NOT_FOUND) { |
| 696 | + $wgOut->addWikiText(wfMsg('pseudonamespace_talk_not_found')); |
| 697 | + } else { |
| 698 | + $wgOut->addWikiText(wfMsg('pseudonamespace_talk_converted')); |
| 699 | + } |
| 700 | + } |
| 701 | + $this->showForm(); |
| 702 | + } |
| 703 | + |
| 704 | + function getSelector($name_array,$parentslot=null) { |
| 705 | + $noparent = wfMsg('no_parent_namespace'); |
| 706 | + $namespaceselect=''; |
| 707 | + foreach ( $name_array as $arr_index => $arr_name ) { |
| 708 | + if( $arr_index < NS_MAIN && $arr_name!=$noparent ) |
| 709 | + continue; |
| 710 | + $list_option = ($arr_index == NS_MAIN ? wfMsg ( 'blanknamespace' ) : $arr_name); |
| 711 | + if(is_null($parentslot)) { |
| 712 | + $arr_name == $noparent ? $selected = ' selected ' : $selected=''; |
| 713 | + } else { |
| 714 | + $arr_index == $parentslot ? $selected = ' selected' : $selected=''; |
| 715 | + } |
| 716 | + $namespaceselect .= "\n<option value='$arr_index'$selected>$list_option</option>"; |
| 717 | + } |
| 718 | + return $namespaceselect; |
| 719 | + |
| 720 | + } |
635 | 721 | } |
636 | 722 | ?> |
Index: branches/wikidata/phase3/languages/Language.php |
— | — | @@ -2195,7 +2195,7 @@ |
2196 | 2196 | 'namespace_name_missing'=>'You have not entered a namespace name.', |
2197 | 2197 | 'namespace_name_dupe'=>'The namespace name is already in use. Please choose a different name.', |
2198 | 2198 | 'namespace_name_not_empty'=>'Some pages still refer to this namespace using this name. It canot be deleted or renamed until all links are changed.', |
2199 | | -'namespace_name_prefix'=>'There are pages which contain this name as a "pseudonamespace" in the title. These pages would become invisible if the namespace was created.', |
| 2199 | +'namespace_name_prefix'=>'There are pages which contain this name as a "pseudonamespace" in the title. These pages would become invisible if the namespace was created. You can fix this manually by creating a temporary namespace name, moving all pages and talk pages there, deleting the redirects, and then renaming the namespace. If there are too many pages, please contact a developer.', |
2200 | 2200 | 'namespace_name_interwiki'=>'The name is already used as an Interwiki prefix to link to another wiki site. This Interwiki prefix would become unusable if this name was used.', |
2201 | 2201 | 'namespace_name_linked'=>'The namespace name is still linked to from some pages. If it was deleted, these links would be broken.', |
2202 | 2202 | 'namespace_error'=>'The namespace "$1" cannot be created or modified.', |
— | — | @@ -2207,6 +2207,19 @@ |
2208 | 2208 | 'canonicalname' => 'canonical name', |
2209 | 2209 | 'namespace_name_header'=>'Namespace name', |
2210 | 2210 | 'namespace_issue_header'=>'Problem', |
| 2211 | +'fix_pseudonamespaces_header'=>'You can convert "pseudonamespaces" (titles with a consistent prefix like "Cookbook:" which is not a real namespace) into real namespaces here, by providing the prefix and selecting a target namespace. If the namespace does not yet exist, create a temporary name for it above first; you can change it after the conversion.', |
| 2212 | +'pseudonamespace_prefix'=>'Pseudonamespace prefix', |
| 2213 | +'pseudonamespace_target'=>'Convert into', |
| 2214 | +'pseudonamespace_converttalk'=>'Try to convert discussion pages into the associated talk namespace', |
| 2215 | +'pseudonamespace_convert'=>'Convert', |
| 2216 | +'pseudonamespace_converted'=>'The pseudonamespace "$1" was successfully converted into the real namespace with the default name "$2".', |
| 2217 | +'pseudonamespace_talk_converted'=>'The associated discussion pages were also converted.', |
| 2218 | +#'pseudonamespace_conversion_error'=>'There was a problem converting the pseudonamespace "$1".', |
| 2219 | +#'pseudonamespace_talk_conversion_error'=>'There was a problem converting the talk pages of the pseudonamespace.', |
| 2220 | +'pseudonamespace_info_missing'=>'You did not provide a namespace name or target namespace.', |
| 2221 | +'pseudonamespace_not_found'=>'No pages with the prefix "$1" were found!', |
| 2222 | +'pseudonamespace_talk_not_found'=>'No talk pages associated with this pseudonamespace were found.', |
| 2223 | + |
2211 | 2224 | # This is appended via JavaScript to the entered namsepace name |
2212 | 2225 | # as a suggested talkpage name in Special:Namespaces. If set to '-', |
2213 | 2226 | # it will not be used. |