userCan changes, which have been done for about 3 weeks. Still TODO includes making...
authorAndrew Garrett <werdna@users.mediawiki.org>
Wed, 1 Aug 2007 10:19:26 +0000 (10:19 +0000)
committerAndrew Garrett <werdna@users.mediawiki.org>
Wed, 1 Aug 2007 10:19:26 +0000 (10:19 +0000)
includes/OutputPage.php
includes/Title.php
languages/messages/MessagesEn.php

index 39d7131..6442fd5 100644 (file)
@@ -821,6 +821,33 @@ class OutputPage {
                $this->returnToMain( false );
        }
 
+       public function showPermissionsErrorPage( $title, $errors )
+       {
+               global $wgTitle;
+
+               $this->mDebugtext .= 'Original title: ' .
+                        $wgTitle->getPrefixedText() . "\n";
+               $this->setPageTitle( wfMsg( 'permissionserrors' ) );
+               $this->setHTMLTitle( wfMsg( 'permissionserrors' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->enableClientCache( false );
+               $this->mRedirect = '';
+               $this->mBodytext = '';
+
+               $this->addWikiText( wfMsg('permissionserrorstext') );
+               $this->addHtml( '<ul class="permissions-errors">' . "\n" );
+
+               foreach( $errors as $error )
+               {
+                       $this->addHtml( '<li>' );
+                       $this->addWikiText( call_user_func_array( 'wfMsg', $error ) );
+                       $this->addHtml( '</li>');
+               }
+               $this->addHtml( '</ul>' );
+
+       }
+
        /** @deprecated */
        public function errorpage( $title, $msg ) {
                throw new ErrorPageError( $title, $msg );
index d5e9d9f..b5a6077 100644 (file)
@@ -1014,42 +1014,110 @@ class Title {
         * @return boolean
         */
        public function userCan( $action, $doExpensiveQueries = true ) {
+               global $wgUser;
+               return ( $this->getUserPermissionsErrorsInternal( $action, $wgUser, $doExpensiveQueries ) === array());
+       }
+
+        /**
+        * Can $user perform $action on this page?
+        * @param string $action action that permission needs to be checked for
+        * @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary queries.
+        * @return array Array of arrays of the arguments to wfMsg to explain permissions problems.
+       */
+       public function getUserPermissionsErrors( $action, $user, $doExpensiveQueries = true ) {
+               $errors = $this->getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries );
+
+               global $wgContLang;
+               global $wgLang;
+
+               if ( wfReadOnly() && $action != 'read' ) {
+                       $errors[] = array( 'readonlytext' );
+               }
+
+               if ( $user->isBlockedFrom( $this ) ) {
+                       $block = $user->mBlock;
+
+                       // This is from OutputPage::blockedPage
+                       // Copied at r23888 by werdna
+
+                       $id = $user->blockedBy();
+                       $reason = $user->blockedFor();
+                       $ip = wfGetIP();
+
+                       if ( is_numeric( $id ) ) {
+                               $name = User::whoIs( $id );
+                       } else {
+                               $name = $id;
+                       }
+
+                       $link = '[[' . $wgContLang->getNsText( NS_USER ) . ":{$name}|{$name}]]";
+                       $blockid = $block->mId;
+                       $blockExpiry = $user->mBlock->mExpiry;
+
+                       if ( $blockExpiry == 'infinity' ) {
+                               // Entry in database (table ipblocks) is 'infinity' but 'ipboptions' uses 'infinite' or 'indefinite'
+                               $scBlockExpiryOptions = wfMsg( 'ipboptions' );
+
+                               foreach ( explode( ',', $scBlockExpiryOptions ) as $option ) {
+                                       if ( strpos( $option, ':' ) == false )
+                                               continue;
+
+                                       list ($show, $value) = explode( ":", $option );
+
+                                       if ( $value == 'infinite' || $value == 'indefinite' ) {
+                                               $blockExpiry = $show;
+                                               break;
+                                       }
+                               }
+                       } else {
+                               $blockExpiry = $wgLang->timeanddate( wfTimestamp( TS_MW, $blockExpiry ), true );
+                       }
+
+                       $intended = $user->mBlock->mAddress;
+
+                       $errors[] = array ( ($block->mAuto ? 'autoblockedtext-concise' : 'blockedtext-concise'), $link, $reason, $ip, name, $blockid, $blockExpiry, $intended );
+               }
+
+               return $errors;
+       }
+
+       /**
+        * Can $user perform $action on this page?
+        * This is an internal function, which checks ONLY that previously checked by userCan (i.e. it leaves out checks on wfReadOnly() and blocks)
+        * @param string $action action that permission needs to be checked for
+        * @param bool $doExpensiveQueries Set this to false to avoid doing unnecessary queries.
+        * @return array Array of arrays of the arguments to wfMsg to explain permissions problems.
+        */
+       private function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true ) {
                $fname = 'Title::userCan';
                wfProfileIn( $fname );
 
-               global $wgUser;
+               $errors = array();
 
-               $result = null;
-               wfRunHooks( 'userCan', array( &$this, &$wgUser, $action, &$result ) );
-               if ( $result !== null ) {
-                       wfProfileOut( $fname );
-                       return $result;
+               if ( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
+                       return $result ? array() : array( array( 'badaccess-group0' ) );
                }
 
                if( NS_SPECIAL == $this->mNamespace ) {
-                       wfProfileOut( $fname );
-                       return false;
+                       $errors[] = array('ns-specialprotected');
                }
                
                if ( $this->isNamespaceProtected() ) {
-                       wfProfileOut( $fname );
-                       return false;
+                       $errors[] = (NS_MEDIAWIKI == $this->mNamespace ? array('protectedinterface') : array( 'namespaceprotected', $wgContLang->getNSText( $this->mNamespace ) ) );
                }
 
                if( $this->mDbkeyform == '_' ) {
                        # FIXME: Is this necessary? Shouldn't be allowed anyway...
-                       wfProfileOut( $fname );
-                       return false;
+                       $errors[] = array('badaccess-group0');
                }
 
                # protect css/js subpages of user pages
                # XXX: this might be better using restrictions
                # XXX: Find a way to work around the php bug that prevents using $this->userCanEditCssJsSubpage() from working
                if( $this->isCssJsSubpage()
-                       && !$wgUser->isAllowed('editinterface')
-                       && !preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) ) {
-                       wfProfileOut( $fname );
-                       return false;
+                       && !$user->isAllowed('editinterface')
+                       && !preg_match('/^'.preg_quote($user->getName(), '/').'\//', $this->mTextform) ) {
+                       $errors[] = array('customcssjsprotected');
                }
                
                if ( $doExpensiveQueries && !$this->isCssJsSubpage() ) {
@@ -1065,9 +1133,11 @@ class Title {
                        if( $cascadingSources > 0 && isset($restrictions[$action]) ) {
                                foreach( $restrictions[$action] as $right ) {
                                        $right = ( $right == 'sysop' ) ? 'protect' : $right;
-                                       if( '' != $right && !$wgUser->isAllowed( $right ) ) {
-                                               wfProfileOut( $fname );
-                                               return false;
+                                       if( '' != $right && !$user->isAllowed( $right ) ) {
+                                               $pages = '';
+                                               foreach( $cascadeSources as $id => $page )
+                                                       $pages .= '* [[:' . $page->getPrefixedText() . "]]\n";
+                                               $errors[] = array( 'cascadeprotected', array_len( $cascadingSources ), $pages );
                                        }
                                }
                        }
@@ -1078,33 +1148,53 @@ class Title {
                        if ( $right == 'sysop' ) {
                                $right = 'protect';
                        }
-                       if( '' != $right && !$wgUser->isAllowed( $right ) ) {
-                               wfProfileOut( $fname );
-                               return false;
+                       if( '' != $right && !$user->isAllowed( $right ) ) {
+                               $errors[] = array( 'protectedpagetext' );
                        }
                }
 
-               if( $action == 'move' &&
-                       !( $this->isMovable() && $wgUser->isAllowed( 'move' ) ) ) {
-                       wfProfileOut( $fname );
-                       return false;
-               }
-
                if( $action == 'create' ) {
-                       if( (  $this->isTalkPage() && !$wgUser->isAllowed( 'createtalk' ) ) ||
-                               ( !$this->isTalkPage() && !$wgUser->isAllowed( 'createpage' ) ) ) {
-                               wfProfileOut( $fname );
-                               return false;
+                       if( (  $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
+                               ( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) ) {
+                               $errors[] = $user->isAnon() ? array ('nocreatetext') : array ('nocreate-loggedin');
                        }
                }
 
-               if( $action == 'edit' && !$wgUser->isAllowed( 'edit' ) ) {
-                       wfProfileOut( $fname );
-                       return false;
+               if( $action == 'move' &&
+                       !( $this->isMovable() && $user->isAllowed( 'move' ) ) ) {
+                       $errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
+                } else if ( !$user->isAllowed( $action ) ) {
+                       $return = null;
+                       $groups = array();
+                       global $wgGroupPermissions;
+                       foreach( $wgGroupPermissions as $key => $value ) {
+                           if( isset( $value[$permission] ) && $value[$permission] == true ) {
+                               $groupName = User::getGroupName( $key );
+                               $groupPage = User::getGroupPage( $key );
+                               if( $groupPage ) {
+                                   $skin = $user->getSkin();
+                                   $groups[] = $skin->makeLinkObj( $groupPage, $groupName );
+                               } else {
+                                   $groups[] = $groupName;
+                               }
+                           }
+                       }
+                       $n = count( $groups );
+                       $groups = implode( ', ', $groups );
+                       switch( $n ) {
+                           case 0:
+                           case 1:
+                           case 2:
+                               $return = array( "badaccess-group$n", $groups );
+                               break;
+                           default:
+                               $return = array( 'badaccess-groups', $groups );
+                       }
+                       $errors[] = $return;
                }
 
                wfProfileOut( $fname );
-               return true;
+               return $errors;
        }
 
        /**
index 4167a53..f610d55 100644 (file)
@@ -788,8 +788,11 @@ Query: $2',
 'protectedinterface'   => 'This page provides interface text for the software, and is locked to prevent abuse.',
 'editinginterface'     => "'''Warning:''' You are editing a page which is used to provide interface text for the software. Changes to this page will affect the appearance of the user interface for other users.",
 'sqlhidden'            => '(SQL query hidden)',
-'cascadeprotected'     => 'This page has been protected from editing, because it is included in the following {{PLURAL:$1|page|pages}}, which are protected with the "cascading" option turned on:',
-'namespaceprotected' => "You do not have permission to edit pages in the '''$1''' namespace.",
+'cascadeprotected'     => "This page has been protected from editing, because it is included in the following {{PLURAL:$1|page|pages}}, which are protected with the \"cascading\" option turned on:
+$2",
+'namespaceprotected'   => "You do not have permission to edit pages in the '''$1''' namespace.",
+'customcssjsprotected' => "You do not have permission to edit this page, because it contains another user's personal settings.",
+'ns-specialprotected'  => "Pages in the special namespace cannot be edited.",
 
 # Login and logout pages
 'logouttitle'                => 'User logout',
@@ -944,7 +947,7 @@ The block was made by $1. The reason given is ''$2''.
 
 You can contact $1 or another [[{{MediaWiki:grouppage-sysop}}|administrator]] to discuss the block.
 You cannot use the 'email this user' feature unless a valid email address is specified in your
-[[Special:Preferences|account preferences]] and you have not been blocked from using it. 
+[[Special:Preferences|account preferences]] and you have not been blocked from using it.
 Your current IP address is $3, and the block ID is #$5. Please include either or both of these in any queries.",
 'autoblockedtext'           => 'Your IP address has been automatically blocked because it was used by another user, who was blocked by $1.
 The reason given is this:
@@ -957,11 +960,18 @@ The reason given is this:
 You may contact $1 or one of the other
 [[{{MediaWiki:grouppage-sysop}}|administrators]] to discuss the block.
 
-Note that you may not use the "e-mail this user" feature unless you have a valid e-mail address 
+Note that you may not use the "e-mail this user" feature unless you have a valid e-mail address
 registered in your [[Special:Preferences|user preferences]] and you have not been blocked from using it.
 
 Your block ID is $5. Please include this ID in any queries you make.',
-'blockedoriginalsource'     => "The source of '''$1''' is shown below:",
+'blockedtext-concise'       => "$7, which matches your username or IP address, has been blocked by $1. The reason given was $2. The expiry time of this block is $6. To discuss the block, you can 
+contact $1, or another administrator. You cannot use the 'email this user' feature unless a valid email address is specified in your account preferences and you have not been blocked from using it. 
+Your current IP address is $3, and the block ID is #$5. Please include either or both of these in any queries.",
+'autoblockedtext-concise'       => "Your IP address has recently been used by a user who was blocked. The block was made by $1. The reason given was $2. The expiry time of this block is $6. To 
+discuss the block, you can contact $1, or another administrator. You cannot use the 'email this user' feature unless a valid email address is specified in your account preferences and you have not 
+been blocked from using it. Your current IP address is $3, and the block ID is #$5. Please include either or both of these in any queries.",
+'blockedoriginalsource'     => "The source of '''$1''' is 
+shown below:",
 'blockededitsource'         => "The text of '''your edits''' to '''$1''' is shown below:",
 'whitelistedittitle'        => 'Login required to edit',
 'whitelistedittext'         => 'You have to $1 to edit pages.',
@@ -1053,7 +1063,10 @@ the text into a text file and save it for later.</strong>',
 'nocreatetitle'             => 'Page creation limited',
 'nocreatetext'              => 'This site has restricted the ability to create new pages.
 You can go back and edit an existing page, or [[Special:Userlogin|log in or create an account]].',
-'recreate-deleted-warn'     => "'''Warning: You are recreating a page that was previously deleted.'''
+'nocreate-loggedin'        => 'You do not have permission to create new pages on this wiki.',
+'permissionserrors'        => "Permissions Errors",
+'permissionserrorstext'            => "You do not have permission to do that, for the following {{PLURAL:$1|reason|reasons}}:",
+'recreate-deleted-warn'     => "'''Warning: You are recreating a page that was previously deleted.''',
 
 You should consider whether it is appropriate to continue editing this page.
 The deletion log for this page is provided here for convenience:",
@@ -2097,6 +2110,7 @@ In those cases, you will have to move or merge the page manually if desired.",
 'movenologin'             => 'Not logged in',
 'movenologintext'         => 'You must be a registered user and [[Special:Userlogin|logged in]]
 to move a page.',
+'movenotallowed'         => 'You do not have permission to move pages on this wiki.',
 'newtitle'                => 'To new title:',
 'move-watch'              => 'Watch this page',
 'movepagebtn'             => 'Move page',