2004-02-18 02:15:00 +00:00
|
|
|
<?php
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* File for articles
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @file
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2003-08-02 20:43:11 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2005-04-12 02:18:57 +00:00
|
|
|
* Class representing a MediaWiki article and history.
|
2004-09-02 23:28:24 +00:00
|
|
|
*
|
2005-04-12 02:07:16 +00:00
|
|
|
* See design.txt for an overview.
|
2004-09-02 23:28:24 +00:00
|
|
|
* Note: edit user interface and cache support functions have been
|
2006-10-11 08:25:26 +00:00
|
|
|
* moved to separate EditPage and HTMLFileCache classes.
|
2004-09-03 00:20:26 +00:00
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2003-04-14 23:10:40 +00:00
|
|
|
class Article {
|
2007-03-28 14:16:43 +00:00
|
|
|
/**@{{
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
|
|
|
|
*/
|
2008-07-25 20:16:24 +00:00
|
|
|
var $mComment = ''; //!<
|
|
|
|
|
var $mContent; //!<
|
|
|
|
|
var $mContentLoaded = false; //!<
|
|
|
|
|
var $mCounter = -1; //!< Not loaded
|
|
|
|
|
var $mCurID = -1; //!< Not loaded
|
|
|
|
|
var $mDataLoaded = false; //!<
|
|
|
|
|
var $mForUpdate = false; //!<
|
|
|
|
|
var $mGoodAdjustment = 0; //!<
|
|
|
|
|
var $mIsRedirect = false; //!<
|
|
|
|
|
var $mLatest = false; //!<
|
|
|
|
|
var $mMinorEdit; //!<
|
|
|
|
|
var $mOldId; //!<
|
|
|
|
|
var $mPreparedEdit = false; //!< Title object if set
|
|
|
|
|
var $mRedirectedFrom = null; //!< Title object if set
|
|
|
|
|
var $mRedirectTarget = null; //!< Title object if set
|
|
|
|
|
var $mRedirectUrl = false; //!<
|
|
|
|
|
var $mRevIdFetched = 0; //!<
|
|
|
|
|
var $mRevision; //!<
|
|
|
|
|
var $mTimestamp = ''; //!<
|
|
|
|
|
var $mTitle; //!<
|
|
|
|
|
var $mTotalAdjustment = 0; //!<
|
|
|
|
|
var $mTouched = '19700101000000'; //!<
|
|
|
|
|
var $mUser = -1; //!< Not loaded
|
|
|
|
|
var $mUserText = ''; //!<
|
2007-03-28 14:16:43 +00:00
|
|
|
/**@}}*/
|
2004-09-02 23:28:24 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor and clear the article
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $title Reference to a Title object.
|
|
|
|
|
* @param $oldId Integer revision ID, null to fetch from request, zero for current
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2008-02-06 20:06:47 +00:00
|
|
|
function __construct( Title $title, $oldId = null ) {
|
2003-09-01 08:30:14 +00:00
|
|
|
$this->mTitle =& $title;
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->mOldId = $oldId;
|
2003-09-01 08:30:14 +00:00
|
|
|
}
|
2008-08-16 13:34:43 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor from an article article
|
|
|
|
|
* @param $id The article ID to load
|
|
|
|
|
*/
|
|
|
|
|
public static function newFromID( $id ) {
|
|
|
|
|
$t = Title::newFromID( $id );
|
|
|
|
|
|
|
|
|
|
return $t == null ? null : new Article( $t );
|
|
|
|
|
}
|
2006-11-20 05:41:53 +00:00
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
/**
|
|
|
|
|
* Tell the page view functions that this view was redirected
|
|
|
|
|
* from another page on the wiki.
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $from Title object.
|
2006-01-13 00:29:20 +00:00
|
|
|
*/
|
|
|
|
|
function setRedirectedFrom( $from ) {
|
|
|
|
|
$this->mRedirectedFrom = $from;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2008-04-11 15:20:45 +00:00
|
|
|
/**
|
|
|
|
|
* 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 mixed Title object, or null if this page is not a redirect
|
|
|
|
|
*/
|
|
|
|
|
public function getRedirectTarget() {
|
|
|
|
|
if(!$this->mTitle || !$this->mTitle->isRedirect())
|
|
|
|
|
return null;
|
|
|
|
|
if(!is_null($this->mRedirectTarget))
|
|
|
|
|
return $this->mRedirectTarget;
|
|
|
|
|
|
|
|
|
|
# Query the redirect table
|
2008-04-15 17:32:23 +00:00
|
|
|
$dbr = wfGetDB(DB_SLAVE);
|
2008-04-11 15:20:45 +00:00
|
|
|
$res = $dbr->select('redirect',
|
|
|
|
|
array('rd_namespace', 'rd_title'),
|
|
|
|
|
array('rd_from' => $this->getID()),
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
$row = $dbr->fetchObject($res);
|
|
|
|
|
if($row)
|
|
|
|
|
return $this->mRedirectTarget = Title::makeTitle($row->rd_namespace, $row->rd_title);
|
|
|
|
|
|
|
|
|
|
# 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
|
|
|
|
|
*/
|
|
|
|
|
public function insertRedirect() {
|
|
|
|
|
$retval = Title::newFromRedirect($this->getContent());
|
|
|
|
|
if(!$retval)
|
|
|
|
|
return null;
|
2008-04-15 17:32:23 +00:00
|
|
|
$dbw = wfGetDB(DB_MASTER);
|
2008-04-15 18:32:48 +00:00
|
|
|
$dbw->replace('redirect', array('rd_from'), array(
|
2008-04-11 15:20:45 +00:00
|
|
|
'rd_from' => $this->getID(),
|
|
|
|
|
'rd_namespace' => $retval->getNamespace(),
|
2008-07-31 02:44:56 +00:00
|
|
|
'rd_title' => $retval->getDBKey()
|
2008-04-15 18:32:48 +00:00
|
|
|
), __METHOD__);
|
2008-04-11 15:20:45 +00:00
|
|
|
return $retval;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
/**
|
2008-04-15 17:32:23 +00:00
|
|
|
* Get the Title object this page redirects to
|
|
|
|
|
*
|
2006-01-13 00:29:20 +00:00
|
|
|
* @return mixed false, Title of in-wiki target, or string with URL
|
|
|
|
|
*/
|
2008-07-04 09:38:12 +00:00
|
|
|
public function followRedirect() {
|
2008-04-15 18:11:28 +00:00
|
|
|
$text = $this->getContent();
|
2008-07-04 09:38:12 +00:00
|
|
|
return self::followRedirectText( $text );
|
|
|
|
|
}
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-07-04 09:38:12 +00:00
|
|
|
/**
|
|
|
|
|
* Get the Title object this text redirects to
|
|
|
|
|
*
|
|
|
|
|
* @return mixed false, Title of in-wiki target, or string with URL
|
|
|
|
|
*/
|
|
|
|
|
public function followRedirectText( $text ) {
|
2008-04-15 18:11:28 +00:00
|
|
|
$rt = Title::newFromRedirect( $text );
|
2006-01-13 00:29:20 +00:00
|
|
|
# process if title object is valid and not special:userlogout
|
|
|
|
|
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.
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
$source = $this->mTitle->getFullURL( 'redirect=no' );
|
|
|
|
|
return $rt->getFullURL( 'rdfrom=' . urlencode( $source ) );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if( $rt->getNamespace() == NS_SPECIAL ) {
|
2006-11-23 08:25:56 +00:00
|
|
|
// Gotta handle redirects to special pages differently:
|
2006-01-13 00:29:20 +00:00
|
|
|
// 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.
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
if( $rt->isSpecial( 'Userlogout' ) ) {
|
2006-01-13 00:29:20 +00:00
|
|
|
// rolleyes
|
|
|
|
|
} else {
|
|
|
|
|
return $rt->getFullURL();
|
|
|
|
|
}
|
2006-03-11 17:13:49 +00:00
|
|
|
}
|
2006-01-14 21:19:17 +00:00
|
|
|
return $rt;
|
2006-01-13 00:29:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// No or invalid redirect
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-12-29 01:07:43 +00:00
|
|
|
/**
|
|
|
|
|
* get the title object of the article
|
|
|
|
|
*/
|
|
|
|
|
function getTitle() {
|
2005-07-01 00:03:31 +00:00
|
|
|
return $this->mTitle;
|
2004-12-29 01:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Clear the object
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
|
|
|
|
function clear() {
|
2005-03-18 08:37:50 +00:00
|
|
|
$this->mDataLoaded = false;
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->mContentLoaded = false;
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-01-17 05:49:39 +00:00
|
|
|
$this->mCurID = $this->mUser = $this->mCounter = -1; # Not loaded
|
2006-01-13 00:29:20 +00:00
|
|
|
$this->mRedirectedFrom = null; # Title object if set
|
2008-04-11 15:20:45 +00:00
|
|
|
$this->mRedirectTarget = null; # Title object if set
|
2006-01-13 00:29:20 +00:00
|
|
|
$this->mUserText =
|
2006-06-20 09:50:57 +00:00
|
|
|
$this->mTimestamp = $this->mComment = '';
|
2005-06-19 00:21:49 +00:00
|
|
|
$this->mGoodAdjustment = $this->mTotalAdjustment = 0;
|
2004-06-08 19:51:10 +00:00
|
|
|
$this->mTouched = '19700101000000';
|
2004-08-20 14:59:49 +00:00
|
|
|
$this->mForUpdate = false;
|
2005-03-18 08:37:50 +00:00
|
|
|
$this->mIsRedirect = false;
|
2005-03-29 16:38:30 +00:00
|
|
|
$this->mRevIdFetched = 0;
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->mRedirectUrl = false;
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->mLatest = false;
|
2007-11-12 07:30:40 +00:00
|
|
|
$this->mPreparedEdit = false;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-01-13 00:29:20 +00:00
|
|
|
* Note that getContent/loadContent do not follow redirects anymore.
|
|
|
|
|
* If you need to fetch redirectable content easily, try
|
|
|
|
|
* the shortcut in Article::followContent()
|
2006-04-19 15:46:24 +00:00
|
|
|
* FIXME
|
|
|
|
|
* @todo There are still side-effects in this!
|
2006-01-13 00:29:20 +00:00
|
|
|
* In general, you should use the Revision class, not Article,
|
|
|
|
|
* to fetch text for purposes other than page views.
|
2004-09-02 23:28:24 +00:00
|
|
|
*
|
2004-09-03 00:20:26 +00:00
|
|
|
* @return Return the text of this revision
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2006-01-13 00:29:20 +00:00
|
|
|
function getContent() {
|
2008-03-04 17:36:44 +00:00
|
|
|
global $wgUser, $wgOut, $wgMessageCache;
|
2004-03-29 14:48:07 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2007-06-27 15:30:43 +00:00
|
|
|
if ( 0 == $this->getID() ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-12-28 14:47:30 +00:00
|
|
|
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
2008-03-04 17:36:44 +00:00
|
|
|
$wgMessageCache->loadAllMessages();
|
2005-12-28 14:47:30 +00:00
|
|
|
$ret = wfMsgWeirdKey ( $this->mTitle->getText() ) ;
|
|
|
|
|
} else {
|
|
|
|
|
$ret = wfMsg( $wgUser->isLoggedIn() ? 'noarticletext' : 'noarticletextanon' );
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2008-04-04 21:51:32 +00:00
|
|
|
return "<div class='noarticletext'>\n$ret\n</div>";
|
2005-07-03 04:00:33 +00:00
|
|
|
} else {
|
2006-01-13 00:29:20 +00:00
|
|
|
$this->loadContent();
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-04-11 08:27:35 +00:00
|
|
|
return $this->mContent;
|
2004-05-13 12:20:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* This function returns the text of a section, specified by a number ($section).
|
2006-04-19 15:46:24 +00:00
|
|
|
* A section is text under a heading like == Heading == or \<h1\>Heading\</h1\>, or
|
2004-09-02 23:28:24 +00:00
|
|
|
* the first section before any such heading (section 0).
|
|
|
|
|
*
|
|
|
|
|
* If a section contains subsections, these are also returned.
|
2004-09-03 00:20:26 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $text String: text to look in
|
|
|
|
|
* @param $section Integer: section number
|
2004-09-03 00:20:26 +00:00
|
|
|
* @return string text of the requested section
|
2006-07-05 22:45:41 +00:00
|
|
|
* @deprecated
|
2004-09-03 00:20:26 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function getSection($text,$section) {
|
2006-06-06 00:51:34 +00:00
|
|
|
global $wgParser;
|
|
|
|
|
return $wgParser->getSection( $text, $section );
|
2004-05-13 17:25:34 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return int The oldid of the article that is to be shown, 0 for the
|
|
|
|
|
* current revision
|
2004-11-13 08:40:34 +00:00
|
|
|
*/
|
|
|
|
|
function getOldID() {
|
2005-12-30 09:33:11 +00:00
|
|
|
if ( is_null( $this->mOldId ) ) {
|
|
|
|
|
$this->mOldId = $this->getOldIDFromRequest();
|
2004-11-13 08:40:34 +00:00
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
return $this->mOldId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets $this->mRedirectUrl to a correct URL if the query parameters are incorrect
|
2006-01-07 12:10:04 +00:00
|
|
|
*
|
|
|
|
|
* @return int The old id for the request
|
2005-12-30 09:33:11 +00:00
|
|
|
*/
|
|
|
|
|
function getOldIDFromRequest() {
|
|
|
|
|
global $wgRequest;
|
|
|
|
|
$this->mRedirectUrl = false;
|
2004-11-13 08:40:34 +00:00
|
|
|
$oldid = $wgRequest->getVal( 'oldid' );
|
2004-07-08 14:53:54 +00:00
|
|
|
if ( isset( $oldid ) ) {
|
2005-08-16 23:36:16 +00:00
|
|
|
$oldid = intval( $oldid );
|
2004-10-02 21:36:36 +00:00
|
|
|
if ( $wgRequest->getVal( 'direction' ) == 'next' ) {
|
|
|
|
|
$nextid = $this->mTitle->getNextRevisionID( $oldid );
|
2004-12-19 08:00:50 +00:00
|
|
|
if ( $nextid ) {
|
2004-10-02 21:36:36 +00:00
|
|
|
$oldid = $nextid;
|
|
|
|
|
} else {
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->mRedirectUrl = $this->mTitle->getFullURL( 'redirect=no' );
|
2004-10-02 21:36:36 +00:00
|
|
|
}
|
|
|
|
|
} elseif ( $wgRequest->getVal( 'direction' ) == 'prev' ) {
|
|
|
|
|
$previd = $this->mTitle->getPreviousRevisionID( $oldid );
|
|
|
|
|
if ( $previd ) {
|
|
|
|
|
$oldid = $previd;
|
|
|
|
|
} else {
|
|
|
|
|
# TODO
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-04-30 16:23:01 +00:00
|
|
|
# unused:
|
|
|
|
|
# $lastid = $oldid;
|
2004-10-02 21:36:36 +00:00
|
|
|
}
|
2006-07-05 22:45:41 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
if ( !$oldid ) {
|
|
|
|
|
$oldid = 0;
|
|
|
|
|
}
|
|
|
|
|
return $oldid;
|
2004-11-13 08:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2005-12-30 09:33:11 +00:00
|
|
|
* Load the revision (including text) into this object
|
2004-12-19 08:00:50 +00:00
|
|
|
*/
|
2006-01-13 00:29:20 +00:00
|
|
|
function loadContent() {
|
2004-11-13 08:40:34 +00:00
|
|
|
if ( $this->mContentLoaded ) return;
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-11-13 08:40:34 +00:00
|
|
|
# Query variables :P
|
|
|
|
|
$oldid = $this->getOldID();
|
|
|
|
|
|
|
|
|
|
# Pre-fill content with error message so that if something
|
|
|
|
|
# fails we'll have something telling us what we intended.
|
2004-12-19 08:00:50 +00:00
|
|
|
$this->mOldId = $oldid;
|
2006-01-13 00:29:20 +00:00
|
|
|
$this->fetchContent( $oldid );
|
2004-12-19 08:00:50 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
|
|
|
|
|
2005-03-14 10:06:28 +00:00
|
|
|
/**
|
|
|
|
|
* Fetch a page record with the given conditions
|
|
|
|
|
* @param Database $dbr
|
|
|
|
|
* @param array $conditions
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2005-03-14 10:06:28 +00:00
|
|
|
*/
|
2007-01-22 23:50:42 +00:00
|
|
|
function pageData( $dbr, $conditions ) {
|
2005-12-07 10:37:48 +00:00
|
|
|
$fields = array(
|
2005-03-14 10:06:28 +00:00
|
|
|
'page_id',
|
|
|
|
|
'page_namespace',
|
|
|
|
|
'page_title',
|
2007-01-12 01:44:33 +00:00
|
|
|
'page_restrictions',
|
2005-03-14 10:06:28 +00:00
|
|
|
'page_counter',
|
|
|
|
|
'page_is_redirect',
|
|
|
|
|
'page_is_new',
|
|
|
|
|
'page_random',
|
|
|
|
|
'page_touched',
|
|
|
|
|
'page_latest',
|
2007-08-15 22:43:59 +00:00
|
|
|
'page_len',
|
|
|
|
|
);
|
|
|
|
|
wfRunHooks( 'ArticlePageDataBefore', array( &$this, &$fields ) );
|
|
|
|
|
$row = $dbr->selectRow(
|
|
|
|
|
'page',
|
2005-12-07 10:37:48 +00:00
|
|
|
$fields,
|
2005-03-14 10:06:28 +00:00
|
|
|
$conditions,
|
2007-08-15 22:43:59 +00:00
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
wfRunHooks( 'ArticlePageDataAfter', array( &$this, &$row ) );
|
2005-12-07 10:37:48 +00:00
|
|
|
return $row ;
|
2005-03-14 10:06:28 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-01-07 12:10:04 +00:00
|
|
|
/**
|
|
|
|
|
* @param Database $dbr
|
|
|
|
|
* @param Title $title
|
|
|
|
|
*/
|
2007-01-22 23:50:42 +00:00
|
|
|
function pageDataFromTitle( $dbr, $title ) {
|
2005-03-14 10:06:28 +00:00
|
|
|
return $this->pageData( $dbr, array(
|
|
|
|
|
'page_namespace' => $title->getNamespace(),
|
|
|
|
|
'page_title' => $title->getDBkey() ) );
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-01-07 12:10:04 +00:00
|
|
|
/**
|
|
|
|
|
* @param Database $dbr
|
|
|
|
|
* @param int $id
|
|
|
|
|
*/
|
2007-01-22 23:50:42 +00:00
|
|
|
function pageDataFromId( $dbr, $id ) {
|
2006-01-07 12:10:04 +00:00
|
|
|
return $this->pageData( $dbr, array( 'page_id' => $id ) );
|
2005-03-14 10:06:28 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-18 08:37:50 +00:00
|
|
|
/**
|
|
|
|
|
* Set the general counter, title etc data loaded from
|
|
|
|
|
* some source.
|
|
|
|
|
*
|
|
|
|
|
* @param object $data
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2005-03-18 08:37:50 +00:00
|
|
|
*/
|
2006-03-16 02:32:30 +00:00
|
|
|
function loadPageData( $data = 'fromdb' ) {
|
|
|
|
|
if ( $data === 'fromdb' ) {
|
2008-06-16 14:18:41 +00:00
|
|
|
$dbr = wfGetDB( DB_MASTER );
|
2006-03-16 02:32:30 +00:00
|
|
|
$data = $this->pageDataFromId( $dbr, $this->getId() );
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2008-04-09 18:23:34 +00:00
|
|
|
$lc = LinkCache::singleton();
|
2006-03-16 02:32:30 +00:00
|
|
|
if ( $data ) {
|
2008-04-09 05:21:00 +00:00
|
|
|
$lc->addGoodLinkObj( $data->page_id, $this->mTitle, $data->page_len, $data->page_is_redirect );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->mTitle->mArticleID = $data->page_id;
|
|
|
|
|
|
2007-01-12 01:44:33 +00:00
|
|
|
# Old-fashioned restrictions.
|
|
|
|
|
$this->mTitle->loadRestrictions( $data->page_restrictions );
|
|
|
|
|
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->mCounter = $data->page_counter;
|
|
|
|
|
$this->mTouched = wfTimestamp( TS_MW, $data->page_touched );
|
|
|
|
|
$this->mIsRedirect = $data->page_is_redirect;
|
|
|
|
|
$this->mLatest = $data->page_latest;
|
|
|
|
|
} else {
|
2006-04-02 03:56:51 +00:00
|
|
|
if ( is_object( $this->mTitle ) ) {
|
|
|
|
|
$lc->addBadLinkObj( $this->mTitle );
|
|
|
|
|
}
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->mTitle->mArticleID = 0;
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
$this->mDataLoaded = true;
|
2005-03-18 08:37:50 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-12-19 08:00:50 +00:00
|
|
|
/**
|
2005-01-11 01:28:18 +00:00
|
|
|
* Get text of an article from database
|
2006-01-13 00:29:20 +00:00
|
|
|
* Does *NOT* follow redirects.
|
2004-12-19 08:00:50 +00:00
|
|
|
* @param int $oldid 0 for whatever the latest revision is
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2006-01-13 00:29:20 +00:00
|
|
|
function fetchContent( $oldid = 0 ) {
|
2004-12-19 08:00:50 +00:00
|
|
|
if ( $this->mContentLoaded ) {
|
|
|
|
|
return $this->mContent;
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2008-06-16 14:18:41 +00:00
|
|
|
$dbr = wfGetDB( DB_MASTER );
|
2004-12-19 08:00:50 +00:00
|
|
|
|
|
|
|
|
# Pre-fill content with error message so that if something
|
|
|
|
|
# fails we'll have something telling us what we intended.
|
|
|
|
|
$t = $this->mTitle->getPrefixedText();
|
2008-06-05 17:33:31 +00:00
|
|
|
$d = $oldid ? wfMsgExt( 'missingarticle-rev', array( 'escape' ), $oldid ) : '';
|
|
|
|
|
$this->mContent = wfMsg( 'missing-article', $t, $d ) ;
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2005-03-14 10:06:28 +00:00
|
|
|
if( $oldid ) {
|
|
|
|
|
$revision = Revision::newFromId( $oldid );
|
|
|
|
|
if( is_null( $revision ) ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__." failed to retrieve specified revision, id $oldid\n" );
|
2004-12-19 08:00:50 +00:00
|
|
|
return false;
|
2003-11-02 13:57:24 +00:00
|
|
|
}
|
2005-03-14 10:06:28 +00:00
|
|
|
$data = $this->pageDataFromId( $dbr, $revision->getPage() );
|
|
|
|
|
if( !$data ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__." failed to get page data linked to revision id $oldid\n" );
|
2005-03-14 10:06:28 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$this->mTitle = Title::makeTitle( $data->page_namespace, $data->page_title );
|
2005-03-18 08:37:50 +00:00
|
|
|
$this->loadPageData( $data );
|
2004-12-19 08:00:50 +00:00
|
|
|
} else {
|
2005-03-18 08:37:50 +00:00
|
|
|
if( !$this->mDataLoaded ) {
|
|
|
|
|
$data = $this->pageDataFromTitle( $dbr, $this->mTitle );
|
|
|
|
|
if( !$data ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__." failed to find page data for title " . $this->mTitle->getPrefixedText() . "\n" );
|
2005-03-18 08:37:50 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$this->loadPageData( $data );
|
2005-03-18 05:38:49 +00:00
|
|
|
}
|
2005-03-18 08:37:50 +00:00
|
|
|
$revision = Revision::newFromId( $this->mLatest );
|
2005-03-18 05:38:49 +00:00
|
|
|
if( is_null( $revision ) ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__." failed to retrieve current page, rev_id {$data->page_latest}\n" );
|
2005-03-18 05:38:49 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2004-12-19 08:00:50 +00:00
|
|
|
}
|
2004-08-07 03:50:46 +00:00
|
|
|
|
2006-03-16 19:04:25 +00:00
|
|
|
// FIXME: Horrible, horrible! This content-loading interface just plain sucks.
|
|
|
|
|
// We should instead work with the Revision object when we need it...
|
2008-03-09 02:18:50 +00:00
|
|
|
$this->mContent = $revision->revText(); // Loads if user is allowed
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-14 10:06:28 +00:00
|
|
|
$this->mUser = $revision->getUser();
|
|
|
|
|
$this->mUserText = $revision->getUserText();
|
|
|
|
|
$this->mComment = $revision->getComment();
|
|
|
|
|
$this->mTimestamp = wfTimestamp( TS_MW, $revision->getTimestamp() );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-05-22 15:02:33 +00:00
|
|
|
$this->mRevIdFetched = $revision->getId();
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->mContentLoaded = true;
|
2005-06-29 05:15:32 +00:00
|
|
|
$this->mRevision =& $revision;
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-12-21 12:02:18 +00:00
|
|
|
wfRunHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) ) ;
|
|
|
|
|
|
2004-03-23 10:11:24 +00:00
|
|
|
return $this->mContent;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Read/write accessor to select FOR UPDATE
|
2006-01-07 12:10:04 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $x Mixed: FIXME
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-20 14:59:49 +00:00
|
|
|
function forUpdate( $x = NULL ) {
|
|
|
|
|
return wfSetVar( $this->mForUpdate, $x );
|
|
|
|
|
}
|
2004-09-01 02:57:26 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Get the database which should be used for reads
|
2006-01-07 12:10:04 +00:00
|
|
|
*
|
|
|
|
|
* @return Database
|
2008-06-16 14:18:41 +00:00
|
|
|
* @deprecated - just call wfGetDB( DB_MASTER ) instead
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2007-01-22 23:50:42 +00:00
|
|
|
function getDB() {
|
2008-06-16 19:49:58 +00:00
|
|
|
wfDeprecated( __METHOD__ );
|
2007-01-12 10:03:51 +00:00
|
|
|
return wfGetDB( DB_MASTER );
|
2004-08-20 14:59:49 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Get options for all SELECT statements
|
2006-01-07 12:10:04 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $options Array: an optional options array which'll be appended to
|
2006-01-07 12:10:04 +00:00
|
|
|
* the default
|
2006-04-19 15:46:24 +00:00
|
|
|
* @return Array: options
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-20 14:59:49 +00:00
|
|
|
function getSelectOptions( $options = '' ) {
|
|
|
|
|
if ( $this->mForUpdate ) {
|
2005-01-11 00:06:00 +00:00
|
|
|
if ( is_array( $options ) ) {
|
2004-08-20 14:59:49 +00:00
|
|
|
$options[] = 'FOR UPDATE';
|
|
|
|
|
} else {
|
|
|
|
|
$options = 'FOR UPDATE';
|
|
|
|
|
}
|
2004-09-01 02:57:26 +00:00
|
|
|
}
|
2004-08-20 14:59:49 +00:00
|
|
|
return $options;
|
|
|
|
|
}
|
2004-09-01 02:57:26 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return int Page ID
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2003-11-24 10:24:04 +00:00
|
|
|
function getID() {
|
|
|
|
|
if( $this->mTitle ) {
|
|
|
|
|
return $this->mTitle->getArticleID();
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-07-01 20:36:04 +00:00
|
|
|
|
2005-06-29 23:44:03 +00:00
|
|
|
/**
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return bool Whether or not the page exists in the database
|
2005-06-29 23:44:03 +00:00
|
|
|
*/
|
|
|
|
|
function exists() {
|
|
|
|
|
return $this->getId() != 0;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-09-11 11:39:24 +00:00
|
|
|
/**
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return int The view count for the page
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function getCount() {
|
2003-04-14 23:10:40 +00:00
|
|
|
if ( -1 == $this->mCounter ) {
|
|
|
|
|
$id = $this->getID();
|
2006-03-16 02:32:30 +00:00
|
|
|
if ( $id == 0 ) {
|
|
|
|
|
$this->mCounter = 0;
|
|
|
|
|
} else {
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->mCounter = $dbr->selectField( 'page', 'page_counter', array( 'page_id' => $id ),
|
|
|
|
|
'Article::getCount', $this->getSelectOptions() );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
return $this->mCounter;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-01-07 12:10:04 +00:00
|
|
|
* Determine whether a page would be suitable for being counted as an
|
|
|
|
|
* article in the site_stats table based on the title & its content
|
|
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $text String: text to analyze
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return bool
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function isCountable( $text ) {
|
2007-01-08 16:31:52 +00:00
|
|
|
global $wgUseCommaCount;
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-01-07 12:10:04 +00:00
|
|
|
$token = $wgUseCommaCount ? ',' : '[[';
|
|
|
|
|
return
|
2007-01-08 16:31:52 +00:00
|
|
|
$this->mTitle->isContentPage()
|
|
|
|
|
&& !$this->isRedirect( $text )
|
2006-01-07 12:10:04 +00:00
|
|
|
&& in_string( $token, $text );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-01 00:03:31 +00:00
|
|
|
/**
|
2004-09-11 11:39:24 +00:00
|
|
|
* Tests if the article text represents a redirect
|
2006-01-07 12:10:04 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @param $text String: FIXME
|
2006-01-07 12:10:04 +00:00
|
|
|
* @return bool
|
2004-09-11 11:39:24 +00:00
|
|
|
*/
|
|
|
|
|
function isRedirect( $text = false ) {
|
|
|
|
|
if ( $text === false ) {
|
2008-08-08 00:01:53 +00:00
|
|
|
if ( $this->mDataLoaded )
|
2008-05-09 10:42:49 +00:00
|
|
|
return $this->mIsRedirect;
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-09 10:42:49 +00:00
|
|
|
// Apparently loadPageData was never called
|
2004-09-11 11:39:24 +00:00
|
|
|
$this->loadContent();
|
2005-06-29 00:31:07 +00:00
|
|
|
$titleObj = Title::newFromRedirect( $this->fetchContent() );
|
2004-09-11 11:39:24 +00:00
|
|
|
} else {
|
|
|
|
|
$titleObj = Title::newFromRedirect( $text );
|
|
|
|
|
}
|
|
|
|
|
return $titleObj !== NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-29 23:44:03 +00:00
|
|
|
/**
|
|
|
|
|
* Returns true if the currently-referenced revision is the current edit
|
|
|
|
|
* to this page (and it exists).
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
function isCurrent() {
|
2007-05-07 07:57:29 +00:00
|
|
|
# If no oldid, this is the current version.
|
|
|
|
|
if ($this->getOldID() == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
2005-06-29 23:44:03 +00:00
|
|
|
return $this->exists() &&
|
|
|
|
|
isset( $this->mRevision ) &&
|
|
|
|
|
$this->mRevision->isCurrent();
|
|
|
|
|
}
|
2005-07-01 20:36:04 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2004-12-19 08:00:50 +00:00
|
|
|
* Loads everything except the text
|
2004-09-02 23:28:24 +00:00
|
|
|
* This isn't necessary for all uses, so it's only done if needed.
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
|
|
|
|
function loadLastEdit() {
|
2004-12-19 08:00:50 +00:00
|
|
|
if ( -1 != $this->mUser )
|
|
|
|
|
return;
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2005-02-06 07:28:21 +00:00
|
|
|
# New or non-existent articles have no user information
|
|
|
|
|
$id = $this->getID();
|
|
|
|
|
if ( 0 == $id ) return;
|
|
|
|
|
|
2008-06-16 14:18:41 +00:00
|
|
|
$this->mLastRevision = Revision::loadFromPageId( wfGetDB( DB_MASTER ), $id );
|
2005-03-18 04:32:55 +00:00
|
|
|
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();
|
2008-05-22 15:02:33 +00:00
|
|
|
$this->mRevIdFetched = $this->mLastRevision->getId();
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
function getTimestamp() {
|
2006-03-16 02:32:30 +00:00
|
|
|
// Check if the field has been filled by ParserCache::get()
|
|
|
|
|
if ( !$this->mTimestamp ) {
|
|
|
|
|
$this->loadLastEdit();
|
|
|
|
|
}
|
2005-08-02 13:35:19 +00:00
|
|
|
return wfTimestamp(TS_MW, $this->mTimestamp);
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
function getUser() {
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->loadLastEdit();
|
|
|
|
|
return $this->mUser;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
function getUserText() {
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->loadLastEdit();
|
|
|
|
|
return $this->mUserText;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
function getComment() {
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->loadLastEdit();
|
|
|
|
|
return $this->mComment;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
function getMinorEdit() {
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->loadLastEdit();
|
|
|
|
|
return $this->mMinorEdit;
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-26 18:24:32 +00:00
|
|
|
function getRevIdFetched() {
|
|
|
|
|
$this->loadLastEdit();
|
|
|
|
|
return $this->mRevIdFetched;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-04-19 15:46:24 +00:00
|
|
|
/**
|
|
|
|
|
* @param $limit Integer: default 0.
|
|
|
|
|
* @param $offset Integer: default 0.
|
|
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function getContributors($limit = 0, $offset = 0) {
|
|
|
|
|
# XXX: this is expensive; cache this info somewhere.
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
$contribs = array();
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2004-12-19 08:00:50 +00:00
|
|
|
$revTable = $dbr->tableName( 'revision' );
|
2004-07-10 03:09:26 +00:00
|
|
|
$userTable = $dbr->tableName( 'user' );
|
|
|
|
|
$user = $this->getUser();
|
2005-01-04 23:49:16 +00:00
|
|
|
$pageId = $this->getId();
|
2004-07-10 03:09:26 +00:00
|
|
|
|
2008-08-18 19:21:55 +00:00
|
|
|
$sql = "SELECT {$userTable}.*, MAX(rev_timestamp) as timestamp
|
2004-12-19 08:00:50 +00:00
|
|
|
FROM $revTable LEFT JOIN $userTable ON rev_user = user_id
|
|
|
|
|
WHERE rev_page = $pageId
|
2005-01-05 22:26:32 +00:00
|
|
|
AND rev_user != $user
|
2004-12-19 08:00:50 +00:00
|
|
|
GROUP BY rev_user, rev_user_text, user_real_name
|
2004-07-10 03:09:26 +00:00
|
|
|
ORDER BY timestamp DESC";
|
2004-04-29 01:58:20 +00:00
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
if ($limit > 0) { $sql .= ' LIMIT '.$limit; }
|
2008-07-07 01:11:50 +00:00
|
|
|
if ($offset > 0) { $sql .= ' OFFSET '.$offset; }
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2004-08-20 14:59:49 +00:00
|
|
|
$sql .= ' '. $this->getSelectOptions();
|
2004-04-29 01:58:20 +00:00
|
|
|
|
2008-08-18 19:21:55 +00:00
|
|
|
$res = $dbr->query($sql, __METHOD__ );
|
2004-09-01 02:57:26 +00:00
|
|
|
|
2008-08-18 19:21:55 +00:00
|
|
|
return new UserArrayFromResult( $res );
|
2004-04-23 21:01:29 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* This is the default action of the script: just view the page of
|
|
|
|
|
* the given title.
|
|
|
|
|
*/
|
2008-04-23 16:08:16 +00:00
|
|
|
function view() {
|
2006-05-31 20:39:14 +00:00
|
|
|
global $wgUser, $wgOut, $wgRequest, $wgContLang;
|
2007-10-29 20:38:58 +00:00
|
|
|
global $wgEnableParserCache, $wgStylePath, $wgParser;
|
2007-05-31 23:09:36 +00:00
|
|
|
global $wgUseTrackbacks, $wgNamespaceRobotPolicies, $wgArticleRobotPolicies;
|
2008-02-06 00:55:52 +00:00
|
|
|
global $wgDefaultRobotPolicy;
|
2006-11-08 07:12:03 +00:00
|
|
|
$sk = $wgUser->getSkin();
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2006-06-04 00:25:53 +00:00
|
|
|
|
2008-04-09 18:23:34 +00:00
|
|
|
$parserCache = ParserCache::singleton();
|
2006-06-04 00:25:53 +00:00
|
|
|
$ns = $this->mTitle->getNamespace(); # shortcut
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-08-09 05:38:11 +00:00
|
|
|
# Get variables from query string
|
2004-11-13 08:40:34 +00:00
|
|
|
$oldid = $this->getOldID();
|
2005-12-30 09:33:11 +00:00
|
|
|
|
|
|
|
|
# getOldID may want us to redirect somewhere else
|
|
|
|
|
if ( $this->mRedirectUrl ) {
|
|
|
|
|
$wgOut->redirect( $this->mRedirectUrl );
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2005-12-30 09:33:11 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-03-29 14:48:07 +00:00
|
|
|
$diff = $wgRequest->getVal( 'diff' );
|
2004-08-09 05:38:11 +00:00
|
|
|
$rcid = $wgRequest->getVal( 'rcid' );
|
2005-03-09 02:02:04 +00:00
|
|
|
$rdfrom = $wgRequest->getVal( 'rdfrom' );
|
2007-01-12 03:36:46 +00:00
|
|
|
$diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
|
2007-09-07 23:07:07 +00:00
|
|
|
$purge = $wgRequest->getVal( 'action' ) == 'purge';
|
2004-03-29 14:48:07 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
$wgOut->setArticleFlag( true );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-01-14 21:28:23 +00:00
|
|
|
# Discourage indexing of printable versions, but encourage following
|
|
|
|
|
if( $wgOut->isPrintable() ) {
|
|
|
|
|
$policy = 'noindex,follow';
|
2007-05-31 23:09:36 +00:00
|
|
|
} elseif ( isset( $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()] ) ) {
|
|
|
|
|
$policy = $wgArticleRobotPolicies[$this->mTitle->getPrefixedText()];
|
2007-01-14 21:28:23 +00:00
|
|
|
} elseif( isset( $wgNamespaceRobotPolicies[$ns] ) ) {
|
|
|
|
|
# Honour customised robot policies for this namespace
|
2006-06-04 00:25:53 +00:00
|
|
|
$policy = $wgNamespaceRobotPolicies[$ns];
|
|
|
|
|
} else {
|
2008-02-06 00:55:52 +00:00
|
|
|
$policy = $wgDefaultRobotPolicy;
|
2006-06-04 00:25:53 +00:00
|
|
|
}
|
2007-01-14 21:28:23 +00:00
|
|
|
$wgOut->setRobotPolicy( $policy );
|
2006-06-04 00:25:53 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
# If we got diff and oldid in the query, we want to see a
|
|
|
|
|
# diff page instead of the article.
|
|
|
|
|
|
2004-05-13 14:17:44 +00:00
|
|
|
if ( !is_null( $diff ) ) {
|
2003-09-01 08:30:14 +00:00
|
|
|
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2007-09-07 23:07:07 +00:00
|
|
|
$de = new DifferenceEngine( $this->mTitle, $oldid, $diff, $rcid, $purge );
|
2005-03-29 16:38:30 +00:00
|
|
|
// DifferenceEngine directly fetched the revision:
|
|
|
|
|
$this->mRevIdFetched = $de->mNewid;
|
2007-01-12 03:36:46 +00:00
|
|
|
$de->showDiffPage( $diffOnly );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-09-10 21:46:54 +00:00
|
|
|
// Needed to get the page's current revision
|
|
|
|
|
$this->loadPageData();
|
|
|
|
|
if( $diff == 0 || $diff == $this->mLatest ) {
|
2004-08-03 04:52:19 +00:00
|
|
|
# Run view updates for current revision only
|
|
|
|
|
$this->viewUpdates();
|
|
|
|
|
}
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-04-14 23:10:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-07-22 00:05:52 +00:00
|
|
|
if ( empty( $oldid ) && $this->checkTouched() ) {
|
2006-01-05 04:26:52 +00:00
|
|
|
$wgOut->setETag($parserCache->getETag($this, $wgUser));
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2003-12-11 20:16:34 +00:00
|
|
|
if( $wgOut->checkLastModified( $this->mTouched ) ){
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-12-11 20:16:34 +00:00
|
|
|
return;
|
|
|
|
|
} else if ( $this->tryFileCache() ) {
|
|
|
|
|
# tell wgOut that output is taken care of
|
|
|
|
|
$wgOut->disable();
|
2003-12-13 21:32:32 +00:00
|
|
|
$this->viewUpdates();
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-12-11 20:16:34 +00:00
|
|
|
return;
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
2006-07-05 22:45:41 +00:00
|
|
|
|
2004-06-04 10:40:44 +00:00
|
|
|
# Should the parser cache be used?
|
2008-07-03 19:05:06 +00:00
|
|
|
$pcache = $this->useParserCache( $oldid );
|
2005-06-29 23:44:03 +00:00
|
|
|
wfDebug( 'Article::view using parser cache: ' . ($pcache ? 'yes' : 'no' ) . "\n" );
|
2005-12-26 13:01:18 +00:00
|
|
|
if ( $wgUser->getOption( 'stubthreshold' ) ) {
|
|
|
|
|
wfIncrStats( 'pcache_miss_stub' );
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
$wasRedirected = false;
|
|
|
|
|
if ( isset( $this->mRedirectedFrom ) ) {
|
|
|
|
|
// This is an internally redirected page view.
|
|
|
|
|
// We'll need a backlink to the source page for navigation.
|
|
|
|
|
if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
|
2006-11-08 07:12:03 +00:00
|
|
|
$redir = $sk->makeKnownLinkObj( $this->mRedirectedFrom, '', 'redirect=no' );
|
2006-01-13 00:29:20 +00:00
|
|
|
$s = wfMsg( 'redirectedfrom', $redir );
|
|
|
|
|
$wgOut->setSubtitle( $s );
|
2006-12-08 06:09:15 +00:00
|
|
|
|
|
|
|
|
// Set the fragment if one was specified in the redirect
|
|
|
|
|
if ( strval( $this->mTitle->getFragment() ) != '' ) {
|
|
|
|
|
$fragment = Xml::escapeJsString( $this->mTitle->getFragmentForURL() );
|
|
|
|
|
$wgOut->addInlineScript( "redirectToFragment(\"$fragment\");" );
|
|
|
|
|
}
|
2006-01-13 00:29:20 +00:00
|
|
|
$wasRedirected = true;
|
|
|
|
|
}
|
|
|
|
|
} elseif ( !empty( $rdfrom ) ) {
|
|
|
|
|
// This is an externally redirected view, from some other wiki.
|
|
|
|
|
// If it was reported from a trusted site, supply a backlink.
|
|
|
|
|
global $wgRedirectSources;
|
|
|
|
|
if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
|
2006-11-08 07:12:03 +00:00
|
|
|
$redir = $sk->makeExternalLink( $rdfrom, $rdfrom );
|
2006-01-13 00:29:20 +00:00
|
|
|
$s = wfMsg( 'redirectedfrom', $redir );
|
|
|
|
|
$wgOut->setSubtitle( $s );
|
|
|
|
|
$wasRedirected = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-06-04 10:40:44 +00:00
|
|
|
$outputDone = false;
|
2007-06-03 22:31:09 +00:00
|
|
|
wfRunHooks( 'ArticleViewHeader', array( &$this, &$outputDone, &$pcache ) );
|
2004-06-04 10:40:44 +00:00
|
|
|
if ( $pcache ) {
|
|
|
|
|
if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
|
2007-05-03 06:08:12 +00:00
|
|
|
// Ensure that UI elements requiring revision ID have
|
|
|
|
|
// the correct version information.
|
|
|
|
|
$wgOut->setRevisionId( $this->mLatest );
|
2004-06-04 10:40:44 +00:00
|
|
|
$outputDone = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-07-03 19:05:06 +00:00
|
|
|
# Fetch content and check for errors
|
2004-06-04 10:40:44 +00:00
|
|
|
if ( !$outputDone ) {
|
2006-01-13 00:29:20 +00:00
|
|
|
$text = $this->getContent();
|
2005-12-30 09:33:11 +00:00
|
|
|
if ( $text === false ) {
|
|
|
|
|
# Failed to load, replace text with error message
|
|
|
|
|
$t = $this->mTitle->getPrefixedText();
|
|
|
|
|
if( $oldid ) {
|
2008-06-05 17:33:31 +00:00
|
|
|
$d = wfMsgExt( 'missingarticle-rev', array( 'escape' ), $oldid );
|
|
|
|
|
$text = wfMsg( 'missing-article', $t, $d );
|
2006-01-19 17:10:57 +00:00
|
|
|
} else {
|
2008-04-22 06:10:01 +00:00
|
|
|
$text = wfMsg( 'noarticletext' );
|
2005-12-30 09:33:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
# Another whitelist check in case oldid is altering the title
|
2004-06-04 10:40:44 +00:00
|
|
|
if ( !$this->mTitle->userCanRead() ) {
|
|
|
|
|
$wgOut->loginToUse();
|
|
|
|
|
$wgOut->output();
|
2008-04-28 17:05:25 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2004-06-04 10:40:44 +00:00
|
|
|
exit;
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-06-04 10:40:44 +00:00
|
|
|
# We're looking at an old revision
|
|
|
|
|
if ( !empty( $oldid ) ) {
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2006-03-18 22:23:50 +00:00
|
|
|
if( is_null( $this->mRevision ) ) {
|
|
|
|
|
// FIXME: This would be a nice place to load the 'no such page' text.
|
|
|
|
|
} else {
|
|
|
|
|
$this->setOldSubtitle( isset($this->mOldId) ? $this->mOldId : $oldid );
|
2006-06-23 06:31:46 +00:00
|
|
|
if( $this->mRevision->isDeleted( Revision::DELETED_TEXT ) ) {
|
|
|
|
|
if( !$this->mRevision->userCan( Revision::DELETED_TEXT ) ) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'rev-deleted-text-permission' );
|
2006-03-18 22:23:50 +00:00
|
|
|
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
|
2008-04-28 17:02:20 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-03-18 22:23:50 +00:00
|
|
|
return;
|
|
|
|
|
} else {
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'rev-deleted-text-view' );
|
2006-03-18 22:23:50 +00:00
|
|
|
// and we are allowed to see...
|
|
|
|
|
}
|
2006-03-16 19:04:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2004-06-04 10:40:44 +00:00
|
|
|
}
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2006-01-01 22:07:14 +00:00
|
|
|
$wgOut->setRevisionId( $this->getRevIdFetched() );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-06-29 04:31:19 +00:00
|
|
|
// Pages containing custom CSS or JavaScript get special treatment
|
|
|
|
|
if( $this->mTitle->isCssOrJsPage() || $this->mTitle->isCssJsSubpage() ) {
|
|
|
|
|
$wgOut->addHtml( wfMsgExt( 'clearyourcache', 'parse' ) );
|
2007-07-02 23:22:39 +00:00
|
|
|
// Give hooks a chance to customise the output
|
|
|
|
|
if( wfRunHooks( 'ShowRawCssJs', array( $this->mContent, $this->mTitle, $wgOut ) ) ) {
|
|
|
|
|
// Wrap the whole lot in a <pre> and don't parse
|
2007-08-21 03:57:54 +00:00
|
|
|
$m = array();
|
2007-07-02 23:22:39 +00:00
|
|
|
preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
|
|
|
|
|
$wgOut->addHtml( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
|
|
|
|
|
$wgOut->addHtml( htmlspecialchars( $this->mContent ) );
|
|
|
|
|
$wgOut->addHtml( "\n</pre>\n" );
|
|
|
|
|
}
|
2008-07-03 19:05:06 +00:00
|
|
|
} else if ( $rt = Title::newFromRedirect( $text ) ) {
|
2008-07-02 10:33:42 +00:00
|
|
|
# Don't append the subtitle if this was an old revision
|
2008-08-02 02:39:09 +00:00
|
|
|
$wgOut->addHTML( $this->viewRedirect( $rt, !$wasRedirected && $this->isCurrent() ) );
|
2005-03-14 07:42:38 +00:00
|
|
|
$parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
|
2006-01-01 21:44:43 +00:00
|
|
|
$wgOut->addParserOutputNoText( $parseout );
|
2004-06-04 10:40:44 +00:00
|
|
|
} else if ( $pcache ) {
|
2004-08-07 03:50:46 +00:00
|
|
|
# Display content and save to parser cache
|
2007-01-10 23:32:38 +00:00
|
|
|
$this->outputWikiText( $text );
|
2004-06-04 10:40:44 +00:00
|
|
|
} else {
|
2004-08-07 03:50:46 +00:00
|
|
|
# Display content, don't attempt to save to parser cache
|
2005-06-29 23:44:03 +00:00
|
|
|
# Don't show section-edit links on old revisions... this way lies madness.
|
|
|
|
|
if( !$this->isCurrent() ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
$oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false );
|
2005-06-29 23:44:03 +00:00
|
|
|
}
|
2006-01-14 23:56:01 +00:00
|
|
|
# Display content and don't save to parser cache
|
2007-01-17 00:54:54 +00:00
|
|
|
# With timing hack -- TS 2006-07-26
|
|
|
|
|
$time = -wfTime();
|
2007-01-10 23:32:38 +00:00
|
|
|
$this->outputWikiText( $text, false );
|
2007-01-17 00:54:54 +00:00
|
|
|
$time += wfTime();
|
|
|
|
|
|
|
|
|
|
# Timing hack
|
|
|
|
|
if ( $time > 3 ) {
|
2007-01-17 22:32:40 +00:00
|
|
|
wfDebugLog( 'slow-parse', sprintf( "%-5.2f %s", $time,
|
2007-01-17 00:54:54 +00:00
|
|
|
$this->mTitle->getPrefixedDBkey()));
|
|
|
|
|
}
|
2005-07-01 20:36:04 +00:00
|
|
|
|
2005-06-29 23:44:03 +00:00
|
|
|
if( !$this->isCurrent() ) {
|
2006-07-26 07:15:39 +00:00
|
|
|
$wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
|
2005-06-29 23:44:03 +00:00
|
|
|
}
|
2004-06-04 10:40:44 +00:00
|
|
|
}
|
2004-02-27 02:24:14 +00:00
|
|
|
}
|
2005-04-07 23:04:08 +00:00
|
|
|
/* title may have been set from the cache */
|
2005-07-01 00:03:31 +00:00
|
|
|
$t = $wgOut->getPageTitle();
|
2005-04-07 23:04:08 +00:00
|
|
|
if( empty( $t ) ) {
|
|
|
|
|
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
|
2008-08-06 19:20:38 +00:00
|
|
|
|
|
|
|
|
# For the main page, overwrite the <title> element with the con-
|
|
|
|
|
# tents of 'pagetitle-view-mainpage' instead of the default (if
|
|
|
|
|
# that's not empty).
|
|
|
|
|
if( $this->mTitle->equals( Title::newMainPage() ) &&
|
|
|
|
|
wfMsgForContent( 'pagetitle-view-mainpage' ) !== '' ) {
|
|
|
|
|
$wgOut->setHTMLTitle( wfMsgForContent( 'pagetitle-view-mainpage' ) );
|
|
|
|
|
}
|
2005-04-07 23:04:08 +00:00
|
|
|
}
|
2006-06-13 11:37:09 +00:00
|
|
|
|
2006-04-11 08:27:35 +00:00
|
|
|
# check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
|
2008-07-03 19:05:06 +00:00
|
|
|
if( $ns == NS_USER_TALK && IP::isValid( $this->mTitle->getText() ) ) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg('anontalkpagetext');
|
2006-04-11 08:27:35 +00:00
|
|
|
}
|
2005-04-07 23:04:08 +00:00
|
|
|
|
2004-08-09 05:38:11 +00:00
|
|
|
# If we have been passed an &rcid= parameter, we want to give the user a
|
|
|
|
|
# chance to mark this new article as patrolled.
|
2007-11-29 06:26:38 +00:00
|
|
|
if( !is_null( $rcid ) && $rcid != 0 && $wgUser->isAllowed( 'patrol' ) && $this->mTitle->exists() ) {
|
2005-05-05 21:37:54 +00:00
|
|
|
$wgOut->addHTML(
|
|
|
|
|
"<div class='patrollink'>" .
|
2007-01-17 22:09:30 +00:00
|
|
|
wfMsgHtml( 'markaspatrolledlink',
|
|
|
|
|
$sk->makeKnownLinkObj( $this->mTitle, wfMsgHtml('markaspatrolledtext'),
|
|
|
|
|
"action=markpatrolled&rcid=$rcid" )
|
2005-05-05 21:37:54 +00:00
|
|
|
) .
|
|
|
|
|
'</div>'
|
|
|
|
|
);
|
2004-08-09 05:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-23 05:47:25 +00:00
|
|
|
# Trackbacks
|
|
|
|
|
if ($wgUseTrackbacks)
|
|
|
|
|
$this->addTrackbacks();
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
$this->viewUpdates();
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2008-08-08 00:01:53 +00:00
|
|
|
|
|
|
|
|
/*
|
2008-07-03 19:05:06 +00:00
|
|
|
* Should the parser cache be used?
|
|
|
|
|
*/
|
|
|
|
|
protected function useParserCache( $oldid ) {
|
|
|
|
|
global $wgUser, $wgEnableParserCache;
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-07-03 19:05:06 +00:00
|
|
|
return $wgEnableParserCache
|
|
|
|
|
&& intval( $wgUser->getOption( 'stubthreshold' ) ) == 0
|
|
|
|
|
&& $this->exists()
|
|
|
|
|
&& empty( $oldid )
|
|
|
|
|
&& !$this->mTitle->isCssOrJsPage()
|
|
|
|
|
&& !$this->mTitle->isCssJsSubpage();
|
|
|
|
|
}
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-08-02 02:39:09 +00:00
|
|
|
/**
|
|
|
|
|
* View redirect
|
|
|
|
|
* @param Title $target Title of destination to redirect
|
|
|
|
|
* @param Bool $appendSubtitle Object[optional]
|
|
|
|
|
* @param Bool $forceKnown Should the image be shown as a bluelink regardless of existence?
|
|
|
|
|
*/
|
|
|
|
|
public function viewRedirect( $target, $appendSubtitle = true, $forceKnown = false ) {
|
2008-05-11 19:49:08 +00:00
|
|
|
global $wgParser, $wgOut, $wgContLang, $wgStylePath, $wgUser;
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-11 19:49:08 +00:00
|
|
|
# Display redirect
|
|
|
|
|
$imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
|
|
|
|
|
$imageUrl = $wgStylePath.'/common/images/redirect' . $imageDir . '.png';
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-07-02 10:33:42 +00:00
|
|
|
if( $appendSubtitle ) {
|
|
|
|
|
$wgOut->appendSubtitle( wfMsgHtml( 'redirectpagesub' ) );
|
2008-05-11 19:49:08 +00:00
|
|
|
}
|
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
|
if ( $forceKnown )
|
|
|
|
|
$link = $sk->makeKnownLinkObj( $target, htmlspecialchars( $target->getFullText() ) );
|
|
|
|
|
else
|
|
|
|
|
$link = $sk->makeLinkObj( $target, htmlspecialchars( $target->getFullText() ) );
|
|
|
|
|
|
2008-08-02 02:39:09 +00:00
|
|
|
return '<img src="'.$imageUrl.'" alt="#REDIRECT " />' .
|
|
|
|
|
'<span class="redirectText">'.$link.'</span>';
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-11 19:49:08 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2005-07-23 05:47:25 +00:00
|
|
|
function addTrackbacks() {
|
2005-07-23 06:30:26 +00:00
|
|
|
global $wgOut, $wgUser;
|
2005-07-23 05:47:25 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB(DB_SLAVE);
|
2005-07-23 05:47:25 +00:00
|
|
|
$tbs = $dbr->select(
|
|
|
|
|
/* FROM */ 'trackbacks',
|
2005-07-23 06:30:26 +00:00
|
|
|
/* SELECT */ array('tb_id', 'tb_title', 'tb_url', 'tb_ex', 'tb_name'),
|
|
|
|
|
/* WHERE */ array('tb_page' => $this->getID())
|
2005-07-23 05:47:25 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!$dbr->numrows($tbs))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
$tbtext = "";
|
|
|
|
|
while ($o = $dbr->fetchObject($tbs)) {
|
2005-08-02 13:35:19 +00:00
|
|
|
$rmvtxt = "";
|
2006-05-10 20:09:30 +00:00
|
|
|
if ($wgUser->isAllowed( 'trackback' )) {
|
2005-07-23 06:30:26 +00:00
|
|
|
$delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid="
|
2007-06-23 10:15:10 +00:00
|
|
|
. $o->tb_id . "&token=" . urlencode( $wgUser->editToken() ) );
|
|
|
|
|
$rmvtxt = wfMsg( 'trackbackremove', htmlspecialchars( $delurl ) );
|
2005-07-23 06:30:26 +00:00
|
|
|
}
|
2008-03-25 21:50:23 +00:00
|
|
|
$tbtext .= "\n";
|
2005-07-23 05:47:25 +00:00
|
|
|
$tbtext .= wfMsg(strlen($o->tb_ex) ? 'trackbackexcerpt' : 'trackback',
|
|
|
|
|
$o->tb_title,
|
|
|
|
|
$o->tb_url,
|
|
|
|
|
$o->tb_ex,
|
2005-07-23 06:30:26 +00:00
|
|
|
$o->tb_name,
|
|
|
|
|
$rmvtxt);
|
2005-07-23 05:47:25 +00:00
|
|
|
}
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'trackbackbox', $tbtext );
|
2005-07-23 05:47:25 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-23 06:30:26 +00:00
|
|
|
function deletetrackback() {
|
|
|
|
|
global $wgUser, $wgRequest, $wgOut, $wgTitle;
|
|
|
|
|
|
|
|
|
|
if (!$wgUser->matchEditToken($wgRequest->getVal('token'))) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'sessionfailure' );
|
2005-07-23 06:30:26 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2007-09-09 08:11:58 +00:00
|
|
|
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser );
|
2005-07-23 06:30:26 +00:00
|
|
|
|
2007-09-09 08:11:58 +00:00
|
|
|
if (count($permission_errors)>0)
|
|
|
|
|
{
|
|
|
|
|
$wgOut->showPermissionsErrorPage( $permission_errors );
|
2005-07-23 06:30:26 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$db = wfGetDB(DB_MASTER);
|
2005-07-23 06:30:26 +00:00
|
|
|
$db->delete('trackbacks', array('tb_id' => $wgRequest->getInt('tbid')));
|
|
|
|
|
$wgTitle->invalidateCache();
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg('trackbackdeleteok');
|
2005-07-23 06:30:26 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-03 04:00:33 +00:00
|
|
|
function render() {
|
|
|
|
|
global $wgOut;
|
|
|
|
|
|
|
|
|
|
$wgOut->setArticleBodyOnly(true);
|
|
|
|
|
$this->view();
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2006-03-01 01:27:36 +00:00
|
|
|
/**
|
|
|
|
|
* Handle action=purge
|
2008-08-18 22:21:13 +00:00
|
|
|
* @param bool $showPage Show the page after purging?
|
2006-03-01 01:27:36 +00:00
|
|
|
*/
|
2008-08-18 22:21:13 +00:00
|
|
|
function purge( $showPage = true ) {
|
2006-03-01 01:27:36 +00:00
|
|
|
global $wgUser, $wgRequest, $wgOut;
|
2005-11-07 04:14:15 +00:00
|
|
|
|
2007-01-13 04:25:25 +00:00
|
|
|
if ( $wgUser->isAllowed( 'purge' ) || $wgRequest->wasPosted() ) {
|
2006-03-01 01:27:36 +00:00
|
|
|
if( wfRunHooks( 'ArticlePurge', array( &$this ) ) ) {
|
|
|
|
|
$this->doPurge();
|
2005-11-07 04:14:15 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$msg = $wgOut->parse( wfMsg( 'confirm_purge' ) );
|
2007-09-07 23:07:07 +00:00
|
|
|
$action = htmlspecialchars( $_SERVER['REQUEST_URI'] );
|
2005-11-07 04:14:15 +00:00
|
|
|
$button = htmlspecialchars( wfMsg( 'confirm_purge_button' ) );
|
2006-01-07 13:09:30 +00:00
|
|
|
$msg = str_replace( '$1',
|
2005-11-07 04:14:15 +00:00
|
|
|
"<form method=\"post\" action=\"$action\">\n" .
|
|
|
|
|
"<input type=\"submit\" name=\"submit\" value=\"$button\" />\n" .
|
|
|
|
|
"</form>\n", $msg );
|
|
|
|
|
|
|
|
|
|
$wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2005-11-07 04:14:15 +00:00
|
|
|
$wgOut->addHTML( $msg );
|
|
|
|
|
}
|
2008-08-18 22:21:13 +00:00
|
|
|
// Show the page post-purge? 99.99% of the time yes, but sometimes no.
|
|
|
|
|
if ( $showPage ) {
|
|
|
|
|
$this->view();
|
|
|
|
|
}
|
2005-11-07 04:14:15 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-01 01:27:36 +00:00
|
|
|
/**
|
|
|
|
|
* Perform the actions of a page purging
|
|
|
|
|
*/
|
|
|
|
|
function doPurge() {
|
|
|
|
|
global $wgUseSquid;
|
|
|
|
|
// Invalidate the cache
|
|
|
|
|
$this->mTitle->invalidateCache();
|
|
|
|
|
|
|
|
|
|
if ( $wgUseSquid ) {
|
|
|
|
|
// Commit the transaction before the purge is sent
|
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
|
|
|
|
$dbw->immediateCommit();
|
|
|
|
|
|
|
|
|
|
// Send purge
|
|
|
|
|
$update = SquidUpdate::newSimplePurge( $this->mTitle );
|
|
|
|
|
$update->doUpdate();
|
|
|
|
|
}
|
2008-02-09 10:01:35 +00:00
|
|
|
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
|
|
|
|
global $wgMessageCache;
|
2008-02-13 05:46:43 +00:00
|
|
|
if ( $this->getID() == 0 ) {
|
|
|
|
|
$text = false;
|
|
|
|
|
} else {
|
|
|
|
|
$text = $this->getContent();
|
|
|
|
|
}
|
2008-02-09 10:01:35 +00:00
|
|
|
$wgMessageCache->replace( $this->mTitle->getDBkey(), $text );
|
|
|
|
|
}
|
2006-03-01 01:27:36 +00:00
|
|
|
}
|
2005-07-03 04:00:33 +00:00
|
|
|
|
2005-03-11 08:38:24 +00:00
|
|
|
/**
|
|
|
|
|
* Insert a new empty page record for this article.
|
|
|
|
|
* This *must* be followed up by creating a revision
|
|
|
|
|
* and running $this->updateToLatest( $rev_id );
|
|
|
|
|
* or else the record will be left in a funky state.
|
|
|
|
|
* Best if all done inside a transaction.
|
|
|
|
|
*
|
|
|
|
|
* @param Database $dbw
|
2005-03-19 10:17:41 +00:00
|
|
|
* @return int The newly created page_id key
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2005-03-11 08:38:24 +00:00
|
|
|
*/
|
2007-01-19 09:50:19 +00:00
|
|
|
function insertOn( $dbw ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-11 08:38:24 +00:00
|
|
|
$page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
|
|
|
|
|
$dbw->insert( 'page', array(
|
|
|
|
|
'page_id' => $page_id,
|
|
|
|
|
'page_namespace' => $this->mTitle->getNamespace(),
|
|
|
|
|
'page_title' => $this->mTitle->getDBkey(),
|
|
|
|
|
'page_counter' => 0,
|
2007-01-19 09:50:19 +00:00
|
|
|
'page_restrictions' => '',
|
2005-03-11 08:38:24 +00:00
|
|
|
'page_is_redirect' => 0, # Will set this shortly...
|
|
|
|
|
'page_is_new' => 1,
|
|
|
|
|
'page_random' => wfRandom(),
|
|
|
|
|
'page_touched' => $dbw->timestamp(),
|
|
|
|
|
'page_latest' => 0, # Fill this in shortly...
|
2005-10-25 23:26:14 +00:00
|
|
|
'page_len' => 0, # Fill this in shortly...
|
2006-06-20 09:50:57 +00:00
|
|
|
), __METHOD__ );
|
2005-03-11 08:38:24 +00:00
|
|
|
$newid = $dbw->insertId();
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-13 00:34:04 +00:00
|
|
|
$this->mTitle->resetArticleId( $newid );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2005-03-11 08:38:24 +00:00
|
|
|
return $newid;
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-11 08:38:24 +00:00
|
|
|
/**
|
|
|
|
|
* Update the page record to point to a newly saved revision.
|
|
|
|
|
*
|
|
|
|
|
* @param Database $dbw
|
2006-01-07 12:10:04 +00:00
|
|
|
* @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
|
|
|
|
|
* be set on.
|
2007-01-17 22:32:40 +00:00
|
|
|
* @param bool $lastRevIsRedirect If given, will optimize adding and
|
2006-10-29 21:25:40 +00:00
|
|
|
* removing rows in redirect table.
|
2005-03-11 08:38:24 +00:00
|
|
|
* @return bool true on success, false on failure
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2005-03-11 08:38:24 +00:00
|
|
|
*/
|
2006-10-29 21:25:40 +00:00
|
|
|
function updateRevisionOn( &$dbw, $revision, $lastRevision = null, $lastRevIsRedirect = null ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-10-29 21:25:40 +00:00
|
|
|
$text = $revision->getText();
|
|
|
|
|
$rt = Title::newFromRedirect( $text );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2005-03-12 10:50:51 +00:00
|
|
|
$conditions = array( 'page_id' => $this->getId() );
|
|
|
|
|
if( !is_null( $lastRevision ) ) {
|
|
|
|
|
# An extra check against threads stepping on each other
|
|
|
|
|
$conditions['page_latest'] = $lastRevision;
|
|
|
|
|
}
|
2005-08-02 13:35:19 +00:00
|
|
|
|
2005-03-11 08:38:24 +00:00
|
|
|
$dbw->update( 'page',
|
|
|
|
|
array( /* SET */
|
2005-03-13 07:49:15 +00:00
|
|
|
'page_latest' => $revision->getId(),
|
2005-03-11 08:38:24 +00:00
|
|
|
'page_touched' => $dbw->timestamp(),
|
2005-06-14 19:24:03 +00:00
|
|
|
'page_is_new' => ($lastRevision === 0) ? 1 : 0,
|
2006-10-29 21:25:40 +00:00
|
|
|
'page_is_redirect' => $rt !== NULL ? 1 : 0,
|
2005-03-12 11:51:02 +00:00
|
|
|
'page_len' => strlen( $text ),
|
2005-03-12 10:50:51 +00:00
|
|
|
),
|
|
|
|
|
$conditions,
|
2006-06-20 09:50:57 +00:00
|
|
|
__METHOD__ );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-10-31 15:57:37 +00:00
|
|
|
$result = $dbw->affectedRows() != 0;
|
|
|
|
|
|
|
|
|
|
if ($result) {
|
2007-01-17 22:32:40 +00:00
|
|
|
$this->updateRedirectOn( $dbw, $rt, $lastRevIsRedirect );
|
2006-10-31 15:57:37 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-10-31 15:57:37 +00:00
|
|
|
return $result;
|
2005-03-11 08:38:24 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-10-29 21:25:40 +00:00
|
|
|
/**
|
2007-01-17 22:32:40 +00:00
|
|
|
* Add row to the redirect table if this is a redirect, remove otherwise.
|
2006-10-29 21:25:40 +00:00
|
|
|
*
|
|
|
|
|
* @param Database $dbw
|
|
|
|
|
* @param $redirectTitle a title object pointing to the redirect target,
|
2007-01-17 22:32:40 +00:00
|
|
|
* or NULL if this is not a redirect
|
|
|
|
|
* @param bool $lastRevIsRedirect If given, will optimize adding and
|
2006-10-29 21:25:40 +00:00
|
|
|
* removing rows in redirect table.
|
|
|
|
|
* @return bool true on success, false on failure
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
|
|
|
|
function updateRedirectOn( &$dbw, $redirectTitle, $lastRevIsRedirect = null ) {
|
|
|
|
|
|
|
|
|
|
// Always update redirects (target link might have changed)
|
|
|
|
|
// Update/Insert if we don't know if the last revision was a redirect or not
|
|
|
|
|
// Delete if changing from redirect to non-redirect
|
|
|
|
|
$isRedirect = !is_null($redirectTitle);
|
|
|
|
|
if ($isRedirect || is_null($lastRevIsRedirect) || $lastRevIsRedirect !== $isRedirect) {
|
|
|
|
|
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
|
|
|
|
|
|
|
|
|
if ($isRedirect) {
|
|
|
|
|
|
|
|
|
|
// This title is a redirect, Add/Update row in the redirect table
|
|
|
|
|
$set = array( /* SET */
|
|
|
|
|
'rd_namespace' => $redirectTitle->getNamespace(),
|
2006-11-01 21:02:00 +00:00
|
|
|
'rd_title' => $redirectTitle->getDBkey(),
|
|
|
|
|
'rd_from' => $this->getId(),
|
2006-10-29 21:25:40 +00:00
|
|
|
);
|
|
|
|
|
|
2006-11-01 21:02:00 +00:00
|
|
|
$dbw->replace( 'redirect', array( 'rd_from' ), $set, __METHOD__ );
|
2006-10-29 21:25:40 +00:00
|
|
|
} else {
|
2007-01-17 22:32:40 +00:00
|
|
|
// This is not a redirect, remove row from redirect table
|
2006-11-01 21:02:00 +00:00
|
|
|
$where = array( 'rd_from' => $this->getId() );
|
2006-10-29 21:25:40 +00:00
|
|
|
$dbw->delete( 'redirect', $where, __METHOD__);
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-12 18:04:46 +00:00
|
|
|
if( $this->getTitle()->getNamespace() == NS_IMAGE )
|
|
|
|
|
RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $this->getTitle() );
|
2006-10-29 21:25:40 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2007-12-31 20:26:53 +00:00
|
|
|
return ( $dbw->affectedRows() != 0 );
|
2006-10-29 21:25:40 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-10-29 21:25:40 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-13 07:22:20 +00:00
|
|
|
/**
|
|
|
|
|
* 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 ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-03-13 07:22:20 +00:00
|
|
|
$row = $dbw->selectRow(
|
|
|
|
|
array( 'revision', 'page' ),
|
2006-10-29 21:25:40 +00:00
|
|
|
array( 'rev_id', 'rev_timestamp', 'page_is_redirect' ),
|
2005-03-13 07:22:20 +00:00
|
|
|
array(
|
|
|
|
|
'page_id' => $this->getId(),
|
|
|
|
|
'page_latest=rev_id' ),
|
2006-06-20 09:50:57 +00:00
|
|
|
__METHOD__ );
|
2005-03-13 07:22:20 +00:00
|
|
|
if( $row ) {
|
2005-08-02 13:35:19 +00:00
|
|
|
if( wfTimestamp(TS_MW, $row->rev_timestamp) >= $revision->getTimestamp() ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2005-03-13 07:22:20 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
$prev = $row->rev_id;
|
2006-10-31 15:57:37 +00:00
|
|
|
$lastRevIsRedirect = (bool)$row->page_is_redirect;
|
2005-03-13 07:22:20 +00:00
|
|
|
} else {
|
|
|
|
|
# No or missing previous revision; mark the page as new
|
|
|
|
|
$prev = 0;
|
2006-10-29 21:25:40 +00:00
|
|
|
$lastRevIsRedirect = null;
|
2005-03-13 07:22:20 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-10-29 21:25:40 +00:00
|
|
|
$ret = $this->updateRevisionOn( $dbw, $revision, $prev, $lastRevIsRedirect );
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2005-03-13 07:22:20 +00:00
|
|
|
return $ret;
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-10-28 07:07:21 +00:00
|
|
|
/**
|
|
|
|
|
* @return string Complete article text, or null if error
|
|
|
|
|
*/
|
2007-09-02 02:50:19 +00:00
|
|
|
function replaceSection($section, $text, $summary = '', $edittime = NULL) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-06 00:51:34 +00:00
|
|
|
if( $section == '' ) {
|
|
|
|
|
// Whole-page edit; let the text through unmolested.
|
|
|
|
|
} else {
|
2005-04-26 09:52:11 +00:00
|
|
|
if( is_null( $edittime ) ) {
|
|
|
|
|
$rev = Revision::newFromTitle( $this->mTitle );
|
|
|
|
|
} else {
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2005-04-26 09:52:11 +00:00
|
|
|
$rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
|
|
|
|
|
}
|
2005-10-28 07:07:21 +00:00
|
|
|
if( is_null( $rev ) ) {
|
|
|
|
|
wfDebug( "Article::replaceSection asked for bogus section (page: " .
|
|
|
|
|
$this->getId() . "; section: $section; edittime: $edittime)\n" );
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2005-04-26 09:52:11 +00:00
|
|
|
$oldtext = $rev->getText();
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-12-18 19:30:26 +00:00
|
|
|
if( $section == 'new' ) {
|
|
|
|
|
# Inserting a new section
|
2007-09-02 01:41:56 +00:00
|
|
|
$subject = $summary ? wfMsgForContent('newsectionheaderdefaultlevel',$summary) . "\n\n" : '';
|
2006-12-18 19:30:26 +00:00
|
|
|
$text = strlen( trim( $oldtext ) ) > 0
|
|
|
|
|
? "{$oldtext}\n\n{$subject}{$text}"
|
2006-12-18 19:32:41 +00:00
|
|
|
: "{$subject}{$text}";
|
2003-07-21 07:36:52 +00:00
|
|
|
} else {
|
2006-12-18 19:30:26 +00:00
|
|
|
# Replacing an existing section; roll out the big guns
|
2006-06-06 00:51:34 +00:00
|
|
|
global $wgParser;
|
|
|
|
|
$text = $wgParser->replaceSection( $oldtext, $section, $text );
|
2003-07-21 07:36:52 +00:00
|
|
|
}
|
2006-12-18 19:30:26 +00:00
|
|
|
|
2003-06-30 00:19:35 +00:00
|
|
|
}
|
2006-06-06 00:51:34 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2004-03-14 22:28:52 +00:00
|
|
|
return $text;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-06-20 09:50:57 +00:00
|
|
|
* @deprecated use Article::doEdit()
|
|
|
|
|
*/
|
2008-01-10 13:33:23 +00:00
|
|
|
function insertNewArticle( $text, $summary, $isminor, $watchthis, $suppressRC=false, $comment=false, $bot=false ) {
|
2006-11-08 08:06:51 +00:00
|
|
|
$flags = EDIT_NEW | EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
|
2006-06-20 09:50:57 +00:00
|
|
|
( $isminor ? EDIT_MINOR : 0 ) |
|
2008-01-13 17:58:14 +00:00
|
|
|
( $suppressRC ? EDIT_SUPPRESS_RC : 0 ) |
|
|
|
|
|
( $bot ? EDIT_FORCE_BOT : 0 );
|
2006-06-20 09:50:57 +00:00
|
|
|
|
|
|
|
|
# If this is a comment, add the summary as headline
|
|
|
|
|
if ( $comment && $summary != "" ) {
|
2007-09-02 01:41:56 +00:00
|
|
|
$text = wfMsgForContent('newsectionheaderdefaultlevel',$summary) . "\n\n".$text;
|
2006-06-20 09:50:57 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
$this->doEdit( $text, $summary, $flags );
|
|
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2006-06-20 09:50:57 +00:00
|
|
|
if ($watchthis) {
|
|
|
|
|
if (!$this->mTitle->userIsWatching()) {
|
|
|
|
|
$dbw->begin();
|
|
|
|
|
$this->doWatch();
|
|
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ( $this->mTitle->userIsWatching() ) {
|
|
|
|
|
$dbw->begin();
|
|
|
|
|
$this->doUnwatch();
|
|
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->doRedirect( $this->isRedirect( $text ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @deprecated use Article::doEdit()
|
|
|
|
|
*/
|
|
|
|
|
function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = '' ) {
|
2006-11-08 08:06:51 +00:00
|
|
|
$flags = EDIT_UPDATE | EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY |
|
2006-06-20 09:50:57 +00:00
|
|
|
( $minor ? EDIT_MINOR : 0 ) |
|
|
|
|
|
( $forceBot ? EDIT_FORCE_BOT : 0 );
|
|
|
|
|
|
|
|
|
|
$good = $this->doEdit( $text, $summary, $flags );
|
|
|
|
|
if ( $good ) {
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2006-06-20 09:50:57 +00:00
|
|
|
if ($watchthis) {
|
|
|
|
|
if (!$this->mTitle->userIsWatching()) {
|
|
|
|
|
$dbw->begin();
|
|
|
|
|
$this->doWatch();
|
|
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ( $this->mTitle->userIsWatching() ) {
|
|
|
|
|
$dbw->begin();
|
|
|
|
|
$this->doUnwatch();
|
|
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-23 09:03:49 +00:00
|
|
|
$extraQuery = ''; // Give extensions a chance to modify URL query on update
|
|
|
|
|
wfRunHooks( 'ArticleUpdateBeforeRedirect', array( $this, &$sectionanchor, &$extraQuery ) );
|
2007-08-15 22:13:03 +00:00
|
|
|
|
2008-05-23 09:03:49 +00:00
|
|
|
$this->doRedirect( $this->isRedirect( $text ), $sectionanchor, $extraQuery );
|
2006-06-20 09:50:57 +00:00
|
|
|
}
|
|
|
|
|
return $good;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Article::doEdit()
|
|
|
|
|
*
|
2007-01-17 22:32:40 +00:00
|
|
|
* Change an existing article or create a new article. Updates RC and all necessary caches,
|
2006-06-20 09:50:57 +00:00
|
|
|
* optionally via the deferred update array.
|
2004-09-11 11:39:24 +00:00
|
|
|
*
|
2006-06-20 09:50:57 +00:00
|
|
|
* $wgUser must be set before calling this function.
|
|
|
|
|
*
|
|
|
|
|
* @param string $text New text
|
|
|
|
|
* @param string $summary Edit summary
|
|
|
|
|
* @param integer $flags bitfield:
|
|
|
|
|
* EDIT_NEW
|
|
|
|
|
* Article is known or assumed to be non-existent, create a new one
|
|
|
|
|
* EDIT_UPDATE
|
|
|
|
|
* Article is known or assumed to be pre-existing, update it
|
|
|
|
|
* EDIT_MINOR
|
|
|
|
|
* Mark this edit minor, if the user is allowed to do so
|
|
|
|
|
* EDIT_SUPPRESS_RC
|
|
|
|
|
* Do not log the change in recentchanges
|
|
|
|
|
* EDIT_FORCE_BOT
|
|
|
|
|
* Mark the edit a "bot" edit regardless of user rights
|
|
|
|
|
* EDIT_DEFER_UPDATES
|
|
|
|
|
* Defer some of the updates until the end of index.php
|
2006-11-08 08:06:51 +00:00
|
|
|
* EDIT_AUTOSUMMARY
|
|
|
|
|
* Fill in blank summaries with generated text where possible
|
2007-01-17 22:32:40 +00:00
|
|
|
*
|
|
|
|
|
* If neither EDIT_NEW nor EDIT_UPDATE is specified, the status of the article will be detected.
|
|
|
|
|
* If EDIT_UPDATE is specified and the article doesn't exist, the function will return false. If
|
2006-06-20 09:50:57 +00:00
|
|
|
* EDIT_NEW is specified and the article does exist, a duplicate key error will cause an exception
|
|
|
|
|
* to be thrown from the Database. These two conditions are also possible with auto-detection due
|
|
|
|
|
* to MediaWiki's performance-optimised locking strategy.
|
2008-05-17 17:53:46 +00:00
|
|
|
* @param $baseRevId, the revision ID this edit was based off, if any
|
2006-06-20 09:50:57 +00:00
|
|
|
*
|
|
|
|
|
* @return bool success
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2008-08-16 13:34:43 +00:00
|
|
|
function doEdit( $text, $summary, $flags = 0, $baseRevId = false, $user = null ) {
|
2008-05-24 14:55:54 +00:00
|
|
|
global $wgUser, $wgDBtransactions, $wgUseAutomaticEditSummaries;
|
2008-08-16 13:34:43 +00:00
|
|
|
|
|
|
|
|
if ($user == null) {
|
|
|
|
|
$user = $wgUser;
|
|
|
|
|
}
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2004-07-10 03:09:26 +00:00
|
|
|
$good = true;
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
if ( !($flags & EDIT_NEW) && !($flags & EDIT_UPDATE) ) {
|
|
|
|
|
$aid = $this->mTitle->getArticleID( GAID_FOR_UPDATE );
|
|
|
|
|
if ( $aid ) {
|
|
|
|
|
$flags |= EDIT_UPDATE;
|
|
|
|
|
} else {
|
|
|
|
|
$flags |= EDIT_NEW;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-16 13:34:43 +00:00
|
|
|
if( !wfRunHooks( 'ArticleSave', array( &$this, &$user, &$text,
|
2006-06-20 09:50:57 +00:00
|
|
|
&$summary, $flags & EDIT_MINOR,
|
2007-01-17 22:32:40 +00:00
|
|
|
null, null, &$flags ) ) )
|
2006-06-20 09:50:57 +00:00
|
|
|
{
|
|
|
|
|
wfDebug( __METHOD__ . ": ArticleSave hook aborted save!\n" );
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
2005-08-23 08:15:14 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Silently ignore EDIT_MINOR if not allowed
|
2008-08-16 13:34:43 +00:00
|
|
|
$isminor = ( $flags & EDIT_MINOR ) && $user->isAllowed('minoredit');
|
2008-01-10 13:33:23 +00:00
|
|
|
$bot = $flags & EDIT_FORCE_BOT;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-11-20 11:48:03 +00:00
|
|
|
$oldtext = $this->getContent();
|
|
|
|
|
$oldsize = strlen( $oldtext );
|
|
|
|
|
|
2008-05-24 14:55:54 +00:00
|
|
|
# Provide autosummaries if one is not provided and autosummaries are enabled.
|
|
|
|
|
if( $wgUseAutomaticEditSummaries && $flags & EDIT_AUTOSUMMARY && $summary == '' ) {
|
2006-11-20 11:48:03 +00:00
|
|
|
$summary = $this->getAutosummary( $oldtext, $text, $flags );
|
2008-05-24 14:55:54 +00:00
|
|
|
}
|
2006-11-06 17:59:02 +00:00
|
|
|
|
2007-11-12 07:30:40 +00:00
|
|
|
$editInfo = $this->prepareTextForEdit( $text );
|
|
|
|
|
$text = $editInfo->pst;
|
2006-12-20 00:06:15 +00:00
|
|
|
$newsize = strlen( $text );
|
2006-06-20 09:50:57 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2005-04-10 18:23:11 +00:00
|
|
|
$now = wfTimestampNow();
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
if ( $flags & EDIT_UPDATE ) {
|
|
|
|
|
# Update article, but only if changed.
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Make sure the revision is either completely inserted or not inserted at all
|
|
|
|
|
if( !$wgDBtransactions ) {
|
|
|
|
|
$userAbort = ignore_user_abort( true );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
$lastRevision = 0;
|
|
|
|
|
$revisionId = 0;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-06 02:50:18 +00:00
|
|
|
$changed = ( strcmp( $text, $oldtext ) != 0 );
|
2006-06-20 09:50:57 +00:00
|
|
|
|
2008-01-06 02:50:18 +00:00
|
|
|
if ( $changed ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
$this->mGoodAdjustment = (int)$this->isCountable( $text )
|
|
|
|
|
- (int)$this->isCountable( $oldtext );
|
|
|
|
|
$this->mTotalAdjustment = 0;
|
|
|
|
|
|
|
|
|
|
$lastRevision = $dbw->selectField(
|
|
|
|
|
'page', 'page_latest', array( 'page_id' => $this->getId() ) );
|
|
|
|
|
|
|
|
|
|
if ( !$lastRevision ) {
|
|
|
|
|
# Article gone missing
|
|
|
|
|
wfDebug( __METHOD__.": EDIT_UPDATE specified but article doesn't exist\n" );
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
$revision = new Revision( array(
|
|
|
|
|
'page' => $this->getId(),
|
|
|
|
|
'comment' => $summary,
|
|
|
|
|
'minor_edit' => $isminor,
|
2008-04-07 23:53:57 +00:00
|
|
|
'text' => $text,
|
|
|
|
|
'parent_id' => $lastRevision
|
2006-06-20 09:50:57 +00:00
|
|
|
) );
|
|
|
|
|
|
|
|
|
|
$dbw->begin();
|
2008-05-17 15:53:58 +00:00
|
|
|
$revisionId = $revision->insertOn( $dbw );
|
2006-06-20 09:50:57 +00:00
|
|
|
|
|
|
|
|
# Update page
|
|
|
|
|
$ok = $this->updateRevisionOn( $dbw, $revision, $lastRevision );
|
|
|
|
|
|
|
|
|
|
if( !$ok ) {
|
|
|
|
|
/* Belated edit conflict! Run away!! */
|
|
|
|
|
$good = false;
|
|
|
|
|
$dbw->rollback();
|
|
|
|
|
} else {
|
2008-07-09 11:30:34 +00:00
|
|
|
wfRunHooks( 'NewRevisionFromEditComplete', array( $this, $revision, $baseRevId ) );
|
|
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Update recentchanges
|
|
|
|
|
if( !( $flags & EDIT_SUPPRESS_RC ) ) {
|
2008-08-16 13:34:43 +00:00
|
|
|
$rcid = RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $user, $summary,
|
2006-06-20 09:50:57 +00:00
|
|
|
$lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
|
|
|
|
|
$revisionId );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-12-18 21:39:36 +00:00
|
|
|
# Mark as patrolled if the user can do so
|
2008-08-16 13:34:43 +00:00
|
|
|
if( $GLOBALS['wgUseRCPatrol'] && $user->isAllowed( 'autopatrol' ) ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
RecentChange::markPatrolled( $rcid );
|
2007-01-16 17:05:30 +00:00
|
|
|
PatrolLog::record( $rcid, true );
|
2006-06-20 09:50:57 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-08-16 13:34:43 +00:00
|
|
|
$user->incEditCount();
|
2006-06-20 09:50:57 +00:00
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2007-08-21 03:21:27 +00:00
|
|
|
$revision = null;
|
2006-06-20 09:50:57 +00:00
|
|
|
// Keep the same revision ID, but do some updates on it
|
|
|
|
|
$revisionId = $this->getRevIdFetched();
|
|
|
|
|
// Update page_touched, this is usually implicit in the page update
|
|
|
|
|
// Other cache updates are done in onArticleEdit()
|
|
|
|
|
$this->mTitle->invalidateCache();
|
|
|
|
|
}
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2006-11-21 09:37:36 +00:00
|
|
|
if( !$wgDBtransactions ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
ignore_user_abort( $userAbort );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
if ( $good ) {
|
2007-01-17 22:32:40 +00:00
|
|
|
# Invalidate cache of this article and all pages using this article
|
2006-06-20 09:50:57 +00:00
|
|
|
# as a template. Partly deferred.
|
|
|
|
|
Article::onArticleEdit( $this->mTitle );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Update links tables, site stats, etc.
|
2006-06-24 13:08:48 +00:00
|
|
|
$this->editUpdates( $text, $summary, $isminor, $now, $revisionId, $changed );
|
2006-06-20 09:50:57 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
# Create new article
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Set statistics members
|
2007-01-17 22:32:40 +00:00
|
|
|
# We work out if it's countable after PST to avoid counter drift
|
2006-06-20 09:50:57 +00:00
|
|
|
# when articles are created with {{subst:}}
|
|
|
|
|
$this->mGoodAdjustment = (int)$this->isCountable( $text );
|
|
|
|
|
$this->mTotalAdjustment = 1;
|
2003-08-17 11:58:33 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
$dbw->begin();
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Add the page record; stake our claim on this title!
|
|
|
|
|
# This will fail with a database query exception if the article already exists
|
|
|
|
|
$newid = $this->insertOn( $dbw );
|
|
|
|
|
|
|
|
|
|
# Save the revision text...
|
2005-03-11 06:00:05 +00:00
|
|
|
$revision = new Revision( array(
|
2006-06-20 09:50:57 +00:00
|
|
|
'page' => $newid,
|
2005-03-11 06:00:05 +00:00
|
|
|
'comment' => $summary,
|
2005-03-11 08:38:24 +00:00
|
|
|
'minor_edit' => $isminor,
|
2005-03-11 06:00:05 +00:00
|
|
|
'text' => $text
|
|
|
|
|
) );
|
2008-05-17 15:53:58 +00:00
|
|
|
$revisionId = $revision->insertOn( $dbw );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
$this->mTitle->resetArticleID( $newid );
|
2005-03-11 08:38:24 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Update the page record with revision data
|
|
|
|
|
$this->updateRevisionOn( $dbw, $revision, 0 );
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-22 01:03:45 +00:00
|
|
|
wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false) );
|
2006-06-20 09:50:57 +00:00
|
|
|
|
|
|
|
|
if( !( $flags & EDIT_SUPPRESS_RC ) ) {
|
2008-08-16 13:34:43 +00:00
|
|
|
$rcid = RecentChange::notifyNew( $now, $this->mTitle, $isminor, $user, $summary, $bot,
|
2006-06-20 09:50:57 +00:00
|
|
|
'', strlen( $text ), $revisionId );
|
2006-12-18 21:39:36 +00:00
|
|
|
# Mark as patrolled if the user can
|
2008-08-16 13:34:43 +00:00
|
|
|
if( ($GLOBALS['wgUseRCPatrol'] || $GLOBALS['wgUseNPPatrol']) && $user->isAllowed( 'autopatrol' ) ) {
|
2006-03-18 22:47:40 +00:00
|
|
|
RecentChange::markPatrolled( $rcid );
|
2007-01-16 17:05:30 +00:00
|
|
|
PatrolLog::record( $rcid, true );
|
2006-03-18 22:47:40 +00:00
|
|
|
}
|
2004-06-11 14:48:31 +00:00
|
|
|
}
|
2008-08-16 13:34:43 +00:00
|
|
|
$user->incEditCount();
|
2006-06-20 09:50:57 +00:00
|
|
|
$dbw->commit();
|
2003-11-28 09:42:13 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Update links, etc.
|
2006-06-24 13:08:48 +00:00
|
|
|
$this->editUpdates( $text, $summary, $isminor, $now, $revisionId, true );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
# Clear caches
|
|
|
|
|
Article::onArticleCreate( $this->mTitle );
|
2005-12-30 09:33:11 +00:00
|
|
|
|
2008-08-16 13:34:43 +00:00
|
|
|
wfRunHooks( 'ArticleInsertComplete', array( &$this, &$user, $text, $summary,
|
2007-07-22 23:16:48 +00:00
|
|
|
$flags & EDIT_MINOR, null, null, &$flags, $revision ) );
|
2004-07-10 03:09:26 +00:00
|
|
|
}
|
2006-06-20 09:50:57 +00:00
|
|
|
|
|
|
|
|
if ( $good && !( $flags & EDIT_DEFER_UPDATES ) ) {
|
|
|
|
|
wfDoUpdates();
|
|
|
|
|
}
|
|
|
|
|
|
2007-09-03 04:19:53 +00:00
|
|
|
if ( $good ) {
|
2008-08-16 13:34:43 +00:00
|
|
|
wfRunHooks( 'ArticleSaveComplete', array( &$this, &$user, $text, $summary,
|
2007-09-03 04:19:53 +00:00
|
|
|
$flags & EDIT_MINOR, null, null, &$flags, $revision ) );
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2004-07-10 03:09:26 +00:00
|
|
|
return $good;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-06-18 12:42:16 +00:00
|
|
|
* @deprecated wrapper for doRedirect
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2005-12-30 09:33:11 +00:00
|
|
|
function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid ) {
|
2006-06-18 12:42:16 +00:00
|
|
|
$this->doRedirect( $this->isRedirect( $text ), $sectionanchor );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
/**
|
|
|
|
|
* Output a redirect back to the article.
|
|
|
|
|
* This is typically used after an edit.
|
|
|
|
|
*
|
|
|
|
|
* @param boolean $noRedir Add redirect=no
|
|
|
|
|
* @param string $sectionAnchor section to redirect to, including "#"
|
2008-05-23 09:03:49 +00:00
|
|
|
* @param string $extraQuery, extra query params
|
2006-06-18 12:42:16 +00:00
|
|
|
*/
|
2008-05-23 09:03:49 +00:00
|
|
|
function doRedirect( $noRedir = false, $sectionAnchor = '', $extraQuery = '' ) {
|
2006-06-18 12:42:16 +00:00
|
|
|
global $wgOut;
|
|
|
|
|
if ( $noRedir ) {
|
|
|
|
|
$query = 'redirect=no';
|
2008-05-23 09:03:49 +00:00
|
|
|
if( $extraQuery )
|
2007-08-15 22:13:03 +00:00
|
|
|
$query .= "&$query";
|
2006-06-18 12:42:16 +00:00
|
|
|
} else {
|
2008-05-23 09:03:49 +00:00
|
|
|
$query = $extraQuery;
|
2006-06-18 12:42:16 +00:00
|
|
|
}
|
|
|
|
|
$wgOut->redirect( $this->mTitle->getFullURL( $query ) . $sectionAnchor );
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2007-10-29 20:38:58 +00:00
|
|
|
* Mark this particular edit/page as patrolled
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function markpatrolled() {
|
2007-10-29 20:38:58 +00:00
|
|
|
global $wgOut, $wgRequest, $wgUseRCPatrol, $wgUseNPPatrol, $wgUser;
|
2006-12-22 19:43:20 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2004-08-09 23:30:02 +00:00
|
|
|
|
2007-10-29 20:38:58 +00:00
|
|
|
# Check patrol config options
|
|
|
|
|
|
|
|
|
|
if ( !($wgUseNPPatrol || $wgUseRCPatrol)) {
|
2008-03-24 15:04:55 +00:00
|
|
|
$wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
|
2008-04-14 07:45:50 +00:00
|
|
|
return;
|
2007-10-29 20:38:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# If we haven't been given an rc_id value, we can't do anything
|
|
|
|
|
$rcid = (int) $wgRequest->getVal('rcid');
|
|
|
|
|
$rc = $rcid ? RecentChange::newFromId($rcid) : null;
|
|
|
|
|
if ( is_null ( $rc ) )
|
|
|
|
|
{
|
2008-03-24 15:04:55 +00:00
|
|
|
$wgOut->showErrorPage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
|
2007-10-29 20:38:58 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-28 21:41:06 +00:00
|
|
|
if ( !$wgUseRCPatrol && $rc->getAttribute( 'rc_type' ) != RC_NEW) {
|
2007-11-16 21:33:00 +00:00
|
|
|
// Only new pages can be patrolled if the general patrolling is off....???
|
|
|
|
|
// @fixme -- is this necessary? Shouldn't we only bother controlling the
|
|
|
|
|
// front end here?
|
2008-03-24 15:04:55 +00:00
|
|
|
$wgOut->showErrorPage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
|
2004-08-09 23:30:02 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-09-27 18:20:06 +00:00
|
|
|
# Check permissions
|
2007-09-27 19:46:33 +00:00
|
|
|
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'patrol', $wgUser );
|
2007-09-27 18:20:06 +00:00
|
|
|
|
|
|
|
|
if (count($permission_errors)>0)
|
|
|
|
|
{
|
|
|
|
|
$wgOut->showPermissionsErrorPage( $permission_errors );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-12-22 19:43:20 +00:00
|
|
|
# Handle the 'MarkPatrolled' hook
|
|
|
|
|
if( !wfRunHooks( 'MarkPatrolled', array( $rcid, &$wgUser, false ) ) ) {
|
|
|
|
|
return;
|
2004-08-09 05:38:11 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-10-29 20:38:58 +00:00
|
|
|
#It would be nice to see where the user had actually come from, but for now just guess
|
2008-02-28 21:41:06 +00:00
|
|
|
$returnto = $rc->getAttribute( 'rc_type' ) == RC_NEW ? 'Newpages' : 'Recentchanges';
|
2007-10-29 20:38:58 +00:00
|
|
|
$return = Title::makeTitle( NS_SPECIAL, $returnto );
|
|
|
|
|
|
2006-12-22 19:43:20 +00:00
|
|
|
# If it's left up to us, check that the user is allowed to patrol this edit
|
|
|
|
|
# If the user has the "autopatrol" right, then we'll assume there are no
|
|
|
|
|
# other conditions stopping them doing so
|
|
|
|
|
if( !$wgUser->isAllowed( 'autopatrol' ) ) {
|
|
|
|
|
$rc = RecentChange::newFromId( $rcid );
|
|
|
|
|
# Graceful error handling, as we've done before here...
|
|
|
|
|
# (If the recent change doesn't exist, then it doesn't matter whether
|
|
|
|
|
# the user is allowed to patrol it or not; nothing is going to happen
|
|
|
|
|
if( is_object( $rc ) && $wgUser->getName() == $rc->getAttribute( 'rc_user_text' ) ) {
|
|
|
|
|
# The user made this edit, and can't patrol it
|
|
|
|
|
# Tell them so, and then back off
|
|
|
|
|
$wgOut->setPageTitle( wfMsg( 'markedaspatrollederror' ) );
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'markedaspatrollederror-noautopatrol' );
|
2006-12-22 19:43:20 +00:00
|
|
|
$wgOut->returnToMain( false, $return );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2004-08-09 05:38:11 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2008-02-28 21:41:06 +00:00
|
|
|
# Check that the revision isn't patrolled already
|
|
|
|
|
# Prevents duplicate log entries
|
|
|
|
|
if( !$rc->getAttribute( 'rc_patrolled' ) ) {
|
|
|
|
|
# Mark the edit as patrolled
|
|
|
|
|
RecentChange::markPatrolled( $rcid );
|
|
|
|
|
PatrolLog::record( $rcid );
|
|
|
|
|
wfRunHooks( 'MarkPatrolledComplete', array( &$rcid, &$wgUser, false ) );
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-12-22 19:43:20 +00:00
|
|
|
# Inform the user
|
|
|
|
|
$wgOut->setPageTitle( wfMsg( 'markedaspatrolled' ) );
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'markedaspatrolledtext' );
|
2006-12-22 19:43:20 +00:00
|
|
|
$wgOut->returnToMain( false, $return );
|
2004-08-09 05:38:11 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-03-11 07:55:42 +00:00
|
|
|
* User-interface handler for the "watch" action
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-11-30 05:45:56 +00:00
|
|
|
function watch() {
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-09-24 13:14:52 +00:00
|
|
|
global $wgUser, $wgOut;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2005-02-21 12:46:37 +00:00
|
|
|
if ( $wgUser->isAnon() ) {
|
2006-06-07 06:40:24 +00:00
|
|
|
$wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
|
2003-04-14 23:10:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ( wfReadOnly() ) {
|
|
|
|
|
$wgOut->readOnlyPage();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
if( $this->doWatch() ) {
|
2004-11-30 05:45:56 +00:00
|
|
|
$wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'addedwatchtext', $this->mTitle->getPrefixedText() );
|
2004-11-30 05:45:56 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-08-06 05:51:09 +00:00
|
|
|
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-03-11 07:55:42 +00:00
|
|
|
* Add this page to $wgUser's watchlist
|
|
|
|
|
* @return bool true on successful watch operation
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2006-03-11 07:55:42 +00:00
|
|
|
function doWatch() {
|
|
|
|
|
global $wgUser;
|
|
|
|
|
if( $wgUser->isAnon() ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
|
|
|
|
|
$wgUser->addWatch( $this->mTitle );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
return wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* User interface handler for the "unwatch" action.
|
|
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function unwatch() {
|
2004-11-30 05:45:56 +00:00
|
|
|
|
|
|
|
|
global $wgUser, $wgOut;
|
|
|
|
|
|
2005-02-21 12:46:37 +00:00
|
|
|
if ( $wgUser->isAnon() ) {
|
2006-06-07 06:40:24 +00:00
|
|
|
$wgOut->showErrorPage( 'watchnologin', 'watchnologintext' );
|
2004-11-30 05:45:56 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if ( wfReadOnly() ) {
|
|
|
|
|
$wgOut->readOnlyPage();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
if( $this->doUnwatch() ) {
|
2004-11-30 05:45:56 +00:00
|
|
|
$wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'removedwatchtext', $this->mTitle->getPrefixedText() );
|
2004-11-30 05:45:56 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-11-30 05:45:56 +00:00
|
|
|
$wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
/**
|
|
|
|
|
* Stop watching a page
|
|
|
|
|
* @return bool true on successful unwatch
|
|
|
|
|
*/
|
|
|
|
|
function doUnwatch() {
|
|
|
|
|
global $wgUser;
|
|
|
|
|
if( $wgUser->isAnon() ) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$this))) {
|
|
|
|
|
$wgUser->removeWatch( $this->mTitle );
|
|
|
|
|
|
|
|
|
|
return wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-03-11 07:55:42 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2005-12-22 05:41:06 +00:00
|
|
|
* action=protect handler
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2005-12-22 05:41:06 +00:00
|
|
|
function protect() {
|
|
|
|
|
$form = new ProtectionForm( $this );
|
2007-01-22 20:59:00 +00:00
|
|
|
$form->execute();
|
2005-12-22 05:41:06 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-12-22 05:41:06 +00:00
|
|
|
/**
|
|
|
|
|
* action=unprotect handler (alias)
|
|
|
|
|
*/
|
|
|
|
|
function unprotect() {
|
|
|
|
|
$this->protect();
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-12-22 05:41:06 +00:00
|
|
|
/**
|
|
|
|
|
* Update the article's restriction field, and leave a log entry.
|
|
|
|
|
*
|
|
|
|
|
* @param array $limit set of restriction keys
|
|
|
|
|
* @param string $reason
|
|
|
|
|
* @return bool true on success
|
|
|
|
|
*/
|
2007-01-22 08:26:41 +00:00
|
|
|
function updateRestrictions( $limit = array(), $reason = '', $cascade = 0, $expiry = null ) {
|
2007-10-01 19:50:25 +00:00
|
|
|
global $wgUser, $wgRestrictionTypes, $wgContLang;
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2003-09-01 08:30:14 +00:00
|
|
|
$id = $this->mTitle->getArticleID();
|
2007-12-01 09:08:43 +00:00
|
|
|
if( array() != $this->mTitle->getUserPermissionsErrors( 'protect', $wgUser ) || wfReadOnly() || $id == 0 ) {
|
2005-12-22 05:41:06 +00:00
|
|
|
return false;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2004-04-21 16:17:49 +00:00
|
|
|
|
2007-01-11 01:17:19 +00:00
|
|
|
if (!$cascade) {
|
|
|
|
|
$cascade = false;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-22 08:26:41 +00:00
|
|
|
// Take this opportunity to purge out expired restrictions
|
|
|
|
|
Title::purgeExpiredRestrictions();
|
|
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
# FIXME: Same limitations as described in ProtectionForm.php (line 37);
|
|
|
|
|
# we expect a single selection, but the schema allows otherwise.
|
|
|
|
|
$current = array();
|
|
|
|
|
foreach( $wgRestrictionTypes as $action )
|
|
|
|
|
$current[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
|
2004-11-28 00:20:37 +00:00
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
$current = Article::flattenRestrictions( $current );
|
|
|
|
|
$updated = Article::flattenRestrictions( $limit );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
$changed = ( $current != $updated );
|
2008-04-12 00:30:01 +00:00
|
|
|
$changed = $changed || ($updated && $this->mTitle->areRestrictionsCascading() != $cascade);
|
|
|
|
|
$changed = $changed || ($updated && $this->mTitle->mRestrictionsExpiry != $expiry);
|
2006-04-08 20:50:08 +00:00
|
|
|
$protect = ( $updated != '' );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
# If nothing's changed, do nothing
|
|
|
|
|
if( $changed ) {
|
|
|
|
|
if( wfRunHooks( 'ArticleProtect', array( &$this, &$wgUser, $limit, $reason ) ) ) {
|
2006-04-08 21:13:11 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-01-23 10:51:33 +00:00
|
|
|
$encodedExpiry = Block::encodeExpiry($expiry, $dbw );
|
|
|
|
|
|
|
|
|
|
$expiry_description = '';
|
|
|
|
|
if ( $encodedExpiry != 'infinity' ) {
|
2008-02-02 11:49:18 +00:00
|
|
|
$expiry_description = ' (' . wfMsgForContent( 'protect-expiring', $wgContLang->timeanddate( $expiry, false, false ) ).')';
|
2007-01-23 10:51:33 +00:00
|
|
|
}
|
|
|
|
|
|
2006-04-08 21:13:11 +00:00
|
|
|
# Prepare a null revision to be added to the history
|
2007-06-13 11:08:57 +00:00
|
|
|
$modified = $current != '' && $protect;
|
|
|
|
|
if ( $protect ) {
|
|
|
|
|
$comment_type = $modified ? 'modifiedarticleprotection' : 'protectedarticle';
|
|
|
|
|
} else {
|
|
|
|
|
$comment_type = 'unprotectedarticle';
|
|
|
|
|
}
|
|
|
|
|
$comment = $wgContLang->ucfirst( wfMsgForContent( $comment_type, $this->mTitle->getPrefixedText() ) );
|
2007-01-23 10:51:33 +00:00
|
|
|
|
2008-06-21 03:17:35 +00:00
|
|
|
# Only restrictions with the 'protect' right can cascade...
|
2008-06-19 20:40:41 +00:00
|
|
|
# Otherwise, people who cannot normally protect can "protect" pages via transclusion
|
2008-06-21 03:17:35 +00:00
|
|
|
foreach( $limit as $action => $restriction ) {
|
|
|
|
|
# FIXME: can $restriction be an array or what? (same as fixme above)
|
|
|
|
|
if( $restriction != 'protect' && $restriction != 'sysop' ) {
|
|
|
|
|
$cascade = false;
|
|
|
|
|
break;
|
2008-06-19 20:40:41 +00:00
|
|
|
}
|
2007-04-24 02:20:04 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-04-24 02:20:04 +00:00
|
|
|
$cascade_description = '';
|
|
|
|
|
if ($cascade) {
|
|
|
|
|
$cascade_description = ' ['.wfMsg('protect-summary-cascade').']';
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-08 21:13:11 +00:00
|
|
|
if( $reason )
|
|
|
|
|
$comment .= ": $reason";
|
|
|
|
|
if( $protect )
|
|
|
|
|
$comment .= " [$updated]";
|
2007-01-23 10:51:33 +00:00
|
|
|
if ( $expiry_description && $protect )
|
|
|
|
|
$comment .= "$expiry_description";
|
2007-04-24 02:20:04 +00:00
|
|
|
if ( $cascade )
|
|
|
|
|
$comment .= "$cascade_description";
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-01-10 23:32:38 +00:00
|
|
|
# Update restrictions table
|
|
|
|
|
foreach( $limit as $action => $restrictions ) {
|
|
|
|
|
if ($restrictions != '' ) {
|
2007-03-08 01:46:12 +00:00
|
|
|
$dbw->replace( 'page_restrictions', array(array('pr_page', 'pr_type')),
|
2007-01-10 23:32:38 +00:00
|
|
|
array( 'pr_page' => $id, 'pr_type' => $action
|
2007-01-22 08:26:41 +00:00
|
|
|
, 'pr_level' => $restrictions, 'pr_cascade' => $cascade ? 1 : 0
|
|
|
|
|
, 'pr_expiry' => $encodedExpiry ), __METHOD__ );
|
2007-01-10 23:32:38 +00:00
|
|
|
} else {
|
|
|
|
|
$dbw->delete( 'page_restrictions', array( 'pr_page' => $id,
|
|
|
|
|
'pr_type' => $action ), __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-01-21 15:04:49 +00:00
|
|
|
|
|
|
|
|
# Insert a null revision
|
|
|
|
|
$nullRevision = Revision::newNullRevision( $dbw, $id, $comment, true );
|
|
|
|
|
$nullRevId = $nullRevision->insertOn( $dbw );
|
2007-01-12 01:44:33 +00:00
|
|
|
|
2008-07-27 19:24:35 +00:00
|
|
|
$latest = $this->getLatest();
|
2007-01-14 12:03:56 +00:00
|
|
|
# Update page record
|
|
|
|
|
$dbw->update( 'page',
|
|
|
|
|
array( /* SET */
|
|
|
|
|
'page_touched' => $dbw->timestamp(),
|
|
|
|
|
'page_restrictions' => '',
|
|
|
|
|
'page_latest' => $nullRevId
|
|
|
|
|
), array( /* WHERE */
|
|
|
|
|
'page_id' => $id
|
2008-06-21 03:17:35 +00:00
|
|
|
), 'Article::protect'
|
2007-01-14 12:03:56 +00:00
|
|
|
);
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-07-27 19:24:35 +00:00
|
|
|
wfRunHooks( 'NewRevisionFromEditComplete', array($this, $nullRevision, $latest) );
|
2006-04-08 20:50:08 +00:00
|
|
|
wfRunHooks( 'ArticleProtectComplete', array( &$this, &$wgUser, $limit, $reason ) );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
# Update the protection log
|
|
|
|
|
$log = new LogPage( 'protect' );
|
|
|
|
|
if( $protect ) {
|
2008-08-08 00:01:53 +00:00
|
|
|
$log->addEntry( $modified ? 'modify' : 'protect', $this->mTitle,
|
2008-06-21 03:17:35 +00:00
|
|
|
trim( $reason . " [$updated]$cascade_description$expiry_description" ) );
|
2006-04-08 20:50:08 +00:00
|
|
|
} else {
|
|
|
|
|
$log->addEntry( 'unprotect', $this->mTitle, $reason );
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-04-08 20:50:08 +00:00
|
|
|
} # End hook
|
|
|
|
|
} # End "changed" check
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2005-12-22 05:41:06 +00:00
|
|
|
return true;
|
2004-04-21 16:17:49 +00:00
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2005-12-22 05:41:06 +00:00
|
|
|
* Take an array of page restrictions and flatten it to a string
|
|
|
|
|
* suitable for insertion into the page_restrictions field.
|
|
|
|
|
* @param array $limit
|
|
|
|
|
* @return string
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2005-12-22 05:41:06 +00:00
|
|
|
function flattenRestrictions( $limit ) {
|
|
|
|
|
if( !is_array( $limit ) ) {
|
2006-06-07 06:40:24 +00:00
|
|
|
throw new MWException( 'Article::flattenRestrictions given non-array restriction set' );
|
2005-12-22 05:41:06 +00:00
|
|
|
}
|
|
|
|
|
$bits = array();
|
2006-04-08 20:50:08 +00:00
|
|
|
ksort( $limit );
|
2005-12-22 05:41:06 +00:00
|
|
|
foreach( $limit as $action => $restrictions ) {
|
|
|
|
|
if( $restrictions != '' ) {
|
|
|
|
|
$bits[] = "$action=$restrictions";
|
|
|
|
|
}
|
2005-12-15 21:25:52 +00:00
|
|
|
}
|
2005-12-22 05:41:06 +00:00
|
|
|
return implode( ':', $bits );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-11-07 19:06:15 +00:00
|
|
|
/**
|
|
|
|
|
* Auto-generates a deletion reason
|
2007-11-19 17:51:48 +00:00
|
|
|
* @param bool &$hasHistory Whether the page has a history
|
2007-11-07 19:06:15 +00:00
|
|
|
*/
|
2007-11-19 17:51:48 +00:00
|
|
|
public function generateReason(&$hasHistory)
|
2007-11-07 19:06:15 +00:00
|
|
|
{
|
|
|
|
|
global $wgContLang;
|
|
|
|
|
$dbw = wfGetDB(DB_MASTER);
|
|
|
|
|
// Get the last revision
|
|
|
|
|
$rev = Revision::newFromTitle($this->mTitle);
|
|
|
|
|
if(is_null($rev))
|
|
|
|
|
return false;
|
|
|
|
|
// Get the article's contents
|
|
|
|
|
$contents = $rev->getText();
|
|
|
|
|
$blank = false;
|
|
|
|
|
// If the page is blank, use the text from the previous revision,
|
|
|
|
|
// which can only be blank if there's a move/import/protect dummy revision involved
|
|
|
|
|
if($contents == '')
|
|
|
|
|
{
|
|
|
|
|
$prev = $rev->getPrevious();
|
|
|
|
|
if($prev)
|
|
|
|
|
{
|
|
|
|
|
$contents = $prev->getText();
|
|
|
|
|
$blank = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find out if there was only one contributor
|
|
|
|
|
// Only scan the last 20 revisions
|
|
|
|
|
$limit = 20;
|
|
|
|
|
$res = $dbw->select('revision', 'rev_user_text', array('rev_page' => $this->getID()), __METHOD__,
|
|
|
|
|
array('LIMIT' => $limit));
|
|
|
|
|
if($res === false)
|
|
|
|
|
// This page has no revisions, which is very weird
|
|
|
|
|
return false;
|
|
|
|
|
if($res->numRows() > 1)
|
|
|
|
|
$hasHistory = true;
|
|
|
|
|
else
|
|
|
|
|
$hasHistory = false;
|
|
|
|
|
$row = $dbw->fetchObject($res);
|
|
|
|
|
$onlyAuthor = $row->rev_user_text;
|
|
|
|
|
// Try to find a second contributor
|
2008-07-27 18:59:46 +00:00
|
|
|
foreach( $res as $row ) {
|
2008-01-09 21:40:40 +00:00
|
|
|
if($row->rev_user_text != $onlyAuthor) {
|
2007-11-07 19:06:15 +00:00
|
|
|
$onlyAuthor = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-01-09 21:40:40 +00:00
|
|
|
}
|
2007-11-07 19:06:15 +00:00
|
|
|
$dbw->freeResult($res);
|
|
|
|
|
|
|
|
|
|
// Generate the summary with a '$1' placeholder
|
2008-01-09 21:40:40 +00:00
|
|
|
if($blank) {
|
2007-11-07 19:06:15 +00:00
|
|
|
// The current revision is blank and the one before is also
|
|
|
|
|
// blank. It's just not our lucky day
|
|
|
|
|
$reason = wfMsgForContent('exbeforeblank', '$1');
|
2008-01-09 21:40:40 +00:00
|
|
|
} else {
|
2007-11-07 19:06:15 +00:00
|
|
|
if($onlyAuthor)
|
|
|
|
|
$reason = wfMsgForContent('excontentauthor', '$1', $onlyAuthor);
|
|
|
|
|
else
|
|
|
|
|
$reason = wfMsgForContent('excontent', '$1');
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-11-07 19:06:15 +00:00
|
|
|
// Replace newlines with spaces to prevent uglyness
|
|
|
|
|
$contents = preg_replace("/[\n\r]/", ' ', $contents);
|
|
|
|
|
// Calculate the maximum amount of chars to get
|
|
|
|
|
// Max content length = max comment length - length of the comment (excl. $1) - '...'
|
|
|
|
|
$maxLength = 255 - (strlen($reason) - 2) - 3;
|
|
|
|
|
$contents = $wgContLang->truncate($contents, $maxLength, '...');
|
|
|
|
|
// Remove possible unfinished links
|
|
|
|
|
$contents = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $contents );
|
|
|
|
|
// Now replace the '$1' placeholder
|
|
|
|
|
$reason = str_replace( '$1', $contents, $reason );
|
|
|
|
|
return $reason;
|
|
|
|
|
}
|
|
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/*
|
|
|
|
|
* UI entry point for page deletion
|
|
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function delete() {
|
2005-12-04 18:27:59 +00:00
|
|
|
global $wgUser, $wgOut, $wgRequest;
|
2007-12-03 00:14:36 +00:00
|
|
|
|
2005-03-11 04:38:01 +00:00
|
|
|
$confirm = $wgRequest->wasPosted() &&
|
2007-12-03 00:14:36 +00:00
|
|
|
$wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-12-03 00:14:36 +00:00
|
|
|
$this->DeleteReasonList = $wgRequest->getText( 'wpDeleteReasonList', 'other' );
|
2007-11-25 17:02:28 +00:00
|
|
|
$this->DeleteReason = $wgRequest->getText( 'wpReason' );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-11-25 17:02:28 +00:00
|
|
|
$reason = $this->DeleteReasonList;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-11-25 17:02:28 +00:00
|
|
|
if ( $reason != 'other' && $this->DeleteReason != '') {
|
|
|
|
|
// Entry from drop down menu + additional comment
|
|
|
|
|
$reason .= ': ' . $this->DeleteReason;
|
|
|
|
|
} elseif ( $reason == 'other' ) {
|
|
|
|
|
$reason = $this->DeleteReason;
|
|
|
|
|
}
|
2008-03-09 02:18:50 +00:00
|
|
|
# Flag to hide all contents of the archived revisions
|
2008-05-25 00:31:28 +00:00
|
|
|
$suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('suppressrevision');
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2003-11-09 11:45:12 +00:00
|
|
|
# This code desperately needs to be totally rewritten
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-01-15 01:55:48 +00:00
|
|
|
# Read-only check...
|
|
|
|
|
if ( wfReadOnly() ) {
|
|
|
|
|
$wgOut->readOnlyPage();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2004-03-29 14:48:07 +00:00
|
|
|
# Check permissions
|
2007-09-09 08:11:58 +00:00
|
|
|
$permission_errors = $this->mTitle->getUserPermissionsErrors( 'delete', $wgUser );
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2008-01-09 21:40:40 +00:00
|
|
|
if (count($permission_errors)>0) {
|
2007-09-09 08:11:58 +00:00
|
|
|
$wgOut->showPermissionsErrorPage( $permission_errors );
|
2003-04-14 23:10:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-29 16:32:49 +00:00
|
|
|
$wgOut->setPagetitle( wfMsg( 'delete-confirm', $this->mTitle->getPrefixedText() ) );
|
|
|
|
|
|
2006-01-08 01:25:50 +00:00
|
|
|
# Better double-check that it hasn't been deleted yet!
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2006-01-08 01:25:50 +00:00
|
|
|
$conds = $this->mTitle->pageCond();
|
2006-06-20 09:50:57 +00:00
|
|
|
$latest = $dbw->selectField( 'page', 'page_latest', $conds, __METHOD__ );
|
2006-01-08 01:25:50 +00:00
|
|
|
if ( $latest === false ) {
|
2006-06-07 06:40:24 +00:00
|
|
|
$wgOut->showFatalError( wfMsg( 'cannotdelete' ) );
|
2003-09-01 09:59:53 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2003-05-23 04:26:51 +00:00
|
|
|
|
2008-01-17 00:29:05 +00:00
|
|
|
# Hack for big sites
|
|
|
|
|
$bigHistory = $this->isBigDeletion();
|
|
|
|
|
if( $bigHistory && !$this->mTitle->userCan( 'bigdelete' ) ) {
|
|
|
|
|
global $wgLang, $wgDeleteRevisionsLimit;
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->wrapWikiMsg( "<div class='error'>\n$1</div>\n",
|
|
|
|
|
array( 'delete-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
|
2008-01-17 00:29:05 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-18 09:45:18 +00:00
|
|
|
if( $confirm ) {
|
2008-03-09 02:18:50 +00:00
|
|
|
$this->doDelete( $reason, $suppress );
|
2006-12-16 21:36:01 +00:00
|
|
|
if( $wgRequest->getCheck( 'wpWatch' ) ) {
|
|
|
|
|
$this->doWatch();
|
|
|
|
|
} elseif( $this->mTitle->userIsWatching() ) {
|
|
|
|
|
$this->doUnwatch();
|
|
|
|
|
}
|
2003-11-15 12:38:02 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2007-11-07 19:06:15 +00:00
|
|
|
// Generate deletion reason
|
|
|
|
|
$hasHistory = false;
|
2007-11-19 03:59:45 +00:00
|
|
|
if ( !$reason ) $reason = $this->generateReason($hasHistory);
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-11-07 19:06:15 +00:00
|
|
|
// If the page has a history, insert a warning
|
|
|
|
|
if( $hasHistory && !$confirm ) {
|
2003-09-01 09:59:53 +00:00
|
|
|
$skin=$wgUser->getSkin();
|
2006-04-09 14:29:37 +00:00
|
|
|
$wgOut->addHTML( '<strong>' . wfMsg( 'historywarning' ) . ' ' . $skin->historyLink() . '</strong>' );
|
2008-01-17 00:29:05 +00:00
|
|
|
if( $bigHistory ) {
|
|
|
|
|
global $wgLang, $wgDeleteRevisionsLimit;
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->wrapWikiMsg( "<div class='error'>\n$1</div>\n",
|
|
|
|
|
array( 'delete-warning-toobig', $wgLang->formatNum( $wgDeleteRevisionsLimit ) ) );
|
2008-01-17 00:29:05 +00:00
|
|
|
}
|
2003-09-01 09:59:53 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-07-07 16:56:32 +00:00
|
|
|
return $this->confirmDelete( $reason );
|
2003-09-01 09:59:53 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-16 23:08:19 +00:00
|
|
|
/**
|
|
|
|
|
* @return bool whether or not the page surpasses $wgDeleteRevisionsLimit revisions
|
|
|
|
|
*/
|
|
|
|
|
function isBigDeletion() {
|
|
|
|
|
global $wgDeleteRevisionsLimit;
|
|
|
|
|
if( $wgDeleteRevisionsLimit ) {
|
|
|
|
|
$revCount = $this->estimateRevisionCount();
|
|
|
|
|
return $revCount > $wgDeleteRevisionsLimit;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-16 23:08:19 +00:00
|
|
|
/**
|
|
|
|
|
* @return int approximate revision count
|
|
|
|
|
*/
|
|
|
|
|
function estimateRevisionCount() {
|
|
|
|
|
$dbr = wfGetDB();
|
|
|
|
|
// For an exact count...
|
|
|
|
|
//return $dbr->selectField( 'revision', 'COUNT(*)',
|
|
|
|
|
// array( 'rev_page' => $this->getId() ), __METHOD__ );
|
|
|
|
|
return $dbr->estimateRowCount( 'revision', '*',
|
|
|
|
|
array( 'rev_page' => $this->getId() ), __METHOD__ );
|
|
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2006-01-08 01:25:50 +00:00
|
|
|
/**
|
2006-03-11 17:13:49 +00:00
|
|
|
* Get the last N authors
|
2006-01-08 01:25:50 +00:00
|
|
|
* @param int $num Number of revisions to get
|
|
|
|
|
* @param string $revLatest The latest rev_id, selected from the master (optional)
|
|
|
|
|
* @return array Array of authors, duplicates not removed
|
|
|
|
|
*/
|
|
|
|
|
function getLastNAuthors( $num, $revLatest = 0 ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2006-01-08 01:25:50 +00:00
|
|
|
|
|
|
|
|
// First try the slave
|
|
|
|
|
// If that doesn't have the latest revision, try the master
|
|
|
|
|
$continue = 2;
|
2007-01-22 23:50:42 +00:00
|
|
|
$db = wfGetDB( DB_SLAVE );
|
2006-01-08 01:25:50 +00:00
|
|
|
do {
|
|
|
|
|
$res = $db->select( array( 'page', 'revision' ),
|
|
|
|
|
array( 'rev_id', 'rev_user_text' ),
|
|
|
|
|
array(
|
|
|
|
|
'page_namespace' => $this->mTitle->getNamespace(),
|
|
|
|
|
'page_title' => $this->mTitle->getDBkey(),
|
|
|
|
|
'rev_page = page_id'
|
2006-06-20 09:50:57 +00:00
|
|
|
), __METHOD__, $this->getSelectOptions( array(
|
2006-01-08 01:25:50 +00:00
|
|
|
'ORDER BY' => 'rev_timestamp DESC',
|
|
|
|
|
'LIMIT' => $num
|
|
|
|
|
) )
|
|
|
|
|
);
|
|
|
|
|
if ( !$res ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-01-08 01:25:50 +00:00
|
|
|
return array();
|
|
|
|
|
}
|
|
|
|
|
$row = $db->fetchObject( $res );
|
|
|
|
|
if ( $continue == 2 && $revLatest && $row->rev_id != $revLatest ) {
|
2007-01-22 23:50:42 +00:00
|
|
|
$db = wfGetDB( DB_MASTER );
|
2006-01-08 01:25:50 +00:00
|
|
|
$continue--;
|
|
|
|
|
} else {
|
|
|
|
|
$continue = 0;
|
|
|
|
|
}
|
|
|
|
|
} while ( $continue );
|
|
|
|
|
|
|
|
|
|
$authors = array( $row->rev_user_text );
|
|
|
|
|
while ( $row = $db->fetchObject( $res ) ) {
|
|
|
|
|
$authors[] = $row->rev_user_text;
|
|
|
|
|
}
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-01-08 01:25:50 +00:00
|
|
|
return $authors;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Output deletion confirmation dialog
|
2008-01-29 16:32:49 +00:00
|
|
|
* @param $reason string Prefilled reason
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2008-07-07 16:56:32 +00:00
|
|
|
function confirmDelete( $reason ) {
|
2008-01-29 16:32:49 +00:00
|
|
|
global $wgOut, $wgUser, $wgContLang;
|
|
|
|
|
$align = $wgContLang->isRtl() ? 'left' : 'right';
|
2003-11-15 12:38:02 +00:00
|
|
|
|
|
|
|
|
wfDebug( "Article::confirmDelete\n" );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-01-29 16:32:49 +00:00
|
|
|
$wgOut->setSubtitle( wfMsg( 'delete-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->mTitle ) ) );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'confirmdeletetext' );
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2008-05-25 00:31:28 +00:00
|
|
|
if( $wgUser->isAllowed( 'suppressrevision' ) ) {
|
2008-03-09 02:18:50 +00:00
|
|
|
$suppress = "<tr id=\"wpDeleteSuppressRow\" name=\"wpDeleteSuppressRow\"><td></td><td>";
|
|
|
|
|
$suppress .= Xml::checkLabel( wfMsg( 'revdelete-suppress' ), 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '2' ) );
|
|
|
|
|
$suppress .= "</td></tr>";
|
|
|
|
|
} else {
|
|
|
|
|
$suppress = '';
|
|
|
|
|
}
|
|
|
|
|
|
2008-07-07 16:56:32 +00:00
|
|
|
$form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->mTitle->getLocalURL( 'action=delete' ), 'id' => 'deleteconfirm' ) ) .
|
2008-03-13 20:36:52 +00:00
|
|
|
Xml::openElement( 'fieldset', array( 'id' => 'mw-delete-table' ) ) .
|
2008-06-12 12:02:28 +00:00
|
|
|
Xml::tags( 'legend', null, wfMsgExt( 'delete-legend', array( 'parsemag', 'escapenoentities' ) ) ) .
|
2008-01-29 16:32:49 +00:00
|
|
|
Xml::openElement( 'table' ) .
|
2008-02-03 09:27:13 +00:00
|
|
|
"<tr id=\"wpDeleteReasonListRow\">
|
2008-01-29 20:23:40 +00:00
|
|
|
<td align='$align'>" .
|
2008-01-29 16:32:49 +00:00
|
|
|
Xml::label( wfMsg( 'deletecomment' ), 'wpDeleteReasonList' ) .
|
|
|
|
|
"</td>
|
|
|
|
|
<td>" .
|
|
|
|
|
Xml::listDropDown( 'wpDeleteReasonList',
|
2008-04-14 07:45:50 +00:00
|
|
|
wfMsgForContent( 'deletereason-dropdown' ),
|
2008-01-29 16:32:49 +00:00
|
|
|
wfMsgForContent( 'deletereasonotherlist' ), '', 'wpReasonDropDown', 1 ) .
|
|
|
|
|
"</td>
|
|
|
|
|
</tr>
|
2008-02-03 09:27:13 +00:00
|
|
|
<tr id=\"wpDeleteReasonRow\">
|
2008-01-29 20:23:40 +00:00
|
|
|
<td align='$align'>" .
|
2008-01-29 16:32:49 +00:00
|
|
|
Xml::label( wfMsg( 'deleteotherreason' ), 'wpReason' ) .
|
|
|
|
|
"</td>
|
|
|
|
|
<td>" .
|
2008-01-30 05:36:09 +00:00
|
|
|
Xml::input( 'wpReason', 60, $reason, array( 'type' => 'text', 'maxlength' => '255', 'tabindex' => '2', 'id' => 'wpReason' ) ) .
|
2008-01-29 16:32:49 +00:00
|
|
|
"</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td></td>
|
|
|
|
|
<td>" .
|
|
|
|
|
Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(), array( 'tabindex' => '3' ) ) .
|
|
|
|
|
"</td>
|
|
|
|
|
</tr>
|
2008-03-09 02:18:50 +00:00
|
|
|
$suppress
|
2008-01-29 16:32:49 +00:00
|
|
|
<tr>
|
|
|
|
|
<td></td>
|
|
|
|
|
<td>" .
|
|
|
|
|
Xml::submitButton( wfMsg( 'deletepage' ), array( 'name' => 'wpConfirmB', 'id' => 'wpConfirmB', 'tabindex' => '4' ) ) .
|
|
|
|
|
"</td>
|
|
|
|
|
</tr>" .
|
|
|
|
|
Xml::closeElement( 'table' ) .
|
|
|
|
|
Xml::closeElement( 'fieldset' ) .
|
|
|
|
|
Xml::hidden( 'wpEditToken', $wgUser->editToken() ) .
|
|
|
|
|
Xml::closeElement( 'form' );
|
|
|
|
|
|
2008-03-06 14:59:28 +00:00
|
|
|
if ( $wgUser->isAllowed( 'editinterface' ) ) {
|
|
|
|
|
$skin = $wgUser->getSkin();
|
2008-03-06 16:52:10 +00:00
|
|
|
$link = $skin->makeLink ( 'MediaWiki:Deletereason-dropdown', wfMsgHtml( 'delete-edit-reasonlist' ) );
|
2008-03-06 14:59:28 +00:00
|
|
|
$form .= '<p class="mw-delete-editreasons">' . $link . '</p>';
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-29 16:32:49 +00:00
|
|
|
$wgOut->addHTML( $form );
|
2007-06-04 23:43:08 +00:00
|
|
|
$this->showLogExtract( $wgOut );
|
2007-03-06 00:10:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2007-06-04 23:43:08 +00:00
|
|
|
* Show relevant lines from the deletion log
|
2007-03-06 00:10:37 +00:00
|
|
|
*/
|
2007-06-04 23:43:08 +00:00
|
|
|
function showLogExtract( $out ) {
|
2008-03-13 20:36:52 +00:00
|
|
|
$out->addHtml( Xml::element( 'h2', null, LogPage::logName( 'delete' ) ) );
|
2008-04-02 20:20:47 +00:00
|
|
|
LogEventsList::showLogExtract( $out, 'delete', $this->mTitle->getPrefixedText() );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 14:27:38 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Perform a deletion and output success or failure messages
|
|
|
|
|
*/
|
2008-03-09 02:18:50 +00:00
|
|
|
function doDelete( $reason, $suppress = false ) {
|
2006-03-07 01:10:39 +00:00
|
|
|
global $wgOut, $wgUser;
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__."\n" );
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-04-28 12:34:27 +00:00
|
|
|
$id = $this->getId();
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-06-27 06:24:42 +00:00
|
|
|
$error = '';
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2008-06-27 06:24:42 +00:00
|
|
|
if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason, &$error))) {
|
2008-03-09 02:18:50 +00:00
|
|
|
if ( $this->doDeleteArticle( $reason, $suppress ) ) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$deleted = $this->mTitle->getPrefixedText();
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-11-28 06:15:22 +00:00
|
|
|
$wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
$loglink = '[[Special:Log/delete|' . wfMsgNoTrans( 'deletionlog' ) . ']]';
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'deletedtext', $deleted, $loglink );
|
2004-11-28 06:15:22 +00:00
|
|
|
$wgOut->returnToMain( false );
|
2008-04-28 12:34:27 +00:00
|
|
|
wfRunHooks('ArticleDeleteComplete', array(&$this, &$wgUser, $reason, $id));
|
2004-11-28 06:15:22 +00:00
|
|
|
} else {
|
2008-06-27 06:24:42 +00:00
|
|
|
if ($error = '')
|
|
|
|
|
$wgOut->showFatalError( wfMsg( 'cannotdelete' ) );
|
|
|
|
|
else
|
|
|
|
|
$wgOut->showFatalError( $error );
|
2004-11-28 06:15:22 +00:00
|
|
|
}
|
2004-03-20 15:03:26 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Back-end article deletion
|
|
|
|
|
* Deletes the article with database consistency, writes logs, purges caches
|
|
|
|
|
* Returns success
|
|
|
|
|
*/
|
2008-03-09 02:18:50 +00:00
|
|
|
function doDeleteArticle( $reason, $suppress = false ) {
|
2006-03-07 01:10:39 +00:00
|
|
|
global $wgUseSquid, $wgDeferredUpdateList;
|
2006-11-23 08:25:56 +00:00
|
|
|
global $wgUseTrackbacks;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfDebug( __METHOD__."\n" );
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2004-03-20 15:03:26 +00:00
|
|
|
$ns = $this->mTitle->getNamespace();
|
2004-07-10 03:09:26 +00:00
|
|
|
$t = $this->mTitle->getDBkey();
|
2004-03-20 15:03:26 +00:00
|
|
|
$id = $this->mTitle->getArticleID();
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-08-14 19:33:59 +00:00
|
|
|
if ( $t == '' || $id == 0 ) {
|
2004-03-20 15:03:26 +00:00
|
|
|
return false;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-13 00:29:20 +00:00
|
|
|
$u = new SiteStatsUpdate( 0, 1, -(int)$this->isCountable( $this->getContent() ), -1 );
|
2003-04-14 23:10:40 +00:00
|
|
|
array_push( $wgDeferredUpdateList, $u );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-03-09 02:18:50 +00:00
|
|
|
// Bitfields to further suppress the content
|
|
|
|
|
if ( $suppress ) {
|
|
|
|
|
$bitfield = 0;
|
|
|
|
|
// This should be 15...
|
|
|
|
|
$bitfield |= Revision::DELETED_TEXT;
|
|
|
|
|
$bitfield |= Revision::DELETED_COMMENT;
|
|
|
|
|
$bitfield |= Revision::DELETED_USER;
|
|
|
|
|
$bitfield |= Revision::DELETED_RESTRICTED;
|
|
|
|
|
} else {
|
|
|
|
|
$bitfield = 'rev_deleted';
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-04-15 23:34:45 +00:00
|
|
|
$dbw->begin();
|
2005-05-01 08:07:25 +00:00
|
|
|
// 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' ),
|
2004-07-10 03:09:26 +00:00
|
|
|
array(
|
2005-03-12 08:06:46 +00:00
|
|
|
'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',
|
2005-01-30 19:46:48 +00:00
|
|
|
'ar_minor_edit' => 'rev_minor_edit',
|
2005-03-12 08:06:46 +00:00
|
|
|
'ar_rev_id' => 'rev_id',
|
2005-05-01 08:07:25 +00:00
|
|
|
'ar_text_id' => 'rev_text_id',
|
2006-12-21 21:40:43 +00:00
|
|
|
'ar_text' => '\'\'', // Be explicit to appease
|
|
|
|
|
'ar_flags' => '\'\'', // MySQL's "strict mode"...
|
2008-03-09 21:08:42 +00:00
|
|
|
'ar_len' => 'rev_len',
|
2007-08-11 14:43:47 +00:00
|
|
|
'ar_page_id' => 'page_id',
|
2008-03-09 02:18:50 +00:00
|
|
|
'ar_deleted' => $bitfield
|
2004-07-10 03:09:26 +00:00
|
|
|
), array(
|
2005-05-01 08:07:25 +00:00
|
|
|
'page_id' => $id,
|
|
|
|
|
'page_id = rev_page'
|
2006-06-20 09:50:57 +00:00
|
|
|
), __METHOD__
|
2004-07-10 03:09:26 +00:00
|
|
|
);
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2007-01-10 23:32:38 +00:00
|
|
|
# Delete restrictions for it
|
|
|
|
|
$dbw->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ );
|
|
|
|
|
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
# Fix category table counts
|
|
|
|
|
$cats = array();
|
|
|
|
|
$res = $dbw->select( 'categorylinks', 'cl_to',
|
|
|
|
|
array( 'cl_from' => $id ), __METHOD__ );
|
|
|
|
|
foreach( $res as $row ) {
|
|
|
|
|
$cats []= $row->cl_to;
|
|
|
|
|
}
|
2008-03-19 13:36:33 +00:00
|
|
|
$this->updateCategoryCounts( array(), $cats );
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
# Now that it's safely backed up, delete it
|
2006-06-20 09:50:57 +00:00
|
|
|
$dbw->delete( 'page', array( 'page_id' => $id ), __METHOD__);
|
2008-04-27 23:45:31 +00:00
|
|
|
$ok = ( $dbw->affectedRows() > 0 ); // getArticleId() uses slave, could be laggy
|
2008-04-15 23:34:45 +00:00
|
|
|
if( !$ok ) {
|
|
|
|
|
$dbw->rollback();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-07-17 00:54:40 +00:00
|
|
|
# If using cascading deletes, we can skip some explicit deletes
|
|
|
|
|
if ( !$dbw->cascadingDeletes() ) {
|
|
|
|
|
$dbw->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ );
|
2005-07-23 06:12:48 +00:00
|
|
|
|
2006-07-17 00:54:40 +00:00
|
|
|
if ($wgUseTrackbacks)
|
|
|
|
|
$dbw->delete( 'trackbacks', array( 'tb_page' => $id ), __METHOD__ );
|
|
|
|
|
|
|
|
|
|
# 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 ) );
|
2006-11-02 11:39:13 +00:00
|
|
|
$dbw->delete( 'redirect', array( 'rd_from' => $id ) );
|
2006-07-17 00:54:40 +00:00
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-07-17 00:54:40 +00:00
|
|
|
# If using cleanup triggers, we can skip some manual deletes
|
|
|
|
|
if ( !$dbw->cleanupTriggers() ) {
|
|
|
|
|
|
|
|
|
|
# Clean up recentchanges entries...
|
2008-04-14 07:45:50 +00:00
|
|
|
$dbw->delete( 'recentchanges',
|
2008-04-14 01:04:10 +00:00
|
|
|
array( 'rc_namespace' => $ns, 'rc_title' => $t, 'rc_type != '.RC_LOG ),
|
|
|
|
|
__METHOD__ );
|
2006-07-17 00:54:40 +00:00
|
|
|
}
|
2008-04-27 23:45:31 +00:00
|
|
|
$dbw->commit();
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
# Clear caches
|
2004-03-20 15:03:26 +00:00
|
|
|
Article::onArticleDelete( $this->mTitle );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-04-11 23:42:09 +00:00
|
|
|
# Clear the cached article id so the interface doesn't act like we exist
|
|
|
|
|
$this->mTitle->resetArticleID( 0 );
|
|
|
|
|
$this->mTitle->mArticleID = 0;
|
|
|
|
|
|
2008-03-09 02:18:50 +00:00
|
|
|
# Log the deletion, if the page was suppressed, log it at Oversight instead
|
2008-04-01 22:50:53 +00:00
|
|
|
$logtype = $suppress ? 'suppress' : 'delete';
|
2008-03-09 02:18:50 +00:00
|
|
|
$log = new LogPage( $logtype );
|
2008-04-27 23:45:31 +00:00
|
|
|
|
2008-04-15 23:34:45 +00:00
|
|
|
# Make sure logging got through
|
2008-04-27 23:45:31 +00:00
|
|
|
$log->addEntry( 'delete', $this->mTitle, $reason, array() );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2004-03-20 15:03:26 +00:00
|
|
|
return true;
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2007-07-09 08:12:44 +00:00
|
|
|
/**
|
2008-01-14 20:17:05 +00:00
|
|
|
* Roll back the most recent consecutive set of edits to a page
|
|
|
|
|
* from the same user; fails if there are no eligible edits to
|
2008-01-15 17:31:07 +00:00
|
|
|
* roll back to, e.g. user is the sole contributor. This function
|
|
|
|
|
* performs permissions checks on $wgUser, then calls commitRollback()
|
|
|
|
|
* to do the dirty work
|
2007-07-09 08:12:44 +00:00
|
|
|
*
|
2008-04-14 07:45:50 +00:00
|
|
|
* @param string $fromP - Name of the user whose edits to rollback.
|
2007-07-07 07:32:34 +00:00
|
|
|
* @param string $summary - Custom summary. Set to default summary if empty.
|
|
|
|
|
* @param string $token - Rollback token.
|
2008-01-16 00:06:42 +00:00
|
|
|
* @param bool $bot - If true, mark all reverted edits as bot.
|
2008-04-14 07:45:50 +00:00
|
|
|
*
|
2008-01-15 17:31:07 +00:00
|
|
|
* @param array $resultDetails contains result-specific array of additional values
|
|
|
|
|
* 'alreadyrolled' : 'current' (rev)
|
|
|
|
|
* success : 'summary' (str), 'current' (rev), 'target' (rev)
|
2008-04-14 07:45:50 +00:00
|
|
|
*
|
2008-01-16 00:06:42 +00:00
|
|
|
* @return array of errors, each error formatted as
|
|
|
|
|
* array(messagekey, param1, param2, ...).
|
|
|
|
|
* On success, the array is empty. This array can also be passed to
|
2008-01-18 15:52:40 +00:00
|
|
|
* OutputPage::showPermissionsErrorPage().
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2007-07-09 08:12:44 +00:00
|
|
|
public function doRollback( $fromP, $summary, $token, $bot, &$resultDetails ) {
|
2008-01-15 17:31:07 +00:00
|
|
|
global $wgUser;
|
2007-07-07 07:32:34 +00:00
|
|
|
$resultDetails = null;
|
2007-09-10 07:48:20 +00:00
|
|
|
|
2008-01-15 17:31:07 +00:00
|
|
|
# Check permissions
|
|
|
|
|
$errors = array_merge( $this->mTitle->getUserPermissionsErrors( 'edit', $wgUser ),
|
|
|
|
|
$this->mTitle->getUserPermissionsErrors( 'rollback', $wgUser ) );
|
2007-07-09 08:12:44 +00:00
|
|
|
if( !$wgUser->matchEditToken( $token, array( $this->mTitle->getPrefixedText(), $fromP ) ) )
|
2008-01-15 17:31:07 +00:00
|
|
|
$errors[] = array( 'sessionfailure' );
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2007-11-20 08:34:59 +00:00
|
|
|
if ( $wgUser->pingLimiter('rollback') || $wgUser->pingLimiter() ) {
|
2008-01-15 17:31:07 +00:00
|
|
|
$errors[] = array( 'actionthrottledtext' );
|
2007-11-20 08:34:59 +00:00
|
|
|
}
|
2008-01-15 17:31:07 +00:00
|
|
|
# If there were errors, bail out now
|
|
|
|
|
if(!empty($errors))
|
|
|
|
|
return $errors;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-15 17:31:07 +00:00
|
|
|
return $this->commitRollback($fromP, $summary, $bot, $resultDetails);
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-01-15 17:31:07 +00:00
|
|
|
/**
|
2008-01-16 00:06:42 +00:00
|
|
|
* Backend implementation of doRollback(), please refer there for parameter
|
|
|
|
|
* and return value documentation
|
2008-01-15 17:31:07 +00:00
|
|
|
*
|
2008-01-16 00:06:42 +00:00
|
|
|
* NOTE: This function does NOT check ANY permissions, it just commits the
|
|
|
|
|
* rollback to the DB Therefore, you should only call this function direct-
|
|
|
|
|
* ly if you want to use custom permissions checks. If you don't, use
|
|
|
|
|
* doRollback() instead.
|
2008-04-14 07:45:50 +00:00
|
|
|
*/
|
2008-01-15 17:31:07 +00:00
|
|
|
public function commitRollback($fromP, $summary, $bot, &$resultDetails) {
|
2008-05-03 16:07:57 +00:00
|
|
|
global $wgUseRCPatrol, $wgUser, $wgLang;
|
2007-07-09 08:12:44 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2008-01-16 00:06:42 +00:00
|
|
|
if( wfReadOnly() ) {
|
|
|
|
|
return array( array( 'readonlytext' ) );
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-29 20:02:26 +00:00
|
|
|
# Get the last editor
|
|
|
|
|
$current = Revision::newFromTitle( $this->mTitle );
|
|
|
|
|
if( is_null( $current ) ) {
|
|
|
|
|
# Something wrong... no page?
|
2008-01-15 17:31:07 +00:00
|
|
|
return array(array('notanarticle'));
|
2007-06-29 20:02:26 +00:00
|
|
|
}
|
|
|
|
|
|
2007-07-07 07:32:34 +00:00
|
|
|
$from = str_replace( '_', ' ', $fromP );
|
2007-06-29 20:02:26 +00:00
|
|
|
if( $from != $current->getUserText() ) {
|
2007-07-09 08:12:44 +00:00
|
|
|
$resultDetails = array( 'current' => $current );
|
2008-01-15 17:31:07 +00:00
|
|
|
return array(array('alreadyrolled',
|
|
|
|
|
htmlspecialchars($this->mTitle->getPrefixedText()),
|
|
|
|
|
htmlspecialchars($fromP),
|
|
|
|
|
htmlspecialchars($current->getUserText())
|
|
|
|
|
));
|
2007-06-29 20:02:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get the last edit not by this guy
|
|
|
|
|
$user = intval( $current->getUser() );
|
|
|
|
|
$user_text = $dbw->addQuotes( $current->getUserText() );
|
|
|
|
|
$s = $dbw->selectRow( 'revision',
|
2008-03-09 02:18:50 +00:00
|
|
|
array( 'rev_id', 'rev_timestamp', 'rev_deleted' ),
|
2008-01-15 17:31:07 +00:00
|
|
|
array( 'rev_page' => $current->getPage(),
|
2007-06-29 20:02:26 +00:00
|
|
|
"rev_user <> {$user} OR rev_user_text <> {$user_text}"
|
2006-06-20 09:50:57 +00:00
|
|
|
), __METHOD__,
|
2008-01-15 17:31:07 +00:00
|
|
|
array( 'USE INDEX' => 'page_timestamp',
|
2007-06-29 20:02:26 +00:00
|
|
|
'ORDER BY' => 'rev_timestamp DESC' )
|
|
|
|
|
);
|
|
|
|
|
if( $s === false ) {
|
2008-01-15 17:31:07 +00:00
|
|
|
# No one else ever edited this page
|
|
|
|
|
return array(array('cantrollback'));
|
2008-03-09 02:18:50 +00:00
|
|
|
} else if( $s->rev_deleted & REVISION::DELETED_TEXT || $s->rev_deleted & REVISION::DELETED_USER ) {
|
|
|
|
|
# Only admins can see this text
|
|
|
|
|
return array(array('notvisiblerev'));
|
2007-06-29 20:02:26 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2005-12-17 00:44:23 +00:00
|
|
|
$set = array();
|
2007-11-20 15:22:06 +00:00
|
|
|
if ( $bot && $wgUser->isAllowed('markbotedits') ) {
|
2007-06-29 20:02:26 +00:00
|
|
|
# Mark all reverted edits as bot
|
2005-12-17 00:44:23 +00:00
|
|
|
$set['rc_bot'] = 1;
|
2007-06-29 20:02:26 +00:00
|
|
|
}
|
|
|
|
|
if ( $wgUseRCPatrol ) {
|
|
|
|
|
# Mark all reverted edits as patrolled
|
2005-12-17 00:44:23 +00:00
|
|
|
$set['rc_patrolled'] = 1;
|
2007-06-29 20:02:26 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2007-06-29 20:02:26 +00:00
|
|
|
if ( $set ) {
|
|
|
|
|
$dbw->update( 'recentchanges', $set,
|
2007-07-07 07:32:34 +00:00
|
|
|
array( /* WHERE */
|
|
|
|
|
'rc_cur_id' => $current->getPage(),
|
|
|
|
|
'rc_user_text' => $current->getUserText(),
|
|
|
|
|
"rc_timestamp > '{$s->rev_timestamp}'",
|
|
|
|
|
), __METHOD__
|
|
|
|
|
);
|
2007-06-29 19:55:46 +00:00
|
|
|
}
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2008-01-15 17:31:07 +00:00
|
|
|
# Generate the edit summary if necessary
|
2007-10-01 19:50:25 +00:00
|
|
|
$target = Revision::newFromId( $s->rev_id );
|
2008-05-03 16:07:57 +00:00
|
|
|
if( empty( $summary ) ){
|
|
|
|
|
$summary = wfMsgForContent( 'revertpage' );
|
2008-01-15 15:38:30 +00:00
|
|
|
}
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-03 16:07:57 +00:00
|
|
|
# Allow the custom summary to use the same args as the default message
|
|
|
|
|
$args = array(
|
|
|
|
|
$target->getUserText(), $from, $s->rev_id,
|
|
|
|
|
$wgLang->timeanddate(wfTimestamp(TS_MW, $s->rev_timestamp), true),
|
|
|
|
|
$current->getId(), $wgLang->timeanddate($current->getTimestamp())
|
|
|
|
|
);
|
2008-08-08 00:01:53 +00:00
|
|
|
$summary = wfMsgReplaceArgs( $summary, $args );
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2007-07-07 00:17:51 +00:00
|
|
|
# Save
|
2007-12-07 09:44:47 +00:00
|
|
|
$flags = EDIT_UPDATE;
|
|
|
|
|
|
|
|
|
|
if ($wgUser->isAllowed('minoredit'))
|
|
|
|
|
$flags |= EDIT_MINOR;
|
|
|
|
|
|
2008-01-10 19:27:49 +00:00
|
|
|
if( $bot && ($wgUser->isAllowed('markbotedits') || $wgUser->isAllowed('bot')) )
|
2007-07-06 09:06:55 +00:00
|
|
|
$flags |= EDIT_FORCE_BOT;
|
2008-05-17 17:53:46 +00:00
|
|
|
$this->doEdit( $target->getText(), $summary, $flags, $target->getId() );
|
2007-07-07 00:17:51 +00:00
|
|
|
|
2007-10-30 07:58:15 +00:00
|
|
|
wfRunHooks( 'ArticleRollbackComplete', array( $this, $wgUser, $target ) );
|
|
|
|
|
|
2007-07-07 07:32:34 +00:00
|
|
|
$resultDetails = array(
|
|
|
|
|
'summary' => $summary,
|
|
|
|
|
'current' => $current,
|
2007-07-09 08:12:44 +00:00
|
|
|
'target' => $target,
|
|
|
|
|
);
|
2008-01-15 17:31:07 +00:00
|
|
|
return array();
|
2007-07-07 07:32:34 +00:00
|
|
|
}
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2007-07-09 08:12:44 +00:00
|
|
|
/**
|
|
|
|
|
* User interface for rollback operations
|
|
|
|
|
*/
|
2007-07-07 07:32:34 +00:00
|
|
|
function rollback() {
|
|
|
|
|
global $wgUser, $wgOut, $wgRequest, $wgUseRCPatrol;
|
2007-07-09 08:12:44 +00:00
|
|
|
$details = null;
|
2007-09-10 07:48:20 +00:00
|
|
|
|
2007-07-09 08:12:44 +00:00
|
|
|
$result = $this->doRollback(
|
|
|
|
|
$wgRequest->getVal( 'from' ),
|
|
|
|
|
$wgRequest->getText( 'summary' ),
|
|
|
|
|
$wgRequest->getVal( 'token' ),
|
2008-01-10 07:52:09 +00:00
|
|
|
$wgRequest->getBool( 'bot' ),
|
2007-07-09 08:12:44 +00:00
|
|
|
$details
|
|
|
|
|
);
|
2008-01-16 00:06:42 +00:00
|
|
|
|
|
|
|
|
if( in_array( array( 'blocked' ), $result ) ) {
|
2008-01-15 17:31:07 +00:00
|
|
|
$wgOut->blockedPage();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-01-16 00:06:42 +00:00
|
|
|
if( in_array( array( 'actionthrottledtext' ), $result ) ) {
|
2008-01-15 17:31:07 +00:00
|
|
|
$wgOut->rateLimited();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-03-05 13:50:17 +00:00
|
|
|
if( isset( $result[0][0] ) && ( $result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback' ) ){
|
|
|
|
|
$wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
|
|
|
|
|
$errArray = $result[0];
|
|
|
|
|
$errMsg = array_shift( $errArray );
|
|
|
|
|
$wgOut->addWikiMsgArray( $errMsg, $errArray );
|
|
|
|
|
if( isset( $details['current'] ) ){
|
|
|
|
|
$current = $details['current'];
|
|
|
|
|
if( $current->getComment() != '' ) {
|
|
|
|
|
$wgOut->addWikiMsgArray( 'editcomment', array( $wgUser->getSkin()->formatComment( $current->getComment() ) ), array( 'replaceafter' ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-01-16 00:06:42 +00:00
|
|
|
# Display permissions errors before read-only message -- there's no
|
|
|
|
|
# point in misleading the user into thinking the inability to rollback
|
|
|
|
|
# is only temporary.
|
|
|
|
|
if( !empty($result) && $result !== array( array('readonlytext') ) ) {
|
|
|
|
|
# array_diff is completely broken for arrays of arrays, sigh. Re-
|
|
|
|
|
# move any 'readonlytext' error manually.
|
|
|
|
|
$out = array();
|
|
|
|
|
foreach( $result as $error ) {
|
|
|
|
|
if( $error != array( 'readonlytext' ) ) {
|
|
|
|
|
$out []= $error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$wgOut->showPermissionsErrorPage( $out );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if( $result == array( array('readonlytext') ) ) {
|
|
|
|
|
$wgOut->readOnlyPage();
|
2008-01-15 17:31:07 +00:00
|
|
|
return;
|
2007-07-07 07:32:34 +00:00
|
|
|
}
|
2007-07-09 08:12:44 +00:00
|
|
|
|
2008-01-15 17:31:07 +00:00
|
|
|
$current = $details['current'];
|
|
|
|
|
$target = $details['target'];
|
|
|
|
|
$wgOut->setPageTitle( wfMsg( 'actioncomplete' ) );
|
|
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
|
|
|
|
$old = $wgUser->getSkin()->userLink( $current->getUser(), $current->getUserText() )
|
|
|
|
|
. $wgUser->getSkin()->userToolLinks( $current->getUser(), $current->getUserText() );
|
|
|
|
|
$new = $wgUser->getSkin()->userLink( $target->getUser(), $target->getUserText() )
|
|
|
|
|
. $wgUser->getSkin()->userToolLinks( $target->getUser(), $target->getUserText() );
|
|
|
|
|
$wgOut->addHtml( wfMsgExt( 'rollback-success', array( 'parse', 'replaceafter' ), $old, $new ) );
|
|
|
|
|
$wgOut->returnToMain( false, $this->mTitle );
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-06-02 00:13:08 +00:00
|
|
|
if( !$wgRequest->getBool( 'hidediff', false ) ) {
|
|
|
|
|
$de = new DifferenceEngine( $this->mTitle, $current->getId(), 'next', false, true );
|
|
|
|
|
$de->showDiff( '', '' );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2007-06-29 20:02:26 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Do standard deferred updates after page view
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
|
|
|
|
function viewUpdates() {
|
2008-05-08 15:01:40 +00:00
|
|
|
global $wgDeferredUpdateList, $wgUser;
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2003-04-14 23:10:40 +00:00
|
|
|
if ( 0 != $this->getID() ) {
|
2008-05-08 15:01:40 +00:00
|
|
|
# Don't update page view counters on views from bot users (bug 14044)
|
2003-11-09 11:45:12 +00:00
|
|
|
global $wgDisableCounters;
|
2008-05-08 15:01:40 +00:00
|
|
|
if( !$wgDisableCounters && !$wgUser->isAllowed( 'bot' ) ) {
|
2003-12-13 21:32:32 +00:00
|
|
|
Article::incViewCount( $this->getID() );
|
2003-11-09 11:45:12 +00:00
|
|
|
$u = new SiteStatsUpdate( 1, 0, 0 );
|
|
|
|
|
array_push( $wgDeferredUpdateList, $u );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-12-07 11:52:34 +00:00
|
|
|
# Update newtalk / watchlist notification status
|
|
|
|
|
$wgUser->clearNotification( $this->mTitle );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2007-11-12 07:30:40 +00:00
|
|
|
/**
|
|
|
|
|
* Prepare text which is about to be saved.
|
2008-06-11 02:51:30 +00:00
|
|
|
* Returns a stdclass with source, pst and output members
|
2007-11-12 07:30:40 +00:00
|
|
|
*/
|
2007-11-15 02:54:28 +00:00
|
|
|
function prepareTextForEdit( $text, $revid=null ) {
|
|
|
|
|
if ( $this->mPreparedEdit && $this->mPreparedEdit->newText == $text && $this->mPreparedEdit->revid == $revid) {
|
2007-11-12 07:30:40 +00:00
|
|
|
// Already prepared
|
|
|
|
|
return $this->mPreparedEdit;
|
|
|
|
|
}
|
|
|
|
|
global $wgParser;
|
|
|
|
|
$edit = (object)array();
|
2007-11-15 02:54:28 +00:00
|
|
|
$edit->revid = $revid;
|
2007-11-12 07:30:40 +00:00
|
|
|
$edit->newText = $text;
|
|
|
|
|
$edit->pst = $this->preSaveTransform( $text );
|
2008-06-11 02:51:30 +00:00
|
|
|
$options = new ParserOptions;
|
2007-11-12 07:30:40 +00:00
|
|
|
$options->setTidy( true );
|
2007-11-30 14:50:48 +00:00
|
|
|
$options->enableLimitReport();
|
2007-11-15 02:54:28 +00:00
|
|
|
$edit->output = $wgParser->parse( $edit->pst, $this->mTitle, $options, true, true, $revid );
|
2007-11-12 07:30:40 +00:00
|
|
|
$edit->oldText = $this->getContent();
|
|
|
|
|
$this->mPreparedEdit = $edit;
|
|
|
|
|
return $edit;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Do standard deferred updates after page edit.
|
2006-06-18 12:42:16 +00:00
|
|
|
* Update links tables, site stats, search index and message cache.
|
2007-09-02 18:23:43 +00:00
|
|
|
* Every 100th edit, prune the recent changes table.
|
2007-01-17 22:32:40 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2006-06-24 13:08:48 +00:00
|
|
|
* @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
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2006-06-24 13:08:48 +00:00
|
|
|
function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange, $newid, $changed = true ) {
|
2008-01-16 02:20:49 +00:00
|
|
|
global $wgDeferredUpdateList, $wgMessageCache, $wgUser, $wgParser, $wgEnableParserCache;
|
2005-12-30 09:33:11 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
# Parse the text
|
2007-11-12 07:30:40 +00:00
|
|
|
# Be careful not to double-PST: $text is usually already PST-ed once
|
2007-11-15 02:54:28 +00:00
|
|
|
if ( !$this->mPreparedEdit || $this->mPreparedEdit->output->getFlag( 'vary-revision' ) ) {
|
|
|
|
|
wfDebug( __METHOD__ . ": No prepared edit or vary-revision is set...\n" );
|
|
|
|
|
$editInfo = $this->prepareTextForEdit( $text, $newid );
|
2007-11-12 07:30:40 +00:00
|
|
|
} else {
|
2007-11-15 02:54:28 +00:00
|
|
|
wfDebug( __METHOD__ . ": No vary-revision, using prepared edit...\n" );
|
2007-11-12 07:30:40 +00:00
|
|
|
$editInfo = $this->mPreparedEdit;
|
|
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
|
|
|
|
|
# Save it to the parser cache
|
2008-01-16 02:20:49 +00:00
|
|
|
if ( $wgEnableParserCache ) {
|
2008-04-09 18:23:34 +00:00
|
|
|
$parserCache = ParserCache::singleton();
|
2008-06-11 02:51:30 +00:00
|
|
|
$parserCache->save( $editInfo->output, $this, $wgUser );
|
2008-01-16 02:20:49 +00:00
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
|
|
|
|
|
# Update the links tables
|
2007-11-12 07:30:40 +00:00
|
|
|
$u = new LinksUpdate( $this->mTitle, $editInfo->output );
|
2005-12-30 09:33:11 +00:00
|
|
|
$u->doUpdate();
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2007-08-22 07:24:30 +00:00
|
|
|
if( wfRunHooks( 'ArticleEditUpdatesDeleteFromRecentchanges', array( &$this ) ) ) {
|
2007-06-22 02:08:22 +00:00
|
|
|
if ( 0 == mt_rand( 0, 99 ) ) {
|
2007-08-22 07:24:30 +00:00
|
|
|
// Flush old entries from the `recentchanges` table; we do this on
|
|
|
|
|
// random requests so as to avoid an increase in writes for no good reason
|
2005-10-08 19:24:47 +00:00
|
|
|
global $wgRCMaxAge;
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2005-10-08 19:24:47 +00:00
|
|
|
$cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
|
|
|
|
|
$recentchanges = $dbw->tableName( 'recentchanges' );
|
|
|
|
|
$sql = "DELETE FROM $recentchanges WHERE rc_timestamp < '{$cutoff}'";
|
|
|
|
|
$dbw->query( $sql );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-01-31 16:59:08 +00:00
|
|
|
$id = $this->getID();
|
|
|
|
|
$title = $this->mTitle->getPrefixedDBkey();
|
|
|
|
|
$shortTitle = $this->mTitle->getDBkey();
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
if ( 0 == $id ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2005-12-30 09:33:11 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
$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
|
2006-06-24 13:08:48 +00:00
|
|
|
# Don't do this if $changed = false otherwise some idiot can null-edit a
|
2006-10-29 12:11:58 +00:00
|
|
|
# load of user talk pages and piss people off, nor if it's a minor edit
|
|
|
|
|
# by a properly-flagged bot.
|
|
|
|
|
if( $this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getTitleKey() && $changed
|
|
|
|
|
&& !($minoredit && $wgUser->isAllowed('nominornewtalk') ) ) {
|
2006-02-14 21:10:31 +00:00
|
|
|
if (wfRunHooks('ArticleEditUpdateNewTalk', array(&$this)) ) {
|
|
|
|
|
$other = User::newFromName( $shortTitle );
|
2008-08-08 09:47:36 +00:00
|
|
|
if ( !$other ) {
|
|
|
|
|
wfDebug( __METHOD__.": invalid username\n" );
|
|
|
|
|
} elseif( User::isIP( $shortTitle ) ) {
|
2006-02-14 21:10:31 +00:00
|
|
|
// An anonymous user
|
|
|
|
|
$other->setNewtalk( true );
|
2008-08-08 09:47:36 +00:00
|
|
|
} elseif( $other->isLoggedIn() ) {
|
2008-08-07 10:39:19 +00:00
|
|
|
$other->setNewtalk( true );
|
|
|
|
|
} else {
|
|
|
|
|
wfDebug( __METHOD__. ": don't need to notify a nonexistent user\n" );
|
2006-02-14 21:10:31 +00:00
|
|
|
}
|
2004-01-31 16:59:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
|
|
|
|
|
if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
|
|
|
|
$wgMessageCache->replace( $shortTitle, $text );
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2004-01-31 16:59:08 +00:00
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-10-09 02:15:12 +00:00
|
|
|
/**
|
|
|
|
|
* Perform article updates on a special page creation.
|
|
|
|
|
*
|
|
|
|
|
* @param Revision $rev
|
|
|
|
|
*
|
2007-09-07 13:30:28 +00:00
|
|
|
* @todo This is a shitty interface function. Kill it and replace the
|
|
|
|
|
* other shitty functions like editUpdates and such so it's not needed
|
2006-10-09 02:15:12 +00:00
|
|
|
* anymore.
|
|
|
|
|
*/
|
|
|
|
|
function createUpdates( $rev ) {
|
|
|
|
|
$this->mGoodAdjustment = $this->isCountable( $rev->getText() );
|
|
|
|
|
$this->mTotalAdjustment = 1;
|
|
|
|
|
$this->editUpdates( $rev->getText(), $rev->getComment(),
|
|
|
|
|
$rev->isMinor(), wfTimestamp(), $rev->getId(), true );
|
|
|
|
|
}
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
2006-01-16 18:34:11 +00:00
|
|
|
* Generate the navigation links when browsing through an article revisions
|
|
|
|
|
* It shows the information as:
|
2006-04-19 15:46:24 +00:00
|
|
|
* Revision as of \<date\>; view current revision
|
|
|
|
|
* \<- Previous version | Next Version -\>
|
2006-01-16 18:34:11 +00:00
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2004-10-02 21:36:36 +00:00
|
|
|
* @param string $oldid Revision ID of this article revision
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-10-02 21:36:36 +00:00
|
|
|
function setOldSubtitle( $oldid=0 ) {
|
2006-11-08 07:12:03 +00:00
|
|
|
global $wgLang, $wgOut, $wgUser;
|
2003-04-14 23:10:40 +00:00
|
|
|
|
2006-07-27 18:51:52 +00:00
|
|
|
if ( !wfRunHooks( 'DisplayOldSubtitle', array(&$this, &$oldid) ) ) {
|
2007-01-17 22:32:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2006-07-27 18:51:52 +00:00
|
|
|
|
2006-06-20 15:19:13 +00:00
|
|
|
$revision = Revision::newFromId( $oldid );
|
|
|
|
|
|
2005-06-29 23:44:03 +00:00
|
|
|
$current = ( $oldid == $this->mLatest );
|
2003-04-14 23:10:40 +00:00
|
|
|
$td = $wgLang->timeanddate( $this->mTimestamp, true );
|
2006-11-08 07:12:03 +00:00
|
|
|
$sk = $wgUser->getSkin();
|
2005-06-29 23:44:03 +00:00
|
|
|
$lnk = $current
|
|
|
|
|
? wfMsg( 'currentrevisionlink' )
|
2008-03-09 21:08:42 +00:00
|
|
|
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'currentrevisionlink' ) );
|
2006-11-16 05:44:59 +00:00
|
|
|
$curdiff = $current
|
|
|
|
|
? wfMsg( 'diff' )
|
|
|
|
|
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=cur&oldid='.$oldid );
|
2006-01-16 18:34:11 +00:00
|
|
|
$prev = $this->mTitle->getPreviousRevisionID( $oldid ) ;
|
|
|
|
|
$prevlink = $prev
|
2006-11-08 07:12:03 +00:00
|
|
|
? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'previousrevision' ), 'direction=prev&oldid='.$oldid )
|
2006-01-16 18:34:11 +00:00
|
|
|
: wfMsg( 'previousrevision' );
|
2006-07-01 18:47:36 +00:00
|
|
|
$prevdiff = $prev
|
2006-11-08 07:12:03 +00:00
|
|
|
? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=prev&oldid='.$oldid )
|
2006-07-01 18:47:36 +00:00
|
|
|
: wfMsg( 'diff' );
|
2005-06-29 23:44:03 +00:00
|
|
|
$nextlink = $current
|
|
|
|
|
? wfMsg( 'nextrevision' )
|
2006-11-08 07:12:03 +00:00
|
|
|
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'nextrevision' ), 'direction=next&oldid='.$oldid );
|
2006-07-01 18:47:36 +00:00
|
|
|
$nextdiff = $current
|
|
|
|
|
? wfMsg( 'diff' )
|
2006-11-08 07:12:03 +00:00
|
|
|
: $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2008-03-09 02:18:50 +00:00
|
|
|
$cdel='';
|
2008-04-14 07:45:50 +00:00
|
|
|
if( $wgUser->isAllowed( 'deleterevision' ) ) {
|
2008-03-09 02:18:50 +00:00
|
|
|
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
|
|
|
|
|
if( $revision->isCurrent() ) {
|
|
|
|
|
// We don't handle top deleted edits too well
|
2008-04-14 07:45:50 +00:00
|
|
|
$cdel = wfMsgHtml('rev-delundel');
|
2008-03-09 02:18:50 +00:00
|
|
|
} else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
|
|
|
|
|
// If revision was hidden from sysops
|
2008-04-14 07:45:50 +00:00
|
|
|
$cdel = wfMsgHtml('rev-delundel');
|
2008-03-09 02:18:50 +00:00
|
|
|
} else {
|
|
|
|
|
$cdel = $sk->makeKnownLinkObj( $revdel,
|
|
|
|
|
wfMsgHtml('rev-delundel'),
|
|
|
|
|
'target=' . urlencode( $this->mTitle->getPrefixedDbkey() ) .
|
|
|
|
|
'&oldid=' . urlencode( $oldid ) );
|
|
|
|
|
// Bolden oversighted content
|
|
|
|
|
if( $revision->isDeleted( Revision::DELETED_RESTRICTED ) )
|
|
|
|
|
$cdel = "<strong>$cdel</strong>";
|
|
|
|
|
}
|
|
|
|
|
$cdel = "(<small>$cdel</small>) ";
|
|
|
|
|
}
|
2008-03-16 21:24:52 +00:00
|
|
|
# Show user links if allowed to see them. Normally they
|
|
|
|
|
# are hidden regardless, but since we can already see the text here...
|
|
|
|
|
$userlinks = $sk->revUserTools( $revision, false );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-06-20 07:28:45 +00:00
|
|
|
$m = wfMsg( 'revision-info-current' );
|
|
|
|
|
$infomsg = $current && !wfEmptyMsg( 'revision-info-current', $m ) && $m != '-'
|
|
|
|
|
? 'revision-info-current'
|
|
|
|
|
: 'revision-info';
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-06-20 07:28:45 +00:00
|
|
|
$r = "\n\t\t\t\t<div id=\"mw-{$infomsg}\">" . wfMsg( $infomsg, $td, $userlinks ) . "</div>\n" .
|
2008-03-09 02:18:50 +00:00
|
|
|
|
|
|
|
|
"\n\t\t\t\t<div id=\"mw-revision-nav\">" . $cdel . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
|
2004-09-01 03:01:37 +00:00
|
|
|
$wgOut->setSubtitle( $r );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* This function is called right before saving the wikitext,
|
|
|
|
|
* so we can do things like signatures and links-in-context.
|
2004-09-03 00:20:26 +00:00
|
|
|
*
|
|
|
|
|
* @param string $text
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function preSaveTransform( $text ) {
|
2004-03-06 01:49:16 +00:00
|
|
|
global $wgParser, $wgUser;
|
|
|
|
|
return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) );
|
2003-04-14 23:10:40 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2003-05-16 13:39:22 +00:00
|
|
|
/* Caching functions */
|
2003-12-11 20:16:34 +00:00
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**
|
|
|
|
|
* 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)
|
|
|
|
|
*/
|
2003-08-02 10:13:27 +00:00
|
|
|
function tryFileCache() {
|
2003-11-24 08:41:40 +00:00
|
|
|
static $called = false;
|
|
|
|
|
if( $called ) {
|
2006-07-03 16:45:51 +00:00
|
|
|
wfDebug( "Article::tryFileCache(): called twice!?\n" );
|
2003-11-24 08:41:40 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$called = true;
|
2003-05-16 13:39:22 +00:00
|
|
|
if($this->isFileCacheable()) {
|
2003-09-05 21:12:24 +00:00
|
|
|
$touched = $this->mTouched;
|
2006-10-11 08:25:26 +00:00
|
|
|
$cache = new HTMLFileCache( $this->mTitle );
|
2003-09-05 21:12:24 +00:00
|
|
|
if($cache->isFileCacheGood( $touched )) {
|
2006-07-03 16:45:51 +00:00
|
|
|
wfDebug( "Article::tryFileCache(): about to load file\n" );
|
2003-08-02 10:13:27 +00:00
|
|
|
$cache->loadFromFileCache();
|
2003-12-11 20:16:34 +00:00
|
|
|
return true;
|
2003-05-16 13:39:22 +00:00
|
|
|
} else {
|
2006-07-03 16:45:51 +00:00
|
|
|
wfDebug( "Article::tryFileCache(): starting buffer\n" );
|
2003-08-02 10:13:27 +00:00
|
|
|
ob_start( array(&$cache, 'saveToFileCache' ) );
|
2003-05-16 13:39:22 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2006-07-03 16:45:51 +00:00
|
|
|
wfDebug( "Article::tryFileCache(): not cacheable\n" );
|
2003-05-16 13:39:22 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**
|
|
|
|
|
* Check if the page can be cached
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
2003-05-16 13:39:22 +00:00
|
|
|
function isFileCacheable() {
|
2007-04-25 13:07:29 +00:00
|
|
|
global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest, $wgLang, $wgContLang;
|
2006-11-29 11:43:58 +00:00
|
|
|
$action = $wgRequest->getVal( 'action' );
|
|
|
|
|
$oldid = $wgRequest->getVal( 'oldid' );
|
|
|
|
|
$diff = $wgRequest->getVal( 'diff' );
|
|
|
|
|
$redirect = $wgRequest->getVal( 'redirect' );
|
|
|
|
|
$printable = $wgRequest->getVal( 'printable' );
|
2007-04-20 12:31:36 +00:00
|
|
|
$page = $wgRequest->getVal( 'page' );
|
2008-08-10 07:10:05 +00:00
|
|
|
$useskin = $wgRequest->getVal( 'useskin' );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2008-04-14 07:45:50 +00:00
|
|
|
//check for non-standard user language; this covers uselang,
|
2007-04-25 13:07:29 +00:00
|
|
|
//and extensions for auto-detecting user language.
|
2008-04-14 07:45:50 +00:00
|
|
|
$ulang = $wgLang->getCode();
|
2007-04-25 13:07:29 +00:00
|
|
|
$clang = $wgContLang->getCode();
|
|
|
|
|
|
|
|
|
|
$cacheable = $wgUseFileCache
|
|
|
|
|
&& (!$wgShowIPinHeader)
|
|
|
|
|
&& ($this->getID() != 0)
|
|
|
|
|
&& ($wgUser->isAnon())
|
|
|
|
|
&& (!$wgUser->getNewtalk())
|
|
|
|
|
&& ($this->mTitle->getNamespace() != NS_SPECIAL )
|
2008-08-10 07:10:05 +00:00
|
|
|
&& (!isset($useskin))
|
2007-04-25 13:07:29 +00:00
|
|
|
&& (empty( $action ) || $action == 'view')
|
|
|
|
|
&& (!isset($oldid))
|
|
|
|
|
&& (!isset($diff))
|
|
|
|
|
&& (!isset($redirect))
|
|
|
|
|
&& (!isset($printable))
|
|
|
|
|
&& !isset($page)
|
|
|
|
|
&& (!$this->mRedirectedFrom)
|
|
|
|
|
&& ($ulang === $clang);
|
|
|
|
|
|
|
|
|
|
if ( $cacheable ) {
|
|
|
|
|
//extension may have reason to disable file caching on some pages.
|
|
|
|
|
$cacheable = wfRunHooks( 'IsFileCacheable', array( $this ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $cacheable;
|
2003-05-16 13:39:22 +00:00
|
|
|
}
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**
|
2005-12-30 09:33:11 +00:00
|
|
|
* Loads page_touched and returns a value indicating if it should be used
|
2004-09-03 00:20:26 +00:00
|
|
|
*
|
|
|
|
|
*/
|
2003-11-09 11:45:12 +00:00
|
|
|
function checkTouched() {
|
2005-03-18 08:37:50 +00:00
|
|
|
if( !$this->mDataLoaded ) {
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->loadPageData();
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
2005-03-18 08:37:50 +00:00
|
|
|
return !$this->mIsRedirect;
|
2003-11-09 11:45:12 +00:00
|
|
|
}
|
2004-05-27 15:24:04 +00:00
|
|
|
|
2005-12-30 09:33:11 +00:00
|
|
|
/**
|
|
|
|
|
* Get the page_touched field
|
|
|
|
|
*/
|
|
|
|
|
function getTouched() {
|
|
|
|
|
# Ensure that page data has been loaded
|
|
|
|
|
if( !$this->mDataLoaded ) {
|
2006-03-16 02:32:30 +00:00
|
|
|
$this->loadPageData();
|
2005-12-30 09:33:11 +00:00
|
|
|
}
|
|
|
|
|
return $this->mTouched;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-16 02:32:30 +00:00
|
|
|
/**
|
|
|
|
|
* Get the page_latest field
|
|
|
|
|
*/
|
|
|
|
|
function getLatest() {
|
|
|
|
|
if ( !$this->mDataLoaded ) {
|
|
|
|
|
$this->loadPageData();
|
|
|
|
|
}
|
|
|
|
|
return $this->mLatest;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**
|
|
|
|
|
* Edit an article without doing all that other stuff
|
2005-03-12 10:50:51 +00:00
|
|
|
* The article must already exist; link tables etc
|
|
|
|
|
* are not updated, caches are not flushed.
|
2004-09-03 00:20:26 +00:00
|
|
|
*
|
|
|
|
|
* @param string $text text submitted
|
|
|
|
|
* @param string $comment comment submitted
|
2005-03-12 10:50:51 +00:00
|
|
|
* @param bool $minor whereas it's a minor modification
|
2004-09-03 00:20:26 +00:00
|
|
|
*/
|
2004-06-08 19:51:10 +00:00
|
|
|
function quickEdit( $text, $comment = '', $minor = 0 ) {
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2004-06-02 13:14:40 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2005-03-12 10:50:51 +00:00
|
|
|
$dbw->begin();
|
|
|
|
|
$revision = new Revision( array(
|
|
|
|
|
'page' => $this->getId(),
|
|
|
|
|
'text' => $text,
|
|
|
|
|
'comment' => $comment,
|
|
|
|
|
'minor_edit' => $minor ? 1 : 0,
|
|
|
|
|
) );
|
2006-11-23 08:25:56 +00:00
|
|
|
$revision->insertOn( $dbw );
|
2005-03-13 07:49:15 +00:00
|
|
|
$this->updateRevisionOn( $dbw, $revision );
|
2005-03-12 10:50:51 +00:00
|
|
|
$dbw->commit();
|
2008-08-08 00:01:53 +00:00
|
|
|
|
2008-05-22 01:03:45 +00:00
|
|
|
wfRunHooks( 'NewRevisionFromEditComplete', array($this, $revision, false) );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2006-06-20 09:50:57 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2004-06-02 13:14:40 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**
|
|
|
|
|
* Used to increment the view counter
|
|
|
|
|
*
|
|
|
|
|
* @static
|
|
|
|
|
* @param integer $id article id
|
|
|
|
|
*/
|
|
|
|
|
function incViewCount( $id ) {
|
2003-12-13 21:32:32 +00:00
|
|
|
$id = intval( $id );
|
2006-04-12 08:15:28 +00:00
|
|
|
global $wgHitcounterUpdateFreq, $wgDBtype;
|
2004-01-17 19:59:42 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
2004-12-19 08:00:50 +00:00
|
|
|
$pageTable = $dbw->tableName( 'page' );
|
2004-07-10 03:09:26 +00:00
|
|
|
$hitcounterTable = $dbw->tableName( 'hitcounter' );
|
|
|
|
|
$acchitsTable = $dbw->tableName( 'acchits' );
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2006-11-28 21:32:59 +00:00
|
|
|
if( $wgHitcounterUpdateFreq <= 1 ) {
|
2004-12-19 08:00:50 +00:00
|
|
|
$dbw->query( "UPDATE $pageTable SET page_counter = page_counter + 1 WHERE page_id = $id" );
|
2004-01-17 19:59:42 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2003-12-13 21:32:32 +00:00
|
|
|
|
|
|
|
|
# Not important enough to warrant an error page in case of failure
|
2004-08-09 05:38:11 +00:00
|
|
|
$oldignore = $dbw->ignoreErrors( true );
|
2003-12-13 21:32:32 +00:00
|
|
|
|
2004-07-10 03:09:26 +00:00
|
|
|
$dbw->query( "INSERT INTO $hitcounterTable (hc_id) VALUES ({$id})" );
|
2003-12-13 21:32:32 +00:00
|
|
|
|
2004-01-17 19:59:42 +00:00
|
|
|
$checkfreq = intval( $wgHitcounterUpdateFreq/25 + 1 );
|
2004-07-10 03:09:26 +00:00
|
|
|
if( (rand() % $checkfreq != 0) or ($dbw->lastErrno() != 0) ){
|
2003-12-13 21:32:32 +00:00
|
|
|
# Most of the time (or on SQL errors), skip row count check
|
2004-08-05 07:48:20 +00:00
|
|
|
$dbw->ignoreErrors( $oldignore );
|
2003-12-13 21:32:32 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2004-07-10 03:09:26 +00:00
|
|
|
$res = $dbw->query("SELECT COUNT(*) as n FROM $hitcounterTable");
|
|
|
|
|
$row = $dbw->fetchObject( $res );
|
2003-12-13 21:32:32 +00:00
|
|
|
$rown = intval( $row->n );
|
2004-07-08 14:53:54 +00:00
|
|
|
if( $rown >= $wgHitcounterUpdateFreq ){
|
2004-06-08 19:51:10 +00:00
|
|
|
wfProfileIn( 'Article::incViewCount-collect' );
|
2003-12-13 21:32:32 +00:00
|
|
|
$old_user_abort = ignore_user_abort( true );
|
|
|
|
|
|
2006-04-12 08:15:28 +00:00
|
|
|
if ($wgDBtype == 'mysql')
|
|
|
|
|
$dbw->query("LOCK TABLES $hitcounterTable WRITE");
|
|
|
|
|
$tabletype = $wgDBtype == 'mysql' ? "ENGINE=HEAP " : '';
|
2006-12-31 23:59:23 +00:00
|
|
|
$dbw->query("CREATE TEMPORARY TABLE $acchitsTable $tabletype AS ".
|
2004-07-10 03:09:26 +00:00
|
|
|
"SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable ".
|
|
|
|
|
'GROUP BY hc_id');
|
|
|
|
|
$dbw->query("DELETE FROM $hitcounterTable");
|
2006-11-28 21:32:59 +00:00
|
|
|
if ($wgDBtype == 'mysql') {
|
2006-04-12 08:15:28 +00:00
|
|
|
$dbw->query('UNLOCK TABLES');
|
2006-11-28 21:32:59 +00:00
|
|
|
$dbw->query("UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n ".
|
|
|
|
|
'WHERE page_id = hc_id');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$dbw->query("UPDATE $pageTable SET page_counter=page_counter + hc_n ".
|
|
|
|
|
"FROM $acchitsTable WHERE page_id = hc_id");
|
|
|
|
|
}
|
2004-07-10 03:09:26 +00:00
|
|
|
$dbw->query("DROP TABLE $acchitsTable");
|
2003-12-13 21:32:32 +00:00
|
|
|
|
|
|
|
|
ignore_user_abort( $old_user_abort );
|
2004-06-08 19:51:10 +00:00
|
|
|
wfProfileOut( 'Article::incViewCount-collect' );
|
2003-12-13 21:32:32 +00:00
|
|
|
}
|
2004-08-05 07:48:20 +00:00
|
|
|
$dbw->ignoreErrors( $oldignore );
|
2003-12-13 21:32:32 +00:00
|
|
|
}
|
2004-01-05 23:32:39 +00:00
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**#@+
|
2004-09-02 23:28:24 +00:00
|
|
|
* The onArticle*() functions are supposed to be a kind of hooks
|
|
|
|
|
* which should be called whenever any of the specified actions
|
|
|
|
|
* are done.
|
2005-07-01 00:03:31 +00:00
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
* This is a good place to put code to clear caches, for instance.
|
2005-07-01 00:03:31 +00:00
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
* This is called on page move and undelete, as well as edit
|
|
|
|
|
* @static
|
|
|
|
|
* @param $title_obj a title object
|
|
|
|
|
*/
|
2004-09-03 00:20:26 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
static function onArticleCreate($title) {
|
2006-06-20 09:50:57 +00:00
|
|
|
# The talk page isn't in the regular link tables, so we need to update manually:
|
|
|
|
|
if ( $title->isTalkPage() ) {
|
|
|
|
|
$other = $title->getSubjectPage();
|
|
|
|
|
} else {
|
|
|
|
|
$other = $title->getTalkPage();
|
|
|
|
|
}
|
|
|
|
|
$other->invalidateCache();
|
|
|
|
|
$other->purgeSquid();
|
|
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
$title->touchLinks();
|
|
|
|
|
$title->purgeSquid();
|
2007-12-11 09:51:56 +00:00
|
|
|
$title->deleteTitleProtection();
|
2004-01-05 23:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
static function onArticleDelete( $title ) {
|
|
|
|
|
global $wgUseFileCache, $wgMessageCache;
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2008-03-25 00:14:32 +00:00
|
|
|
// Update existence markers on article/talk tabs...
|
|
|
|
|
if( $title->isTalkPage() ) {
|
|
|
|
|
$other = $title->getSubjectPage();
|
|
|
|
|
} else {
|
|
|
|
|
$other = $title->getTalkPage();
|
|
|
|
|
}
|
|
|
|
|
$other->invalidateCache();
|
|
|
|
|
$other->purgeSquid();
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2005-10-05 01:32:55 +00:00
|
|
|
$title->touchLinks();
|
2006-06-18 12:42:16 +00:00
|
|
|
$title->purgeSquid();
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
# File cache
|
|
|
|
|
if ( $wgUseFileCache ) {
|
2006-10-11 08:25:26 +00:00
|
|
|
$cm = new HTMLFileCache( $title );
|
2006-06-18 12:42:16 +00:00
|
|
|
@unlink( $cm->fileCacheName() );
|
|
|
|
|
}
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2008-05-21 05:23:20 +00:00
|
|
|
# Messages
|
|
|
|
|
if( $title->getNamespace() == NS_MEDIAWIKI ) {
|
2005-10-05 01:32:55 +00:00
|
|
|
$wgMessageCache->replace( $title->getDBkey(), false );
|
|
|
|
|
}
|
2008-05-21 05:23:20 +00:00
|
|
|
# Images
|
2008-01-26 18:45:54 +00:00
|
|
|
if( $title->getNamespace() == NS_IMAGE ) {
|
|
|
|
|
$update = new HTMLCacheUpdate( $title, 'imagelinks' );
|
|
|
|
|
$update->doUpdate();
|
|
|
|
|
}
|
2008-05-21 05:23:20 +00:00
|
|
|
# User talk pages
|
|
|
|
|
if( $title->getNamespace() == NS_USER_TALK ) {
|
|
|
|
|
$user = User::newFromName( $title->getText(), false );
|
|
|
|
|
$user->setNewtalk( false );
|
|
|
|
|
}
|
2004-01-05 23:32:39 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-12-08 01:36:33 +00:00
|
|
|
/**
|
|
|
|
|
* Purge caches on page update etc
|
|
|
|
|
*/
|
2006-06-18 12:42:16 +00:00
|
|
|
static function onArticleEdit( $title ) {
|
|
|
|
|
global $wgDeferredUpdateList, $wgUseFileCache;
|
2006-01-07 13:31:29 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
// Invalidate caches of articles which include this page
|
2008-01-17 12:31:54 +00:00
|
|
|
$wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'templatelinks' );
|
2005-12-08 01:36:33 +00:00
|
|
|
|
2008-01-17 12:31:54 +00:00
|
|
|
// Invalidate the caches of all pages which redirect here
|
|
|
|
|
$wgDeferredUpdateList[] = new HTMLCacheUpdate( $title, 'redirect' );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
# Purge squid for this page only
|
|
|
|
|
$title->purgeSquid();
|
2005-12-08 01:36:33 +00:00
|
|
|
|
2006-06-18 12:42:16 +00:00
|
|
|
# Clear file cache
|
2005-12-08 01:36:33 +00:00
|
|
|
if ( $wgUseFileCache ) {
|
2006-10-11 08:25:26 +00:00
|
|
|
$cm = new HTMLFileCache( $title );
|
2005-12-08 01:36:33 +00:00
|
|
|
@unlink( $cm->fileCacheName() );
|
|
|
|
|
}
|
2004-01-05 23:32:39 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2004-09-03 00:20:26 +00:00
|
|
|
/**#@-*/
|
2004-08-12 14:27:38 +00:00
|
|
|
|
2008-03-01 15:54:07 +00:00
|
|
|
/**
|
|
|
|
|
* Overriden by ImagePage class, only present here to avoid a fatal error
|
|
|
|
|
* Called for ?action=revert
|
|
|
|
|
*/
|
|
|
|
|
public function revert(){
|
|
|
|
|
global $wgOut;
|
|
|
|
|
$wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Info about this page
|
2005-02-28 04:52:37 +00:00
|
|
|
* Called for ?action=info when $wgAllowPageInfo is on.
|
|
|
|
|
*
|
2006-04-19 15:46:24 +00:00
|
|
|
* @public
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2004-08-12 14:27:38 +00:00
|
|
|
function info() {
|
2005-10-06 14:20:45 +00:00
|
|
|
global $wgLang, $wgOut, $wgAllowPageInfo, $wgUser;
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2004-07-09 11:42:24 +00:00
|
|
|
if ( !$wgAllowPageInfo ) {
|
2006-06-07 06:40:24 +00:00
|
|
|
$wgOut->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
|
2004-07-09 11:42:24 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2004-08-09 05:38:11 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
$page = $this->mTitle->getSubjectPage();
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
$wgOut->setPagetitle( $page->getPrefixedText() );
|
2007-07-22 14:45:12 +00:00
|
|
|
$wgOut->setPageTitleActionText( wfMsg( 'info_short' ) );
|
2007-08-01 01:23:44 +00:00
|
|
|
$wgOut->setSubtitle( wfMsg( 'infosubtitle' ) );
|
|
|
|
|
|
|
|
|
|
if( !$this->mTitle->exists() ) {
|
|
|
|
|
$wgOut->addHtml( '<div class="noarticletext">' );
|
|
|
|
|
if( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
|
|
|
|
|
// This doesn't quite make sense; the user is asking for
|
|
|
|
|
// information about the _page_, not the message... -- RC
|
|
|
|
|
$wgOut->addHtml( htmlspecialchars( wfMsgWeirdKey( $this->mTitle->getText() ) ) );
|
2005-12-28 14:47:30 +00:00
|
|
|
} else {
|
2007-08-01 01:23:44 +00:00
|
|
|
$msg = $wgUser->isLoggedIn()
|
|
|
|
|
? 'noarticletext'
|
|
|
|
|
: 'noarticletextanon';
|
|
|
|
|
$wgOut->addHtml( wfMsgExt( $msg, 'parse' ) );
|
2005-12-28 14:47:30 +00:00
|
|
|
}
|
2007-08-01 01:23:44 +00:00
|
|
|
$wgOut->addHtml( '</div>' );
|
2004-07-08 14:53:54 +00:00
|
|
|
} else {
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2005-02-28 04:52:37 +00:00
|
|
|
$wl_clause = array(
|
|
|
|
|
'wl_title' => $page->getDBkey(),
|
|
|
|
|
'wl_namespace' => $page->getNamespace() );
|
|
|
|
|
$numwatchers = $dbr->selectField(
|
|
|
|
|
'watchlist',
|
|
|
|
|
'COUNT(*)',
|
|
|
|
|
$wl_clause,
|
2006-06-20 09:50:57 +00:00
|
|
|
__METHOD__,
|
2004-08-20 14:59:49 +00:00
|
|
|
$this->getSelectOptions() );
|
2004-07-08 14:53:54 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
$pageInfo = $this->pageCountInfo( $page );
|
|
|
|
|
$talkInfo = $this->pageCountInfo( $page->getTalkPage() );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
$wgOut->addHTML( "<ul><li>" . wfMsg("numwatchers", $wgLang->formatNum( $numwatchers ) ) . '</li>' );
|
|
|
|
|
$wgOut->addHTML( "<li>" . wfMsg('numedits', $wgLang->formatNum( $pageInfo['edits'] ) ) . '</li>');
|
|
|
|
|
if( $talkInfo ) {
|
|
|
|
|
$wgOut->addHTML( '<li>' . wfMsg("numtalkedits", $wgLang->formatNum( $talkInfo['edits'] ) ) . '</li>');
|
2004-07-08 14:53:54 +00:00
|
|
|
}
|
2005-02-28 04:52:37 +00:00
|
|
|
$wgOut->addHTML( '<li>' . wfMsg("numauthors", $wgLang->formatNum( $pageInfo['authors'] ) ) . '</li>' );
|
|
|
|
|
if( $talkInfo ) {
|
|
|
|
|
$wgOut->addHTML( '<li>' . wfMsg('numtalkauthors', $wgLang->formatNum( $talkInfo['authors'] ) ) . '</li>' );
|
2004-07-08 14:53:54 +00:00
|
|
|
}
|
2005-02-28 04:52:37 +00:00
|
|
|
$wgOut->addHTML( '</ul>' );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
/**
|
|
|
|
|
* Return the total number of edits and number of unique editors
|
|
|
|
|
* on a given page. If page does not exist, returns false.
|
|
|
|
|
*
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @return array
|
2006-04-19 15:46:24 +00:00
|
|
|
* @private
|
2005-02-28 04:52:37 +00:00
|
|
|
*/
|
|
|
|
|
function pageCountInfo( $title ) {
|
|
|
|
|
$id = $title->getArticleId();
|
|
|
|
|
if( $id == 0 ) {
|
|
|
|
|
return false;
|
2004-07-08 14:53:54 +00:00
|
|
|
}
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2005-02-28 04:52:37 +00:00
|
|
|
|
|
|
|
|
$rev_clause = array( 'rev_page' => $id );
|
|
|
|
|
|
|
|
|
|
$edits = $dbr->selectField(
|
|
|
|
|
'revision',
|
|
|
|
|
'COUNT(rev_page)',
|
|
|
|
|
$rev_clause,
|
2006-06-20 09:50:57 +00:00
|
|
|
__METHOD__,
|
2005-02-28 04:52:37 +00:00
|
|
|
$this->getSelectOptions() );
|
|
|
|
|
|
|
|
|
|
$authors = $dbr->selectField(
|
|
|
|
|
'revision',
|
|
|
|
|
'COUNT(DISTINCT rev_user_text)',
|
|
|
|
|
$rev_clause,
|
2006-06-20 09:50:57 +00:00
|
|
|
__METHOD__,
|
2005-02-28 04:52:37 +00:00
|
|
|
$this->getSelectOptions() );
|
2005-07-01 00:03:31 +00:00
|
|
|
|
2005-02-28 04:52:37 +00:00
|
|
|
return array( 'edits' => $edits, 'authors' => $authors );
|
2004-07-08 14:53:54 +00:00
|
|
|
}
|
2005-04-03 07:01:29 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return a list of templates used by this article.
|
2005-12-30 09:33:11 +00:00
|
|
|
* Uses the templatelinks table
|
2005-04-03 07:01:29 +00:00
|
|
|
*
|
2005-12-30 09:33:11 +00:00
|
|
|
* @return array Array of Title objects
|
2005-04-03 07:01:29 +00:00
|
|
|
*/
|
|
|
|
|
function getUsedTemplates() {
|
|
|
|
|
$result = array();
|
|
|
|
|
$id = $this->mTitle->getArticleID();
|
2006-03-07 04:23:09 +00:00
|
|
|
if( $id == 0 ) {
|
|
|
|
|
return array();
|
|
|
|
|
}
|
2005-04-03 07:01:29 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2005-12-30 09:33:11 +00:00
|
|
|
$res = $dbr->select( array( 'templatelinks' ),
|
|
|
|
|
array( 'tl_namespace', 'tl_title' ),
|
|
|
|
|
array( 'tl_from' => $id ),
|
2008-07-25 19:36:13 +00:00
|
|
|
__METHOD__ );
|
2008-07-27 18:59:46 +00:00
|
|
|
if( false !== $res ) {
|
|
|
|
|
foreach( $res as $row ) {
|
|
|
|
|
$result[] = Title::makeTitle( $row->tl_namespace, $row->tl_title );
|
2005-04-03 07:01:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-12-30 09:33:11 +00:00
|
|
|
$dbr->freeResult( $res );
|
2005-04-03 07:01:29 +00:00
|
|
|
return $result;
|
|
|
|
|
}
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2008-02-25 13:38:21 +00:00
|
|
|
/**
|
|
|
|
|
* Returns a list of hidden categories this page is a member of.
|
|
|
|
|
* Uses the page_props and categorylinks tables.
|
|
|
|
|
*
|
|
|
|
|
* @return array Array of Title objects
|
|
|
|
|
*/
|
|
|
|
|
function getHiddenCategories() {
|
|
|
|
|
$result = array();
|
|
|
|
|
$id = $this->mTitle->getArticleID();
|
|
|
|
|
if( $id == 0 ) {
|
|
|
|
|
return array();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
|
|
|
$res = $dbr->select( array( 'categorylinks', 'page_props', 'page' ),
|
|
|
|
|
array( 'cl_to' ),
|
2008-04-14 07:45:50 +00:00
|
|
|
array( 'cl_from' => $id, 'pp_page=page_id', 'pp_propname' => 'hiddencat',
|
2008-02-25 13:38:21 +00:00
|
|
|
'page_namespace' => NS_CATEGORY, 'page_title=cl_to'),
|
2008-07-25 19:36:13 +00:00
|
|
|
__METHOD__ );
|
2008-02-25 13:38:21 +00:00
|
|
|
if ( false !== $res ) {
|
2008-07-27 18:59:46 +00:00
|
|
|
foreach( $res as $row ) {
|
|
|
|
|
$result[] = Title::makeTitle( NS_CATEGORY, $row->cl_to );
|
2008-02-25 13:38:21 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$dbr->freeResult( $res );
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-20 11:48:03 +00:00
|
|
|
/**
|
|
|
|
|
* Return an applicable autosummary if one exists for the given edit.
|
|
|
|
|
* @param string $oldtext The previous text of the page.
|
|
|
|
|
* @param string $newtext The submitted text of the page.
|
|
|
|
|
* @param bitmask $flags A bitmask of flags submitted for the edit.
|
|
|
|
|
* @return string An appropriate autosummary, or an empty string.
|
|
|
|
|
*/
|
|
|
|
|
public static function getAutosummary( $oldtext, $newtext, $flags ) {
|
2008-05-24 14:55:54 +00:00
|
|
|
# Decide what kind of autosummary is needed.
|
2006-11-20 11:48:03 +00:00
|
|
|
|
2008-05-24 14:55:54 +00:00
|
|
|
# Redirect autosummaries
|
|
|
|
|
$rt = Title::newFromRedirect( $newtext );
|
|
|
|
|
if( is_object( $rt ) ) {
|
|
|
|
|
return wfMsgForContent( 'autoredircomment', $rt->getFullText() );
|
|
|
|
|
}
|
2006-11-20 11:48:03 +00:00
|
|
|
|
2008-05-24 14:55:54 +00:00
|
|
|
# New page autosummaries
|
|
|
|
|
if( $flags & EDIT_NEW && strlen( $newtext ) ) {
|
|
|
|
|
# If they're making a new article, give its text, truncated, in the summary.
|
2006-11-23 09:32:28 +00:00
|
|
|
global $wgContLang;
|
2006-12-22 19:58:25 +00:00
|
|
|
$truncatedtext = $wgContLang->truncate(
|
|
|
|
|
str_replace("\n", ' ', $newtext),
|
|
|
|
|
max( 0, 200 - strlen( wfMsgForContent( 'autosumm-new') ) ),
|
|
|
|
|
'...' );
|
2008-05-24 14:55:54 +00:00
|
|
|
return wfMsgForContent( 'autosumm-new', $truncatedtext );
|
2006-11-23 09:32:28 +00:00
|
|
|
}
|
|
|
|
|
|
2008-05-24 14:55:54 +00:00
|
|
|
# Blanking autosummaries
|
|
|
|
|
if( $oldtext != '' && $newtext == '' ) {
|
|
|
|
|
return wfMsgForContent('autosumm-blank');
|
|
|
|
|
} elseif( strlen( $oldtext ) > 10 * strlen( $newtext ) && strlen( $newtext ) < 500) {
|
|
|
|
|
# Removing more than 90% of the article
|
|
|
|
|
global $wgContLang;
|
|
|
|
|
$truncatedtext = $wgContLang->truncate(
|
|
|
|
|
$newtext,
|
|
|
|
|
max( 0, 200 - strlen( wfMsgForContent( 'autosumm-replace' ) ) ),
|
|
|
|
|
'...'
|
|
|
|
|
);
|
|
|
|
|
return wfMsgForContent( 'autosumm-replace', $truncatedtext );
|
|
|
|
|
}
|
2006-11-20 11:48:03 +00:00
|
|
|
|
2008-05-24 14:55:54 +00:00
|
|
|
# If we reach this point, there's no applicable autosummary for our case, so our
|
|
|
|
|
# autosummary is empty.
|
|
|
|
|
return '';
|
2006-11-20 11:48:03 +00:00
|
|
|
}
|
2007-01-10 23:32:38 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Add the primary page-view wikitext to the output buffer
|
|
|
|
|
* Saves the text into the parser cache if possible.
|
2007-01-11 00:31:04 +00:00
|
|
|
* Updates templatelinks if it is out of date.
|
2007-01-10 23:32:38 +00:00
|
|
|
*
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @param bool $cache
|
|
|
|
|
*/
|
|
|
|
|
public function outputWikiText( $text, $cache = true ) {
|
2008-01-16 02:20:49 +00:00
|
|
|
global $wgParser, $wgUser, $wgOut, $wgEnableParserCache;
|
2007-01-10 23:32:38 +00:00
|
|
|
|
|
|
|
|
$popts = $wgOut->parserOptions();
|
|
|
|
|
$popts->setTidy(true);
|
2007-11-30 16:57:02 +00:00
|
|
|
$popts->enableLimitReport();
|
2007-01-11 00:31:04 +00:00
|
|
|
$parserOutput = $wgParser->parse( $text, $this->mTitle,
|
|
|
|
|
$popts, true, true, $this->getRevIdFetched() );
|
2007-01-10 23:32:38 +00:00
|
|
|
$popts->setTidy(false);
|
2007-11-30 16:57:02 +00:00
|
|
|
$popts->enableLimitReport( false );
|
2008-01-16 02:20:49 +00:00
|
|
|
if ( $wgEnableParserCache && $cache && $this && $parserOutput->getCacheTime() != -1 ) {
|
2008-04-09 18:23:34 +00:00
|
|
|
$parserCache = ParserCache::singleton();
|
2007-01-11 00:44:55 +00:00
|
|
|
$parserCache->save( $parserOutput, $this, $wgUser );
|
2007-01-10 23:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
2007-01-14 10:55:23 +00:00
|
|
|
if ( !wfReadOnly() && $this->mTitle->areRestrictionsCascading() ) {
|
|
|
|
|
// templatelinks table may have become out of sync,
|
|
|
|
|
// especially if using variable-based transclusions.
|
|
|
|
|
// For paranoia, check if things have changed and if
|
|
|
|
|
// so apply updates to the database. This will ensure
|
|
|
|
|
// that cascaded protections apply as soon as the changes
|
|
|
|
|
// are visible.
|
2007-01-10 23:32:38 +00:00
|
|
|
|
|
|
|
|
# Get templates from templatelinks
|
2007-01-11 00:31:04 +00:00
|
|
|
$id = $this->mTitle->getArticleID();
|
|
|
|
|
|
2007-01-11 00:52:50 +00:00
|
|
|
$tlTemplates = array();
|
2007-01-10 23:32:38 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2007-01-11 00:31:04 +00:00
|
|
|
$res = $dbr->select( array( 'templatelinks' ),
|
|
|
|
|
array( 'tl_namespace', 'tl_title' ),
|
|
|
|
|
array( 'tl_from' => $id ),
|
2008-07-25 19:36:13 +00:00
|
|
|
__METHOD__ );
|
2007-01-11 00:31:04 +00:00
|
|
|
|
2007-01-11 00:44:55 +00:00
|
|
|
global $wgContLang;
|
|
|
|
|
|
2007-01-11 00:31:04 +00:00
|
|
|
if ( false !== $res ) {
|
2008-07-27 18:59:46 +00:00
|
|
|
foreach( $res as $row ) {
|
|
|
|
|
$tlTemplates[] = $wgContLang->getNsText( $row->tl_namespace ) . ':' . $row->tl_title ;
|
2007-01-11 00:31:04 +00:00
|
|
|
}
|
2007-01-10 23:32:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get templates from parser output.
|
|
|
|
|
$poTemplates_allns = $parserOutput->getTemplates();
|
|
|
|
|
|
|
|
|
|
$poTemplates = array ();
|
|
|
|
|
foreach ( $poTemplates_allns as $ns_templates ) {
|
|
|
|
|
$poTemplates = array_merge( $poTemplates, $ns_templates );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Get the diff
|
|
|
|
|
$templates_diff = array_diff( $poTemplates, $tlTemplates );
|
|
|
|
|
|
|
|
|
|
if ( count( $templates_diff ) > 0 ) {
|
|
|
|
|
# Whee, link updates time.
|
|
|
|
|
$u = new LinksUpdate( $this->mTitle, $parserOutput );
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbw = wfGetDb( DB_MASTER );
|
2007-01-10 23:32:38 +00:00
|
|
|
$dbw->begin();
|
2007-01-17 22:32:40 +00:00
|
|
|
|
2007-01-10 23:32:38 +00:00
|
|
|
$u->doUpdate();
|
|
|
|
|
|
|
|
|
|
$dbw->commit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$wgOut->addParserOutput( $parserOutput );
|
|
|
|
|
}
|
|
|
|
|
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
/**
|
|
|
|
|
* Update all the appropriate counts in the category table, given that
|
|
|
|
|
* we've added the categories $added and deleted the categories $deleted.
|
|
|
|
|
*
|
|
|
|
|
* @param $added array The names of categories that were added
|
|
|
|
|
* @param $deleted array The names of categories that were deleted
|
|
|
|
|
* @return null
|
|
|
|
|
*/
|
2008-03-19 13:36:33 +00:00
|
|
|
public function updateCategoryCounts( $added, $deleted ) {
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
$ns = $this->mTitle->getNamespace();
|
2008-03-19 13:36:33 +00:00
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
|
|
|
|
|
# First make sure the rows exist. If one of the "deleted" ones didn't
|
|
|
|
|
# exist, we might legitimately not create it, but it's simpler to just
|
|
|
|
|
# create it and then give it a negative value, since the value is bogus
|
|
|
|
|
# anyway.
|
|
|
|
|
#
|
|
|
|
|
# Sometimes I wish we had INSERT ... ON DUPLICATE KEY UPDATE.
|
|
|
|
|
$insertCats = array_merge( $added, $deleted );
|
2008-03-20 17:33:32 +00:00
|
|
|
if( !$insertCats ) {
|
|
|
|
|
# Okay, nothing to do
|
|
|
|
|
return;
|
|
|
|
|
}
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
$insertRows = array();
|
|
|
|
|
foreach( $insertCats as $cat ) {
|
2008-03-19 11:19:00 +00:00
|
|
|
$insertRows[] = array( 'cat_title' => $cat );
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
}
|
2008-03-21 02:16:28 +00:00
|
|
|
$dbw->insert( 'category', $insertRows, __METHOD__, 'IGNORE' );
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
|
|
|
|
|
$addFields = array( 'cat_pages = cat_pages + 1' );
|
|
|
|
|
$removeFields = array( 'cat_pages = cat_pages - 1' );
|
|
|
|
|
if( $ns == NS_CATEGORY ) {
|
2008-03-19 11:19:00 +00:00
|
|
|
$addFields[] = 'cat_subcats = cat_subcats + 1';
|
|
|
|
|
$removeFields[] = 'cat_subcats = cat_subcats - 1';
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
} elseif( $ns == NS_IMAGE ) {
|
2008-03-19 11:19:00 +00:00
|
|
|
$addFields[] = 'cat_files = cat_files + 1';
|
|
|
|
|
$removeFields[] = 'cat_files = cat_files - 1';
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
}
|
|
|
|
|
|
2008-03-19 11:19:00 +00:00
|
|
|
if ( $added ) {
|
|
|
|
|
$dbw->update(
|
|
|
|
|
'category',
|
|
|
|
|
$addFields,
|
|
|
|
|
array( 'cat_title' => $added ),
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if ( $deleted ) {
|
|
|
|
|
$dbw->update(
|
|
|
|
|
'category',
|
|
|
|
|
$removeFields,
|
|
|
|
|
array( 'cat_title' => $deleted ),
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
|
|
|
|
}
|
This is a schema change. It's only a table creation, but the table must be created on Wikimedia servers before this revision goes live. The maintenance script populateCategory.php should be run when convenient. If it's not run, there's only one substantial case where display will be harmed: the page of a category with more than 200 net pages added since the patch goes live will give an erroneously low count. In other cases category pages will just be better-worded, and it will recognize the count in the table is bogus.
* Adds Category and CategoryList classes to represent categories themselves.
* Adds a category table, giving each category a name, ID, and counts of all members, subcats only, and files.
* Adds a maintenance script to populate the category table efficiently. This script is careful to wait for slaves and should be safe to run on a live database. The maintenance script's includes file is called by update.php.
* Until the category table is populated, the patch handles weird category table rows gracefully. It detects whether they're obviously impossible, and if so, it outputs appropriate messages.
2008-03-18 00:17:28 +00:00
|
|
|
}
|
2007-07-22 14:45:12 +00:00
|
|
|
}
|