X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FTitle.php;h=0728065c3051f0cbfaa83ba0bef0475c225c3582;hb=61d9828a88940e223461eb4d628b32295201ffbb;hp=28db064f329d122c851b8a9aeac046403d1970f8;hpb=05468d1009cc1e3270b7eb242593f188f759403b;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Title.php b/includes/Title.php index 28db064f32..0728065c30 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -22,6 +22,7 @@ * @file */ +use Wikimedia\Rdbms\Database; use Wikimedia\Rdbms\IDatabase; use MediaWiki\Linker\LinkTarget; use MediaWiki\Interwiki\InterwikiLookup; @@ -1019,12 +1020,25 @@ class Title implements LinkTarget { } /** - * Could this title have a corresponding talk page? + * Can this title have a corresponding talk page? * - * @return bool + * @deprecated since 1.30, use canHaveTalkPage() instead. + * + * @return bool True if this title either is a talk page or can have a talk page associated. */ public function canTalk() { - return MWNamespace::canTalk( $this->mNamespace ); + return $this->canHaveTalkPage(); + } + + /** + * Can this title have a corresponding talk page? + * + * @see MWNamespace::hasTalkNamespace + * + * @return bool True if this title either is a talk page or can have a talk page associated. + */ + public function canHaveTalkPage() { + return MWNamespace::hasTalkNamespace( $this->mNamespace ); } /** @@ -1418,13 +1432,22 @@ class Title implements LinkTarget { * @return string The prefixed text */ private function prefix( $name ) { + global $wgContLang; + $p = ''; if ( $this->isExternal() ) { $p = $this->mInterwiki . ':'; } if ( 0 != $this->mNamespace ) { - $p .= $this->getNsText() . ':'; + $nsText = $this->getNsText(); + + if ( $nsText === false ) { + // See T165149. Awkward, but better than erroneously linking to the main namespace. + $nsText = $wgContLang->getNsText( NS_SPECIAL ) . ":Badtitle/NS{$this->mNamespace}"; + } + + $p .= $nsText . ':'; } return $p . $name; } @@ -2122,7 +2145,7 @@ class Title implements LinkTarget { private function checkSpecialsAndNSPermissions( $action, $user, $errors, $rigor, $short ) { # Only 'createaccount' can be performed on special pages, # which don't actually exist in the DB. - if ( NS_SPECIAL == $this->mNamespace && $action !== 'createaccount' ) { + if ( $this->isSpecialPage() && $action !== 'createaccount' ) { $errors[] = [ 'ns-specialprotected' ]; } @@ -3149,7 +3172,7 @@ class Title implements LinkTarget { if ( $limit > -1 ) { $options['LIMIT'] = $limit; } - $this->mSubpages = TitleArray::newFromResult( + return TitleArray::newFromResult( $dbr->select( 'page', [ 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ], $conds, @@ -3157,7 +3180,6 @@ class Title implements LinkTarget { $options ) ); - return $this->mSubpages; } /** @@ -3425,7 +3447,7 @@ class Title implements LinkTarget { $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' ); # We already know that some pages won't be in the database! - if ( $this->isExternal() || $this->mNamespace == NS_SPECIAL ) { + if ( $this->isExternal() || $this->isSpecialPage() ) { $this->mArticleID = 0; } @@ -3712,8 +3734,8 @@ class Title implements LinkTarget { * @return array|bool True on success, getUserPermissionsErrors()-like array on failure */ public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true, - array $changeTags = [] ) { - + array $changeTags = [] + ) { global $wgUser; $err = $this->isValidMoveOperation( $nt, $auth, $reason ); if ( is_array( $err ) ) { @@ -3750,8 +3772,8 @@ class Title implements LinkTarget { * no pages were moved */ public function moveSubpages( $nt, $auth = true, $reason = '', $createRedirect = true, - array $changeTags = [] ) { - + array $changeTags = [] + ) { global $wgMaximumMovedPages; // Check permissions if ( !$this->userCan( 'move-subpages' ) ) { @@ -3993,29 +4015,52 @@ class Title implements LinkTarget { } /** - * Get the revision ID of the previous revision - * + * Get next/previous revision ID relative to another revision ID * @param int $revId Revision ID. Get the revision that was before this one. * @param int $flags Title::GAID_FOR_UPDATE - * @return int|bool Old revision ID, or false if none exists - */ - public function getPreviousRevisionID( $revId, $flags = 0 ) { - /* This function and getNextRevisionID have bad performance when - used on a page with many revisions on mysql. An explicit extended - primary key may help in some cases, if the PRIMARY KEY is banned: - T159319 */ + * @param string $dir 'next' or 'prev' + * @return int|bool New revision ID, or false if none exists + */ + private function getRelativeRevisionID( $revId, $flags, $dir ) { + $revId = (int)$revId; + if ( $dir === 'next' ) { + $op = '>'; + $sort = 'ASC'; + } elseif ( $dir === 'prev' ) { + $op = '<'; + $sort = 'DESC'; + } else { + throw new InvalidArgumentException( '$dir must be "next" or "prev"' ); + } + if ( $flags & self::GAID_FOR_UPDATE ) { $db = wfGetDB( DB_MASTER ); } else { $db = wfGetDB( DB_REPLICA, 'contributions' ); } + + // Intentionally not caring if the specified revision belongs to this + // page. We only care about the timestamp. + $ts = $db->selectField( 'revision', 'rev_timestamp', [ 'rev_id' => $revId ], __METHOD__ ); + if ( $ts === false ) { + $ts = $db->selectField( 'archive', 'ar_timestamp', [ 'ar_rev_id' => $revId ], __METHOD__ ); + if ( $ts === false ) { + // Or should this throw an InvalidArgumentException or something? + return false; + } + } + $ts = $db->addQuotes( $ts ); + $revId = $db->selectField( 'revision', 'rev_id', [ 'rev_page' => $this->getArticleID( $flags ), - 'rev_id < ' . intval( $revId ) + "rev_timestamp $op $ts OR (rev_timestamp = $ts AND rev_id $op $revId)" ], __METHOD__, - [ 'ORDER BY' => 'rev_id DESC', 'IGNORE INDEX' => 'PRIMARY' ] + [ + 'ORDER BY' => "rev_timestamp $sort, rev_id $sort", + 'IGNORE INDEX' => 'rev_timestamp', // Probably needed for T159319 + ] ); if ( $revId === false ) { @@ -4025,6 +4070,17 @@ class Title implements LinkTarget { } } + /** + * Get the revision ID of the previous revision + * + * @param int $revId Revision ID. Get the revision that was before this one. + * @param int $flags Title::GAID_FOR_UPDATE + * @return int|bool Old revision ID, or false if none exists + */ + public function getPreviousRevisionID( $revId, $flags = 0 ) { + return $this->getRelativeRevisionID( $revId, $flags, 'prev' ); + } + /** * Get the revision ID of the next revision * @@ -4033,25 +4089,7 @@ class Title implements LinkTarget { * @return int|bool Next revision ID, or false if none exists */ public function getNextRevisionID( $revId, $flags = 0 ) { - if ( $flags & self::GAID_FOR_UPDATE ) { - $db = wfGetDB( DB_MASTER ); - } else { - $db = wfGetDB( DB_REPLICA, 'contributions' ); - } - $revId = $db->selectField( 'revision', 'rev_id', - [ - 'rev_page' => $this->getArticleID( $flags ), - 'rev_id > ' . intval( $revId ) - ], - __METHOD__, - [ 'ORDER BY' => 'rev_id', 'IGNORE INDEX' => 'PRIMARY' ] - ); - - if ( $revId === false ) { - return false; - } else { - return intval( $revId ); - } + return $this->getRelativeRevisionID( $revId, $flags, 'next' ); } /** @@ -4068,8 +4106,8 @@ class Title implements LinkTarget { [ 'rev_page' => $pageId ], __METHOD__, [ - 'ORDER BY' => 'rev_timestamp ASC', - 'IGNORE INDEX' => 'rev_timestamp' + 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC', + 'IGNORE INDEX' => 'rev_timestamp', // See T159319 ] ); if ( $row ) { @@ -4650,7 +4688,7 @@ class Title implements LinkTarget { } /** - * Whether the magic words __INDEX__ and __NOINDEX__ function for this page. + * Whether the magic words __INDEX__ and __NOINDEX__ function for this page. * * @return bool */