X-Git-Url: https://git.heureux-cyclage.org/w/index.php?a=blobdiff_plain;f=includes%2FTitle.php;h=5951552a5625944e521576f5cba87cf268cb2220;hb=a26d5a49d755ff4b8039b11d1f26abb5d7bc7e8c;hp=b4c681c6b9a4096047c5dbbbae09f32bb39c3797;hpb=29c06f2b2fd0579e31358e1a798fe8b6ce5616eb;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Title.php b/includes/Title.php index b4c681c6b9..5951552a56 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -9,6 +9,8 @@ require_once( 'normal/UtfNormal.php' ); $wgTitleInterwikiCache = array(); +$wgTitleCache = array(); + define ( 'GAID_FOR_UPDATE', 1 ); # Title::newFromTitle maintains a cache to avoid @@ -103,6 +105,7 @@ class Title { * @access public */ function newFromText( $text, $defaultNamespace = NS_MAIN ) { + global $wgTitleCache; $fname = 'Title::newFromText'; wfProfileIn( $fname ); @@ -118,10 +121,9 @@ class Title { * * In theory these are value objects and won't get changed... */ - static $titleCache = array(); - if( $defaultNamespace == NS_MAIN && isset( $titleCache[$text] ) ) { + if( $defaultNamespace == NS_MAIN && isset( $wgTitleCache[$text] ) ) { wfProfileOut( $fname ); - return $titleCache[$text]; + return $wgTitleCache[$text]; } /** @@ -135,11 +137,11 @@ class Title { if( $t->secureAndSplit() ) { if( $defaultNamespace == NS_MAIN ) { - if( count( $titleCache ) >= MW_TITLECACHE_MAX ) { + if( count( $wgTitleCache ) >= MW_TITLECACHE_MAX ) { # Avoid memory leaks on mass operations... - $titleCache = array(); + $wgTitleCache = array(); } - $titleCache[$text] =& $t; + $wgTitleCache[$text] =& $t; } wfProfileOut( $fname ); return $t; @@ -159,15 +161,17 @@ class Title { * @access public */ function newFromURL( $url ) { - global $wgLang, $wgServer; + global $wgLegalTitleChars; $t = new Title(); - # For compatibility with old buggy URLs. "+" is not valid in titles, + # For compatibility with old buggy URLs. "+" is usually not valid in titles, # but some URLs used it as a space replacement and they still come # from some external search tools. - $s = str_replace( '+', ' ', $url ); + if ( strpos( $wgLegalTitleChars, '+' ) === false ) { + $url = str_replace( '+', ' ', $url ); + } - $t->mDbkeyform = str_replace( ' ', '_', $s ); + $t->mDbkeyform = str_replace( ' ', '_', $url ); if( $t->secureAndSplit() ) { return $t; } else { @@ -316,24 +320,8 @@ class Title { * @access public */ function legalChars() { - # Missing characters: - # * []|# Needed for link syntax - # * % and + are corrupted by Apache when they appear in the path - # - # % seems to work though - # - # The problem with % is that URLs are double-unescaped: once by Apache's - # path conversion code, and again by PHP. So %253F, for example, becomes "?". - # Our code does not double-escape to compensate for this, indeed double escaping - # would break if the double-escaped title was passed in the query string - # rather than the path. This is a minor security issue because articles can be - # created such that they are hard to view or edit. -- TS - # - # Theoretically 0x80-0x9F of ISO 8859-1 should be disallowed, but - # this breaks interlanguage links - - $set = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF"; - return $set; + global $wgLegalTitleChars; + return $wgLegalTitleChars; } /** @@ -346,7 +334,7 @@ class Title { * search index */ /* static */ function indexTitle( $ns, $title ) { - global $wgDBminWordLen, $wgContLang; + global $wgContLang; require_once( 'SearchEngine.php' ); $lc = SearchEngine::legalSearchChars() . '&#;'; @@ -387,12 +375,14 @@ class Title { * @static (arguably) * @access public */ - function getInterwikiLink( $key, $transludeonly = false ) { + function getInterwikiLink( $key ) { global $wgMemc, $wgDBname, $wgInterwikiExpiry, $wgTitleInterwikiCache; $fname = 'Title::getInterwikiLink'; wfProfileIn( $fname ); + $key = strtolower( $key ); + $k = $wgDBname.':interwiki:'.$key; if( array_key_exists( $k, $wgTitleInterwikiCache ) ) { wfProfileOut( $fname ); @@ -481,7 +471,6 @@ class Title { * @access public */ function touchArray( $titles, $timestamp = '' ) { - global $wgUseFileCache; if ( count( $titles ) == 0 ) { return; @@ -490,8 +479,8 @@ class Title { if ( $timestamp == '' ) { $timestamp = $dbw->timestamp(); } - $page = $dbw->tableName( 'page' ); /* + $page = $dbw->tableName( 'page' ); $sql = "UPDATE $page SET page_touched='{$timestamp}' WHERE page_id IN ("; $first = true; @@ -554,6 +543,25 @@ class Title { * @access public */ function getNamespace() { return $this->mNamespace; } + /** + * Get the namespace text + * @return string + * @access public + */ + function getNsText() { + global $wgContLang; + return $wgContLang->getNsText( $this->mNamespace ); + } + /** + * Get the namespace text of the subject (rather than talk) page + * @return string + * @access public + */ + function getSubjectNsText() { + global $wgContLang; + return $wgContLang->getNsText( Namespace::getSubject( $this->mNamespace ) ); + } + /** * Get the interwiki prefix (or null string) * @return string @@ -602,7 +610,7 @@ class Title { */ function getPrefixedText() { global $wgContLang; - if ( empty( $this->mPrefixedText ) ) { + if ( empty( $this->mPrefixedText ) ) { // FIXME: bad usage of empty() ? $s = $this->prefix( $this->mTextform ); $s = str_replace( '_', ' ', $s ); $this->mPrefixedText = $s; @@ -654,93 +662,33 @@ class Title { * @access public */ function getFullURL( $query = '' ) { - global $wgContLang, $wgServer, $wgScript, $wgMakeDumpLinks, $wgArticlePath; + global $wgContLang, $wgServer; if ( '' == $this->mInterwiki ) { - return $wgServer . $this->getLocalUrl( $query ); - } elseif ( $wgMakeDumpLinks && $wgContLang->getLanguageName( $this->mInterwiki ) ) { - $baseUrl = str_replace( '$1', "../../{$this->mInterwiki}/$1", $wgArticlePath ); - $baseUrl = str_replace( '$1', $this->getHashedDirectory() . '/$1', $baseUrl ); + $url = $wgServer . $this->getLocalUrl( $query ); } else { $baseUrl = $this->getInterwikiLink( $this->mInterwiki ); - } - $namespace = $wgContLang->getNsText( $this->mNamespace ); - if ( '' != $namespace ) { - # Can this actually happen? Interwikis shouldn't be parsed. - $namespace .= ':'; - } - $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl ); - if( $query != '' ) { - if( false === strpos( $url, '?' ) ) { - $url .= '?'; - } else { - $url .= '&'; + $namespace = $wgContLang->getNsText( $this->mNamespace ); + if ( '' != $namespace ) { + # Can this actually happen? Interwikis shouldn't be parsed. + $namespace .= ':'; } - $url .= $query; - } - if ( '' != $this->mFragment ) { - $url .= '#' . $this->mFragment; - } - return $url; - } - - /** - * Get a relative directory for putting an HTML version of this article into - */ - function getHashedDirectory() { - global $wgMakeDumpLinks, $wgInputEncoding; - $dbkey = $this->getDBkey(); - - # Split into characters - if ( $wgInputEncoding == 'UTF-8' ) { - preg_match_all( '/./us', $dbkey, $m ); - } else { - preg_match_all( '/./s', $dbkey, $m ); - } - $chars = $m[0]; - $length = count( $chars ); - $dir = ''; - - for ( $i = 0; $i < $wgMakeDumpLinks; $i++ ) { - if ( $i ) { - $dir .= '/'; + $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl ); + if( $query != '' ) { + if( false === strpos( $url, '?' ) ) { + $url .= '?'; + } else { + $url .= '&'; + } + $url .= $query; } - if ( $i >= $length ) { - $dir .= '_'; - } elseif ( ord( $chars[$i] ) > 32 ) { - $dir .= strtolower( $chars[$i] ); - } else { - $dir .= sprintf( "%02X", ord( $chars[$i] ) ); + if ( '' != $this->mFragment ) { + $url .= '#' . $this->mFragment; } } - return $dir; - } - - function getHashedFilename() { - $dbkey = $this->getPrefixedDBkey(); - $mainPage = Title::newMainPage(); - if ( $mainPage->getPrefixedDBkey() == $dbkey ) { - return 'index.html'; - } - - $dir = $this->getHashedDirectory(); - - # Replace illegal charcters for Windows paths with underscores - $friendlyName = strtr( $dbkey, '/\\*?"<>|~', '_________' ); - - # Work out lower case form. We assume we're on a system with case-insensitive - # filenames, so unless the case is of a special form, we have to disambiguate - $lowerCase = $this->prefix( ucfirst( strtolower( $this->getDBkey() ) ) ); - - # Make it mostly unique - if ( $lowerCase != $friendlyName ) { - $friendlyName .= '_' . substr(md5( $dbkey ), 0, 4); - } - # Handle colon specially by replacing it with tilde - # Thus we reduce the number of paths with hashes appended - $friendlyName = str_replace( ':', '~', $friendlyName ); - return "$dir/$friendlyName.html"; + wfRunHooks( 'GetFullURL', array( &$this, &$url, $query ) ); + return $url; } /** @@ -752,40 +700,42 @@ class Title { * @access public */ function getLocalURL( $query = '' ) { - global $wgLang, $wgArticlePath, $wgScript, $wgMakeDumpLinks, $wgServer, $action; + global $wgArticlePath, $wgScript, $wgServer, $wgRequest; if ( $this->isExternal() ) { - return $this->getFullURL(); - } - - $dbkey = wfUrlencode( $this->getPrefixedDBkey() ); - if ( $wgMakeDumpLinks ) { - $url = str_replace( '$1', wfUrlencode( $this->getHashedFilename() ), $wgArticlePath ); - } elseif ( $query == '' ) { - $url = str_replace( '$1', $dbkey, $wgArticlePath ); + $url = $this->getFullURL(); } else { - global $wgActionPaths; - if( !empty( $wgActionPaths ) && - preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches ) ) { - $action = urldecode( $matches[2] ); - if( isset( $wgActionPaths[$action] ) ) { - $query = $matches[1]; - if( isset( $matches[4] ) ) $query .= $matches[4]; - $url = str_replace( '$1', $dbkey, $wgActionPaths[$action] ); - if( $query != '' ) $url .= '?' . $query; - return $url; + $dbkey = wfUrlencode( $this->getPrefixedDBkey() ); + if ( $query == '' ) { + $url = str_replace( '$1', $dbkey, $wgArticlePath ); + } else { + global $wgActionPaths; + $url = false; + if( !empty( $wgActionPaths ) && + preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches ) ) + { + $action = urldecode( $matches[2] ); + if( isset( $wgActionPaths[$action] ) ) { + $query = $matches[1]; + if( isset( $matches[4] ) ) $query .= $matches[4]; + $url = str_replace( '$1', $dbkey, $wgActionPaths[$action] ); + if( $query != '' ) $url .= '?' . $query; + } + } + if ( $url === false ) { + if ( $query == '-' ) { + $query = ''; + } + $url = "{$wgScript}?title={$dbkey}&{$query}"; } } - if ( $query == '-' ) { - $query = ''; + + if ($wgRequest->getText('action') == 'render') { + $url = $wgServer . $url; } - $url = "{$wgScript}?title={$dbkey}&{$query}"; } - - if ($action == 'render') - return $wgServer . $url; - else - return $url; + wfRunHooks( 'GetLocalURL', array( &$this, &$url, $query ) ); + return $url; } /** @@ -822,7 +772,9 @@ class Title { */ function getInternalURL( $query = '' ) { global $wgInternalServer; - return $wgInternalServer . $this->getLocalURL( $query ); + $url = $wgInternalServer . $this->getLocalURL( $query ); + wfRunHooks( 'GetInternalURL', array( &$this, &$url, $query ) ); + return $url; } /** @@ -896,13 +848,13 @@ class Title { } /** - * Is $wgUser perform $action this page? + * Can $wgUser perform $action this page? * @param string $action action that permission needs to be checked for * @return boolean * @access private */ function userCan($action) { - $fname = 'Title::userCanEdit'; + $fname = 'Title::userCan'; wfProfileIn( $fname ); global $wgUser; @@ -910,11 +862,14 @@ class Title { wfProfileOut( $fname ); return false; } + // XXX: This is the code that prevents unprotecting a page in NS_MEDIAWIKI + // from taking effect -ævar if( NS_MEDIAWIKI == $this->mNamespace && !$wgUser->isAllowed('editinterface') ) { wfProfileOut( $fname ); return false; } + if( $this->mDbkeyform == '_' ) { # FIXME: Is this necessary? Shouldn't be allowed anyway... wfProfileOut( $fname ); @@ -951,11 +906,19 @@ class Title { } } - if( $action == 'move' && !$this->isMovable() ) { + if( $action == 'move' && + !( $this->isMovable() && $wgUser->isAllowed( 'move' ) ) ) { wfProfileOut( $fname ); return false; } + if( $action == 'create' ) { + if( ( $this->isTalkPage() && !$wgUser->isAllowed( 'createtalk' ) ) || + ( !$this->isTalkPage() && !$wgUser->isAllowed( 'createpage' ) ) ) { + return false; + } + } + wfProfileOut( $fname ); return true; } @@ -1139,14 +1102,14 @@ class Title { * @access public */ function getArticleID( $flags = 0 ) { - global $wgLinkCache; + $linkCache =& LinkCache::singleton(); if ( $flags & GAID_FOR_UPDATE ) { - $oldUpdate = $wgLinkCache->forUpdate( true ); - $this->mArticleID = $wgLinkCache->addLinkObj( $this ); - $wgLinkCache->forUpdate( $oldUpdate ); + $oldUpdate = $linkCache->forUpdate( true ); + $this->mArticleID = $linkCache->addLinkObj( $this ); + $linkCache->forUpdate( $oldUpdate ); } else { if ( -1 == $this->mArticleID ) { - $this->mArticleID = $wgLinkCache->addLinkObj( $this ); + $this->mArticleID = $linkCache->addLinkObj( $this ); } } return $this->mArticleID; @@ -1165,7 +1128,7 @@ class Title { /** * This clears some fields in this object, and clears any associated - * keys in the "bad links" section of $wgLinkCache. + * keys in the "bad links" section of the link cache. * * - This is called from Article::insertNewArticle() to allow * loading of the new page_id. It's also called from @@ -1175,8 +1138,8 @@ class Title { * @access public */ function resetArticleID( $newid ) { - global $wgLinkCache; - $wgLinkCache->clearBadLink( $this->getPrefixedDBkey() ); + $linkCache =& LinkCache::singleton(); + $linkCache->clearBadLink( $this->getPrefixedDBkey() ); if ( 0 == $newid ) { $this->mArticleID = -1; } else { $this->mArticleID = $newid; } @@ -1196,7 +1159,6 @@ class Title { return; } - $now = wfTimestampNow(); $dbw =& wfGetDB( DB_MASTER ); $success = $dbw->update( 'page', array( /* SET */ @@ -1311,7 +1273,7 @@ class Title { # Interwiki link $t = $m[2]; - $this->mInterwiki = $p; + $this->mInterwiki = strtolower( $p ); # Redundant interwiki prefix to the local wiki if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) { @@ -1441,8 +1403,8 @@ class Title { * @return array the Title objects linking here * @access public */ - function getLinksTo( $options = '' ) { - global $wgLinkCache; + function getLinksTo( $options = '', $table = 'pagelinks', $prefix = 'pl' ) { + $linkCache =& LinkCache::singleton(); $id = $this->getArticleID(); if ( $options ) { @@ -1451,12 +1413,12 @@ class Title { $db =& wfGetDB( DB_SLAVE ); } - $res = $db->select( array( 'page', 'pagelinks' ), + $res = $db->select( array( 'page', $table ), array( 'page_namespace', 'page_title', 'page_id' ), array( - 'pl_from=page_id', - 'pl_namespace' => $this->getNamespace(), - 'pl_title' => $this->getDbKey() ), + "{$prefix}_from=page_id", + "{$prefix}_namespace" => $this->getNamespace(), + "{$prefix}_title" => $this->getDbKey() ), 'Title::getLinksTo', $options ); @@ -1464,7 +1426,7 @@ class Title { if ( $db->numRows( $res ) ) { while ( $row = $db->fetchObject( $res ) ) { if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) { - $wgLinkCache->addGoodLinkObj( $row->page_id, $titleObj ); + $linkCache->addGoodLinkObj( $row->page_id, $titleObj ); $retVal[] = $titleObj; } } @@ -1473,6 +1435,18 @@ class Title { return $retVal; } + /** + * Get an array of Title objects using this Title as a template + * Also stores the IDs in the link cache. + * + * @param string $options may be FOR UPDATE + * @return array the Title objects linking here + * @access public + */ + function getTemplateLinksTo( $options = '' ) { + return $this->getLinksTo( $options, 'templatelinks', 'tl' ); + } + /** * Get an array of Title objects referring to non-existent articles linked from this page * @@ -1481,8 +1455,6 @@ class Title { * @access public */ function getBrokenLinksFrom( $options = '' ) { - global $wgLinkCache; - if ( $options ) { $db =& wfGetDB( DB_MASTER ); } else { @@ -1547,7 +1519,7 @@ class Title { * @return mixed true on success, message name on failure * @access public */ - function isValidMoveOperation( &$nt, $auth = true, $reason = '' ) { + function isValidMoveOperation( &$nt, $auth = true ) { global $wgUser; if( !$this or !$nt ) { return 'badtitletext'; @@ -1559,7 +1531,6 @@ class Title { return 'immobile_namespace'; } - $fname = 'Title::move'; $oldid = $this->getArticleID(); $newid = $nt->getArticleID(); @@ -1599,7 +1570,7 @@ class Title { * @access public */ function moveTo( &$nt, $auth = true, $reason = '' ) { - $err = $this->isValidMoveOperation( $nt, $auth, $reason ); + $err = $this->isValidMoveOperation( $nt, $auth ); if( is_string( $err ) ) { return $err; } @@ -1658,6 +1629,7 @@ class Title { $u->doUpdate(); } + global $wgUser; wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) ); return true; } @@ -1671,7 +1643,7 @@ class Title { * @access private */ function moveOverExistingRedirect( &$nt, $reason = '' ) { - global $wgUser, $wgLinkCache, $wgUseSquid, $wgMwRedir; + global $wgUser, $wgUseSquid, $wgMwRedir; $fname = 'Title::moveOverExistingRedirect'; $comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ); @@ -1684,7 +1656,7 @@ class Title { $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); $dbw =& wfGetDB( DB_MASTER ); - $links = $dbw->tableName( 'links' ); + $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. @@ -1709,7 +1681,7 @@ class Title { /* WHERE */ array( 'page_id' => $oldid ), $fname ); - $wgLinkCache->clearLink( $nt->getPrefixedDBkey() ); + $linkCache->clearLink( $nt->getPrefixedDBkey() ); # Recreate the redirect, this time in the other direction. $redirectText = $wgMwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n"; @@ -1721,7 +1693,7 @@ class Title { 'text' => $redirectText ) ); $revid = $redirectRevision->insertOn( $dbw ); $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 ); - $wgLinkCache->clearLink( $this->getPrefixedDBkey() ); + $linkCache->clearLink( $this->getPrefixedDBkey() ); # Log the move $log = new LogPage( 'move' ); @@ -1752,7 +1724,7 @@ class Title { * @access private */ function moveToNewTitle( &$nt, &$newid, $reason = '' ) { - global $wgUser, $wgLinkCache, $wgUseSquid; + global $wgUser, $wgUseSquid; global $wgMwRedir; $fname = 'MovePageForm::moveToNewTitle'; $comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ); @@ -1764,8 +1736,8 @@ class Title { $oldid = $this->getArticleID(); $dbw =& wfGetDB( DB_MASTER ); $now = $dbw->timestamp(); - wfSeedRandom(); $rand = wfRandom(); + $linkCache =& LinkCache::singleton(); # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision( $dbw, $oldid, @@ -1785,7 +1757,7 @@ class Title { $fname ); - $wgLinkCache->clearLink( $nt->getPrefixedDBkey() ); + $linkCache->clearLink( $nt->getPrefixedDBkey() ); # Insert redirect $redirectText = $wgMwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n"; @@ -1797,7 +1769,7 @@ class Title { 'text' => $redirectText ) ); $revid = $redirectRevision->insertOn( $dbw ); $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 ); - $wgLinkCache->clearLink( $this->getPrefixedDBkey() ); + $linkCache->clearLink( $this->getPrefixedDBkey() ); # Log the move $log = new LogPage( 'move' ); @@ -1846,7 +1818,7 @@ class Title { # Is it a redirect? $id = $nt->getArticleID(); $obj = $dbw->selectRow( array( 'page', 'revision', 'text'), - array( 'page_is_redirect','old_text' ), + array( 'page_is_redirect','old_text','old_flags' ), array( 'page_id' => $id, 'page_latest=rev_id', 'rev_text_id=old_id' ), $fname, 'FOR UPDATE' ); @@ -1854,14 +1826,18 @@ class Title { # Not a redirect return false; } + $text = Revision::getRevisionText( $obj ); # Does the redirect point to the source? - if ( preg_match( "/\\[\\[\\s*([^\\]\\|]*)]]/", $obj->old_text, $m ) ) { + if ( preg_match( "/\\[\\[\\s*([^\\]\\|]*)]]/", $text, $m ) ) { $redirTitle = Title::newFromText( $m[1] ); if( !is_object( $redirTitle ) || $redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() ) { return false; } + } else { + # Fail safe + return false; } # Does the article have a history? @@ -1930,8 +1906,6 @@ class Title { global $wgContLang,$wgUser; $titlekey = $this->getArticleId(); - $sk =& $wgUser->getSkin(); - $parents = array(); $dbr =& wfGetDB( DB_SLAVE ); $categorylinks = $dbr->tableName( 'categorylinks' ); @@ -1964,8 +1938,7 @@ class Title { $parents = $this->getParentCategories(); if($parents != '') { - foreach($parents as $parent => $current) - { + foreach($parents as $parent => $current) { if ( array_key_exists( $parent, $children ) ) { # Circular reference $stack[$parent] = array(); @@ -2037,7 +2010,7 @@ class Title { * @param Title $title * @return bool */ - function equals( &$title ) { + function equals( $title ) { return $this->getInterwiki() == $title->getInterwiki() && $this->getNamespace() == $title->getNamespace() && $this->getDbkey() == $title->getDbkey(); @@ -2054,14 +2027,12 @@ class Title { /** * Should a link should be displayed as a known link, just based on its title? * - * Currently, a self-link with a fragment, special pages and image pages are in - * this category. Special pages never exist in the database. Some images do not - * have description pages in the database, but the description page contains - * useful history information that the user may want to link to. + * Currently, a self-link with a fragment and special pages are in + * this category. Special pages never exist in the database. */ function isAlwaysKnown() { return $this->isExternal() || ( 0 == $this->mNamespace && "" == $this->mDbkeyform ) - || NS_SPECIAL == $this->mNamespace || NS_IMAGE == $this->mNamespace; + || NS_SPECIAL == $this->mNamespace; } /** @@ -2080,15 +2051,25 @@ class Title { 'pl_namespace' => $this->getNamespace(), 'pl_title' => $this->getDbKey() ), $fname ); - if ( 0 == $dbw->numRows( $res ) ) { - return; - } - $arr = array(); $toucharr = array(); while( $row = $dbw->fetchObject( $res ) ) { $toucharr[] = $row->pl_from; } + $dbw->freeResult( $res ); + + if( $this->getNamespace() == NS_CATEGORY ) { + // Categories show up in a separate set of links as well + $res = $dbw->select( 'categorylinks', + array( 'cl_from' ), + array( 'cl_to' => $this->getDbKey() ), + $fname ); + while( $row = $dbw->fetchObject( $res ) ) { + $toucharr[] = $row->cl_from; + } + $dbw->freeResult( $res ); + } + if (!count($toucharr)) return; $dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),