* @internal documentation reviewed 15 Mar 2010
*/
class WikiPage extends Page {
+ // doDeleteArticleReal() return values. Values less than zero indicate fatal errors,
+ // values greater than zero indicate that there were problems not resulting in page
+ // not being deleted
+
+ /**
+ * Delete operation aborted by hook
+ */
+ const DELETE_HOOK_ABORTED = -1;
+
+ /**
+ * Deletion successful
+ */
+ const DELETE_SUCCESS = 0;
+
+ /**
+ * Page not found
+ */
+ const DELETE_NO_PAGE = 1;
+
+ /**
+ * No revisions found to delete
+ */
+ const DELETE_NO_REVISIONS = 2;
+
/**
* @var Title
*/
public $mDataLoaded = false; // !< Boolean
public $mIsRedirect = false; // !< Boolean
public $mLatest = false; // !< Integer (false means "not loaded")
- public $mPreparedEdit = false; // !< Array
+ public $mPreparedEdit = false; // !< Array
+ /**@}}*/
/**
* @var Title
*/
protected $mLastRevision = null;
- protected $mTimestamp = ''; // !< String
- protected $mTouched = '19700101000000'; // !< String
- /**@}}*/
+ /**
+ * @var string; timestamp of the current revision or empty string if not loaded
+ */
+ protected $mTimestamp = '';
+
+ /**
+ * @var string
+ */
+ protected $mTouched = '19700101000000';
+
+ /**
+ * @var int|null
+ */
+ protected $mCounter = null;
/**
* Constructor and clear the article
*
* @param $id Int article ID to load
*
- * @return WikiPage
+ * @return WikiPage|null
*/
public static function newFromID( $id ) {
$t = Title::newFromID( $id );
return array();
}
- /**
- * If this page is a redirect, get its target
- *
- * The target will be fetched from the redirect table if possible.
- * If this page doesn't have an entry there, call insertRedirect()
- * @return Title|mixed object, or null if this page is not a redirect
- */
- public function getRedirectTarget() {
- if ( !$this->mTitle->isRedirect() ) {
- return null;
- }
-
- if ( $this->mRedirectTarget !== null ) {
- return $this->mRedirectTarget;
- }
-
- # Query the redirect table
- $dbr = wfGetDB( DB_SLAVE );
- $row = $dbr->selectRow( 'redirect',
- array( 'rd_namespace', 'rd_title', 'rd_fragment', 'rd_interwiki' ),
- array( 'rd_from' => $this->getId() ),
- __METHOD__
- );
-
- // rd_fragment and rd_interwiki were added later, populate them if empty
- if ( $row && !is_null( $row->rd_fragment ) && !is_null( $row->rd_interwiki ) ) {
- return $this->mRedirectTarget = Title::makeTitle(
- $row->rd_namespace, $row->rd_title,
- $row->rd_fragment, $row->rd_interwiki );
- }
-
- # This page doesn't have an entry in the redirect table
- return $this->mRedirectTarget = $this->insertRedirect();
- }
-
- /**
- * Insert an entry for this page into the redirect table.
- *
- * Don't call this function directly unless you know what you're doing.
- * @return Title object or null if not a redirect
- */
- public function insertRedirect() {
- // recurse through to only get the final target
- $retval = Title::newFromRedirectRecurse( $this->getRawText() );
- if ( !$retval ) {
- return null;
- }
- $this->insertRedirectEntry( $retval );
- return $retval;
- }
-
- /**
- * Insert or update the redirect table entry for this page to indicate
- * it redirects to $rt .
- * @param $rt Title redirect target
- */
- public function insertRedirectEntry( $rt ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->replace( 'redirect', array( 'rd_from' ),
- array(
- 'rd_from' => $this->getId(),
- 'rd_namespace' => $rt->getNamespace(),
- 'rd_title' => $rt->getDBkey(),
- 'rd_fragment' => $rt->getFragment(),
- 'rd_interwiki' => $rt->getInterwiki(),
- ),
- __METHOD__
- );
- }
-
- /**
- * Get the Title object or URL this page redirects to
- *
- * @return mixed false, Title of in-wiki target, or string with URL
- */
- public function followRedirect() {
- return $this->getRedirectURL( $this->getRedirectTarget() );
- }
-
- /**
- * Get the Title object or URL to use for a redirect. We use Title
- * objects for same-wiki, non-special redirects and URLs for everything
- * else.
- * @param $rt Title Redirect target
- * @return mixed false, Title object of local target, or string with URL
- */
- public function getRedirectURL( $rt ) {
- if ( $rt ) {
- if ( $rt->getInterwiki() != '' ) {
- if ( $rt->isLocal() ) {
- // Offsite wikis need an HTTP redirect.
- //
- // This can be hard to reverse and may produce loops,
- // so they may be disabled in the site configuration.
- $source = $this->mTitle->getFullURL( 'redirect=no' );
- return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
- }
- } else {
- if ( $rt->isSpecialPage() ) {
- // Gotta handle redirects to special pages differently:
- // Fill the HTTP response "Location" header and ignore
- // the rest of the page we're on.
- //
- // This can be hard to reverse, so they may be disabled.
- if ( $rt->isSpecial( 'Userlogout' ) ) {
- // rolleyes
- } else {
- return $rt->getFullURL();
- }
- }
-
- return $rt;
- }
- }
-
- // No or invalid redirect
- return false;
- }
-
/**
* Get the title object of the article
* @return Title object of this page
public function clear() {
$this->mDataLoaded = false;
+ $this->mCounter = null;
$this->mRedirectTarget = null; # Title object if set
$this->mLastRevision = null; # Latest revision
- $this->mTimestamp = '';
$this->mTouched = '19700101000000';
+ $this->mTimestamp = '';
$this->mIsRedirect = false;
$this->mLatest = false;
$this->mPreparedEdit = false;
}
- /**
- * Get the text that needs to be saved in order to undo all revisions
- * between $undo and $undoafter. Revisions must belong to the same page,
- * must exist and must not be deleted
- * @param $undo Revision
- * @param $undoafter Revision Must be an earlier revision than $undo
- * @return mixed string on success, false on failure
- */
- public function getUndoText( Revision $undo, Revision $undoafter = null ) {
- $cur_text = $this->getRawText();
- if ( $cur_text === false ) {
- return false; // no page
- }
- $undo_text = $undo->getText();
- $undoafter_text = $undoafter->getText();
-
- if ( $cur_text == $undo_text ) {
- # No use doing a merge if it's just a straight revert.
- return $undoafter_text;
- }
-
- $undone_text = '';
-
- if ( !wfMerge( $undo_text, $undoafter_text, $cur_text, $undone_text ) ) {
- return false;
- }
-
- return $undone_text;
- }
-
/**
* Return the list of revision fields that should be selected to create
* a new page.
# Old-fashioned restrictions
$this->mTitle->loadRestrictions( $data->page_restrictions );
+ $this->mCounter = intval( $data->page_counter );
$this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
$this->mIsRedirect = intval( $data->page_is_redirect );
$this->mLatest = intval( $data->page_latest );
}
/**
- * Get the number of views of this page
- *
* @return int The view count for the page
*/
public function getCount() {
- return $this->mTitle->getCount();
- }
-
- /**
- * Determine whether a page would be suitable for being counted as an
- * article in the site_stats table based on the title & its content
- *
- * @param $editInfo Object or false: object returned by prepareTextForEdit(),
- * if false, the current database state will be used
- * @return Boolean
- */
- public function isCountable( $editInfo = false ) {
- global $wgArticleCountMethod;
-
- if ( !$this->mTitle->isContentPage() ) {
- return false;
- }
-
- $text = $editInfo ? $editInfo->pst : false;
-
- if ( $this->isRedirect( $text ) ) {
- return false;
+ if ( !$this->mDataLoaded ) {
+ $this->loadPageData();
}
- switch ( $wgArticleCountMethod ) {
- case 'any':
- return true;
- case 'comma':
- if ( $text === false ) {
- $text = $this->getRawText();
- }
- return strpos( $text, ',' ) !== false;
- case 'link':
- if ( $editInfo ) {
- // ParserOutput::getLinks() is a 2D array of page links, so
- // to be really correct we would need to recurse in the array
- // but the main array should only have items in it if there are
- // links.
- return (bool)count( $editInfo->output->getLinks() );
- } else {
- return (bool)wfGetDB( DB_SLAVE )->selectField( 'pagelinks', 1,
- array( 'pl_from' => $this->getId() ), __METHOD__ );
- }
- }
+ return $this->mCounter;
}
/**
* Revision::FOR_PUBLIC to be displayed to all users
* Revision::FOR_THIS_USER to be displayed to $wgUser
* Revision::RAW get the text regardless of permissions
- * @return String|false The text of the current revision
+ * @return String|bool The text of the current revision. False on failure
*/
public function getText( $audience = Revision::FOR_PUBLIC ) {
$this->loadLastEdit();
/**
* Get the text of the current revision. No side-effects...
*
- * @return String|false The text of the current revision
+ * @return String|bool The text of the current revision. False on failure
*/
public function getRawText() {
$this->loadLastEdit();
if ( !$this->mTimestamp ) {
$this->loadLastEdit();
}
+
return wfTimestamp( TS_MW, $this->mTimestamp );
}
$wgMemc->set( $key, wfTimestamp( TS_MW, $timestamp ), 60*15 );
}
+ /**
+ * Determine whether a page would be suitable for being counted as an
+ * article in the site_stats table based on the title & its content
+ *
+ * @param $editInfo Object or false: object returned by prepareTextForEdit(),
+ * if false, the current database state will be used
+ * @return Boolean
+ */
+ public function isCountable( $editInfo = false ) {
+ global $wgArticleCountMethod;
+
+ if ( !$this->mTitle->isContentPage() ) {
+ return false;
+ }
+
+ $text = $editInfo ? $editInfo->pst : false;
+
+ if ( $this->isRedirect( $text ) ) {
+ return false;
+ }
+
+ switch ( $wgArticleCountMethod ) {
+ case 'any':
+ return true;
+ case 'comma':
+ if ( $text === false ) {
+ $text = $this->getRawText();
+ }
+ return strpos( $text, ',' ) !== false;
+ case 'link':
+ if ( $editInfo ) {
+ // ParserOutput::getLinks() is a 2D array of page links, so
+ // to be really correct we would need to recurse in the array
+ // but the main array should only have items in it if there are
+ // links.
+ return (bool)count( $editInfo->output->getLinks() );
+ } else {
+ return (bool)wfGetDB( DB_SLAVE )->selectField( 'pagelinks', 1,
+ array( 'pl_from' => $this->getId() ), __METHOD__ );
+ }
+ }
+ }
+
+ /**
+ * If this page is a redirect, get its target
+ *
+ * The target will be fetched from the redirect table if possible.
+ * If this page doesn't have an entry there, call insertRedirect()
+ * @return Title|mixed object, or null if this page is not a redirect
+ */
+ public function getRedirectTarget() {
+ if ( !$this->mTitle->isRedirect() ) {
+ return null;
+ }
+
+ if ( $this->mRedirectTarget !== null ) {
+ return $this->mRedirectTarget;
+ }
+
+ # Query the redirect table
+ $dbr = wfGetDB( DB_SLAVE );
+ $row = $dbr->selectRow( 'redirect',
+ array( 'rd_namespace', 'rd_title', 'rd_fragment', 'rd_interwiki' ),
+ array( 'rd_from' => $this->getId() ),
+ __METHOD__
+ );
+
+ // rd_fragment and rd_interwiki were added later, populate them if empty
+ if ( $row && !is_null( $row->rd_fragment ) && !is_null( $row->rd_interwiki ) ) {
+ return $this->mRedirectTarget = Title::makeTitle(
+ $row->rd_namespace, $row->rd_title,
+ $row->rd_fragment, $row->rd_interwiki );
+ }
+
+ # This page doesn't have an entry in the redirect table
+ return $this->mRedirectTarget = $this->insertRedirect();
+ }
+
+ /**
+ * Insert an entry for this page into the redirect table.
+ *
+ * Don't call this function directly unless you know what you're doing.
+ * @return Title object or null if not a redirect
+ */
+ public function insertRedirect() {
+ // recurse through to only get the final target
+ $retval = Title::newFromRedirectRecurse( $this->getRawText() );
+ if ( !$retval ) {
+ return null;
+ }
+ $this->insertRedirectEntry( $retval );
+ return $retval;
+ }
+
+ /**
+ * Insert or update the redirect table entry for this page to indicate
+ * it redirects to $rt .
+ * @param $rt Title redirect target
+ */
+ public function insertRedirectEntry( $rt ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->replace( 'redirect', array( 'rd_from' ),
+ array(
+ 'rd_from' => $this->getId(),
+ 'rd_namespace' => $rt->getNamespace(),
+ 'rd_title' => $rt->getDBkey(),
+ 'rd_fragment' => $rt->getFragment(),
+ 'rd_interwiki' => $rt->getInterwiki(),
+ ),
+ __METHOD__
+ );
+ }
+
+ /**
+ * Get the Title object or URL this page redirects to
+ *
+ * @return mixed false, Title of in-wiki target, or string with URL
+ */
+ public function followRedirect() {
+ return $this->getRedirectURL( $this->getRedirectTarget() );
+ }
+
+ /**
+ * Get the Title object or URL to use for a redirect. We use Title
+ * objects for same-wiki, non-special redirects and URLs for everything
+ * else.
+ * @param $rt Title Redirect target
+ * @return mixed false, Title object of local target, or string with URL
+ */
+ public function getRedirectURL( $rt ) {
+ if ( !$rt ) {
+ return false;
+ }
+
+ if ( $rt->isExternal() ) {
+ if ( $rt->isLocal() ) {
+ // Offsite wikis need an HTTP redirect.
+ //
+ // This can be hard to reverse and may produce loops,
+ // so they may be disabled in the site configuration.
+ $source = $this->mTitle->getFullURL( 'redirect=no' );
+ return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
+ } else {
+ // External pages pages without "local" bit set are not valid
+ // redirect targets
+ return false;
+ }
+ }
+
+ if ( $rt->isSpecialPage() ) {
+ // Gotta handle redirects to special pages differently:
+ // Fill the HTTP response "Location" header and ignore
+ // the rest of the page we're on.
+ //
+ // Some pages are not valid targets
+ if ( $rt->isValidRedirectTarget() ) {
+ return $rt->getFullURL();
+ } else {
+ return false;
+ }
+ }
+
+ return $rt;
+ }
+
/**
* Get a list of users who have edited this article, not including the user who made
* the most recent revision, which you can get from $article->getUser() if you want it
/**
* Perform the actions of a page purging
+ * @return bool
*/
public function doPurge() {
global $wgUseSquid;
if ( $wgUseSquid ) {
// Commit the transaction before the purge is sent
$dbw = wfGetDB( DB_MASTER );
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
// Send purge
$update = SquidUpdate::newSimplePurge( $this->mTitle );
* @param $dbw DatabaseBase
* @param $redirectTitle Title object pointing to the redirect target,
* or NULL if this is not a redirect
- * @param $lastRevIsRedirect If given, will optimize adding and
+ * @param $lastRevIsRedirect null|bool If given, will optimize adding and
* removing rows in redirect table.
* @return bool true on success, false on failure
* @private
// Delete if changing from redirect to non-redirect
$isRedirect = !is_null( $redirectTitle );
- if ( !$isRedirect && !is_null( $lastRevIsRedirect ) && $lastRevIsRedirect === $isRedirect ) {
+ if ( !$isRedirect && $lastRevIsRedirect === false ) {
return true;
}
* If the given revision is newer than the currently set page_latest,
* update the page record. Otherwise, do nothing.
*
- * @param $dbw Database object
+ * @param $dbw DatabaseBase object
* @param $revision Revision object
* @return mixed
*/
}
/**
- * @param $section empty/null/false or a section number (0, 1, 2, T1, T2...)
+ * Get the text that needs to be saved in order to undo all revisions
+ * between $undo and $undoafter. Revisions must belong to the same page,
+ * must exist and must not be deleted
+ * @param $undo Revision
+ * @param $undoafter Revision Must be an earlier revision than $undo
+ * @return mixed string on success, false on failure
+ */
+ public function getUndoText( Revision $undo, Revision $undoafter = null ) {
+ $cur_text = $this->getRawText();
+ if ( $cur_text === false ) {
+ return false; // no page
+ }
+ $undo_text = $undo->getText();
+ $undoafter_text = $undoafter->getText();
+
+ if ( $cur_text == $undo_text ) {
+ # No use doing a merge if it's just a straight revert.
+ return $undoafter_text;
+ }
+
+ $undone_text = '';
+
+ if ( !wfMerge( $undo_text, $undoafter_text, $cur_text, $undone_text ) ) {
+ return false;
+ }
+
+ return $undone_text;
+ }
+
+ /**
+ * @param $section null|bool|int or a section number (0, 1, 2, T1, T2...)
* @param $text String: new text of the section
* @param $sectionTitle String: new section's subject, only if $section is 'new'
* @param $edittime String: revision timestamp or null to use the current revision
$oldtext = $this->getRawText();
if ( $oldtext === false ) {
wfDebug( __METHOD__ . ": no page text\n" );
+ wfProfileOut( __METHOD__ );
return null;
}
} else {
* edit-already-exists error will be returned. These two conditions are also possible with
* auto-detection due to MediaWiki's performance-optimised locking strategy.
*
- * @param $baseRevId the revision ID this edit was based off, if any
+ * @param $baseRevId int the revision ID this edit was based off, if any
* @param $user User the user doing the edit
*
* @return Status object. Possible errors:
# Update article, but only if changed.
$status->value['new'] = false;
+ if ( !$oldid ) {
+ # Article gone missing
+ wfDebug( __METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n" );
+ $status->fatal( 'edit-gone-missing' );
+
+ wfProfileOut( __METHOD__ );
+ return $status;
+ }
+
# Make sure the revision is either completely inserted or not inserted at all
if ( !$wgDBtransactions ) {
$userAbort = ignore_user_abort( true );
$changed = ( strcmp( $text, $oldtext ) != 0 );
if ( $changed ) {
- if ( !$this->mLatest ) {
- # Article gone missing
- wfDebug( __METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n" );
- $status->fatal( 'edit-gone-missing' );
-
- wfProfileOut( __METHOD__ );
- return $status;
- }
-
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
$revisionId = $revision->insertOn( $dbw );
# Update page
}
$revisionId = 0;
- $dbw->rollback();
+ $dbw->rollback( __METHOD__ );
} else {
global $wgUseRCPatrol;
wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId, $user ) );
# Log auto-patrolled edits
if ( $patrolled ) {
- PatrolLog::record( $rc, true );
+ PatrolLog::record( $rc, true, $user );
}
}
$user->incEditCount();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
}
+ } else {
+ // Bug 32948: revision ID must be set to page {{REVISIONID}} and
+ // related variables correctly
+ $revision->setId( $this->getLatest() );
}
if ( !$wgDBtransactions ) {
if ( !$changed ) {
$status->warning( 'edit-no-change' );
$revision = null;
- // Keep the same revision ID, but do some updates on it
- $revisionId = $this->getLatest();
// Update page_touched, this is usually implicit in the page update
// Other cache updates are done in onArticleEdit()
$this->mTitle->invalidateCache();
# Create new article
$status->value['new'] = true;
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
# Add the page record; stake our claim on this title!
# This will return false if the article already exists
$newid = $this->insertOn( $dbw );
if ( $newid === false ) {
- $dbw->rollback();
+ $dbw->rollback( __METHOD__ );
$status->fatal( 'edit-already-exists' );
wfProfileOut( __METHOD__ );
# Log auto-patrolled edits
if ( $patrolled ) {
- PatrolLog::record( $rc, true );
+ PatrolLog::record( $rc, true, $user );
}
}
$user->incEditCount();
- $dbw->commit();
+ $dbw->commit( __METHOD__ );
# Update links, etc.
$this->doEditUpdates( $revision, $user, array( 'created' => true ) );
/**
* Prepare text which is about to be saved.
* Returns a stdclass with source, pst and output members
+ * @return bool|object
*/
public function prepareTextForEdit( $text, $revid = null, User $user = null ) {
global $wgParser, $wgContLang, $wgUser;
}
/**
- * Back-end article deletion
+ * Same as doDeleteArticleReal(), but returns more detailed success/failure status
* Deletes the article with database consistency, writes logs, purges caches
*
* @param $reason string delete reason for deletion log
- * @param $suppress bitfield
+ * @param $suppress int bitfield
* Revision::DELETED_TEXT
* Revision::DELETED_COMMENT
* Revision::DELETED_USER
* Revision::DELETED_RESTRICTED
* @param $id int article ID
* @param $commit boolean defaults to true, triggers transaction end
- * @param &$errors Array of errors to append to
- * @param $user User The relevant user
+ * @param &$error Array of errors to append to
+ * @param $user User The deleting user
* @return boolean true if successful
*/
public function doDeleteArticle(
$reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
+ ) {
+ return $this->doDeleteArticleReal( $reason, $suppress, $id, $commit, $error, $user )
+ == WikiPage::DELETE_SUCCESS;
+ }
+
+ /**
+ * Back-end article deletion
+ * Deletes the article with database consistency, writes logs, purges caches
+ *
+ * @param $reason string delete reason for deletion log
+ * @param $suppress int bitfield
+ * Revision::DELETED_TEXT
+ * Revision::DELETED_COMMENT
+ * Revision::DELETED_USER
+ * Revision::DELETED_RESTRICTED
+ * @param $id int article ID
+ * @param $commit boolean defaults to true, triggers transaction end
+ * @param &$error Array of errors to append to
+ * @param $user User The deleting user
+ * @return int: One of WikiPage::DELETE_* constants
+ */
+ public function doDeleteArticleReal(
+ $reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null
) {
global $wgUser;
$user = is_null( $user ) ? $wgUser : $user;
wfDebug( __METHOD__ . "\n" );
if ( ! wfRunHooks( 'ArticleDelete', array( &$this, &$user, &$reason, &$error ) ) ) {
- return false;
+ return WikiPage::DELETE_HOOK_ABORTED;
}
$dbw = wfGetDB( DB_MASTER );
$t = $this->mTitle->getDBkey();
$id = $id ? $id : $this->mTitle->getArticleID( Title::GAID_FOR_UPDATE );
if ( $t === '' || $id == 0 ) {
- return false;
+ return WikiPage::DELETE_NO_PAGE;
}
- DeferredUpdates::addUpdate(
- new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 )
- );
-
// Bitfields to further suppress the content
if ( $suppress ) {
$bitfield = 0;
$bitfield = 'rev_deleted';
}
- $dbw->begin();
+ $dbw->begin( __METHOD__ );
// 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
), __METHOD__
);
- # Delete restrictions for it
- $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
-
# Now that it's safely backed up, delete it
$dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__ );
- $ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy
+ $ok = ( $dbw->affectedRows() > 0 ); // getArticleID() uses slave, could be laggy
if ( !$ok ) {
- $dbw->rollback();
- return false;
+ $dbw->rollback( __METHOD__ );
+ return WikiPage::DELETE_NO_REVISIONS;
}
+ $this->doDeleteUpdates( $id );
+
+ # Log the deletion, if the page was suppressed, log it at Oversight instead
+ $logtype = $suppress ? 'suppress' : 'delete';
+
+ $logEntry = new ManualLogEntry( $logtype, 'delete' );
+ $logEntry->setPerformer( $user );
+ $logEntry->setTarget( $this->mTitle );
+ $logEntry->setComment( $reason );
+ $logid = $logEntry->insert();
+ $logEntry->publish( $logid );
+
+ if ( $commit ) {
+ $dbw->commit( __METHOD__ );
+ }
+
+ wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id ) );
+ return WikiPage::DELETE_SUCCESS;
+ }
+
+ /**
+ * Do some database updates after deletion
+ *
+ * @param $id Int: page_id value of the page being deleted
+ */
+ public function doDeleteUpdates( $id ) {
+ DeferredUpdates::addUpdate( new SiteStatsUpdate( 0, 1, - (int)$this->isCountable(), -1 ) );
+
+ $dbw = wfGetDB( DB_MASTER );
+
+ # Delete restrictions for it
+ $dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
+
# Fix category table counts
$cats = array();
$res = $dbw->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ );
# Clear caches
self::onArticleDelete( $this->mTitle );
+ # Reset this object
+ $this->clear();
+
# Clear the cached article id so the interface doesn't act like we exist
$this->mTitle->resetArticleID( 0 );
-
- # Log the deletion, if the page was suppressed, log it at Oversight instead
- $logtype = $suppress ? 'suppress' : 'delete';
-
- $logEntry = new ManualLogEntry( $logtype, 'delete' );
- $logEntry->setPerformer( $user );
- $logEntry->setTarget( $this->mTitle );
- $logEntry->setComment( $reason );
- $logid = $logEntry->insert();
- $logEntry->publish( $logid );
-
- if ( $commit ) {
- $dbw->commit();
- }
-
- wfRunHooks( 'ArticleDeleteComplete', array( &$this, &$user, $reason, $id ) );
- return true;
}
/**
*
* @param $resultDetails Array: contains result-specific array of additional values
* @param $guser User The user performing the rollback
+ * @return array
*/
public function commitRollback( $fromP, $summary, $bot, &$resultDetails, User $guser ) {
global $wgUseRCPatrol, $wgContLang;
}
# Get the last editor
- $current = Revision::newFromTitle( $this->mTitle );
+ $current = $this->getRevision();
if ( is_null( $current ) ) {
# Something wrong... no page?
return array( array( 'notanarticle' ) );
}
# Actually store the edit
- $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId() );
+ $status = $this->doEdit( $target->getText(), $summary, $flags, $target->getId(), $guser );
if ( !empty( $status->value['revision'] ) ) {
$revId = $status->value['revision']->getId();
} else {
/**#@-*/
- /**
- * Return a list of templates used by this article.
- * Uses the templatelinks table
- *
- * @return Array of Title objects
- */
- public function getUsedTemplates() {
- $result = array();
- $id = $this->mTitle->getArticleID();
-
- if ( $id == 0 ) {
- return array();
- }
-
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( array( 'templatelinks' ),
- array( 'tl_namespace', 'tl_title' ),
- array( 'tl_from' => $id ),
- __METHOD__ );
-
- if ( $res !== false ) {
- foreach ( $res as $row ) {
- $result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title );
- }
- }
-
- return $result;
- }
-
/**
* Returns a list of hidden categories this page is a member of.
* Uses the page_props and categorylinks tables.
public function getAutoDeleteReason( &$hasHistory ) {
global $wgContLang;
- $dbw = wfGetDB( DB_MASTER );
// Get the last revision
- $rev = Revision::newFromTitle( $this->getTitle() );
+ $rev = $this->getRevision();
if ( is_null( $rev ) ) {
return false;
}
}
+ $dbw = wfGetDB( DB_MASTER );
+
// Find out if there was only one contributor
// Only scan the last 20 revisions
$res = $dbw->select( 'revision', 'rev_user_text',
}
}
+ /**
+ * Return a list of templates used by this article.
+ * Uses the templatelinks table
+ *
+ * @deprecated in 1.19; use Title::getTemplateLinksFrom()
+ * @return Array of Title objects
+ */
+ public function getUsedTemplates() {
+ return $this->mTitle->getTemplateLinksFrom();
+ }
+
/**
* Perform article updates on a special page creation.
*
/**
* @deprecated since 1.18
+ * @return bool
*/
public function useParserCache( $oldid ) {
wfDeprecated( __METHOD__, '1.18' );
private $text;
/**
- * @var ParserOutput|false
+ * @var ParserOutput|bool
*/
private $parserOutput = false;
private $isDirty = false;
/**
- * @var Status|false
+ * @var Status|bool
*/
private $error = false;
/**
* Get a Status object in case of error or false otherwise
*
- * @return Status|false
+ * @return Status|bool
*/
public function getError() {
return $this->error;
$text = $rev->getText();
}
- $time = - wfTime();
+ $time = - microtime( true );
$this->parserOutput = $wgParser->parse( $text, $this->page->getTitle(),
$this->parserOptions, true, true, $this->revid );
- $time += wfTime();
+ $time += microtime( true );
# Timing hack
if ( $time > 3 ) {
/**
* @param $status Status
+ * @return bool
*/
function error( $status ) {
$this->error = $status;