title.php
来自「php 开发的内容管理系统」· PHP 代码 · 共 2,308 行 · 第 1/5 页
PHP
2,308 行
<?php/** * See title.txt * * @package MediaWiki *//** */require_once( 'normal/UtfNormal.php' );define ( 'GAID_FOR_UPDATE', 1 );# Title::newFromTitle maintains a cache to avoid# expensive re-normalization of commonly used titles.# On a batch operation this can become a memory leak# if not bounded. After hitting this many titles,# reset the cache.define( 'MW_TITLECACHE_MAX', 1000 );/** * Title class * - Represents a title, which may contain an interwiki designation or namespace * - Can fetch various kinds of data from the database, albeit inefficiently. * * @package MediaWiki */class Title { /** * Static cache variables */ static private $titleCache=array(); static private $interwikiCache=array(); /** * All member variables should be considered private * Please use the accessor functions */ /**#@+ * @private */ var $mTextform; # Text form (spaces not underscores) of the main part var $mUrlform; # URL-encoded form of the main part var $mDbkeyform; # Main part with underscores var $mNamespace; # Namespace index, i.e. one of the NS_xxxx constants var $mInterwiki; # Interwiki prefix (or null string) var $mFragment; # Title fragment (i.e. the bit after the #) var $mArticleID; # Article ID, fetched from the link cache on demand var $mLatestID; # ID of most recent revision var $mRestrictions; # Array of groups allowed to edit this article # Only null or "sysop" are supported var $mRestrictionsLoaded; # Boolean for initialisation on demand var $mPrefixedText; # Text form including namespace/interwiki, initialised on demand var $mDefaultNamespace; # Namespace index when there is no namespace # Zero except in {{transclusion}} tags var $mWatched; # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching() /**#@-*/ /** * Constructor * @private */ /* private */ function Title() { $this->mInterwiki = $this->mUrlform = $this->mTextform = $this->mDbkeyform = ''; $this->mArticleID = -1; $this->mNamespace = NS_MAIN; $this->mRestrictionsLoaded = false; $this->mRestrictions = array(); # Dont change the following, NS_MAIN is hardcoded in several place # See bug #696 $this->mDefaultNamespace = NS_MAIN; $this->mWatched = NULL; $this->mLatestID = false; } /** * Create a new Title from a prefixed DB key * @param string $key The database key, which has underscores * instead of spaces, possibly including namespace and * interwiki prefixes * @return Title the new object, or NULL on an error * @static * @access public */ /* static */ function newFromDBkey( $key ) { $t = new Title(); $t->mDbkeyform = $key; if( $t->secureAndSplit() ) return $t; else return NULL; } /** * Create a new Title from text, such as what one would * find in a link. Decodes any HTML entities in the text. * * @param string $text the link text; spaces, prefixes, * and an initial ':' indicating the main namespace * are accepted * @param int $defaultNamespace the namespace to use if * none is specified by a prefix * @return Title the new object, or NULL on an error * @static * @access public */ function newFromText( $text, $defaultNamespace = NS_MAIN ) { $fname = 'Title::newFromText'; if( is_object( $text ) ) { throw new MWException( 'Title::newFromText given an object' ); } /** * Wiki pages often contain multiple links to the same page. * Title normalization and parsing can become expensive on * pages with many links, so we can save a little time by * caching them. * * In theory these are value objects and won't get changed... */ if( $defaultNamespace == NS_MAIN && isset( Title::$titleCache[$text] ) ) { return Title::$titleCache[$text]; } /** * Convert things like é ā or 〗 into real text... */ $filteredText = Sanitizer::decodeCharReferences( $text ); $t =& new Title(); $t->mDbkeyform = str_replace( ' ', '_', $filteredText ); $t->mDefaultNamespace = $defaultNamespace; static $cachedcount = 0 ; if( $t->secureAndSplit() ) { if( $defaultNamespace == NS_MAIN ) { if( $cachedcount >= MW_TITLECACHE_MAX ) { # Avoid memory leaks on mass operations... Title::$titleCache = array(); $cachedcount=0; } $cachedcount++; Title::$titleCache[$text] =& $t; } return $t; } else { $ret = NULL; return $ret; } } /** * Create a new Title from URL-encoded text. Ensures that * the given title's length does not exceed the maximum. * @param string $url the title, as might be taken from a URL * @return Title the new object, or NULL on an error * @static * @access public */ function newFromURL( $url ) { global $wgLegalTitleChars; $t = new Title(); # 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. if ( strpos( $wgLegalTitleChars, '+' ) === false ) { $url = str_replace( '+', ' ', $url ); } $t->mDbkeyform = str_replace( ' ', '_', $url ); if( $t->secureAndSplit() ) { return $t; } else { return NULL; } } /** * Create a new Title from an article ID * * @todo This is inefficiently implemented, the page row is requested * but not used for anything else * * @param int $id the page_id corresponding to the Title to create * @return Title the new object, or NULL on an error * @access public * @static */ function newFromID( $id ) { $fname = 'Title::newFromID'; $dbr =& wfGetDB( DB_SLAVE ); $row = $dbr->selectRow( 'page', array( 'page_namespace', 'page_title' ), array( 'page_id' => $id ), $fname ); if ( $row !== false ) { $title = Title::makeTitle( $row->page_namespace, $row->page_title ); } else { $title = NULL; } return $title; } /** * Make an array of titles from an array of IDs */ function newFromIDs( $ids ) { $dbr =& wfGetDB( DB_SLAVE ); $res = $dbr->select( 'page', array( 'page_namespace', 'page_title' ), 'page_id IN (' . $dbr->makeList( $ids ) . ')', __METHOD__ ); $titles = array(); while ( $row = $dbr->fetchObject( $res ) ) { $titles[] = Title::makeTitle( $row->page_namespace, $row->page_title ); } return $titles; } /** * Create a new Title from a namespace index and a DB key. * It's assumed that $ns and $title are *valid*, for instance when * they came directly from the database or a special page name. * For convenience, spaces are converted to underscores so that * eg user_text fields can be used directly. * * @param int $ns the namespace of the article * @param string $title the unprefixed database key form * @return Title the new object * @static * @access public */ function &makeTitle( $ns, $title ) { $t =& new Title(); $t->mInterwiki = ''; $t->mFragment = ''; $t->mNamespace = intval( $ns ); $t->mDbkeyform = str_replace( ' ', '_', $title ); $t->mArticleID = ( $ns >= 0 ) ? -1 : 0; $t->mUrlform = wfUrlencode( $t->mDbkeyform ); $t->mTextform = str_replace( '_', ' ', $title ); return $t; } /** * Create a new Title frrom a namespace index and a DB key. * The parameters will be checked for validity, which is a bit slower * than makeTitle() but safer for user-provided data. * * @param int $ns the namespace of the article * @param string $title the database key form * @return Title the new object, or NULL on an error * @static * @access public */ function makeTitleSafe( $ns, $title ) { $t = new Title(); $t->mDbkeyform = Title::makeName( $ns, $title ); if( $t->secureAndSplit() ) { return $t; } else { return NULL; } } /** * Create a new Title for the Main Page * * @static * @return Title the new object * @access public */ function newMainPage() { return Title::newFromText( wfMsgForContent( 'mainpage' ) ); } /** * Create a new Title for a redirect * @param string $text the redirect title text * @return Title the new object, or NULL if the text is not a * valid redirect * @static * @access public */ function newFromRedirect( $text ) { $mwRedir = MagicWord::get( MAG_REDIRECT ); $rt = NULL; if ( $mwRedir->matchStart( $text ) ) { if ( preg_match( '/\[{2}(.*?)(?:\||\]{2})/', $text, $m ) ) { # categories are escaped using : for example one can enter: # #REDIRECT [[:Category:Music]]. Need to remove it. if ( substr($m[1],0,1) == ':') { # We don't want to keep the ':' $m[1] = substr( $m[1], 1 ); } $rt = Title::newFromText( $m[1] ); # Disallow redirects to Special:Userlogout if ( !is_null($rt) && $rt->getNamespace() == NS_SPECIAL && preg_match( '/^Userlogout/i', $rt->getText() ) ) { $rt = NULL; } } } return $rt; }#----------------------------------------------------------------------------# Static functions#---------------------------------------------------------------------------- /** * Get the prefixed DB key associated with an ID * @param int $id the page_id of the article * @return Title an object representing the article, or NULL * if no such article was found * @static * @access public */ function nameOf( $id ) { $fname = 'Title::nameOf'; $dbr =& wfGetDB( DB_SLAVE ); $s = $dbr->selectRow( 'page', array( 'page_namespace','page_title' ), array( 'page_id' => $id ), $fname ); if ( $s === false ) { return NULL; } $n = Title::makeName( $s->page_namespace, $s->page_title ); return $n; } /** * Get a regex character class describing the legal characters in a link * @return string the list of characters, not delimited * @static * @access public */ function legalChars() { global $wgLegalTitleChars; return $wgLegalTitleChars; } /** * Get a string representation of a title suitable for * including in a search index * * @param int $ns a namespace index * @param string $title text-form main part * @return string a stripped-down title string ready for the * search index */ /* static */ function indexTitle( $ns, $title ) { global $wgContLang; $lc = SearchEngine::legalSearchChars() . '&#;'; $t = $wgContLang->stripForSearch( $title ); $t = preg_replace( "/[^{$lc}]+/", ' ', $t ); $t = strtolower( $t ); # Handle 's, s' $t = preg_replace( "/([{$lc}]+)'s( |$)/", "\\1 \\1's ", $t ); $t = preg_replace( "/([{$lc}]+)s'( |$)/", "\\1s ", $t ); $t = preg_replace( "/\\s+/", ' ', $t ); if ( $ns == NS_IMAGE ) { $t = preg_replace( "/ (png|gif|jpg|jpeg|ogg)$/", "", $t ); } return trim( $t ); } /* * Make a prefixed DB key from a DB key and a namespace index * @param int $ns numerical representation of the namespace * @param string $title the DB key form the title * @return string the prefixed form of the title */ /* static */ function makeName( $ns, $title ) { global $wgContLang; $n = $wgContLang->getNsText( $ns ); return $n == '' ? $title : "$n:$title"; } /** * Returns the URL associated with an interwiki prefix * @param string $key the interwiki prefix (e.g. "MeatBall") * @return the associated URL, containing "$1", which should be * replaced by an article title * @static (arguably) * @access public */ function getInterwikiLink( $key ) { global $wgMemc, $wgDBname, $wgInterwikiExpiry; global $wgInterwikiCache; $fname = 'Title::getInterwikiLink'; $key = strtolower( $key ); $k = $wgDBname.':interwiki:'.$key; if( array_key_exists( $k, Title::$interwikiCache ) ) { return Title::$interwikiCache[$k]->iw_url; } if ($wgInterwikiCache) { return Title::getInterwikiCached( $key ); } $s = $wgMemc->get( $k ); # Ignore old keys with no iw_local if( $s && isset( $s->iw_local ) && isset($s->iw_trans)) { Title::$interwikiCache[$k] = $s; return $s->iw_url; } $dbr =& wfGetDB( DB_SLAVE ); $res = $dbr->select( 'interwiki', array( 'iw_url', 'iw_local', 'iw_trans' ), array( 'iw_prefix' => $key ), $fname ); if( !$res ) { return ''; } $s = $dbr->fetchObject( $res ); if( !$s ) { # Cache non-existence: create a blank object and save it to memcached $s = (object)false; $s->iw_url = ''; $s->iw_local = 0; $s->iw_trans = 0; } $wgMemc->set( $k, $s, $wgInterwikiExpiry ); Title::$interwikiCache[$k] = $s; return $s->iw_url; } /** * Fetch interwiki prefix data from local cache in constant database * * More logic is explained in DefaultSettings * * @return string URL of interwiki site * @access public */ function getInterwikiCached( $key ) { global $wgDBname, $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite; static $db, $site; if (!$db) $db=dba_open($wgInterwikiCache,'r','cdb'); /* Resolve site name */ if ($wgInterwikiScopes>=3 and !$site) { $site = dba_fetch("__sites:{$wgDBname}", $db); if ($site=="") $site = $wgInterwikiFallbackSite; } $value = dba_fetch("{$wgDBname}:{$key}", $db); if ($value=='' and $wgInterwikiScopes>=3) { /* try site-level */ $value = dba_fetch("_{$site}:{$key}", $db);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?