article.php
来自「php 开发的内容管理系统」· PHP 代码 · 共 2,311 行 · 第 1/5 页
PHP
2,311 行
$wgOut->addWikiText( $text ); $wgOut->returnToMain( false ); wfRunHooks('ArticleDeleteComplete', array(&$this, &$wgUser, $reason)); } else { $wgOut->showFatalError( wfMsg( 'cannotdelete' ) ); } } } /** * Back-end article deletion * Deletes the article with database consistency, writes logs, purges caches * Returns success */ function doDeleteArticle( $reason ) { global $wgUseSquid, $wgDeferredUpdateList; global $wgPostCommitUpdateList, $wgUseTrackbacks; wfDebug( __METHOD__."\n" ); $dbw =& wfGetDB( DB_MASTER ); $ns = $this->mTitle->getNamespace(); $t = $this->mTitle->getDBkey(); $id = $this->mTitle->getArticleID(); if ( $t == '' || $id == 0 ) { return false; } $u = new SiteStatsUpdate( 0, 1, -(int)$this->isCountable( $this->getContent() ), -1 ); array_push( $wgDeferredUpdateList, $u ); // For now, shunt the revision data into the archive table. // Text is *not* removed from the text table; bulk storage // is left intact to avoid breaking block-compression or // immutable storage schemes. // // For backwards compatibility, note that some older archive // table entries will have ar_text and ar_flags fields still. // // In the future, we may keep revisions and mark them with // the rev_deleted field, which is reserved for this purpose. $dbw->insertSelect( 'archive', array( 'page', 'revision' ), array( 'ar_namespace' => 'page_namespace', 'ar_title' => 'page_title', 'ar_comment' => 'rev_comment', 'ar_user' => 'rev_user', 'ar_user_text' => 'rev_user_text', 'ar_timestamp' => 'rev_timestamp', 'ar_minor_edit' => 'rev_minor_edit', 'ar_rev_id' => 'rev_id', 'ar_text_id' => 'rev_text_id', ), array( 'page_id' => $id, 'page_id = rev_page' ), __METHOD__ ); # Now that it's safely backed up, delete it $dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ ); $dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__); if ($wgUseTrackbacks) $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ ); # Clean up recentchanges entries... $dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), __METHOD__ ); # Finally, clean up the link tables $t = $this->mTitle->getPrefixedDBkey(); # Clear caches Article::onArticleDelete( $this->mTitle ); # Delete outgoing links $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) ); $dbw->delete( 'imagelinks', array( 'il_from' => $id ) ); $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) ); $dbw->delete( 'templatelinks', array( 'tl_from' => $id ) ); $dbw->delete( 'externallinks', array( 'el_from' => $id ) ); $dbw->delete( 'langlinks', array( 'll_from' => $id ) ); # Log the deletion $log = new LogPage( 'delete' ); $log->addEntry( 'delete', $this->mTitle, $reason ); # Clear the cached article id so the interface doesn't act like we exist $this->mTitle->resetArticleID( 0 ); $this->mTitle->mArticleID = 0; return true; } /** * Revert a modification */ function rollback() { global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol; if( $wgUser->isAllowed( 'rollback' ) ) { if( $wgUser->isBlocked() ) { $wgOut->blockedPage(); return; } } else { $wgOut->permissionRequired( 'rollback' ); return; } if ( wfReadOnly() ) { $wgOut->readOnlyPage( $this->getContent() ); return; } if( !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ), array( $this->mTitle->getPrefixedText(), $wgRequest->getVal( 'from' ) ) ) ) { $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) ); $wgOut->addWikiText( wfMsg( 'sessionfailure' ) ); return; } $dbw =& wfGetDB( DB_MASTER ); # Enhanced rollback, marks edits rc_bot=1 $bot = $wgRequest->getBool( 'bot' ); # Replace all this user's current edits with the next one down $tt = $this->mTitle->getDBKey(); $n = $this->mTitle->getNamespace(); # Get the last editor $current = Revision::newFromTitle( $this->mTitle ); if( is_null( $current ) ) { # Something wrong... no page? $wgOut->addHTML( wfMsg( 'notanarticle' ) ); return; } $from = str_replace( '_', ' ', $wgRequest->getVal( 'from' ) ); if( $from != $current->getUserText() ) { $wgOut->setPageTitle( wfMsg('rollbackfailed') ); $wgOut->addWikiText( wfMsg( 'alreadyrolled', htmlspecialchars( $this->mTitle->getPrefixedText()), htmlspecialchars( $from ), htmlspecialchars( $current->getUserText() ) ) ); if( $current->getComment() != '') { $wgOut->addHTML( wfMsg( 'editcomment', htmlspecialchars( $current->getComment() ) ) ); } return; } # Get the last edit not by this guy $user = intval( $current->getUser() ); $user_text = $dbw->addQuotes( $current->getUserText() ); $s = $dbw->selectRow( 'revision', array( 'rev_id', 'rev_timestamp' ), array( 'rev_page' => $current->getPage(), "rev_user <> {$user} OR rev_user_text <> {$user_text}" ), __METHOD__, array( 'USE INDEX' => 'page_timestamp', 'ORDER BY' => 'rev_timestamp DESC' ) ); if( $s === false ) { # Something wrong $wgOut->setPageTitle(wfMsg('rollbackfailed')); $wgOut->addHTML( wfMsg( 'cantrollback' ) ); return; } $set = array(); if ( $bot ) { # Mark all reverted edits as bot $set['rc_bot'] = 1; } if ( $wgUseRCPatrol ) { # Mark all reverted edits as patrolled $set['rc_patrolled'] = 1; } if ( $set ) { $dbw->update( 'recentchanges', $set, array( /* WHERE */ 'rc_cur_id' => $current->getPage(), 'rc_user_text' => $current->getUserText(), "rc_timestamp > '{$s->rev_timestamp}'", ), __METHOD__ ); } # Get the edit summary $target = Revision::newFromId( $s->rev_id ); $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from ); $newComment = $wgRequest->getText( 'summary', $newComment ); # Save it! $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); $wgOut->addHTML( '<h2>' . htmlspecialchars( $newComment ) . "</h2>\n<hr />\n" ); $this->updateArticle( $target->getText(), $newComment, 1, $this->mTitle->userIsWatching(), $bot ); $wgOut->returnToMain( false ); } /** * Do standard deferred updates after page view * @private */ function viewUpdates() { global $wgDeferredUpdateList; if ( 0 != $this->getID() ) { global $wgDisableCounters; if( !$wgDisableCounters ) { Article::incViewCount( $this->getID() ); $u = new SiteStatsUpdate( 1, 0, 0 ); array_push( $wgDeferredUpdateList, $u ); } } # Update newtalk / watchlist notification status global $wgUser; $wgUser->clearNotification( $this->mTitle ); } /** * Do standard deferred updates after page edit. * Update links tables, site stats, search index and message cache. * Every 1000th edit, prune the recent changes table. * * @private * @param $text New text of the article * @param $summary Edit summary * @param $minoredit Minor edit * @param $timestamp_of_pagechange Timestamp associated with the page change * @param $newid rev_id value of the new revision * @param $changed Whether or not the content actually changed */ function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange, $newid, $changed = true ) { global $wgDeferredUpdateList, $wgMessageCache, $wgUser, $wgParser; wfProfileIn( __METHOD__ ); # Parse the text $options = new ParserOptions; $options->setTidy(true); $poutput = $wgParser->parse( $text, $this->mTitle, $options, true, true, $newid ); # Save it to the parser cache $parserCache =& ParserCache::singleton(); $parserCache->save( $poutput, $this, $wgUser ); # Update the links tables $u = new LinksUpdate( $this->mTitle, $poutput ); $u->doUpdate(); if ( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) { wfSeedRandom(); if ( 0 == mt_rand( 0, 999 ) ) { # Periodically flush old entries from the recentchanges table. global $wgRCMaxAge; $dbw =& wfGetDB( DB_MASTER ); $cutoff = $dbw->timestamp( time() - $wgRCMaxAge ); $recentchanges = $dbw->tableName( 'recentchanges' ); $sql = "DELETE FROM $recentchanges WHERE rc_timestamp < '{$cutoff}'"; $dbw->query( $sql ); } } $id = $this->getID(); $title = $this->mTitle->getPrefixedDBkey(); $shortTitle = $this->mTitle->getDBkey(); if ( 0 == $id ) { wfProfileOut( __METHOD__ ); return; } $u = new SiteStatsUpdate( 0, 1, $this->mGoodAdjustment, $this->mTotalAdjustment ); array_push( $wgDeferredUpdateList, $u ); $u = new SearchUpdate( $id, $title, $text ); array_push( $wgDeferredUpdateList, $u ); # If this is another user's talk page, update newtalk # Don't do this if $changed = false otherwise some idiot can null-edit a # load of user talk pages and piss people off if( $this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getName() && $changed ) { if (wfRunHooks('ArticleEditUpdateNewTalk', array(&$this)) ) { $other = User::newFromName( $shortTitle ); if( is_null( $other ) && User::isIP( $shortTitle ) ) { // An anonymous user $other = new User(); $other->setName( $shortTitle ); } if( $other ) { $other->setNewtalk( true ); } } } if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) { $wgMessageCache->replace( $shortTitle, $text ); } wfProfileOut( __METHOD__ ); } /** * Generate the navigation links when browsing through an article revisions * It shows the information as: * Revision as of \<date\>; view current revision * \<- Previous version | Next Version -\> * * @private * @param string $oldid Revision ID of this article revision */ function setOldSubtitle( $oldid=0 ) { global $wgLang, $wgOut, $wgUser; $revision = Revision::newFromId( $oldid ); $current = ( $oldid == $this->mLatest ); $td = $wgLang->timeanddate( $this->mTimestamp, true ); $sk = $wgUser->getSkin(); $lnk = $current ? wfMsg( 'currentrevisionlink' ) : $lnk = $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'currentrevisionlink' ) ); $prev = $this->mTitle->getPreviousRevisionID( $oldid ) ; $prevlink = $prev ? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'previousrevision' ), 'direction=prev&oldid='.$oldid ) : wfMsg( 'previousrevision' ); $prevdiff = $prev ? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=prev&oldid='.$oldid ) : wfMsg( 'diff' ); $nextlink = $current ? wfMsg( 'nextrevision' ) : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'nextrevision' ), 'direction=next&oldid='.$oldid ); $nextdiff = $current ? wfMsg( 'diff' ) : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid ); $userlinks = $sk->userLink( $revision->getUser(), $revision->getUserText() ) . $sk->userToolLinks( $revision->getUser(), $revision->getUserText() ); $r = wfMsg( 'old-revision-navigation', $td, $lnk, $prevlink, $nextlink, $userlinks, $prevdiff, $nextdiff ); $wgOut->setSubtitle( $r ); } /** * This function is called right before saving the wikitext, * so we can do things like signatures and links-in-context. * * @param string $text */ function preSaveTransform( $text ) { global $wgParser, $wgUser; return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) ); } /* Caching functions */ /** * checkLastModified returns true if it has taken care of all * output to the client that is necessary for this request. * (that is, it has sent a cached version of the page) */ function tryFileCache() { static $called = false; if( $called ) { wfDebug( "Article::tryFileCache(): called twice!?\n" ); return; } $called = true; if($this->isFileCacheable()) { $touched = $this->mTouched; $cache = new CacheManager( $this->mTitle ); if($cache->isFileCacheGood( $touched )) { wfDebug( "Article::tryFileCache(): about to load file\n" ); $cache->loadFromFileCache(); return true; } else { wfDebug( "Article::tryFileCache(): starting buffer\n" ); ob_start( array(&$cache, 'saveToFileCache' ) ); } } else { wfDebug( "Article::tryFileCache(): not cacheable\n" ); } } /** * Check if the page can be cached * @return bool */ function isFileCacheable() { global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest; extract( $wgRequest->getValues( 'action', 'oldid', 'diff', 'redirect', 'printable' ) ); return $wgUseFileCache and (!$wgShowIPinHeader) and ($this->getID() != 0) and ($wgUser->isAnon()) and (!$wgUser->getNewtalk()) and ($this->mTitle->getNamespace() != NS_SPECIAL ) and (empty( $action ) || $action == 'view') and (!isset($oldid)) and (!isset($diff)) and (!isset($redirect)) and (!isset($printable)) and (!$this->mRedirectedFrom); } /** * Loads page_touched and returns a value indicating if it should be used * */ function checkTouched() { if( !$this->mDataLoaded ) { $this->loadPageData(); } return !$this->mIsRedirect; } /** * Get the page_touched field */ function getTouched() { # Ensure that page data has been loaded if( !$this->mDataLoaded ) { $this->loadPageData(); } return $this->mTouched; } /** * Get the page_latest field */ function getLatest() { if ( !$this->mDataLoaded ) { $this->loadPageData(); } return $this->mLatest; } /** * Edit an article without doing all that other stuff * The article must already exist; link tables etc * are not updated, caches are not flushed. * * @param string $text text submitted * @param string $comment comment submitted * @param bool $minor whereas it's a minor modification */ function quickEdit( $text, $comment = '', $minor = 0 ) { wfProfileIn( __METHOD__
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?