title.php
来自「php 开发的内容管理系统」· PHP 代码 · 共 2,308 行 · 第 1/5 页
PHP
2,308 行
/* private */ function prefix( $name ) { global $wgContLang; $p = ''; if ( '' != $this->mInterwiki ) { $p = $this->mInterwiki . ':'; } if ( 0 != $this->mNamespace ) { $p .= $wgContLang->getNsText( $this->mNamespace ) . ':'; } return $p . $name; } /** * Secure and split - main initialisation function for this object * * Assumes that mDbkeyform has been set, and is urldecoded * and uses underscores, but not otherwise munged. This function * removes illegal characters, splits off the interwiki and * namespace prefixes, sets the other forms, and canonicalizes * everything. * @return bool true on success * @private */ /* private */ function secureAndSplit() { global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks; $fname = 'Title::secureAndSplit'; # Initialisation static $rxTc = false; if( !$rxTc ) { # % is needed as well $rxTc = '/[^' . Title::legalChars() . ']|%[0-9A-Fa-f]{2}/S'; } $this->mInterwiki = $this->mFragment = ''; $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN # Clean up whitespace # $t = preg_replace( '/[ _]+/', '_', $this->mDbkeyform ); $t = trim( $t, '_' ); if ( '' == $t ) { return false; } if( false !== strpos( $t, UTF8_REPLACEMENT ) ) { # Contained illegal UTF-8 sequences or forbidden Unicode chars. return false; } $this->mDbkeyform = $t; # Initial colon indicates main namespace rather than specified default # but should not create invalid {ns,title} pairs such as {0,Project:Foo} if ( ':' == $t{0} ) { $this->mNamespace = NS_MAIN; $t = substr( $t, 1 ); # remove the colon but continue processing } # Namespace or interwiki prefix $firstPass = true; do { if ( preg_match( "/^(.+?)_*:_*(.*)$/S", $t, $m ) ) { $p = $m[1]; $lowerNs = strtolower( $p ); if ( $ns = Namespace::getCanonicalIndex( $lowerNs ) ) { # Canonical namespace $t = $m[2]; $this->mNamespace = $ns; } elseif ( $ns = $wgContLang->getNsIndex( $lowerNs )) { # Ordinary namespace $t = $m[2]; $this->mNamespace = $ns; } elseif( $this->getInterwikiLink( $p ) ) { if( !$firstPass ) { # Can't make a local interwiki link to an interwiki link. # That's just crazy! return false; } # Interwiki link $t = $m[2]; $this->mInterwiki = strtolower( $p ); # Redundant interwiki prefix to the local wiki if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) { if( $t == '' ) { # Can't have an empty self-link return false; } $this->mInterwiki = ''; $firstPass = false; # Do another namespace split... continue; } # If there's an initial colon after the interwiki, that also # resets the default namespace if ( $t !== '' && $t[0] == ':' ) { $this->mNamespace = NS_MAIN; $t = substr( $t, 1 ); } } # If there's no recognized interwiki or namespace, # then let the colon expression be part of the title. } break; } while( true ); $r = $t; # We already know that some pages won't be in the database! # if ( '' != $this->mInterwiki || -1 == $this->mNamespace ) { $this->mArticleID = 0; } $f = strstr( $r, '#' ); if ( false !== $f ) { $this->mFragment = substr( $f, 1 ); $r = substr( $r, 0, strlen( $r ) - strlen( $f ) ); # remove whitespace again: prevents "Foo_bar_#" # becoming "Foo_bar_" $r = preg_replace( '/_*$/', '', $r ); } # Reject illegal characters. # if( preg_match( $rxTc, $r ) ) { return false; } /** * Pages with "/./" or "/../" appearing in the URLs will * often be unreachable due to the way web browsers deal * with 'relative' URLs. Forbid them explicitly. */ if ( strpos( $r, '.' ) !== false && ( $r === '.' || $r === '..' || strpos( $r, './' ) === 0 || strpos( $r, '../' ) === 0 || strpos( $r, '/./' ) !== false || strpos( $r, '/../' ) !== false ) ) { return false; } # We shouldn't need to query the DB for the size. #$maxSize = $dbr->textFieldSize( 'page', 'page_title' ); if ( strlen( $r ) > 255 ) { return false; } /** * Normally, all wiki links are forced to have * an initial capital letter so [[foo]] and [[Foo]] * point to the same place. * * Don't force it for interwikis, since the other * site might be case-sensitive. */ if( $wgCapitalLinks && $this->mInterwiki == '') { $t = $wgContLang->ucfirst( $r ); } else { $t = $r; } /** * Can't make a link to a namespace alone... * "empty" local links can only be self-links * with a fragment identifier. */ if( $t == '' && $this->mInterwiki == '' && $this->mNamespace != NS_MAIN ) { return false; } // Any remaining initial :s are illegal. if ( $t !== '' && ':' == $t{0} ) { return false; } # Fill fields $this->mDbkeyform = $t; $this->mUrlform = wfUrlencode( $t ); $this->mTextform = str_replace( '_', ' ', $t ); return true; } /** * Get a Title object associated with the talk page of this article * @return Title the object for the talk page * @access public */ function getTalkPage() { return Title::makeTitle( Namespace::getTalk( $this->getNamespace() ), $this->getDBkey() ); } /** * Get a title object associated with the subject page of this * talk page * * @return Title the object for the subject page * @access public */ function getSubjectPage() { return Title::makeTitle( Namespace::getSubject( $this->getNamespace() ), $this->getDBkey() ); } /** * Get an array of Title objects linking to this Title * Also stores the IDs in the link cache. * * WARNING: do not use this function on arbitrary user-supplied titles! * On heavily-used templates it will max out the memory. * * @param string $options may be FOR UPDATE * @return array the Title objects linking here * @access public */ function getLinksTo( $options = '', $table = 'pagelinks', $prefix = 'pl' ) { $linkCache =& LinkCache::singleton(); $id = $this->getArticleID(); if ( $options ) { $db =& wfGetDB( DB_MASTER ); } else { $db =& wfGetDB( DB_SLAVE ); } $res = $db->select( array( 'page', $table ), array( 'page_namespace', 'page_title', 'page_id' ), array( "{$prefix}_from=page_id", "{$prefix}_namespace" => $this->getNamespace(), "{$prefix}_title" => $this->getDbKey() ), 'Title::getLinksTo', $options ); $retVal = array(); if ( $db->numRows( $res ) ) { while ( $row = $db->fetchObject( $res ) ) { if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) { $linkCache->addGoodLinkObj( $row->page_id, $titleObj ); $retVal[] = $titleObj; } } } $db->freeResult( $res ); return $retVal; } /** * Get an array of Title objects using this Title as a template * Also stores the IDs in the link cache. * * WARNING: do not use this function on arbitrary user-supplied titles! * On heavily-used templates it will max out the memory. * * @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 * * @param string $options may be FOR UPDATE * @return array the Title objects * @access public */ function getBrokenLinksFrom( $options = '' ) { if ( $options ) { $db =& wfGetDB( DB_MASTER ); } else { $db =& wfGetDB( DB_SLAVE ); } $res = $db->safeQuery( "SELECT pl_namespace, pl_title FROM ! LEFT JOIN ! ON pl_namespace=page_namespace AND pl_title=page_title WHERE pl_from=? AND page_namespace IS NULL !", $db->tableName( 'pagelinks' ), $db->tableName( 'page' ), $this->getArticleId(), $options ); $retVal = array(); if ( $db->numRows( $res ) ) { while ( $row = $db->fetchObject( $res ) ) { $retVal[] = Title::makeTitle( $row->pl_namespace, $row->pl_title ); } } $db->freeResult( $res ); return $retVal; } /** * Get a list of URLs to purge from the Squid cache when this * page changes * * @return array the URLs * @access public */ function getSquidURLs() { return array( $this->getInternalURL(), $this->getInternalURL( 'action=history' ) ); } function purgeSquid() { global $wgUseSquid; if ( $wgUseSquid ) { $urls = $this->getSquidURLs(); $u = new SquidUpdate( $urls ); $u->doUpdate(); } } /** * Move this page without authentication * @param Title &$nt the new page Title * @access public */ function moveNoAuth( &$nt ) { return $this->moveTo( $nt, false ); } /** * Check whether a given move operation would be valid. * Returns true if ok, or a message key string for an error message * if invalid. (Scarrrrry ugly interface this.) * @param Title &$nt the new title * @param bool $auth indicates whether $wgUser's permissions * should be checked * @return mixed true on success, message name on failure * @access public */ function isValidMoveOperation( &$nt, $auth = true ) { if( !$this or !$nt ) { return 'badtitletext'; } if( $this->equals( $nt ) ) { return 'selfmove'; } if( !$this->isMovable() || !$nt->isMovable() ) { return 'immobile_namespace'; } $oldid = $this->getArticleID(); $newid = $nt->getArticleID(); if ( strlen( $nt->getDBkey() ) < 1 ) { return 'articleexists'; } if ( ( '' == $this->getDBkey() ) || ( !$oldid ) || ( '' == $nt->getDBkey() ) ) { return 'badarticleerror'; } if ( $auth && ( !$this->userCanEdit() || !$nt->userCanEdit() || !$this->userCanMove() || !$nt->userCanMove() ) ) { return 'protectedpage'; } # The move is allowed only if (1) the target doesn't exist, or # (2) the target is a redirect to the source, and has no history # (so we can undo bad moves right after they're done). if ( 0 != $newid ) { # Target exists; check for validity if ( ! $this->isValidMoveTarget( $nt ) ) { return 'articleexists'; } } return true; } /** * Move a title to a new location * @param Title &$nt the new title * @param bool $auth indicates whether $wgUser's permissions * should be checked * @return mixed true on success, message name on failure * @access public */ function moveTo( &$nt, $auth = true, $reason = '' ) { $err = $this->isValidMoveOperation( $nt, $auth ); if( is_string( $err ) ) { return $err; } $pageid = $this->getArticleID(); if( $nt->exists() ) { $this->moveOverExistingRedirect( $nt, $reason ); $pageCountChange = 0; } else { # Target didn't exist, do normal move. $this->moveToNewTitle( $nt, $reason ); $pageCountChange = 1; } $redirid = $this->getArticleID(); # Fixing category links (those without piped 'alternate' names) to be sorted under the new title $dbw =& wfGetDB( DB_MASTER ); $categorylinks = $dbw->tableName( 'categorylinks' ); $sql = "UPDATE $categorylinks SET cl_sortkey=" . $dbw->addQuotes( $nt->getPrefixedText() ) . " WHERE cl_from=" . $dbw->addQuotes( $pageid ) . " AND cl_sortkey=" . $dbw->addQuotes( $this->getPrefixedText() ); $dbw->query( $sql, 'SpecialMovepage::doSubmit' ); # Update watchlists $oldnamespace = $this->getNamespace() & ~1; $newnamespace = $nt->getNamespace() & ~1; $oldtitle = $this->getDBkey(); $newtitle = $nt->getDBkey(); if( $oldnamespace != $newnamespace || $oldtitle != $newtitle ) { WatchedItem::duplicateEntries( $this, $nt ); } # Update search engine $u = new SearchUpdate( $pageid, $nt->getPrefixedDBkey() ); $u->doUpdate(); $u = new SearchUpdate( $redirid, $this->getPrefixedDBkey(), '' ); $u->doUpdate(); # Update site_stats if ( $this->getNamespace() == NS_MAIN and $nt->getNamespace() != NS_MAIN ) { # Moved out of main namespace # not viewed, edited, removing $u = new SiteStatsUpdate( 0, 1, -1, $pageCountChange); } elseif ( $this->getNamespace() != NS_MAIN and $nt->getNamespace() == NS_MAIN ) { # Moved into main namespace # not viewed, edited, adding $u = new SiteStatsUpdate( 0, 1, +1, $pageCountChange ); } elseif ( $pageCountChange ) { # Added redirect $u = new SiteStatsUpdate( 0, 0, 0, 1 ); } else{ $u = false; } if ( $u ) { $u->doUpdate(); } global $wgUser; wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?