Merge "Improve clarity of diff-multi message"
[lhc/web/wiklou.git] / includes / Title.php
index 096a04d..5423f09 100644 (file)
@@ -60,7 +60,7 @@ class Title {
        var $mUserCaseDBKey;              // /< DB key with the initial letter in the case specified by the user
        var $mNamespace = NS_MAIN;        // /< Namespace index, i.e. one of the NS_xxxx constants
        var $mInterwiki = '';             // /< Interwiki prefix
-       var $mFragment;                   // /< Title fragment (i.e. the bit after the #)
+       var $mFragment = '';              // /< Title fragment (i.e. the bit after the #)
        var $mArticleID = -1;             // /< Article ID, fetched from the link cache on demand
        var $mLatestID = false;           // /< ID of most recent revision
        var $mContentModel = false;       // /< ID of the page's content model, i.e. one of the CONTENT_MODEL_XXX constants
@@ -706,6 +706,8 @@ class Title {
        /**
         * Get the interwiki prefix
         *
+        * Use Title::isExternal to check if a interwiki is set
+        *
         * @return String Interwiki prefix
         */
        public function getInterwiki() {
@@ -1194,21 +1196,33 @@ class Title {
        /**
         * Get the Title fragment (i.e.\ the bit after the #) in text form
         *
+        * Use Title::hasFragment to check for a fragment
+        *
         * @return String Title fragment
         */
        public function getFragment() {
                return $this->mFragment;
        }
 
+       /**
+        * Check if a Title fragment is set
+        *
+        * @return bool
+        * @since 1.23
+        */
+       public function hasFragment() {
+               return $this->mFragment !== '';
+       }
+
        /**
         * Get the fragment in URL form, including the "#" character if there is one
         * @return String Fragment in URL form
         */
        public function getFragmentForURL() {
-               if ( $this->mFragment == '' ) {
+               if ( !$this->hasFragment() ) {
                        return '';
                } else {
-                       return '#' . Title::escapeFragmentForURL( $this->mFragment );
+                       return '#' . Title::escapeFragmentForURL( $this->getFragment() );
                }
        }
 
@@ -1290,8 +1304,8 @@ class Title {
         */
        public function getFullText() {
                $text = $this->getPrefixedText();
-               if ( $this->mFragment != '' ) {
-                       $text .= '#' . $this->mFragment;
+               if ( $this->hasFragment() ) {
+                       $text .= '#' . $this->getFragment();
                }
                return $text;
        }
@@ -1628,7 +1642,7 @@ class Title {
                wfProfileIn( __METHOD__ );
                if ( $this->isExternal() || $proto !== PROTO_RELATIVE ) {
                        $ret = $this->getFullURL( $query, $query2, $proto );
-               } elseif ( $this->getPrefixedText() === '' && $this->getFragment() !== '' ) {
+               } elseif ( $this->getPrefixedText() === '' && $this->hasFragment() ) {
                        $ret = $this->getFragmentForURL();
                } else {
                        $ret = $this->getLocalURL( $query, $query2 ) . $this->getFragmentForURL();
@@ -2555,6 +2569,19 @@ class Title {
                return ( $sources > 0 );
        }
 
+       /**
+        * Determines whether cascading protection sources have already been loaded from
+        * the database.
+        *
+        * @param bool $getPages True to check if the pages are loaded, or false to check
+        * if the status is loaded.
+        * @return bool Whether or not the specified information has been loaded
+        * @since 1.23
+        */
+       public function areCascadeProtectionSourcesLoaded( $getPages = true ) {
+               return $getPages ? isset( $this->mCascadeSources ) : isset( $this->mHasCascadingRestrictions );
+       }
+
        /**
         * Cascading protection: Get the source of any cascading restrictions on this page.
         *
@@ -2655,6 +2682,17 @@ class Title {
                return array( $sources, $pagerestrictions );
        }
 
+       /**
+        * Accessor for mRestrictionsLoaded
+        *
+        * @return bool Whether or not the page's restrictions have already been
+        * loaded from the database
+        * @since 1.23
+        */
+       public function areRestrictionsLoaded() {
+               return $this->mRestrictionsLoaded;
+       }
+
        /**
         * Accessor/initialisation for mRestrictions
         *
@@ -2670,6 +2708,21 @@ class Title {
                                : array();
        }
 
+       /**
+        * Accessor/initialisation for mRestrictions
+        *
+        * @return Array of Arrays of Strings the first level indexed by
+        * action, the second level containing the names of the groups
+        * allowed to perform each action
+        * @since 1.23
+        */
+       public function getAllRestrictions() {
+               if ( !$this->mRestrictionsLoaded ) {
+                       $this->loadRestrictions();
+               }
+               return $this->mRestrictions;
+       }
+
        /**
         * Get the expiry time for the restriction against a given action
         *
@@ -3161,7 +3214,8 @@ class Title {
                global $wgContLang, $wgLocalInterwiki;
 
                # Initialisation
-               $this->mInterwiki = $this->mFragment = '';
+               $this->mInterwiki = '';
+               $this->mFragment = '';
                $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN
 
                $dbkey = $this->mDbkeyform;
@@ -3256,10 +3310,6 @@ class Title {
                        break;
                } while ( true );
 
-               # We already know that some pages won't be in the database!
-               if ( $this->isExternal() || NS_SPECIAL == $this->mNamespace ) {
-                       $this->mArticleID = 0;
-               }
                $fragment = strstr( $dbkey, '#' );
                if ( false !== $fragment ) {
                        $this->setFragment( $fragment );
@@ -3329,9 +3379,9 @@ class Title {
                // there are numerous ways to present the same IP. Having sp:contribs scan
                // them all is silly and having some show the edits and others not is
                // inconsistent. Same for talk/userpages. Keep them normalized instead.
-               $dbkey = ( $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK )
-                       ? IP::sanitizeIP( $dbkey )
-                       : $dbkey;
+               if ( $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK ) {
+                       $dbkey = IP::sanitizeIP( $dbkey );
+               }
 
                // Any remaining initial :s are illegal.
                if ( $dbkey !== '' && ':' == $dbkey[0] ) {
@@ -3344,6 +3394,11 @@ class Title {
 
                $this->mTextform = str_replace( '_', ' ', $dbkey );
 
+               # We already know that some pages won't be in the database!
+               if ( $this->isExternal() || $this->mNamespace == NS_SPECIAL ) {
+                       $this->mArticleID = 0;
+               }
+
                return true;
        }
 
@@ -4376,9 +4431,11 @@ class Title {
        }
 
        /**
-        * Get the number of authors between the given revisions or revision IDs.
+        * Get the authors between the given revisions or revision IDs.
         * Used for diffs and other things that really need it.
         *
+        * @since 1.23
+        *
         * @param int|Revision $old Old revision or rev ID (first before range by default)
         * @param int|Revision $new New revision or rev ID (first after range by default)
         * @param int $limit Maximum number of authors
@@ -4387,9 +4444,9 @@ class Title {
         *     'include_new' Include $new in the range; $old is excluded.
         *     'include_both' Include both $old and $new in the range.
         *     Unknown option values are ignored.
-        * @return int Number of revision authors in the range; zero if not both revisions exist
+        * @return array|null Names of revision authors in the range; null if not both revisions exist
         */
-       public function countAuthorsBetween( $old, $new, $limit, $options = array() ) {
+       public function getAuthorsBetween( $old, $new, $limit, $options = array() ) {
                if ( !( $old instanceof Revision ) ) {
                        $old = Revision::newFromTitle( $this, (int)$old );
                }
@@ -4400,8 +4457,9 @@ class Title {
                // Add $old->getPage() != $new->getPage() || $old->getPage() != $this->getArticleID()
                // in the sanity check below?
                if ( !$old || !$new ) {
-                       return 0; // nothing to compare
+                       return null; // nothing to compare
                }
+               $authors = array();
                $old_cmp = '>';
                $new_cmp = '<';
                $options = (array)$options;
@@ -4417,12 +4475,19 @@ class Title {
                }
                // No DB query needed if $old and $new are the same or successive revisions:
                if ( $old->getId() === $new->getId() ) {
-                       return ( $old_cmp === '>' && $new_cmp === '<' ) ? 0 : 1;
+                       return ( $old_cmp === '>' && $new_cmp === '<' ) ? array() : array( $old->getRawUserText() );
                } elseif ( $old->getId() === $new->getParentId() ) {
-                       if ( $old_cmp === '>' || $new_cmp === '<' ) {
-                               return ( $old_cmp === '>' && $new_cmp === '<' ) ? 0 : 1;
+                       if ( $old_cmp === '>=' && $new_cmp === '<=' ) {
+                               $authors[] = $old->getRawUserText();
+                               if ( $old->getRawUserText() != $new->getRawUserText() ) {
+                                       $authors[] = $new->getRawUserText();
+                               }
+                       } elseif ( $old_cmp === '>=' ) {
+                               $authors[] = $old->getRawUserText();
+                       } elseif ( $new_cmp === '<=' ) {
+                               $authors[] = $new->getRawUserText();
                        }
-                       return ( $old->getRawUserText() === $new->getRawUserText() ) ? 1 : 2;
+                       return $authors;
                }
                $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'revision', 'DISTINCT rev_user_text',
@@ -4433,7 +4498,29 @@ class Title {
                        ), __METHOD__,
                        array( 'LIMIT' => $limit + 1 ) // add one so caller knows it was truncated
                );
-               return (int)$dbr->numRows( $res );
+               foreach ( $res as $row ) {
+                       $authors[] = $row->rev_user_text;
+               }
+               return $authors;
+       }
+
+       /**
+        * Get the number of authors between the given revisions or revision IDs.
+        * Used for diffs and other things that really need it.
+        *
+        * @param int|Revision $old Old revision or rev ID (first before range by default)
+        * @param int|Revision $new New revision or rev ID (first after range by default)
+        * @param int $limit Maximum number of authors
+        * @param string|array $options (Optional): Single option, or an array of options:
+        *     'include_old' Include $old in the range; $new is excluded.
+        *     'include_new' Include $new in the range; $old is excluded.
+        *     'include_both' Include both $old and $new in the range.
+        *     Unknown option values are ignored.
+        * @return int Number of revision authors in the range; zero if not both revisions exist
+        */
+       public function countAuthorsBetween( $old, $new, $limit, $options = array() ) {
+               $authors = $this->getAuthorsBetween( $old, $new, $limit, $options );
+               return $authors ? count( $authors ) : 0;
        }
 
        /**