X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2FArticle.php;h=df050746d7dbe664c6e84514946de7f7cf99853a;hb=c1ac86e5600e3334d8c0de30ad41cbd3db9f23dc;hp=c885c5998216d46ef14088c701552633f1fa5150;hpb=a5e10a4cbcced463855eb2291e7e65c0b584349d;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Article.php b/includes/Article.php index c885c59982..df050746d7 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -14,9 +14,9 @@ $wgArticleCurContentFields = false; $wgArticleOldContentFields = false; /** - * Class representing a Wikipedia article and history. + * Class representing a MediaWiki article and history. * - * See design.doc for an overview. + * See design.txt for an overview. * Note: edit user interface and cache support functions have been * moved to separate EditPage and CacheManager classes. * @@ -34,6 +34,7 @@ class Article { var $mId, $mTable; var $mForUpdate; var $mOldId; + var $mRevIdFetched; /**#@-*/ /** @@ -58,13 +59,17 @@ class Article { * @private */ function clear() { + $this->mDataLoaded = false; $this->mContentLoaded = false; + $this->mCurID = $this->mUser = $this->mCounter = -1; # Not loaded $this->mRedirectedFrom = $this->mUserText = $this->mTimestamp = $this->mComment = $this->mFileCache = ''; $this->mCountAdjustment = 0; $this->mTouched = '19700101000000'; $this->mForUpdate = false; + $this->mIsRedirect = false; + $this->mRevIdFetched = 0; } /** @@ -75,7 +80,7 @@ class Article { * @return Return the text of this revision */ function getContent( $noredir ) { - global $wgRequest; + global $wgRequest, $wgUser; # Get variables from query string :P $action = $wgRequest->getText( 'action', 'view' ); @@ -95,7 +100,7 @@ class Article { $this->loadContent( $noredir ); # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page if ( $this->mTitle->getNamespace() == NS_USER_TALK && - preg_match('/^\d{1,3}\.\d{1,3}.\d{1,3}\.\d{1,3}$/',$this->mTitle->getText()) && + $wgUser->isIP($this->mTitle->getText()) && $action=='view' ) { wfProfileOut( $fname ); @@ -256,11 +261,67 @@ class Article { $t = $this->mTitle->getPrefixedText(); - $noredir = $noredir || ($wgRequest->getVal( 'redirect' ) == 'no'); + $noredir = $noredir || ($wgRequest->getVal( 'redirect' ) == 'no') + || $wgRequest->getCheck( 'rdfrom' ); $this->mOldId = $oldid; $this->fetchContent( $oldid, $noredir, true ); } + + /** + * Fetch a page record with the given conditions + * @param Database $dbr + * @param array $conditions + * @access private + */ + function pageData( &$dbr, $conditions ) { + return $dbr->selectRow( 'page', + array( + 'page_id', + 'page_namespace', + 'page_title', + 'page_restrictions', + 'page_counter', + 'page_is_redirect', + 'page_is_new', + 'page_random', + 'page_touched', + 'page_latest', + 'page_len' ), + $conditions, + 'Article::pageData' ); + } + + function pageDataFromTitle( &$dbr, $title ) { + return $this->pageData( $dbr, array( + 'page_namespace' => $title->getNamespace(), + 'page_title' => $title->getDBkey() ) ); + } + + function pageDataFromId( &$dbr, $id ) { + return $this->pageData( $dbr, array( + 'page_id' => IntVal( $id ) ) ); + } + + /** + * Set the general counter, title etc data loaded from + * some source. + * + * @param object $data + * @access private + */ + function loadPageData( $data ) { + $this->mTitle->mRestrictions = explode( ',', trim( $data->page_restrictions ) ); + $this->mTitle->mRestrictionsLoaded = true; + + $this->mCounter = $data->page_counter; + $this->mTouched = wfTimestamp( TS_MW, $data->page_touched ); + $this->mIsRedirect = $data->page_is_redirect; + $this->mLatest = $data->page_latest; + + $this->mDataLoaded = true; + } + /** * Get text of an article from database * @param int $oldid 0 for whatever the latest revision is @@ -287,32 +348,39 @@ class Article { } $this->mContent = wfMsg( 'missingarticle', $t ); - if( !$oldid ) { - # Retrieve current version - $id = $this->getID(); - if ( 0 == $id ) { + if( $oldid ) { + $revision = Revision::newFromId( $oldid ); + if( is_null( $revision ) ) { + wfDebug( "$fname failed to retrieve specified revision, id $oldid\n" ); return false; } - - $s = $dbr->selectRow( array( 'text', 'revision', 'page' ), - $this->getContentFields(), - "page_id='$id' AND rev_page=page_id AND rev_id=page_latest AND old_id=rev_id", - $fname, $this->getSelectOptions() ); + $data = $this->pageDataFromId( $dbr, $revision->getPage() ); + if( !$data ) { + wfDebug( "$fname failed to get page data linked to revision id $oldid\n" ); + return false; + } + $this->mTitle = Title::makeTitle( $data->page_namespace, $data->page_title ); + $this->loadPageData( $data ); } else { - # Historical revision - $s = $dbr->selectRow( array( 'text', 'revision', 'page' ), - $this->getContentFields(), - "rev_page=page_id AND rev_id='$oldid' AND old_id=rev_id", - $fname, $this->getSelectOptions() ); - } - if ( $s === false ) { - return false; + if( !$this->mDataLoaded ) { + $data = $this->pageDataFromTitle( $dbr, $this->mTitle ); + if( !$data ) { + wfDebug( "$fname failed to find page data for title " . $this->mTitle->getPrefixedText() . "\n" ); + return false; + } + $this->loadPageData( $data ); + } + $revision = Revision::newFromId( $this->mLatest ); + if( is_null( $revision ) ) { + wfDebug( "$fname failed to retrieve current page, rev_id $data->page_latest\n" ); + return false; + } } # If we got a redirect, follow it (unless we've been told # not to by either the function parameter or the query if ( !$oldid && !$noredir ) { - $rt = Title::newFromRedirect( Revision::getRevisionText( $s ) ); + $rt = Title::newFromRedirect( $revision->getText() ); # process if title object is valid and not special:userlogout if ( $rt && ! ( $rt->getNamespace() == NS_SPECIAL && $rt->getText() == 'Userlogout' ) ) { # Gotta hand redirects to special pages differently: @@ -321,7 +389,8 @@ class Article { if( $globalTitle ) { global $wgOut; if ( $rt->getInterwiki() != '' && $rt->isLocal() ) { - $wgOut->redirect( $rt->getFullURL() ) ; + $source = $this->mTitle->getFullURL( 'redirect=no' ); + $wgOut->redirect( $rt->getFullURL( 'rdfrom=' . urlencode( $source ) ) ) ; return false; } if ( $rt->getNamespace() == NS_SPECIAL ) { @@ -329,46 +398,39 @@ class Article { return false; } } - $rid = $rt->getArticleID(); - if ( 0 != $rid ) { - $redirRow = $dbr->selectRow( array( 'text', 'revision', 'page' ), - $this->getContentFields(), - "page_id='$rid' AND rev_page=page_id AND rev_id=page_latest AND old_id=rev_id", - $fname, $this->getSelectOptions() ); - - if ( $redirRow !== false ) { + $redirData = $this->pageDataFromTitle( $dbr, $rt ); + if( $redirData ) { + $redirRev = Revision::newFromId( $redirData->page_latest ); + if( !is_null( $redirRev ) ) { $this->mRedirectedFrom = $this->mTitle->getPrefixedText(); $this->mTitle = $rt; - $s = $redirRow; + $data = $redirData; + $this->loadPageData( $data ); + $revision = $redirRev; } } } } # if the title's different from expected, update... - if( $globalTitle && - ( $this->mTitle->getNamespace() != $s->page_namespace || - $this->mTitle->getDBkey() != $s->page_title ) ) { - $oldTitle = Title::makeTitle( $s->page_namesapce, $s->page_title ); - $this->mTitle = $oldTitle; + if( $globalTitle ) { global $wgTitle; - $wgTitle = $oldTitle; + if( !$this->mTitle->equals( $wgTitle ) ) { + $wgTitle = $this->mTitle; + } } # Back to the business at hand... - $this->mCounter = $s->page_counter; - $this->mTitle->mRestrictions = explode( ',', trim( $s->page_restrictions ) ); - $this->mTitle->mRestrictionsLoaded = true; - $this->mTouched = wfTimestamp( TS_MW, $s->page_touched ); - - $this->mContent = Revision::getRevisionText( $s ); + $this->mContent = $revision->getText(); - $this->mUser = $s->rev_user; - $this->mUserText = $s->rev_user_text; - $this->mComment = $s->rev_comment; - $this->mTimestamp = wfTimestamp( TS_MW, $s->rev_timestamp ); + $this->mUser = $revision->getUser(); + $this->mUserText = $revision->getUserText(); + $this->mComment = $revision->getComment(); + $this->mTimestamp = wfTimestamp( TS_MW, $revision->getTimestamp() ); + $this->mRevIdFetched = $revision->getID(); $this->mContentLoaded = true; + return $this->mContent; } @@ -461,7 +523,7 @@ class Article { function isRedirect( $text = false ) { if ( $text === false ) { $this->loadContent(); - $titleObj = Title::newFromRedirect( $this->mText ); + $titleObj = Title::newFromRedirect( $this->fetchRevisionText() ); } else { $titleObj = Title::newFromRedirect( $text ); } @@ -475,7 +537,7 @@ class Article { */ function loadLastEdit() { global $wgOut; - + if ( -1 != $this->mUser ) return; @@ -483,19 +545,13 @@ class Article { $id = $this->getID(); if ( 0 == $id ) return; - $fname = 'Article::loadLastEdit'; - - $dbr =& $this->getDB(); - $s = $dbr->selectRow( array( 'revision', 'page') , - array( 'rev_user','rev_user_text','rev_timestamp', 'rev_comment','rev_minor_edit' ), - array( 'page_id' => $id, 'page_latest=rev_id' ), $fname, $this->getSelectOptions() ); - - if ( $s !== false ) { - $this->mUser = $s->rev_user; - $this->mUserText = $s->rev_user_text; - $this->mTimestamp = wfTimestamp(TS_MW,$s->rev_timestamp); - $this->mComment = $s->rev_comment; - $this->mMinorEdit = $s->rev_minor_edit; + $this->mLastRevision = Revision::loadFromPageId( $this->getDB(), $id ); + if( !is_null( $this->mLastRevision ) ) { + $this->mUser = $this->mLastRevision->getUser(); + $this->mUserText = $this->mLastRevision->getUserText(); + $this->mTimestamp = $this->mLastRevision->getTimestamp(); + $this->mComment = $this->mLastRevision->getComment(); + $this->mMinorEdit = $this->mLastRevision->isMinor(); } } @@ -523,6 +579,11 @@ class Article { $this->loadLastEdit(); return $this->mMinorEdit; } + + function getRevIdFetched() { + $this->loadLastEdit(); + return $this->mRevIdFetched; + } function getContributors($limit = 0, $offset = 0) { $fname = 'Article::getContributors'; @@ -566,7 +627,7 @@ class Article { function view() { global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgLang; global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol; - global $wgEnotif; + global $wgEnotif, $wgParser; $sk = $wgUser->getSkin(); $fname = 'Article::view'; @@ -585,8 +646,12 @@ class Article { if ( !is_null( $diff ) ) { require_once( 'DifferenceEngine.php' ); $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); + $de = new DifferenceEngine( $oldid, $diff, $rcid ); + // DifferenceEngine directly fetched the revision: + $this->mRevIdFetched = $de->mNewid; $de->showDiffPage(); + if( $diff == 0 ) { # Run view updates for current revision only $this->viewUpdates(); @@ -607,7 +672,7 @@ class Article { } } # Should the parser cache be used? - if ( $wgEnableParserCache && intval($wgUser->getOption( 'stubthreshold' )) == 0 && empty( $oldid ) ) { + if ( $wgEnableParserCache && intval($wgUser->getOption( 'stubthreshold' )) == 0 && empty( $oldid ) && $this->getID() ) { $pcache = true; } else { $pcache = false; @@ -646,10 +711,13 @@ class Article { # Can't cache redirects $pcache = false; } elseif ( !empty( $rdfrom ) ) { - $sk = $wgUser->getSkin(); - $redir = $sk->makeExternalLink( $rdfrom, $rdfrom ); - $s = wfMsg( 'redirectedfrom', $redir ); - $wgOut->setSubtitle( $s ); + global $wgRedirectSources; + if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) { + $sk = $wgUser->getSkin(); + $redir = $sk->makeExternalLink( $rdfrom, $rdfrom ); + $s = wfMsg( 'redirectedfrom', $redir ); + $wgOut->setSubtitle( $s ); + } } # wrap user css and user js in pre and don't parse @@ -669,7 +737,11 @@ class Article { $wgOut->addHTML( '#REDIRECT' . ''.$link.'' ); - + + $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser)); + $catlinks = $parseout->getCategoryLinks(); + $wgOut->addCategoryLinks($catlinks); + $skin = $wgUser->getSkin(); } else if ( $pcache ) { # Display content and save to parser cache $wgOut->addPrimaryWikiText( $text, $this ); @@ -678,7 +750,12 @@ class Article { $wgOut->addWikiText( $text ); } } - $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); + /* title may have been set from the cache */ + $t = $wgOut->getPageTitle(); + if( empty( $t ) ) { + $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); + } + # If we have been passed an &rcid= parameter, we want to give the user a # chance to mark this new article as patrolled. if ( $wgUseRCPatrol && !is_null ( $rcid ) && $rcid != 0 && $wgUser->isLoggedIn() && @@ -698,8 +775,6 @@ class Article { $this->viewUpdates(); wfProfileOut( $fname ); - - $wgUser->clearNotification( $this->mTitle ); } /** @@ -710,10 +785,11 @@ class Article { * Best if all done inside a transaction. * * @param Database $dbw - * @return int The newly created page_id key + * @param string $restrictions + * @return int The newly created page_id key * @access private */ - function insertOn( &$dbw ) { + function insertOn( &$dbw, $restrictions = '' ) { $fname = 'Article::insertOn'; wfProfileIn( $fname ); @@ -723,7 +799,7 @@ class Article { 'page_namespace' => $this->mTitle->getNamespace(), 'page_title' => $this->mTitle->getDBkey(), 'page_counter' => 0, - 'page_restrictions' => '', + 'page_restrictions' => $restrictions, 'page_is_redirect' => 0, # Will set this shortly... 'page_is_new' => 1, 'page_random' => wfRandom(), @@ -732,6 +808,8 @@ class Article { ), $fname ); $newid = $dbw->insertId(); + $this->mTitle->resetArticleId( $newid ); + wfProfileOut( $fname ); return $newid; } @@ -740,8 +818,8 @@ class Article { * Update the page record to point to a newly saved revision. * * @param Database $dbw - * @param int $revId - * @param string $text -- used to set length and redirect status if given + * @param Revision $revision -- for ID number, and text used to set + length and redirect status fields * @param int $lastRevision -- if given, will not overwrite the page field * when different from the currently set value. * Giving 0 indicates the new page flag should @@ -749,7 +827,7 @@ class Article { * @return bool true on success, false on failure * @access private */ - function updateRevisionOn( &$dbw, $revId, $text = '', $lastRevision = null ) { + function updateRevisionOn( &$dbw, $revision, $lastRevision = null ) { $fname = 'Article::updateToRevision'; wfProfileIn( $fname ); @@ -758,9 +836,10 @@ class Article { # An extra check against threads stepping on each other $conditions['page_latest'] = $lastRevision; } + $text = $revision->getText(); $dbw->update( 'page', array( /* SET */ - 'page_latest' => $revId, + 'page_latest' => $revision->getId(), 'page_touched' => $dbw->timestamp(), 'page_is_new' => ($lastRevision === 0) ? 0 : 1, 'page_is_redirect' => Article::isRedirect( $text ), @@ -773,6 +852,40 @@ class Article { return ( $dbw->affectedRows() != 0 ); } + /** + * If the given revision is newer than the currently set page_latest, + * update the page record. Otherwise, do nothing. + * + * @param Database $dbw + * @param Revision $revision + */ + function updateIfNewerOn( &$dbw, $revision ) { + $fname = 'Article::updateIfNewerOn'; + wfProfileIn( $fname ); + + $row = $dbw->selectRow( + array( 'revision', 'page' ), + array( 'rev_id', 'rev_timestamp' ), + array( + 'page_id' => $this->getId(), + 'page_latest=rev_id' ), + $fname ); + if( $row ) { + if( $row->rev_timestamp >= $revision->getTimestamp() ) { + wfProfileOut( $fname ); + return false; + } + $prev = $row->rev_id; + } else { + # No or missing previous revision; mark the page as new + $prev = 0; + } + + $ret = $this->updateRevisionOn( $dbw, $revision, $prev ); + wfProfileOut( $fname ); + return $ret; + } + /** * Theoretically we could defer these whole insert and update * functions for after display, but that's taking a big leap @@ -780,7 +893,7 @@ class Article { * errors at some point. * @private */ - function insertNewArticle( $text, $summary, $isminor, $watchthis ) { + function insertNewArticle( $text, $summary, $isminor, $watchthis, $suppressRC=false ) { global $wgOut, $wgUser; global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer; @@ -792,6 +905,7 @@ class Article { $ttl = $this->mTitle->getDBkey(); $text = $this->preSaveTransform( $text ); $isminor = ( $isminor && $wgUser->isLoggedIn() ) ? 1 : 0; + $now = wfTimestampNow(); $dbw =& wfGetDB( DB_MASTER ); @@ -810,10 +924,12 @@ class Article { $this->mTitle->resetArticleID( $newid ); # Update the page record with revision data - $this->updateRevisionOn( $dbw, $revisionId, $text, 0 ); + $this->updateRevisionOn( $dbw, $revision, 0 ); Article::onArticleCreate( $this->mTitle ); - RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary ); + if(!$suppressRC) { + RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary ); + } if ($watchthis) { if(!$this->mTitle->userIsWatching()) $this->watch(); @@ -841,6 +957,8 @@ class Article { /** * Fetch and uncompress the text for a given revision. * Can ask by rev_id number or timestamp (set $field) + * FIXME: This function is broken. Eliminate all uses and remove. + * Use Revision class in place. */ function fetchRevisionText( $revId = null, $field = 'rev_id' ) { $fname = 'Article::fetchRevisionText'; @@ -870,12 +988,15 @@ class Article { function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary = '', $edittime = NULL) { $fname = 'Article::getTextOfLastEditWithSectionReplacedOrAdded'; - if( is_null( $edittime ) ) { - $oldtext = $this->fetchRevisionText(); - } else { - $oldtext = $this->fetchRevisionText( $edittime, 'rev_timestamp' ); - } if ($section != '') { + if( is_null( $edittime ) ) { + $rev = Revision::newFromTitle( $this->mTitle ); + } else { + $dbw =& wfGetDB( DB_MASTER ); + $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime ); + } + $oldtext = $rev->getText(); + if($section=='new') { if($summary) $subject="== {$summary} ==\n\n"; $text=$oldtext."\n\n".$subject.$text; @@ -977,19 +1098,19 @@ class Article { $text = $this->preSaveTransform( $text ); $dbw =& wfGetDB( DB_MASTER ); + $now = wfTimestampNow(); # Update article, but only if changed. # It's important that we either rollback or complete, otherwise an attacker could # overwrite cur entries by sending precisely timed user aborts. Random bored users # could conceivably have the same effect, especially if cur is locked for long periods. - if( $wgDBtransactions ) { - $dbw->query( 'BEGIN', $fname ); - } else { + if( !$wgDBtransactions ) { $userAbort = ignore_user_abort( true ); } $oldtext = $this->getContent( true ); + $lastRevision = 0; if ( 0 != strcmp( $text, $oldtext ) ) { $this->mCountAdjustment = $this->isCountable( $text ) @@ -1008,7 +1129,7 @@ class Article { $revisionId = $revision->insertOn( $dbw ); # Update page - $ok = $this->updateRevisionOn( $dbw, $revisionId, $text, $lastRevision ); + $ok = $this->updateRevisionOn( $dbw, $revision, $lastRevision ); if( !$ok ) { /* Belated edit conflict! Run away!! */ @@ -1016,15 +1137,13 @@ class Article { } else { # Update recentchanges and purge cache and whatnot $bot = (int)($wgUser->isBot() || $forceBot); - RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary, + RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary, $lastRevision, $this->getTimestamp(), $bot ); Article::onArticleEdit( $this->mTitle ); } } - if( $wgDBtransactions ) { - $dbw->query( 'COMMIT', $fname ); - } else { + if( !$wgDBtransactions ) { ignore_user_abort( $userAbort ); } @@ -1060,7 +1179,7 @@ class Article { array_push( $wgPostCommitUpdateList, $u ); } - $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor, $me2, $now, $summary, $lastRevision ); + $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor, $isminor, $now, $summary, $lastRevision ); } return $good; } @@ -1139,6 +1258,31 @@ class Article { } } + /** + * Validate function + */ + function validate() { + global $wgOut, $wgUser, $wgRequest, $wgUseValidation; + + if ( !$wgUseValidation ) # Are we using article validation at all? + { + $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" ); + return ; + } + + $wgOut->setRobotpolicy( 'noindex,follow' ); + $revision = $wgRequest->getVal( 'revision' ); + + include_once ( "SpecialValidate.php" ) ; # The "Validation" class + + $v = new Validation ; + if ( $wgRequest->getVal ( "mode" , "" ) == "list" ) + $t = $v->showList ( $this ) ; + else + $t = $v->validatePageForm ( $this , $revision ) ; + + $wgOut->addHTML ( $t ) ; + } /** * Add this page to $wgUser's watchlist @@ -1157,13 +1301,13 @@ class Article { return; } - if (wfRunHooks('WatchArticle', $wgUser, $this)) { + if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) { $wgUser->addWatch( $this->mTitle ); $wgUser->saveSettings(); - wfRunHooks('WatchArticleComplete', $wgUser, $this); - + wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this)); + $wgOut->setPagetitle( wfMsg( 'addedwatch' ) ); $wgOut->setRobotpolicy( 'noindex,follow' ); @@ -1192,12 +1336,12 @@ class Article { return; } - if (wfRunHooks('UnwatchArticle', $wgUser, $this)) { + if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$this))) { $wgUser->removeWatch( $this->mTitle ); $wgUser->saveSettings(); - wfRunHooks('UnwatchArticleComplete', $wgUser, $this); + wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this)); $wgOut->setPagetitle( wfMsg( 'removedwatch' ) ); $wgOut->setRobotpolicy( 'noindex,follow' ); @@ -1250,7 +1394,7 @@ class Article { if( !$moveonly ) { $restrictions .= ":edit=" . $limit; } - if (wfRunHooks('ArticleProtect', $this, $wgUser, $limit == 'sysop', $reason, $moveonly)) { + if (wfRunHooks('ArticleProtect', array(&$this, &$wgUser, $limit == 'sysop', $reason, $moveonly))) { $dbw =& wfGetDB( DB_MASTER ); $dbw->update( 'page', @@ -1262,7 +1406,7 @@ class Article { ), 'Article::protect' ); - wfRunHooks('ArticleProtectComplete', $this, $wgUser, $limit == 'sysop', $reason, $moveonly); + wfRunHooks('ArticleProtectComplete', array(&$this, &$wgUser, $limit == 'sysop', $reason, $moveonly)); $log = new LogPage( 'protect' ); if ( $limit === '' ) { @@ -1322,9 +1466,6 @@ class Article { - - -   " ); if($moveonly != '') { $wgOut->AddHTML( " @@ -1332,7 +1473,7 @@ class Article { - + " ); @@ -1346,7 +1487,7 @@ class Article { -\n" ); +" ); $wgOut->returnToMain( false ); } @@ -1500,9 +1641,6 @@ class Article { - -   -   @@ -1525,7 +1663,7 @@ class Article { $fname = 'Article::doDelete'; wfDebug( $fname."\n" ); - if (wfRunHooks('ArticleDelete', $this, $wgUser, $reason)) { + if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason))) { if ( $this->doDeleteArticle( $reason ) ) { $deleted = $this->mTitle->getPrefixedText(); @@ -1533,15 +1671,15 @@ class Article { $wgOut->setRobotpolicy( 'noindex,nofollow' ); $sk = $wgUser->getSkin(); - $loglink = $sk->makeKnownLink( $wgContLang->getNsText( NS_PROJECT ) . - ':' . wfMsgForContent( 'dellogpage' ), + $loglink = $sk->makeKnownLink( $wgContLang->getNsText( NS_SPECIAL ) . + ':Log/delete', wfMsg( 'deletionlog' ) ); $text = wfMsg( 'deletedtext', $deleted, $loglink ); $wgOut->addHTML( '

' . $text . "

\n" ); $wgOut->returnToMain( false ); - wfRunHooks('ArticleDeleteComplete', $this, $wgUser, $reason); + wfRunHooks('ArticleDeleteComplete', array(&$this, &$wgUser, $reason)); } else { $wgOut->fatalError( wfMsg( 'cannotdelete' ) ); } @@ -1580,11 +1718,8 @@ class Article { $this->mTitle->getInternalURL(), $this->mTitle->getInternalURL( 'history' ) ); - foreach ( $linksTo as $linkTo ) { - $urls[] = $linkTo->getInternalURL(); - } - $u = new SquidUpdate( $urls ); + $u = SquidUpdate::newFromTitles( $linksTo, $urls ); array_push( $wgPostCommitUpdateList, $u ); } @@ -1592,33 +1727,39 @@ class Article { # Client and file cache invalidation Title::touchArray( $linksTo ); - # Move article and history to the "archive" table - $dbw->insertSelect( 'archive', array( 'page','revision', 'text' ), + // 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_text' => 'old_text', '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_flags' => 'old_flags', 'ar_rev_id' => 'rev_id', + 'ar_text_id' => 'rev_text_id', ), array( - 'page_namespace' => $ns, - 'page_title' => $t, - 'page_id = rev_page AND old_id = rev_id' + 'page_id' => $id, + 'page_id = rev_page' ), $fname ); - + # Now that it's safely backed up, delete it - - $dbw->deleteJoin( 'text', 'revision', 'old_id', 'rev_id', array( "rev_page = {$id}" ), $fname ); $dbw->delete( 'revision', array( 'rev_page' => $id ), $fname ); $dbw->delete( 'page', array( 'page_id' => $id ), $fname); - + + # Clean up recentchanges entries... $dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), $fname ); # Finally, clean up the link tables @@ -1782,7 +1923,10 @@ class Article { $this->mTitle->getText() == $wgUser->getName()) { require_once( 'UserTalkUpdate.php' ); $u = new UserTalkUpdate( 0, $this->mTitle->getNamespace(), $this->mTitle->getDBkey(), false, false, false ); + } else { + $wgUser->clearNotification( $this->mTitle ); } + } /** @@ -1921,16 +2065,14 @@ class Article { */ function checkTouched() { $fname = 'Article::checkTouched'; - $id = $this->getID(); - $dbr =& $this->getDB(); - $s = $dbr->selectRow( 'page', array( 'page_touched', 'page_is_redirect' ), - array( 'page_id' => $id ), $fname, $this->getSelectOptions() ); - if( $s !== false ) { - $this->mTouched = wfTimestamp( TS_MW, $s->page_touched ); - return !$s->page_is_redirect; - } else { - return false; + if( !$this->mDataLoaded ) { + $dbr =& $this->getDB(); + $data = $this->pageDataFromId( $dbr, $this->getId() ); + if( $data ) { + $this->loadPageData( $data ); + } } + return !$this->mIsRedirect; } /** @@ -1955,7 +2097,7 @@ class Article { 'minor_edit' => $minor ? 1 : 0, ) ); $revisionId = $revision->insertOn( $dbw ); - $this->updateRevisionOn( $dbw, $revisionId, $text ); + $this->updateRevisionOn( $dbw, $revision ); $dbw->commit(); wfProfileOut( $fname ); @@ -2143,6 +2285,35 @@ class Article { return array( 'edits' => $edits, 'authors' => $authors ); } + + /** + * Return a list of templates used by this article. + * Uses the links table to find the templates + * + * @return array + */ + function getUsedTemplates() { + $result = array(); + $id = $this->mTitle->getArticleID(); + + $db =& wfGetDB( DB_SLAVE ); + $page = $db->tableName( 'page' ); + $links = $db->tableName( 'links' ); + $sql = "SELECT page_title ". + "FROM $page,$links WHERE l_to=page_id AND l_from={$id} and page_namespace=".NS_TEMPLATE; + $res = $db->query( $sql, "Article:getUsedTemplates" ); + if ( false !== $res ) { + if ( $db->numRows( $res ) ) { + while ( $row = $db->fetchObject( $res ) ) { + $result[] = $row->page_title; + } + } + } + $db->freeResult( $res ); + return $result; + } + + }