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;
}
}
if ( is_object( $text ) ) {
throw new InvalidArgumentException( '$text must be a string.' );
} elseif ( !is_string( $text ) ) {
+ 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();
/**
$filteredText = Sanitizer::decodeCharReferencesAndNormalize( $text );
$t = new Title();
- $t->mDbkeyform = str_replace( ' ', '_', $filteredText );
+ $t->mDbkeyform = strtr( $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;
}
/**
# but some URLs used it as a space replacement and they still come
# from some external search tools.
if ( strpos( self::legalChars(), '+' ) === false ) {
- $url = str_replace( '+', ' ', $url );
+ $url = strtr( $url, '+', ' ' );
}
- $t->mDbkeyform = str_replace( ' ', '_', $url );
- if ( $t->secureAndSplit() ) {
+ $t->mDbkeyform = strtr( $url, ' ', '_' );
+
+ try {
+ $t->secureAndSplit();
return $t;
- } else {
+ } catch ( MalformedTitleException $ex ) {
return null;
}
}
$t->mInterwiki = $interwiki;
$t->mFragment = $fragment;
$t->mNamespace = $ns = intval( $ns );
- $t->mDbkeyform = str_replace( ' ', '_', $title );
+ $t->mDbkeyform = strtr( $title, ' ', '_' );
$t->mArticleID = ( $ns >= 0 ) ? -1 : 0;
$t->mUrlform = wfUrlencode( $t->mDbkeyform );
- $t->mTextform = str_replace( '_', ' ', $title );
+ $t->mTextform = strtr( $title, '_', ' ' );
$t->mContentModel = false; # initialized lazily in getContentModel()
return $t;
}
$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;
}
}
/**
* 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
*/
$this->mContentModel = ContentHandler::getDefaultModelFor( $this );
}
- if ( !$this->mContentModel ) {
- throw new MWException( 'Failed to determine content model!' );
- }
-
return $this->mContentModel;
}
* @param string $fragment Text
*/
public function setFragment( $fragment ) {
- $this->mFragment = str_replace( '_', ' ', substr( $fragment, 1 ) );
+ $this->mFragment = strtr( substr( $fragment, 1 ), '_', ' ' );
}
/**
*/
public function getPrefixedDBkey() {
$s = $this->prefix( $this->mDbkeyform );
- $s = str_replace( ' ', '_', $s );
+ $s = strtr( $s, ' ', '_' );
return $s;
}
public function getPrefixedText() {
if ( $this->mPrefixedText === null ) {
$s = $this->prefix( $this->mTextform );
- $s = str_replace( '_', ' ', $s );
+ $s = strtr( $s, '_', ' ' );
$this->mPrefixedText = $s;
}
return $this->mPrefixedText;
*/
public function getSubpageUrlForm() {
$text = $this->getSubpageText();
- $text = wfUrlencode( str_replace( ' ', '_', $text ) );
+ $text = wfUrlencode( strtr( $text, ' ', '_' ) );
return $text;
}
*/
public function getPrefixedURL() {
$s = $this->prefix( $this->mDbkeyform );
- $s = wfUrlencode( str_replace( ' ', '_', $s ) );
+ $s = wfUrlencode( strtr( $s, ' ', '_' ) );
return $s;
}
$this->mIsBigDeletion = null;
}
+ public static function clearCaches() {
+ $linkCache = LinkCache::singleton();
+ $linkCache->clear();
+
+ $titleCache = self::getTitleCache();
+ $titleCache->clear();
+ }
+
/**
* Capitalize a text string for a title if it belongs to a namespace that capitalizes
*
* namespace prefixes, sets the other forms, and canonicalizes
* everything.
*
+ * @throws MalformedTitleException On invalid titles
* @return bool True on success
*/
private function secureAndSplit() {
$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'] );
$this->mDbkeyform = $parts['dbkey'];
$this->mUrlform = wfUrlencode( $this->mDbkeyform );
- $this->mTextform = str_replace( '_', ' ', $this->mDbkeyform );
+ $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
# We already know that some pages won't be in the database!
if ( $this->isExternal() || $this->mNamespace == NS_SPECIAL ) {
);
}
- return $errors ? : true;
+ return $errors ?: true;
}
/**
* 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;
}
/**
* Updates page_touched for this page; called from LinksUpdate.php
*
+ * @param integer $purgeTime TS_MW timestamp [optional]
* @return bool True if the update succeeded
*/
- public function invalidateCache() {
+ public function invalidateCache( $purgeTime = null ) {
if ( wfReadOnly() ) {
return false;
}
$method = __METHOD__;
$dbw = wfGetDB( DB_MASTER );
$conds = $this->pageCond();
- $dbw->onTransactionIdle( function () use ( $dbw, $conds, $method ) {
+ $dbw->onTransactionIdle( function () use ( $dbw, $conds, $method, $purgeTime ) {
+ $dbTimestamp = $dbw->timestamp( $purgeTime ?: time() );
+
$dbw->update(
'page',
- array( 'page_touched' => $dbw->timestamp() ),
- $conds,
+ array( 'page_touched' => $dbTimestamp ),
+ $conds + array( 'page_touched < ' . $dbw->addQuotes( $dbTimestamp ) ),
$method
);
} );
public function isValidRedirectTarget() {
global $wgInvalidRedirectTargets;
- // invalid redirect targets are stored in a global array, but explicitly disallow Userlogout here
- if ( $this->isSpecial( 'Userlogout' ) ) {
- return false;
- }
-
- foreach ( $wgInvalidRedirectTargets as $target ) {
- if ( $this->isSpecial( $target ) ) {
+ if ( $this->isSpecialPage() ) {
+ // invalid redirect targets are stored in a global array, but explicitly disallow Userlogout here
+ if ( $this->isSpecial( 'Userlogout' ) ) {
return false;
}
+
+ foreach ( $wgInvalidRedirectTargets as $target ) {
+ if ( $this->isSpecial( $target ) ) {
+ return false;
+ }
+ }
}
return true;
}
} else {
// Even if there are no subpages in namespace, we still don't want "/" in MediaWiki message keys
- $editnoticeText = $editnotice_ns . '-' . str_replace( '/', '-', $this->getDBkey() );
+ $editnoticeText = $editnotice_ns . '-' . strtr( $this->getDBkey(), '/', '-' );
$msg = wfMessage( $editnoticeText );
if ( $msg->exists() ) {
$html = $msg->parseAsBlock();
Hooks::run( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
return $notices;
}
+
+ /**
+ * @return array
+ */
+ public function __sleep() {
+ return array(
+ 'mNamespace',
+ 'mDbkeyform',
+ 'mFragment',
+ 'mInterwiki',
+ 'mLocalInterwiki',
+ 'mUserCaseDBKey',
+ 'mDefaultNamespace',
+ );
+ }
+
+ public function __wakeup() {
+ $this->mArticleID = ( $this->mNamespace >= 0 ) ? -1 : 0;
+ $this->mUrlform = wfUrlencode( $this->mDbkeyform );
+ $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
+ }
+
}