X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FTitle.php;h=601211d1b11cc40e4d3ae9d432088e8e8100f976;hb=448c7ea03aef4194bc7cff8987c2b9d4cd379d8b;hp=bf0fb8e1fd79645d6a6a7f1a368d865fe46044c8;hpb=b3efe0ca7d05ce6551b82e63de46b2dc44c1f4af;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Title.php b/includes/Title.php index bf0fb8e1fd..601211d1b1 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -96,7 +96,7 @@ class Title { /** @var array Array of groups allowed to edit this article */ public $mRestrictions = array(); - /** @var bool */ + /** @var string|bool */ protected $mOldRestrictions = false; /** @var bool Cascade restrictions on this page to included templates and images? */ @@ -225,9 +225,11 @@ class Title { public static function newFromDBkey( $key ) { $t = new Title(); $t->mDbkeyform = $key; - if ( $t->secureAndSplit() ) { + + try { + $t->secureAndSplit(); return $t; - } else { + } catch ( MalformedTitleException $ex ) { return null; } } @@ -263,7 +265,34 @@ class Title { if ( is_object( $text ) ) { throw new InvalidArgumentException( '$text must be a string.' ); } elseif ( !is_string( $text ) ) { - wfWarn( __METHOD__ . ': $text must be a string. This will throw an InvalidArgumentException in future.' ); + wfDebugLog( 'T76305', wfGetAllCallers( 5 ) ); + wfWarn( __METHOD__ . ': $text must be a string. This will throw an InvalidArgumentException in future.', 2 ); + } + + try { + return Title::newFromTextThrow( $text, $defaultNamespace ); + } catch ( MalformedTitleException $ex ) { + return null; + } + } + + /** + * Like Title::newFromText(), but throws MalformedTitleException when the title is invalid, + * rather than returning null. + * + * The exception subclasses encode detailed information about why the title is invalid. + * + * @see Title::newFromText + * + * @since 1.25 + * @param string $text Title text to check + * @param int $defaultNamespace + * @throws MalformedTitleException If the title is invalid + * @return Title + */ + public static function newFromTextThrow( $text, $defaultNamespace = NS_MAIN ) { + if ( is_object( $text ) ) { + throw new MWException( 'Title::newFromTextThrow given an object' ); } $cache = self::getTitleCache(); @@ -287,14 +316,11 @@ class Title { $t->mDbkeyform = str_replace( ' ', '_', $filteredText ); $t->mDefaultNamespace = intval( $defaultNamespace ); - if ( $t->secureAndSplit() ) { - if ( $defaultNamespace == NS_MAIN ) { - $cache->set( $text, $t ); - } - return $t; - } else { - return null; + $t->secureAndSplit(); + if ( $defaultNamespace == NS_MAIN ) { + $cache->set( $text, $t ); } + return $t; } /** @@ -323,9 +349,11 @@ class Title { } $t->mDbkeyform = str_replace( ' ', '_', $url ); - if ( $t->secureAndSplit() ) { + + try { + $t->secureAndSplit(); return $t; - } else { + } catch ( MalformedTitleException $ex ) { return null; } } @@ -451,6 +479,9 @@ class Title { if ( isset( $row->page_lang ) ) { $this->mDbPageLanguage = (string)$row->page_lang; } + if ( isset( $row->page_restrictions ) ) { + $this->mOldRestrictions = $row->page_restrictions; + } } else { // page not found $this->mArticleID = 0; $this->mLength = 0; @@ -504,9 +535,11 @@ class Title { $t = new Title(); $t->mDbkeyform = Title::makeName( $ns, $title, $fragment, $interwiki, true ); - if ( $t->secureAndSplit() ) { + + try { + $t->secureAndSplit(); return $t; - } else { + } catch ( MalformedTitleException $ex ) { return null; } } @@ -937,7 +970,6 @@ class Title { /** * Get the page's content model id, see the CONTENT_MODEL_XXX constants. * - * @throws MWException * @param int $flags A bit field; may be Title::GAID_FOR_UPDATE to select for update * @return string Content model id */ @@ -952,10 +984,6 @@ class Title { $this->mContentModel = ContentHandler::getDefaultModelFor( $this ); } - if ( !$this->mContentModel ) { - throw new MWException( 'Failed to determine content model!' ); - } - return $this->mContentModel; } @@ -2574,6 +2602,7 @@ class Title { if ( $row['permission'] == 'autoconfirmed' ) { $row['permission'] = 'editsemiprotected'; // B/C } + $row['expiry'] = $dbr->decodeExpiry( $row['expiry'] ); } $this->mTitleProtection = $row; } @@ -2711,7 +2740,6 @@ class Title { * false. */ public function getCascadeProtectionSources( $getPages = true ) { - global $wgContLang; $pagerestrictions = array(); if ( $this->mCascadeSources !== null && $getPages ) { @@ -2754,7 +2782,7 @@ class Title { $now = wfTimestampNow(); foreach ( $res as $row ) { - $expiry = $wgContLang->formatExpiry( $row->pr_expiry, TS_MW ); + $expiry = $dbr->decodeExpiry( $row->pr_expiry ); if ( $expiry > $now ) { if ( $getPages ) { $page_id = $row->pr_page; @@ -2887,28 +2915,29 @@ class Title { * restrictions from page table (pre 1.10) */ public function loadRestrictionsFromRows( $rows, $oldFashionedRestrictions = null ) { - global $wgContLang; $dbr = wfGetDB( DB_SLAVE ); $restrictionTypes = $this->getRestrictionTypes(); foreach ( $restrictionTypes as $type ) { $this->mRestrictions[$type] = array(); - $this->mRestrictionsExpiry[$type] = $wgContLang->formatExpiry( '', TS_MW ); + $this->mRestrictionsExpiry[$type] = 'infinity'; } $this->mCascadeRestriction = false; # Backwards-compatibility: also load the restrictions from the page record (old format). + if ( $oldFashionedRestrictions !== null ) { + $this->mOldRestrictions = $oldFashionedRestrictions; + } - if ( $oldFashionedRestrictions === null ) { - $oldFashionedRestrictions = $dbr->selectField( 'page', 'page_restrictions', + if ( $this->mOldRestrictions === false ) { + $this->mOldRestrictions = $dbr->selectField( 'page', 'page_restrictions', array( 'page_id' => $this->getArticleID() ), __METHOD__ ); } - if ( $oldFashionedRestrictions != '' ) { - - foreach ( explode( ':', trim( $oldFashionedRestrictions ) ) as $restrict ) { + if ( $this->mOldRestrictions != '' ) { + foreach ( explode( ':', trim( $this->mOldRestrictions ) ) as $restrict ) { $temp = explode( '=', trim( $restrict ) ); if ( count( $temp ) == 1 ) { // old old format should be treated as edit/move restriction @@ -2921,9 +2950,6 @@ class Title { } } } - - $this->mOldRestrictions = true; - } if ( count( $rows ) ) { @@ -2940,7 +2966,7 @@ class Title { // 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 - $expiry = $wgContLang->formatExpiry( $row->pr_expiry, TS_MW ); + $expiry = $dbr->decodeExpiry( $row->pr_expiry ); // Only apply the restrictions if they haven't expired! if ( !$expiry || $expiry > $now ) { @@ -2962,11 +2988,9 @@ class Title { * restrictions from page table (pre 1.10) */ public function loadRestrictions( $oldFashionedRestrictions = null ) { - global $wgContLang; if ( !$this->mRestrictionsLoaded ) { + $dbr = wfGetDB( DB_SLAVE ); if ( $this->exists() ) { - $dbr = wfGetDB( DB_SLAVE ); - $res = $dbr->select( 'page_restrictions', array( 'pr_type', 'pr_expiry', 'pr_level', 'pr_cascade' ), @@ -2980,7 +3004,7 @@ class Title { if ( $title_protection ) { $now = wfTimestampNow(); - $expiry = $wgContLang->formatExpiry( $title_protection['expiry'], TS_MW ); + $expiry = $dbr->decodeExpiry( $title_protection['expiry'] ); if ( !$expiry || $expiry > $now ) { // Apply the restrictions @@ -2990,7 +3014,7 @@ class Title { $this->mTitleProtection = false; } } else { - $this->mRestrictionsExpiry['create'] = $wgContLang->formatExpiry( '', TS_MW ); + $this->mRestrictionsExpiry['create'] = 'infinity'; } $this->mRestrictionsLoaded = true; } @@ -3274,6 +3298,7 @@ class Title { } $this->mRestrictionsLoaded = false; $this->mRestrictions = array(); + $this->mOldRestrictions = false; $this->mRedirect = null; $this->mLength = -1; $this->mLatestID = false; @@ -3310,6 +3335,7 @@ class Title { * namespace prefixes, sets the other forms, and canonicalizes * everything. * + * @throws MalformedTitleException On invalid titles * @return bool True on success */ private function secureAndSplit() { @@ -3320,15 +3346,12 @@ class Title { $dbkey = $this->mDbkeyform; - try { - // @note: splitTitleString() is a temporary hack to allow MediaWikiTitleCodec to share - // the parsing code with Title, while avoiding massive refactoring. - // @todo: get rid of secureAndSplit, refactor parsing code. - $titleParser = self::getTitleParser(); - $parts = $titleParser->splitTitleString( $dbkey, $this->getDefaultNamespace() ); - } catch ( MalformedTitleException $ex ) { - return false; - } + // @note: splitTitleString() is a temporary hack to allow MediaWikiTitleCodec to share + // the parsing code with Title, while avoiding massive refactoring. + // @todo: get rid of secureAndSplit, refactor parsing code. + $titleParser = self::getTitleParser(); + // MalformedTitleException can be thrown here + $parts = $titleParser->splitTitleString( $dbkey, $this->getDefaultNamespace() ); # Fill fields $this->setFragment( '#' . $parts['fragment'] ); @@ -3420,8 +3443,6 @@ class Title { * @return array Array of Title objects linking here */ public function getLinksFrom( $options = array(), $table = 'pagelinks', $prefix = 'pl' ) { - global $wgContentHandlerUseDB; - $id = $this->getArticleID(); # If the page doesn't exist; there can't be any link from this page @@ -3435,49 +3456,36 @@ class Title { $db = wfGetDB( DB_SLAVE ); } - $namespaceFiled = "{$prefix}_namespace"; - $titleField = "{$prefix}_title"; - - $fields = array( - $namespaceFiled, - $titleField, - 'page_id', - 'page_len', - 'page_is_redirect', - 'page_latest' - ); - - if ( $wgContentHandlerUseDB ) { - $fields[] = 'page_content_model'; - } + $blNamespace = "{$prefix}_namespace"; + $blTitle = "{$prefix}_title"; $res = $db->select( array( $table, 'page' ), - $fields, + array_merge( + array( $blNamespace, $blTitle ), + WikiPage::selectFields() + ), array( "{$prefix}_from" => $id ), __METHOD__, $options, array( 'page' => array( 'LEFT JOIN', - array( "page_namespace=$namespaceFiled", "page_title=$titleField" ) + array( "page_namespace=$blNamespace", "page_title=$blTitle" ) ) ) ); $retVal = array(); - if ( $res->numRows() ) { - $linkCache = LinkCache::singleton(); - foreach ( $res as $row ) { - $titleObj = Title::makeTitle( $row->$namespaceFiled, $row->$titleField ); - if ( $titleObj ) { - if ( $row->page_id ) { - $linkCache->addGoodLinkObjFromRow( $titleObj, $row ); - } else { - $linkCache->addBadLinkObj( $titleObj ); - } - $retVal[] = $titleObj; - } + $linkCache = LinkCache::singleton(); + foreach ( $res as $row ) { + if ( $row->page_id ) { + $titleObj = Title::newFromRow( $row ); + } else { + $titleObj = Title::makeTitle( $row->$blNamespace, $row->$blTitle ); + $linkCache->addBadLinkObj( $titleObj ); } + $retVal[] = $titleObj; } + return $retVal; } @@ -4228,10 +4236,12 @@ class Title { * If you want to know if a title can be meaningfully viewed, you should * probably call the isKnown() method instead. * + * @param int $flags An optional bit field; may be Title::GAID_FOR_UPDATE to check + * from master/for update * @return bool */ - public function exists() { - $exists = $this->getArticleID() != 0; + public function exists( $flags = 0 ) { + $exists = $this->getArticleID( $flags ) != 0; Hooks::run( 'TitleExists', array( $this, &$exists ) ); return $exists; } @@ -4424,35 +4434,29 @@ class Title { * @return string|null */ public function getNotificationTimestamp( $user = null ) { - global $wgUser, $wgShowUpdatedMarker; + global $wgUser; + // Assume current user if none given if ( !$user ) { $user = $wgUser; } // Check cache first $uid = $user->getId(); + if ( !$uid ) { + return false; + } // avoid isset here, as it'll return false for null entries if ( array_key_exists( $uid, $this->mNotificationTimestamp ) ) { return $this->mNotificationTimestamp[$uid]; } - if ( !$uid || !$wgShowUpdatedMarker || !$user->isAllowed( 'viewmywatchlist' ) ) { - $this->mNotificationTimestamp[$uid] = false; - return $this->mNotificationTimestamp[$uid]; - } // Don't cache too much! if ( count( $this->mNotificationTimestamp ) >= self::CACHE_MAX ) { $this->mNotificationTimestamp = array(); } - $dbr = wfGetDB( DB_SLAVE ); - $this->mNotificationTimestamp[$uid] = $dbr->selectField( 'watchlist', - 'wl_notificationtimestamp', - array( - 'wl_user' => $user->getId(), - 'wl_namespace' => $this->getNamespace(), - 'wl_title' => $this->getDBkey(), - ), - __METHOD__ - ); + + $watchedItem = WatchedItem::fromUserTitle( $user, $this ); + $this->mNotificationTimestamp[$uid] = $watchedItem->getNotificationTimestamp(); + return $this->mNotificationTimestamp[$uid]; }