r88925 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r88924‎ | r88925 | r88926 >
Date:20:26, 26 May 2011
Author:robin
Status:ok
Tags:
Comment:
* Fix bug in SpecialViewUserLang: use prefs of target user, not viewing user
* Prevent users from creating unprefixed pages (or moving a page to an unprefixed title), instead of just showing a warning (TitleBlacklist blocks it anyway currently on Incubator)
* Improve language code and prefix checks, and allow more language codes as valid (not only xx[x])
Modified paths:
  • /trunk/extensions/WikimediaIncubator/IncubatorTest.php (modified) (history)
  • /trunk/extensions/WikimediaIncubator/SpecialViewUserLang.php (modified) (history)
  • /trunk/extensions/WikimediaIncubator/WikimediaIncubator.i18n.php (modified) (history)
  • /trunk/extensions/WikimediaIncubator/WikimediaIncubator.php (modified) (history)

Diff [purge]

Index: trunk/extensions/WikimediaIncubator/IncubatorTest.php
@@ -49,27 +49,65 @@
5050 }
5151
5252 /*
53 - * This validates a language code. Currently it is set
54 - * to only allow two or three-letter codes strictly, but
55 - * it can be changed when the policy changes.
56 - * See also $wmincLangCodeLength.
 53+ * This validates a given language code.
 54+ * Only "xx[x]" and "xx[x]-x[xxxxxxxx]" are allowed.
5755 */
5856 static function validateLanguageCode( $code ) {
59 - return (bool) preg_match( '/[a-z][a-z][a-z]?/', $code );
 57+ global $wmincLangCodeLength;
 58+ if( strlen( $code ) > $wmincLangCodeLength ) { return false; }
 59+ if( $code == 'be-x-old' ) { return true; } // one exception...
 60+ return (bool) preg_match( '/^[a-z][a-z][a-z]?(-[a-z]+)?$/', $code );
6061 }
6162
6263 /*
63 - * Same as above, but for full prefix in a given title.
 64+ * This validates a full prefix in a given title.
 65+ * It gives an array with the project and language code, containing
 66+ * the key 'error' if it is invalid.
 67+ * Use validatePrefix() if you just want true or false.
 68+ * Use displayPrefixedTitle() to make a prefix page title!
 69+ *
6470 * @param $onlyprefix Bool Whether to validate only the prefix, or
6571 * also allow other text within the page title (Wx/xxx vs Wx/xxx/Text)
6672 */
67 - static function validatePrefix( $title, $onlyprefix = false ) {
 73+ static function analyzePrefix( $title, $onlyprefix = false ) {
 74+ $data = array();
 75+ // split title into parts
 76+ $titleparts = explode( '/', $title );
 77+ if( !is_array( $titleparts ) || !isset( $titleparts[1] ) ) {
 78+ $data['error'] = 'noslash';
 79+ } else {
 80+ $data['project'] = $titleparts[0][1]; // get the x from Wx/...
 81+ $data['lang'] = $titleparts[1];
 82+ $data['prefix'] = 'W'.$data['project'].'/'.$data['lang'];
 83+ // check language code
 84+ if( !self::validateLanguageCode( $data['lang'] ) ) {
 85+ $data['error'] = 'invalidlangcode';
 86+ }
 87+ }
6888 global $wmincProjects;
6989 $listProjects = implode( '', $wmincProjects ); // something like: pbtqn
70 - return (bool) preg_match( '/^W['.$listProjects.']\/[a-z][a-z][a-z]?' .
71 - ($onlyprefix ? '$' : '' ) . '/', $title );
 90+ if( !preg_match( '/^W['.$listProjects.']\/[a-z-]+' .
 91+ ($onlyprefix ? '$/' : '(\/.+)?$/' ), $title ) ) {
 92+ $data['error'] = 'invalidprefix';
 93+ }
 94+ if( !$onlyprefix && ( isset( $data['error'] ) &&
 95+ $data['error'] != 'invalidprefix' ) ) { // there is a Page_title
 96+ $prefixn = strlen( $data['prefix'].'/' ); // number of chars in prefix
 97+ // get Page_title from Wx/xx/Page_title
 98+ $data['realtitle'] = substr( $title, $prefixn );
 99+ }
 100+ return $data; // return an array with information
72101 }
73102
 103+ /*
 104+ * This returns simply true or false based on analyzePrefix().
 105+ */
 106+ static function validatePrefix( $title, $onlyprefix = false ) {
 107+ $data = self::analyzePrefix( $title, $onlyprefix );
 108+ if( isset( $data['error'] ) ) { return true; }
 109+ return false;
 110+ }
 111+
74112 /*
75113 * Returns true if the given project (or preference
76114 * by default) is one of the projects using the
@@ -99,7 +137,7 @@
100138
101139 /*
102140 * Makes a full prefixed title of a given page title and namespace
103 - * @param $ns Tnt numeric value of namespace
 141+ * @param $ns Int numeric value of namespace
104142 */
105143 static function displayPrefixedTitle( $title, $ns = 0 ) {
106144 global $wgLang, $wmincTestWikiNamespaces;
@@ -139,42 +177,69 @@
140178 return true;
141179 }
142180
143 - static function checkPrefixOnEditPage( $editpage ) {
144 - global $wmincProjectSite;
145 - // If user has "project" as test wiki preference, it isn't needed to check
146 - if ( self::displayPrefix() == $wmincProjectSite['short'] ) {
 181+ /* Return an error if the user wants to create an unprefixed page
 182+ */
 183+ static function checkPrefixCreatePermissions( $title, $user, $action, &$result ) {
 184+ global $wmincProjectSite, $wmincTestWikiNamespaces, $wmincPseudoCategoryNSes;
 185+ $titletext = $title->getText();
 186+ $ns = $title->getNamespace();
 187+ $prefixdata = self::analyzePrefix( $titletext );
 188+ if( $action != 'create' ) {
 189+ // only check on page creation
147190 return true;
148 - }
149 - global $wgTitle, $wmincTestWikiNamespaces;
150 - $title = $wgTitle->getText();
151 - $ns = $wgTitle->getNamespace();
152 - // If it's in one of the content namespaces or if the page title has a prefix, return
153 - if ( !in_array( $ns, $wmincTestWikiNamespaces ) || self::validatePrefix( $title ) ) {
 191+ } elseif( self::displayPrefix() == $wmincProjectSite['short'] ) {
 192+ // If user has "project" as test wiki preference, it isn't needed to check
154193 return true;
155 - }
156 - $warning = '<div id="wminc-warning"><span id="wm-warning-unprefixed">'
157 - . wfMsg( 'wminc-warning-unprefixed' )
158 - . '</span>';
159 - // If the user has a test wiki pref, suggest a page title with prefix
160 - if ( self::isContentProject() ) {
161 - global $wgUser;
162 - $suggest = self::displayPrefixedTitle( $title, $ns );
163 - if ( !$wgTitle->exists() ) { // Creating a page, so suggest to create a prefixed page
164 - $warning .= ' <span id="wminc-warning-suggest">'
165 - . wfMsg( 'wminc-warning-suggest', $suggest )
166 - . '</span>';
167 - } elseif ( $wgUser->isAllowed( 'move' ) ) { // Page exists, so suggest to move
168 - $warning .= ' <span id="wminc-warning-suggest-move" class="plainlinks">'
169 - . wfMsg( 'wminc-warning-suggest-move', $suggest, wfUrlencode( $suggest ), wfUrlencode( $wgTitle ) )
170 - . '</span>';
 194+ } elseif( !in_array( $ns, $wmincTestWikiNamespaces ) ) {
 195+ // OK if it's not in one of the content namespaces
 196+ return true;
 197+ } elseif( !isset( $prefixdata['error'] ) ) {
 198+ // no error in prefix -> no error to show
 199+ return true;
 200+ } elseif( ($ns == NS_CATEGORY || $ns == NS_CATEGORY_TALK) &&
 201+ preg_match('/^('.implode('|',$wmincPseudoCategoryNSes).'):.+$/', $titletext) ) {
 202+ // whitelisting
 203+ return true;
 204+ } elseif( $prefixdata['error'] == 'invalidlangcode' ) {
 205+ $error[] = array( 'wminc-error-wronglangcode', $prefixdata['lang'] );
 206+ } elseif ( self::isContentProject() ) {
 207+ // If the user has a test wiki pref, suggest a page title with prefix
 208+ $suggesttitle = (isset( $prefixdata['realtitle'] ) ?
 209+ $prefixdata['realtitle'] : $titletext );
 210+ $suggest = self::displayPrefixedTitle( $suggesttitle, $ns );
 211+ if ( !$title->exists() ) {
 212+ // Creating a page, so suggest to create a prefixed page
 213+ $error[] = array( 'wminc-error-unprefixed-suggest', $suggest );
171214 }
 215+ } else {
 216+ $error = 'wminc-error-unprefixed';
172217 }
173 - $warning .= '</div>';
174 - global $wgOut;
175 - $wgOut->addWikiText( $warning );
176 - return true;
 218+ $result = $error;
 219+ return false;
177220 }
178221
 222+ /* Return an error if the user wants to move
 223+ * an existing page to an unprefixed title
 224+ */
 225+ static function checkPrefixMovePermissions( $oldtitle, $newtitle, $user, &$error ) {
 226+ global $wmincProjectSite, $wmincTestWikiNamespaces;
 227+ $prefixdata = self::analyzePrefix( $newtitle->getText() );
 228+ $ns = $newtitle->getNamespace();
 229+ if( !isset( $prefixdata['error'] ) ) {
 230+ // if there is no error with the page title
 231+ return true;
 232+ } elseif( self::displayPrefix() == $wmincProjectSite['short'] ) {
 233+ // If user has "project" as test wiki preference, it isn't needed to check
 234+ return true;
 235+ } elseif( !in_array( $ns, $wmincTestWikiNamespaces ) ) {
 236+ // OK if it's not in one of the content namespaces
 237+ return true;
 238+ }
 239+ // now there should be an error with the new page title
 240+ $error = wfMsgWikiHtml( 'wminc-error-move-unprefixed' );
 241+ return false;
 242+ }
 243+
179244 /**
180245 * Add a link to Special:ViewUserLang from Special:Contributions/USERNAME
181246 * if the user has 'viewuserlang' permission
Index: trunk/extensions/WikimediaIncubator/WikimediaIncubator.i18n.php
@@ -22,12 +22,14 @@
2323 'wminc-prefinfo-code' => 'The ISO 639 language code',
2424 'wminc-prefinfo-project' => 'Select the Wikimedia project (Incubator option is for users who do general work)',
2525 'wminc-prefinfo-error' => 'You selected a project that needs a language code.',
26 - 'wminc-warning-unprefixed' => "'''Warning:''' The page you are editing is unprefixed!",
27 - 'wminc-warning-suggest' => 'You can create a page at [[:$1]].',
28 - 'wminc-warning-suggest-move' => 'You can [{{fullurl:Special:MovePage/$3|wpNewTitle=$2}} move this page to $1].',
 26+ 'wminc-error-move-unprefixed' => "Error: The page you are trying to move to [[{{MediaWiki:Helppage}}|is unprefixed or has a wrong prefix]]!",
 27+ 'wminc-error-wronglangcode' => "'''Error:''' The page you are trying to edit contains a [[{{MediaWiki:Helppage}}|wrong language code]] \"$1\"!",
 28+ 'wminc-error-unprefixed' => "'''Error:''' The page you are trying to edit is [[{{MediaWiki:Helppage}}|unprefixed]]!",
 29+ 'wminc-error-unprefixed-suggest' => "'''Error:''' The page you are trying to edit is [[{{MediaWiki:Helppage}}|unprefixed]]! You can create a page at [[:$1]].",
2930 'right-viewuserlang' => 'View [[Special:ViewUserLang|user language and test wiki]]',
3031 'randombytest' => 'Random page by test wiki',
3132 'randombytest-nopages' => 'There are no pages in your test wiki, in the namespace: $1.',
 33+ 'wminc-recentchanges-all' => 'All recent changes',
3234 );
3335
3436 /** Message documentation (Message documentation)
Index: trunk/extensions/WikimediaIncubator/WikimediaIncubator.php
@@ -13,7 +13,7 @@
1414 'path' => __FILE__,
1515 'name' => 'Wikimedia Incubator',
1616 'author' => 'SPQRobin',
17 - 'version' => '3.0.1',
 17+ 'version' => '3.1.0',
1818 'url' => 'http://www.mediawiki.org/wiki/Extension:WikimediaIncubator',
1919 'descriptionmsg' => 'wminc-desc',
2020 );
@@ -25,6 +25,7 @@
2626 /* General (globals and/or configuration) */
2727 $wmincPref = 'incubatortestwiki'; // Name of the preference
2828 $dir = dirname( __FILE__ ) . '/';
 29+// only one-letter codes can be used for projects
2930 $wmincProjects = array(
3031 'Wikipedia' => 'p',
3132 'Wikibooks' => 'b',
@@ -41,7 +42,11 @@
4243 NS_TEMPLATE, NS_TEMPLATE_TALK,
4344 NS_CATEGORY, NS_CATEGORY_TALK,
4445 );
45 -$wmincLangCodeLength = 3; // can be increased if needed (depends on policy)
 46+$wmincLangCodeLength = 12; // can be changed if needed (depends on policy)
 47+// Pseudo category namespaces like "Category:Maintenance:Delete", for easy whitelisting and structure
 48+$wmincPseudoCategoryNSes = array(
 49+ 'Incubator', 'Help', 'Users', 'Maintenance', 'Files',
 50+);
4651
4752 $wgExtensionMessagesFiles['WikimediaIncubator'] = $dir . 'WikimediaIncubator.i18n.php';
4853
@@ -59,8 +64,9 @@
6065 $wgHooks['LanguageGetMagic'][] = 'IncubatorTest::magicWord';
6166 $wgHooks['ParserGetVariableValueSwitch'][] = 'IncubatorTest::magicWordValue';
6267
63 -/* Edit page */
64 -$wgHooks['EditPage::showEditForm:initial'][] = 'IncubatorTest::checkPrefixOnEditPage';
 68+/* Create/move page permissions */
 69+$wgHooks['getUserPermissionsErrors'][] = 'IncubatorTest::checkPrefixCreatePermissions';
 70+$wgHooks['AbortMove'][] = 'IncubatorTest::checkPrefixMovePermissions';
6571
6672 /* Recent Changes */
6773 $wgAutoloadClasses['TestWikiRC'] = $dir . 'TestWikiRC.php';
Index: trunk/extensions/WikimediaIncubator/SpecialViewUserLang.php
@@ -67,7 +67,7 @@
6868 * @param $target Mixed: user whose language and test wiki we're looking up
6969 */
7070 function showInfo( $target ) {
71 - global $wgOut, $wgLang, $wmincPref, $wmincProjectSite;
 71+ global $wgOut, $wmincPref, $wmincProjectSite;
7272 $sk = $this->getSkin();
7373 $user = User::newFromName( $target );
7474 $langNames = Language::getLanguageNames();
@@ -75,9 +75,13 @@
7676 // show error if a user with that name does not exist
7777 $wgOut->addHTML( Xml::span( wfMsg( 'wminc-userdoesnotexist', $target ), 'error' ) );
7878 } else {
 79+ $prefix = IncubatorTest::displayPrefix(
 80+ $user->getOption( $wmincPref . '-project' ),
 81+ $user->getOption( $wmincPref . '-code' )
 82+ );
7983 if ( IncubatorTest::isContentProject() ) {
80 - $testwiki = $sk->link( Title::newFromText( IncubatorTest::displayPrefix() ) );
81 - } elseif ( IncubatorTest::displayPrefix() == $wmincProjectSite['short'] ) {
 84+ $testwiki = $sk->link( Title::newFromText( $prefix ) );
 85+ } elseif ( $prefix == $wmincProjectSite['short'] ) {
8286 $testwiki = htmlspecialchars( $wmincProjectSite['name'] );
8387 } else {
8488 $testwiki = wfMsgHtml( 'wminc-testwiki-none' );

Status & tagging log