Index: trunk/extensions/WikimediaIncubator/WikimediaIncubator.php |
— | — | @@ -14,7 +14,7 @@ |
15 | 15 | 'path' => __FILE__, |
16 | 16 | 'name' => 'Wikimedia Incubator', |
17 | 17 | 'author' => 'SPQRobin', |
18 | | - 'version' => '4.0', |
| 18 | + 'version' => '4.1', |
19 | 19 | 'url' => 'http://www.mediawiki.org/wiki/Extension:WikimediaIncubator', |
20 | 20 | 'descriptionmsg' => 'wminc-desc', |
21 | 21 | ); |
— | — | @@ -119,9 +119,8 @@ |
120 | 120 | 's' => 'wikisource', |
121 | 121 | 'v' => 'wikiversity', |
122 | 122 | ); |
123 | | -# if WMF/SiteMatrix config is available, use it |
124 | | -# NOTICE: include SiteMatrix extension before this extension (this is the case for WMF) |
125 | | -$wmincClosedWikis = isset( $wgSiteMatrixClosedSites ) ? $wgSiteMatrixClosedSites : null; |
| 123 | +# set this to an array or file of closed wikis (like SiteMatrix $wgSiteMatrixClosedSites) |
| 124 | +$wmincClosedWikis = false; |
126 | 125 | |
127 | 126 | /* Wx/xx[x] info page */ |
128 | 127 | $wgAutoloadClasses['InfoPage'] = $dir . 'InfoPage.php'; |
Index: trunk/extensions/WikimediaIncubator/IncubatorTest.php |
— | — | @@ -93,10 +93,12 @@ |
94 | 94 | * @param $title String The given title (often $wgTitle->getText() ) |
95 | 95 | * @param $onlyInfoPage Bool Whether to validate only the prefix, or |
96 | 96 | * also allow other text within the page title (Wx/xxx vs Wx/xxx/Text) |
| 97 | + * @param $allowSister Bool Whether to allow sister projects when checking |
| 98 | + * for the project code. |
97 | 99 | * @return Array with 'error' or 'project', 'lang', 'prefix' and |
98 | 100 | * optionally 'realtitle' |
99 | 101 | */ |
100 | | - static function analyzePrefix( $title, $onlyInfoPage = false ) { |
| 102 | + static function analyzePrefix( $title, $onlyInfoPage = false, $allowSister = false ) { |
101 | 103 | $data = array( 'error' => null ); |
102 | 104 | # split title into parts |
103 | 105 | $titleparts = explode( '/', $title ); |
— | — | @@ -111,8 +113,12 @@ |
112 | 114 | $data['error'] = 'invalidlangcode'; |
113 | 115 | } |
114 | 116 | } |
115 | | - global $wmincProjects; |
116 | | - $listProjects = implode( '', array_keys( $wmincProjects ) ); # something like: pbtqn |
| 117 | + global $wmincProjects, $wmincSisterProjects; |
| 118 | + $listProjects = implode( '', array_keys( $wmincProjects ) ); # project codes like: pbtqn |
| 119 | + if( $allowSister && is_array( $wmincSisterProjects ) ) { |
| 120 | + # join the project codes with those of the sister projects, like: pbtqnsv |
| 121 | + $listProjects = $listProjects . implode( '', array_keys( $wmincSisterProjects ) ); |
| 122 | + } |
117 | 123 | if( !preg_match( '/^W['.$listProjects.']\/[a-z-]+' . |
118 | 124 | ($onlyInfoPage ? '$/' : '(\/.+)?$/' ), $title ) ) { |
119 | 125 | $data['error'] = 'invalidprefix'; |
— | — | @@ -157,13 +163,16 @@ |
158 | 164 | } |
159 | 165 | |
160 | 166 | /** |
161 | | - * Whether the given project (or preference by default) is one of the |
162 | | - * projects using the format Wx/xxx (as defined in $wmincProjects) |
163 | | - * @param $project the project code |
164 | | - * @return Boolean |
| 167 | + * Returns the project code or name if the given project code or name (or preference by default) |
| 168 | + * is one of the projects using the format Wx/xxx (as defined in $wmincProjects) |
| 169 | + * Returns false if it is not valid. |
| 170 | + * @param $project String The project code |
| 171 | + * @param $returnName Bool Whether to return the project name instead of the code |
| 172 | + * @param $includeSister Bool Whether to include sister projects |
| 173 | + * @return String or false |
165 | 174 | */ |
166 | | - static function isContentProject( $project = '' ) { |
167 | | - global $wgUser, $wmincPref, $wmincProjects; |
| 175 | + static function getProject( $project = '', $returnName = false, $includeSister = false ) { |
| 176 | + global $wgUser, $wmincPref, $wmincProjects, $wmincSisterProjects; |
168 | 177 | $url = self::getUrlParam(); |
169 | 178 | if( $project ) { |
170 | 179 | $r = $project; # Precedence to given value |
— | — | @@ -172,10 +181,27 @@ |
173 | 182 | } else { |
174 | 183 | $r = $wgUser->getOption( $wmincPref . '-project' ); # Defaults to preference |
175 | 184 | } |
176 | | - return (bool) array_key_exists( $r, $wmincProjects ); |
| 185 | + $projects = $includeSister ? array_merge( $wmincProjects, $wmincSisterProjects ) : $wmincProjects; |
| 186 | + if( array_key_exists( $r, $projects ) ) { |
| 187 | + # If a code is given, return what is wanted |
| 188 | + return $returnName ? $projects[$r] : $r; |
| 189 | + } elseif( array_search( $r, $projects ) ) { |
| 190 | + # If a name is given, return what is wanted |
| 191 | + return $returnName ? $r : array_search( $r, $projects ); |
| 192 | + } |
| 193 | + # Unknown code or name given -> false |
| 194 | + return false; |
177 | 195 | } |
178 | 196 | |
179 | 197 | /** |
| 198 | + * Returns a simple boolean based on getProject() |
| 199 | + * @return Bool |
| 200 | + */ |
| 201 | + static function isContentProject( $project = '', $returnName = false, $includeSister = false ) { |
| 202 | + return (bool) self::getProject( $project, $returnName, $includeSister ); |
| 203 | + } |
| 204 | + |
| 205 | + /** |
180 | 206 | * display the prefix by the given project and code |
181 | 207 | * (or the URL &testwiki= or user preference if no parameters are given) |
182 | 208 | * @return String |
— | — | @@ -398,7 +424,7 @@ |
399 | 425 | */ |
400 | 426 | static function getDBClosedWikis() { |
401 | 427 | global $wmincClosedWikis; |
402 | | - if( !self::canWeCheckDB() ) { |
| 428 | + if( !self::canWeCheckDB() || !$wmincClosedWikis ) { |
403 | 429 | return false; |
404 | 430 | } |
405 | 431 | # Is probably a file, but it might be that an array is given |
— | — | @@ -415,10 +441,11 @@ |
416 | 442 | if( !$db ) { |
417 | 443 | return false; |
418 | 444 | } |
419 | | - global $wmincExistingWikis, $wmincClosedWikis; |
| 445 | + global $wmincExistingWikis; |
| 446 | + $closed = self::getDBClosedWikis(); |
420 | 447 | if( !in_array( $db, $wmincExistingWikis ) ) { |
421 | 448 | return 'missing'; # not in the list |
422 | | - } elseif( in_array( $db, self::getDBClosedWikis() ) ) { |
| 449 | + } elseif( is_array( $closed ) && in_array( $db, $closed ) ) { |
423 | 450 | return 'closed'; # in the list of closed wikis |
424 | 451 | } |
425 | 452 | return 'existing'; |
— | — | @@ -433,26 +460,35 @@ |
434 | 461 | static function onShowMissingArticle( $article ) { |
435 | 462 | global $wgOut; |
436 | 463 | $title = $article->getTitle(); |
437 | | - $prefix = self::analyzePrefix( $title->getText(), true /* only info pages */ ); |
| 464 | + $prefix = self::analyzePrefix( $title->getText(), |
| 465 | + true /* only info pages */, true /* allow sister projects */ ); |
438 | 466 | |
439 | 467 | if( $prefix['error'] ) { # We are not on info pages |
440 | | - $prefix2 = self::analyzePrefix( $title->getText() ); |
| 468 | + global $wmincSisterProjects; |
| 469 | + $prefix2 = self::analyzePrefix( $title->getText(), false, true ); |
| 470 | + $linker = class_exists( 'DummyLinker' ) ? new DummyLinker : new Linker; |
| 471 | + $p = $prefix2['project']; |
| 472 | + $link = self::getSubdomain( $prefix2['lang'], $p, |
| 473 | + ( $title->getNsText() ? $title->getNsText() . ':' : '' ) . |
| 474 | + $prefix2['realtitle'] ); |
441 | 475 | if( self::getDBState( $prefix2 ) == 'existing' ) { |
442 | | - $link = self::getSubdomain( $prefix2['lang'], |
443 | | - $prefix2['project'], ( $title->getNsText() ? $title->getNsText() . ':' : '' ) . |
444 | | - $prefix2['realtitle'] ); |
445 | 476 | if( self::displayPrefix() == $prefix2['prefix'] ) { |
446 | 477 | # Redirect to the existing wiki if the user has this wiki as preference |
447 | 478 | $wgOut->redirect( $link ); |
448 | 479 | return true; |
449 | 480 | } else { |
450 | 481 | # Show a link to the existing wiki |
451 | | - $linker = class_exists( 'DummyLinker' ) ? new DummyLinker : new Linker; |
452 | 482 | $showLink = $linker->makeExternalLink( $link, $link ); |
453 | 483 | $wgOut->addHtml( '<div class="wminc-wiki-exists">' . |
454 | 484 | wfMsgHtml( 'wminc-error-wiki-exists', $showLink ) . |
455 | 485 | '</div>' ); |
456 | 486 | } |
| 487 | + } elseif( array_key_exists( $p, $wmincSisterProjects ) ) { |
| 488 | + # A sister project is not hosted here, so direct the user to the relevant wiki |
| 489 | + $showLink = $linker->makeExternalLink( $link, $link ); |
| 490 | + $wgOut->addHtml( '<div class="wminc-wiki-sister">' . |
| 491 | + wfMsgHtml( 'wminc-error-wiki-sister', $showLink ) . |
| 492 | + '</div>' ); |
457 | 493 | } elseif ( self::shouldWeShowUnprefixedError( $title ) ) { |
458 | 494 | # Unprefixed pages |
459 | 495 | if( self::isContentProject() ) { |
— | — | @@ -488,6 +524,8 @@ |
489 | 525 | } else { |
490 | 526 | $wgOut->addHtml( $infopage->showMissingWiki() ); |
491 | 527 | } |
| 528 | + # Set the page title from "Wx/xyz - Incubator" to "Wikiproject Language - Incubator" |
| 529 | + $wgOut->setHTMLTitle( wfMsg( 'pagetitle', htmlspecialchars( $infopage->mFormatTitle ) ) ); |
492 | 530 | return true; |
493 | 531 | } |
494 | 532 | |
— | — | @@ -514,19 +552,20 @@ |
515 | 553 | |
516 | 554 | /** |
517 | 555 | * This forms a URL based on the language and project. |
518 | | - * @param $lang Language code |
519 | | - * @param $project Project code |
| 556 | + * @param $lang String Language code |
| 557 | + * @param $project String Project code |
| 558 | + * @param $title String Page name |
520 | 559 | * @return String |
521 | 560 | */ |
522 | | - public static function getSubdomain( $lang, $projectCode ) { |
523 | | - global $wgConf, $wmincProjectDatabases; |
| 561 | + public static function getSubdomain( $lang, $projectCode, $title = '' ) { |
| 562 | + global $wgConf, $wmincProjectDatabases, $wgArticlePath; |
524 | 563 | $projectName = strtolower( $wmincProjectDatabases[$projectCode] ); |
525 | 564 | # Imitate analyzePrefix() array :p |
526 | 565 | $prefix = array( 'error' => null, 'lang' => $lang, 'project' => $projectCode ); |
527 | 566 | return $wgConf->get( 'wgServer', |
528 | 567 | self::getDB( $prefix ), $projectName, |
529 | 568 | array( 'lang' => str_replace( '_', '-', $lang ), 'site' => $projectName ) |
530 | | - ); |
| 569 | + ) . ( $title ? preg_replace( '/\$1/', $title, $wgArticlePath ) : '' ); |
531 | 570 | } |
532 | 571 | |
533 | 572 | /** |
— | — | @@ -638,7 +677,6 @@ |
639 | 678 | /** |
640 | 679 | * Make the page content language depend on the test wiki |
641 | 680 | * Only works for codes that are known to MediaWiki :( |
642 | | - * @return true |
643 | 681 | */ |
644 | 682 | static function onPageContentLanguage( $title, &$pageLang ) { |
645 | 683 | global $wmincTestWikiNamespaces, $wgOut; |
Index: trunk/extensions/WikimediaIncubator/InfoPage.i18n.php |
— | — | @@ -31,6 +31,7 @@ |
32 | 32 | 'wminc-infopage-missingwiki-text' => 'A $1 in this language does not yet exist.', |
33 | 33 | 'wminc-infopage-option-startwiki' => 'If you want to start this wiki, |
34 | 34 | you can [{{fullurl:{{FULLPAGENAME}}|action=edit}} create the page] and follow [[{{MediaWiki:Wminc-manual-url}}|our manual]].', |
| 35 | + 'wminc-infopage-option-startsister' => 'If you want to start this wiki, you can go to <b>[$2 $1]</b>.', |
35 | 36 | 'wminc-infopage-option-languages-existing' => 'You can search for [http://www.$1.org existing language editions of $1].', |
36 | 37 | 'wminc-infopage-option-sisterprojects-existing' => 'You can search for existing projects in this language:', |
37 | 38 | 'wminc-infopage-option-sisterprojects-other' => 'You can search for other projects in this language:', |
— | — | @@ -44,6 +45,7 @@ |
45 | 46 | 'wminc-infopage-contribute' => 'If you know this language, you are encouraged to contribute!', |
46 | 47 | |
47 | 48 | 'wminc-infopage-status-imported' => 'This Incubator wiki has been imported from $1 after the wiki was closed.', |
| 49 | + 'wminc-infopage-status-closedsister' => 'This subdomain was closed. Go to <b>$2</b> to contribute to this wiki.', |
48 | 50 | 'wminc-infopage-status-created' => 'This project has been approved by the language committee and is now available at $1.', |
49 | 51 | 'wminc-infopage-status-beforeincubator' => 'This project was created before Wikimedia Incubator started and is available at $1.', |
50 | 52 | ); |
Index: trunk/extensions/WikimediaIncubator/InfoPage.php |
— | — | @@ -20,22 +20,26 @@ |
21 | 21 | |
22 | 22 | class InfoPage { |
23 | 23 | public function __construct( $title, $prefixdata ) { |
24 | | - global $wmincProjects; |
| 24 | + global $wmincProjects, $wmincSisterProjects; |
25 | 25 | $this->mTitle = $title; |
26 | 26 | $this->mPrefix = $prefixdata['prefix']; |
27 | 27 | $this->mLangCode = $prefixdata['lang']; |
28 | 28 | $this->mProjectCode = $prefixdata['project']; |
29 | | - $this->mProjectName = isset( $wmincProjects[$this->mProjectCode] ) ? |
30 | | - $wmincProjects[$this->mProjectCode] : ''; |
| 29 | + $allProjects = array_merge( $wmincProjects, $wmincSisterProjects ); |
| 30 | + $this->mProjectName = isset( $allProjects[$this->mProjectCode] ) ? |
| 31 | + $allProjects[$this->mProjectCode] : ''; |
31 | 32 | if( isset( $prefixdata['error'] ) || $title->getNamespace() != NS_MAIN ) { |
32 | 33 | return; |
33 | 34 | } |
| 35 | + $this->mPortal = IncubatorTest::getSubdomain( 'www', $this->mProjectCode ); |
| 36 | + $this->mIsSister = array_key_exists( $this->mProjectCode, $wmincSisterProjects ); |
34 | 37 | $this->mDBStatus = ''; |
35 | 38 | $this->mSubStatus = ''; |
36 | 39 | $this->mThisLangData = array( 'type' => 'valid' ); # For later code check feature |
37 | 40 | $this->mLangNames = IncubatorTest::getLanguageNames(); |
38 | 41 | $this->mLangName = ( isset( $this->mLangNames[$this->mLangCode] ) ? |
39 | 42 | $this->mLangNames[$this->mLangCode] : wfMsg( 'wminc-unknownlang', $this->mLangCode ) ); |
| 43 | + $this->mFormatTitle = wfMsg( 'wminc-infopage-title', $this->mProjectName, $this->mLangName ); |
40 | 44 | return; |
41 | 45 | } |
42 | 46 | |
— | — | @@ -47,7 +51,7 @@ |
48 | 52 | global $wgUser; |
49 | 53 | $projectForFile = preg_replace('/ /', '-', strtolower( $project ) ); |
50 | 54 | $imageobj = wfFindFile( wfMsg( 'wminc-logo-' . $projectForFile ) ); |
51 | | - $useUrl = $url ? $url : 'http://www.'.strtolower( $project ).'.org/'; |
| 55 | + $useUrl = $url ? $url : IncubatorTest::getSubdomain( 'www', IncubatorTest::getProject( $project, false, true ) ); |
52 | 56 | if ( !$imageobj ) { # image not found |
53 | 57 | if( !$clickable ) { |
54 | 58 | return $logo; |
— | — | @@ -106,8 +110,7 @@ |
107 | 111 | $this->makeLogo( $this->mProjectName, true, 175 ) |
108 | 112 | ) . |
109 | 113 | Html::rawElement( 'div', array( 'class' => 'wminc-infopage-title' ), |
110 | | - wfMsg( 'wminc-infopage-title', $this->mProjectName, $this->mLangName ) . |
111 | | - $aftertitle ) . |
| 114 | + $this->mFormatTitle . $aftertitle ) . |
112 | 115 | $content ); |
113 | 116 | } |
114 | 117 | |
— | — | @@ -119,8 +122,8 @@ |
120 | 123 | ) . |
121 | 124 | Html::rawElement( 'ul', array( 'class' => 'wminc-infopage-options' ), |
122 | 125 | Html::rawElement( 'li', null, |
123 | | - wfMsgExt( 'wminc-infopage-option-startwiki', |
124 | | - array( 'parseinline' ), $this->mProjectName ) ) . |
| 126 | + wfMsgExt( 'wminc-infopage-option-' . ( $this->mIsSister ? 'startsister' : 'startwiki' ), |
| 127 | + array( 'parseinline' ), $this->mProjectName, $this->mPortal ) ) . |
125 | 128 | Html::rawElement( 'li', null, |
126 | 129 | wfMsgExt( 'wminc-infopage-option-languages-existing', |
127 | 130 | array( 'parseinline' ), $this->mProjectName ) ) . |
— | — | @@ -135,21 +138,24 @@ |
136 | 139 | } |
137 | 140 | |
138 | 141 | public function showIncubatingWiki() { |
139 | | - global $wgUser; |
140 | | - $bug = isset( $this->mBug ) ? $this->mBug : ''; |
| 142 | + global $wgUser, $wgLang; |
| 143 | + $substatus = $this->mSubStatus; |
| 144 | + if( $substatus == 'imported' && $this->mIsSister ) { |
| 145 | + $substatus = 'closedsister'; |
| 146 | + } |
| 147 | + $portalLink = $wgUser->getSkin()->makeExternalLink( $this->mPortal, $this->mProjectName ); |
141 | 148 | if( $this->mThisLangData['type'] != 'invalid' ) { |
| 149 | + $gotoLink = $wgUser->getSkin()->link( |
| 150 | + Title::newFromText( IncubatorTest::getMainPage( $this->mLangCode, $this->mPrefix ) ), |
| 151 | + wfMsgNoTrans( 'wminc-infopage-enter' ) ); |
142 | 152 | $gotoMainPage = Html::rawElement( 'span', |
143 | 153 | array( 'class' => 'wminc-infopage-entertest' ), |
144 | | - '→ ' . $wgUser->getSkin()->link( |
145 | | - Title::newFromText( IncubatorTest::getMainPage( $this->mLangCode, $this->mPrefix ) ), |
146 | | - wfMsgNoTrans( 'wminc-infopage-enter' ) |
147 | | - ) |
148 | | - ); |
| 154 | + $wgLang->getArrow() . ' ' . ( $this->mIsSister ? $portalLink : $gotoLink ) ); |
149 | 155 | } |
150 | 156 | $subdomain = IncubatorTest::getSubdomain( $this->mLangCode, $this->mProjectCode ); |
151 | 157 | $subdomainLink = $wgUser->getSkin()->makeExternalLink( $subdomain, $subdomain ); |
152 | 158 | $content = Html::rawElement( 'div', array( 'class' => 'wminc-infopage-status' ), |
153 | | - wfMsgWikiHtml( 'wminc-infopage-status-' . $this->mSubStatus, $subdomainLink ) ); |
| 159 | + wfMsgWikiHtml( 'wminc-infopage-status-' . $substatus, $subdomainLink, $portalLink ) ); |
154 | 160 | if( $this->mSubStatus != 'approved' && $this->mThisLangData['type'] != 'invalid' ) { |
155 | 161 | $content .= Html::element( 'div', |
156 | 162 | array( 'class' => 'wminc-infopage-contribute' ), |
Index: trunk/extensions/WikimediaIncubator/WikimediaIncubator.i18n.php |
— | — | @@ -31,6 +31,7 @@ |
32 | 32 | 'wminc-error-unprefixed' => "'''Error:''' This page is [[{{MediaWiki:Helppage}}|unprefixed]]!", |
33 | 33 | 'wminc-error-unprefixed-suggest' => "'''Error:''' This page is [[{{MediaWiki:Helppage}}|unprefixed]]! You can create a page at [[:$1]].", |
34 | 34 | 'wminc-error-wiki-exists' => 'This wiki already exists. You can find this page on $1. If the wiki was recently created, please wait a few hours or days until all content is imported.', |
| 35 | + 'wminc-error-wiki-sister' => 'This page belongs to a project that is not hosted here. Please go to $1 to find the wiki.', |
35 | 36 | |
36 | 37 | # Special:RandomByTest |
37 | 38 | 'randombytest' => 'Random page by test wiki', |