Drop some useless parameters to silly methods on the pretty much broken MediaWiki...
[lhc/web/wiklou.git] / includes / Title.php
index b858b26..0c91eab 100644 (file)
@@ -268,7 +268,12 @@ class Title {
         * @return Title the new object
         */
        public static function newMainPage() {
-               return Title::newFromText( wfMsgForContent( 'mainpage' ) );
+               $title = Title::newFromText( wfMsgForContent( 'mainpage' ) );
+               // Don't give fatal errors if the message is broken
+               if ( !$title ) {
+                       $title = Title::newFromText( 'Main Page' );
+               }
+               return $title;
        }
 
        /**
@@ -280,10 +285,10 @@ class Title {
         */
        public static function newFromRedirect( $text ) {
                $redir = MagicWord::get( 'redirect' );
-               if( $redir->matchStart( $text ) ) {
+               if( $redir->matchStart( trim($text) ) ) {
                        // Extract the first link and see if it's usable
                        $m = array();
-                       if( preg_match( '!\[{2}(.*?)(?:\||\]{2})!', $text, $m ) ) {
+                       if( preg_match( '!\[{2}(.*?)(?:\|.*?)?\]{2}!', $text, $m ) ) {
                                // Strip preceding colon used to "escape" categories, etc.
                                // and URL-decode links
                                if( strpos( $m[1], '%' ) !== false ) {
@@ -572,7 +577,7 @@ class Title {
         */
        public function getSubjectNsText() {
                global $wgContLang;
-               return $wgContLang->getNsText( Namespace::getSubject( $this->mNamespace ) );
+               return $wgContLang->getNsText( MWNamespace::getSubject( $this->mNamespace ) );
        }
 
        /**
@@ -581,7 +586,7 @@ class Title {
         */
        public function getTalkNsText() {
                global $wgContLang;
-               return( $wgContLang->getNsText( Namespace::getTalk( $this->mNamespace ) ) );
+               return( $wgContLang->getNsText( MWNamespace::getTalk( $this->mNamespace ) ) );
        }
 
        /**
@@ -589,7 +594,7 @@ class Title {
         * @return bool
         */
        public function canTalk() {
-               return( Namespace::canTalk( $this->mNamespace ) );
+               return( MWNamespace::canTalk( $this->mNamespace ) );
        }
 
        /**
@@ -937,27 +942,20 @@ class Title {
         * @return boolean
         */
        public function isProtected( $action = '' ) {
-               global $wgRestrictionLevels;
+               global $wgRestrictionLevels, $wgRestrictionTypes;
 
                # Special pages have inherent protection
                if( $this->getNamespace() == NS_SPECIAL )
                        return true;
 
-               # Check regular protection levels                               
-               if( $action == 'edit' || $action == '' ) {
-                       $r = $this->getRestrictions( 'edit' );
-                       foreach( $wgRestrictionLevels as $level ) {
-                               if( in_array( $level, $r ) && $level != '' ) {
-                                       return( true );
-                               }
-                       }
-               }
-               
-               if( $action == 'move' || $action == '' ) {
-                       $r = $this->getRestrictions( 'move' );
-                       foreach( $wgRestrictionLevels as $level ) {
-                               if( in_array( $level, $r ) && $level != '' ) {
-                                       return( true );
+               # Check regular protection levels
+               foreach( $wgRestrictionTypes as $type ){                
+                       if( $action == $type || $action == '' ) {
+                               $r = $this->getRestrictions( $type );
+                               foreach( $wgRestrictionLevels as $level ) {
+                                       if( in_array( $level, $r ) && $level != '' ) {
+                                               return true;
+                                       }
                                }
                        }
                }
@@ -966,7 +964,7 @@ class Title {
        }
 
        /**
-        * Is $wgUser is watching this page?
+        * Is $wgUser watching this page?
         * @return boolean
         */
        public function userIsWatching() {
@@ -1032,6 +1030,7 @@ class Title {
         * FIXME: This *does not* check throttles (User::pingLimiter()).
         *
         * @param string $action action that permission needs to be checked for
+        * @param User $user user to check
         * @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.
         */
@@ -1040,7 +1039,7 @@ class Title {
 
                global $wgContLang;
                global $wgLang;
-               global $wgEmailConfirmToEdit, $wgUser;
+               global $wgEmailConfirmToEdit;
 
                if ( $wgEmailConfirmToEdit && !$user->isEmailConfirmed() ) {
                        $errors[] = array( 'confirmedittext' );
@@ -1103,6 +1102,7 @@ class Title {
         * checks on wfReadOnly() and blocks)
         *
         * @param string $action action that permission needs to be checked for
+        * @param User $user user to check
         * @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.
         */
@@ -1193,7 +1193,18 @@ class Title {
                                $right = 'protect';
                        }
                        if( '' != $right && !$user->isAllowed( $right ) ) {
-                               $errors[] = array( 'protectedpagetext', $right );
+                               //Users with 'editprotected' permission can edit protected pages
+                               if( $action=='edit' && $user->isAllowed( 'editprotected' ) ) {
+                                       //Users with 'editprotected' permission cannot edit protected pages
+                                       //with cascading option turned on.
+                                       if($this->mCascadeRestriction) {
+                                               $errors[] = array( 'protectedpagetext', $right );
+                                       } else {
+                                               //Nothing, user can edit!
+                                       }
+                               } else {
+                                       $errors[] = array( 'protectedpagetext', $right );
+                               }
                        }
                }
 
@@ -1366,7 +1377,7 @@ class Title {
         * @return boolean
         */
        public function isMovable() {
-               return Namespace::isMovable( $this->getNamespace() )
+               return MWNamespace::isMovable( $this->getNamespace() )
                        && $this->getInterwiki() == '';
        }
 
@@ -1377,17 +1388,17 @@ class Title {
         */
        public function userCanRead() {
                global $wgUser, $wgGroupPermissions;
-               
-               # Shortcut for public wikis, allows skipping quite a bit of code path
-               if ($wgGroupPermissions['*']['read'])
-                       return true;
-               
+
                $result = null;
                wfRunHooks( 'userCan', array( &$this, &$wgUser, 'read', &$result ) );
                if ( $result !== null ) {
                        return $result;
                }
 
+               # Shortcut for public wikis, allows skipping quite a bit of code
+               if ($wgGroupPermissions['*']['read'])
+                       return true;
+
                if( $wgUser->isAllowed( 'read' ) ) {
                        return true;
                } else {
@@ -1407,14 +1418,14 @@ class Title {
                        if( !is_array($wgWhitelistRead) ) {
                                return false;
                        }
-                       
+
                        /**
                         * Check for explicit whitelisting
                         */
                        $name = $this->getPrefixedText();
                        if( in_array( $name, $wgWhitelistRead, true ) )
                                return true;
-                       
+
                        /**
                         * Old settings might have the title prefixed with
                         * a colon for main-namespace pages
@@ -1423,7 +1434,7 @@ class Title {
                                if( in_array( ':' . $name, $wgWhitelistRead ) )
                                        return true;
                        }
-                       
+
                        /**
                         * If it's a special page, ditch the subpage bit
                         * and check again
@@ -1450,7 +1461,7 @@ class Title {
         * @return bool
         */
        public function isTalkPage() {
-               return Namespace::isTalk( $this->getNamespace() );
+               return MWNamespace::isTalk( $this->getNamespace() );
        }
 
        /**
@@ -1510,14 +1521,14 @@ class Title {
         * @return bool
         */
        public function isCssSubpage() {
-               return ( NS_USER == $this->mNamespace and preg_match("/\\/.*\\.css$/", $this->mTextform ) );
+               return ( NS_USER == $this->mNamespace && preg_match("/\\/.*\\.css$/", $this->mTextform ) );
        }
        /**
         * Is this a .js subpage of a user page?
         * @return bool
         */
        public function isJsSubpage() {
-               return ( NS_USER == $this->mNamespace and preg_match("/\\/.*\\.js$/", $this->mTextform ) );
+               return ( NS_USER == $this->mNamespace && preg_match("/\\/.*\\.js$/", $this->mTextform ) );
        }
        /**
         * Protect css/js subpages of user pages: can $wgUser edit
@@ -1528,7 +1539,7 @@ class Title {
         */
        public function userCanEditCssJsSubpage() {
                global $wgUser;
-               return ( $wgUser->isAllowed('editusercssjs') or preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) );
+               return ( $wgUser->isAllowed('editusercssjs') || preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) );
        }
 
        /**
@@ -1649,10 +1660,15 @@ class Title {
         * @param resource $res restrictions as an SQL result.
         */
        private function loadRestrictionsFromRow( $res, $oldFashionedRestrictions = NULL ) {
-               $dbr = wfGetDb( DB_SLAVE );
+               global $wgRestrictionTypes;
+               $dbr = wfGetDB( DB_SLAVE );
+
+               foreach( $wgRestrictionTypes as $type ){
+                       $this->mRestrictions[$type] = array();
+               }
 
-               $this->mRestrictions['edit'] = array();
-               $this->mRestrictions['move'] = array();
+               $this->mCascadeRestriction = false;
+               $this->mRestrictionsExpiry = Block::decodeExpiry('');
 
                # Backwards-compatibility: also load the restrictions from the page record (old format).
 
@@ -1666,16 +1682,14 @@ class Title {
                                $temp = explode( '=', trim( $restrict ) );
                                if(count($temp) == 1) {
                                        // old old format should be treated as edit/move restriction
-                                       $this->mRestrictions["edit"] = explode( ',', trim( $temp[0] ) );
-                                       $this->mRestrictions["move"] = explode( ',', trim( $temp[0] ) );
+                                       $this->mRestrictions['edit'] = explode( ',', trim( $temp[0] ) );
+                                       $this->mRestrictions['move'] = explode( ',', trim( $temp[0] ) );
                                } else {
                                        $this->mRestrictions[$temp[0]] = explode( ',', trim( $temp[1] ) );
                                }
                        }
 
                        $this->mOldRestrictions = true;
-                       $this->mCascadeRestriction = false;
-                       $this->mRestrictionsExpiry = Block::decodeExpiry('');
 
                }
 
@@ -1686,6 +1700,10 @@ class Title {
 
                        while ($row = $dbr->fetchObject( $res ) ) {
                                # Cycle through all the restrictions.
+                               
+                               // Don't take care of restrictions types that aren't in $wgRestrictionTypes
+                               if( !in_array( $row->pr_type, $wgRestrictionTypes ) )
+                                       continue;
 
                                // This code should be refactored, now that it's being used more generally,
                                // But I don't really see any harm in leaving it in Block for now -werdna
@@ -2032,7 +2050,9 @@ class Title {
                       strpos( $dbkey, './' ) === 0  ||
                       strpos( $dbkey, '../' ) === 0 ||
                       strpos( $dbkey, '/./' ) !== false ||
-                      strpos( $dbkey, '/../' ) !== false ) )
+                      strpos( $dbkey, '/../' ) !== false  ||
+                      substr( $dbkey, -2 ) == '/.' ||
+                      substr( $dbkey, -3 ) == '/..' ) )
                {
                        return false;
                }
@@ -2120,7 +2140,7 @@ class Title {
         * @return Title the object for the talk page
         */
        public function getTalkPage() {
-               return Title::makeTitle( Namespace::getTalk( $this->getNamespace() ), $this->getDBkey() );
+               return Title::makeTitle( MWNamespace::getTalk( $this->getNamespace() ), $this->getDBkey() );
        }
 
        /**
@@ -2130,7 +2150,7 @@ class Title {
         * @return Title the object for the subject page
         */
        public function getSubjectPage() {
-               return Title::makeTitle( Namespace::getSubject( $this->getNamespace() ), $this->getDBkey() );
+               return Title::makeTitle( MWNamespace::getSubject( $this->getNamespace() ), $this->getDBkey() );
        }
 
        /**
@@ -2425,6 +2445,8 @@ class Title {
                # Update message cache for interface messages
                if( $nt->getNamespace() == NS_MEDIAWIKI ) {
                        global $wgMessageCache;
+                       $oldarticle = new Article( $this );
+                       $wgMessageCache->replace( $this->getDBkey(), $oldarticle->getContent() );
                        $newarticle = new Article( $nt );
                        $wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() );
                }
@@ -2457,13 +2479,25 @@ class Title {
                $newid = $nt->getArticleID();
                $oldid = $this->getArticleID();
                $dbw = wfGetDB( DB_MASTER );
-               $linkCache =& LinkCache::singleton();
 
                # Delete the old redirect. We don't save it to history since
                # by definition if we've got here it's rather uninteresting.
                # We have to remove it so that the next step doesn't trigger
                # a conflict on the unique namespace+title index...
                $dbw->delete( 'page', array( 'page_id' => $newid ), $fname );
+               if ( !$dbw->cascadingDeletes() ) {
+                       $dbw->delete( 'revision', array( 'rev_page' => $newid ), __METHOD__ );
+                       global $wgUseTrackbacks;
+                       if ($wgUseTrackbacks)
+                               $dbw->delete( 'trackbacks', array( 'tb_page' => $newid ), __METHOD__ );
+                       $dbw->delete( 'pagelinks', array( 'pl_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'imagelinks', array( 'il_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'categorylinks', array( 'cl_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'templatelinks', array( 'tl_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'externallinks', array( 'el_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'langlinks', array( 'll_from' => $newid ), __METHOD__ );
+                       $dbw->delete( 'redirect', array( 'rd_from' => $newid ), __METHOD__ );
+               }
 
                # Save a null revision in the page's history notifying of the move
                $nullRevision = Revision::newNullRevision( $dbw, $oldid, $comment, true );
@@ -2480,7 +2514,7 @@ class Title {
                        /* WHERE */ array( 'page_id' => $oldid ),
                        $fname
                );
-               $linkCache->clearLink( $nt->getPrefixedDBkey() );
+               $nt->resetArticleID( $oldid );
 
                # Recreate the redirect, this time in the other direction.
                if($createRedirect || !$wgUser->isAllowed('suppressredirect'))
@@ -2495,7 +2529,6 @@ class Title {
                                'text'    => $redirectText ) );
                        $redirectRevision->insertOn( $dbw );
                        $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
-                       $linkCache->clearLink( $this->getPrefixedDBkey() );
 
                        # Now, we record the link from the redirect to the new title.
                        # It should have no other outgoing links...
@@ -2506,6 +2539,8 @@ class Title {
                                        'pl_namespace' => $nt->getNamespace(),
                                        'pl_title'     => $nt->getDBkey() ),
                                $fname );
+               } else {
+                       $this->resetArticleID( 0 );
                }
                
                # Log the move
@@ -2539,13 +2574,12 @@ class Title {
                $oldid = $this->getArticleID();
                $dbw = wfGetDB( DB_MASTER );
                $now = $dbw->timestamp();
-               $linkCache =& LinkCache::singleton();
 
                # Save a null revision in the page's history notifying of the move
                $nullRevision = Revision::newNullRevision( $dbw, $oldid, $comment, true );
                $nullRevId = $nullRevision->insertOn( $dbw );
 
-               # Rename cur entry
+               # Rename page entry
                $dbw->update( 'page',
                        /* SET */ array(
                                'page_touched'   => $now,
@@ -2556,8 +2590,7 @@ class Title {
                        /* WHERE */ array( 'page_id' => $oldid ),
                        $fname
                );
-
-               $linkCache->clearLink( $nt->getPrefixedDBkey() );
+               $nt->resetArticleID( $oldid );
 
                if($createRedirect || !$wgUser->isAllowed('suppressredirect'))
                {
@@ -2572,7 +2605,7 @@ class Title {
                                'text'    => $redirectText ) );
                        $redirectRevision->insertOn( $dbw );
                        $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
-                       $linkCache->clearLink( $this->getPrefixedDBkey() );
+
                        # Record the just-created redirect's linking to the page
                        $dbw->insert( 'pagelinks',
                                array(
@@ -2580,6 +2613,8 @@ class Title {
                                        'pl_namespace' => $nt->getNamespace(),
                                        'pl_title'     => $nt->getDBkey() ),
                                $fname );
+               } else {
+                       $this->resetArticleID( 0 );
                }
 
                # Log the move
@@ -2656,7 +2691,7 @@ class Title {
         */
        public function isWatchable() {
                return !$this->isExternal()
-                       && Namespace::isWatchable( $this->getNamespace() );
+                       && MWNamespace::isWatchable( $this->getNamespace() );
        }
 
        /**
@@ -2698,6 +2733,7 @@ class Title {
         * @return array
         */
        public function getParentCategoryTree( $children = array() ) {
+               $stack = array();
                $parents = $this->getParentCategories();
 
                if($parents != '') {
@@ -2859,7 +2895,12 @@ class Title {
                $title = htmlspecialchars($this->getText());
                $tburl = $this->trackbackURL();
 
-               return "
+               // Autodiscovery RDF is placed in comments so HTML validator
+               // won't barf. This is a rather icky workaround, but seems
+               // frequently used by this kind of RDF thingy.
+               //
+               // Spec: http://www.sixapart.com/pronet/docs/trackback_spec
+               return "<!--
 <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
          xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
          xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
@@ -2868,7 +2909,8 @@ class Title {
    dc:identifier=\"$url\"
    dc:title=\"$title\"
    trackback:ping=\"$tburl\" />
-</rdf:RDF>";
+</rdf:RDF>
+-->";
        }
 
        /**
@@ -2950,7 +2992,7 @@ class Title {
         * @return bool
         */
        public function isContentPage() {
-               return Namespace::isContent( $this->getNamespace() );
+               return MWNamespace::isContent( $this->getNamespace() );
        }
        
 }