2003-12-21 12:01:29 +00:00
|
|
|
<?php
|
2004-09-02 23:28:24 +00:00
|
|
|
/**
|
|
|
|
|
* Page history
|
2005-06-29 03:37:57 +00:00
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
* Split off from Article.php and Skin.php, 2003-12-22
|
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
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2005-06-29 03:37:57 +00:00
|
|
|
* This class handles printing the history page for an article. In order to
|
|
|
|
|
* be efficient, it uses timestamps rather than offsets for paging, to avoid
|
|
|
|
|
* costly LIMIT,offset queries.
|
|
|
|
|
*
|
|
|
|
|
* Construct it by passing in an Article, and call $h->history() to print the
|
|
|
|
|
* history.
|
|
|
|
|
*
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
2003-12-21 12:01:29 +00:00
|
|
|
class PageHistory {
|
2006-06-06 12:28:44 +00:00
|
|
|
const DIR_PREV = 0;
|
|
|
|
|
const DIR_NEXT = 1;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-11-08 07:12:03 +00:00
|
|
|
var $mArticle, $mTitle, $mSkin;
|
2006-05-11 22:40:38 +00:00
|
|
|
var $lastdate;
|
|
|
|
|
var $linesonpage;
|
|
|
|
|
var $mLatestId = null;
|
2009-02-09 07:42:54 +00:00
|
|
|
|
|
|
|
|
private $mOldIdChecked = 0;
|
2005-06-29 03:37:57 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a new PageHistory.
|
|
|
|
|
*
|
|
|
|
|
* @param Article $article
|
|
|
|
|
* @returns nothing
|
|
|
|
|
*/
|
2008-11-08 19:41:38 +00:00
|
|
|
function __construct( $article ) {
|
2006-11-08 07:12:03 +00:00
|
|
|
global $wgUser;
|
2003-12-21 12:01:29 +00:00
|
|
|
$this->mArticle =& $article;
|
|
|
|
|
$this->mTitle =& $article->mTitle;
|
2006-11-08 07:12:03 +00:00
|
|
|
$this->mSkin = $wgUser->getSkin();
|
2008-03-09 02:27:03 +00:00
|
|
|
$this->preCacheMessages();
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-05-23 09:03:49 +00:00
|
|
|
function getArticle() {
|
|
|
|
|
return $this->mArticle;
|
|
|
|
|
}
|
2008-08-21 00:45:13 +00:00
|
|
|
|
2008-05-23 16:47:39 +00:00
|
|
|
function getTitle() {
|
|
|
|
|
return $this->mTitle;
|
|
|
|
|
}
|
2008-05-23 09:03:49 +00:00
|
|
|
|
2008-03-09 02:27:03 +00:00
|
|
|
/**
|
|
|
|
|
* As we use the same small set of messages in various methods and that
|
|
|
|
|
* they are called often, we call them once and save them in $this->message
|
|
|
|
|
*/
|
|
|
|
|
function preCacheMessages() {
|
|
|
|
|
// Precache various messages
|
|
|
|
|
if( !isset( $this->message ) ) {
|
|
|
|
|
foreach( explode(' ', 'cur last rev-delundel' ) as $msg ) {
|
|
|
|
|
$this->message[$msg] = wfMsgExt( $msg, array( 'escape') );
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-12-21 12:01:29 +00:00
|
|
|
}
|
2004-08-28 18:54:23 +00:00
|
|
|
|
2005-06-29 03:37:57 +00:00
|
|
|
/**
|
|
|
|
|
* Print the history page for an article.
|
|
|
|
|
*
|
|
|
|
|
* @returns nothing
|
|
|
|
|
*/
|
2004-09-02 23:28:24 +00:00
|
|
|
function history() {
|
2009-04-11 23:05:13 +00:00
|
|
|
global $wgOut, $wgRequest, $wgScript;
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2005-06-29 03:37:57 +00:00
|
|
|
/*
|
|
|
|
|
* Allow client caching.
|
|
|
|
|
*/
|
2008-03-18 18:43:03 +00:00
|
|
|
if( $wgOut->checkLastModified( $this->mArticle->getTouched() ) )
|
2008-11-08 19:41:38 +00:00
|
|
|
return; // Client cache fresh and headers sent, nothing more to do.
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2008-03-09 21:08:42 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2005-06-29 03:37:57 +00:00
|
|
|
/*
|
|
|
|
|
* Setup page variables.
|
|
|
|
|
*/
|
2007-09-20 08:03:01 +00:00
|
|
|
$wgOut->setPageTitle( wfMsg( 'history-title', $this->mTitle->getPrefixedText() ) );
|
2007-07-22 14:45:12 +00:00
|
|
|
$wgOut->setPageTitleActionText( wfMsg( 'history_short' ) );
|
2003-12-21 12:01:29 +00:00
|
|
|
$wgOut->setArticleFlag( false );
|
2004-01-17 09:49:43 +00:00
|
|
|
$wgOut->setArticleRelated( true );
|
2008-07-23 19:05:43 +00:00
|
|
|
$wgOut->setRobotPolicy( 'noindex,nofollow' );
|
2006-05-28 03:47:28 +00:00
|
|
|
$wgOut->setSyndicated( true );
|
2008-01-12 00:13:53 +00:00
|
|
|
$wgOut->setFeedAppendQuery( 'action=history' );
|
2008-05-09 20:51:32 +00:00
|
|
|
$wgOut->addScriptFile( 'history.js' );
|
2006-05-28 03:47:28 +00:00
|
|
|
|
2006-10-30 06:25:31 +00:00
|
|
|
$logPage = SpecialPage::getTitleFor( 'Log' );
|
2009-06-07 15:02:12 +00:00
|
|
|
$logLink = $this->mSkin->link(
|
|
|
|
|
$logPage,
|
|
|
|
|
wfMsgHtml( 'viewpagelogs' ),
|
|
|
|
|
array(),
|
2009-06-15 12:32:59 +00:00
|
|
|
array( 'page' => $this->mTitle->getPrefixedText() ),
|
2009-06-07 15:02:12 +00:00
|
|
|
array( 'known', 'noclasses' )
|
|
|
|
|
);
|
2007-12-04 11:12:10 +00:00
|
|
|
$wgOut->setSubtitle( $logLink );
|
2006-07-04 04:08:35 +00:00
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
$feedType = $wgRequest->getVal( 'feed' );
|
|
|
|
|
if( $feedType ) {
|
2008-03-09 21:08:42 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2006-05-28 03:47:28 +00:00
|
|
|
return $this->feed( $feedType );
|
|
|
|
|
}
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2005-06-29 03:37:57 +00:00
|
|
|
/*
|
|
|
|
|
* Fail if article doesn't exist.
|
|
|
|
|
*/
|
2005-08-12 16:14:20 +00:00
|
|
|
if( !$this->mTitle->exists() ) {
|
2008-02-18 07:25:35 +00:00
|
|
|
$wgOut->addWikiMsg( 'nohistory' );
|
2008-03-09 21:08:42 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
2003-12-21 12:01:29 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2004-08-28 18:54:23 +00:00
|
|
|
|
2008-08-01 22:59:06 +00:00
|
|
|
/**
|
|
|
|
|
* Add date selector to quickly get to a certain time
|
|
|
|
|
*/
|
|
|
|
|
$year = $wgRequest->getInt( 'year' );
|
|
|
|
|
$month = $wgRequest->getInt( 'month' );
|
2009-01-28 19:08:18 +00:00
|
|
|
$tagFilter = $wgRequest->getVal( 'tagfilter' );
|
2009-01-30 23:24:29 +00:00
|
|
|
$tagSelector = ChangeTags::buildTagFilterSelector( $tagFilter );
|
2008-08-21 00:45:13 +00:00
|
|
|
|
2008-08-01 22:59:06 +00:00
|
|
|
$action = htmlspecialchars( $wgScript );
|
2008-08-03 19:40:37 +00:00
|
|
|
$wgOut->addHTML(
|
2008-10-28 18:05:25 +00:00
|
|
|
"<form action=\"$action\" method=\"get\" id=\"mw-history-searchform\">" .
|
2008-11-08 19:41:38 +00:00
|
|
|
Xml::fieldset( wfMsg( 'history-fieldset-title' ), false, array( 'id' => 'mw-history-search' ) ) .
|
|
|
|
|
Xml::hidden( 'title', $this->mTitle->getPrefixedDBKey() ) . "\n" .
|
|
|
|
|
Xml::hidden( 'action', 'history' ) . "\n" .
|
2009-02-12 19:23:14 +00:00
|
|
|
xml::dateMenu( $year, $month ) . ' ' .
|
2009-01-30 23:24:29 +00:00
|
|
|
( $tagSelector ? ( implode( ' ', $tagSelector ) . ' ' ) : '' ) .
|
2008-11-08 19:41:38 +00:00
|
|
|
Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
|
|
|
|
|
'</fieldset></form>'
|
|
|
|
|
);
|
2007-12-04 11:12:10 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
wfRunHooks( 'PageHistoryBeforeList', array( &$this->mArticle ) );
|
2005-06-29 00:23:42 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
/**
|
|
|
|
|
* Do the list
|
|
|
|
|
*/
|
2009-01-28 19:08:18 +00:00
|
|
|
$pager = new PageHistoryPager( $this, $year, $month, $tagFilter );
|
2008-11-08 19:41:38 +00:00
|
|
|
$this->linesonpage = $pager->getNumRows();
|
|
|
|
|
$wgOut->addHTML(
|
2008-04-14 07:45:50 +00:00
|
|
|
$pager->getNavigationBar() .
|
|
|
|
|
$this->beginHistoryList() .
|
2006-11-19 17:16:34 +00:00
|
|
|
$pager->getBody() .
|
2006-07-07 17:11:47 +00:00
|
|
|
$this->endHistoryList() .
|
|
|
|
|
$pager->getNavigationBar()
|
2008-11-08 19:41:38 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
2003-12-21 12:01:29 +00:00
|
|
|
}
|
2008-08-21 00:45:13 +00:00
|
|
|
|
2007-12-11 17:00:12 +00:00
|
|
|
/**
|
|
|
|
|
* Creates begin of history list with a submit button
|
|
|
|
|
*
|
|
|
|
|
* @return string HTML output
|
|
|
|
|
*/
|
2004-09-02 23:28:24 +00:00
|
|
|
function beginHistoryList() {
|
2009-04-11 23:05:13 +00:00
|
|
|
global $wgUser, $wgScript, $wgEnableHtmlDiff;
|
2005-03-31 11:40:05 +00:00
|
|
|
$this->lastdate = '';
|
2006-04-27 14:50:45 +00:00
|
|
|
$s = wfMsgExt( 'histlegend', array( 'parse') );
|
2009-04-16 04:51:43 +00:00
|
|
|
if( $this->linesonpage > 1 && $wgUser->isAllowed('deleterevision') ) {
|
2009-04-11 17:38:21 +00:00
|
|
|
$revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
|
|
|
|
|
$s .= Xml::openElement( 'form',
|
|
|
|
|
array(
|
In Special:RevisionDelete:
* Refactored to remove massive duplication
* Removed page parameter and associated contextPage member variable, doesn't seem to do anything.
* Put ID lists into a single ids parameter and member variable instead of having one for each type.
* Fixed inappropriate call of Title::newFromUrl(), always wrong
* Don't pretend to use the return value from functions that don't return anything, this reduces readability.
* Use the table names for deleteKey/typeName values, they look more like English
* Use protected not private
* Remove requirement for log type to be specified in the target
* Use POST for RevisionDelete entry forms, to avoid URL size limits and issues with non-PATH_INFO URLs
* Don't purge all pages that use the given file
* LocalFile::purgeCache() already calls purgeHistory,() no need to do it again. But do call purgeDescription().
* Removed token from unhide=1 links, unnecessary
* Tokens are necessary on file streaming links, added them
* Fixed private data leakage due to incorrect use of LocalRepo::newFromArchiveName(). Non-existent placeholder file was returned which meant that $oimage->userCan(File::DELETED_FILE) was always true. Pass the archive name to tryShowFile() instead of the storage key.
* Using ls_field='oi_timestamp' is not correct, oi_timestamp refers to the timestamp of the revision in question, whereas the key that is stored is the timestamp of the previous revision (i.e. the timestamp in oi_archive_name). oi_archive_name would be more correct, although only half the field is used.
Elsewhere:
* Added missing message filehist-missing
* Fixed double asterisk in Status::getWikiText()
* Fixed escaping of the target parameter to Special:RevisionDelete from ImagePage
* Deleted FileStore.php. Deprecated in filerepo refactor except for get()/export() but somehow resurrected by RevisionDelete. Hopefully this will be the end of it. New interfaces will be added for wfStreamFile() in a later commit.
* Added convenience function File::getStorageKey(), factored out of Special:Undelete
* Added convenience function Revision::newFromArchiveRow(), factored out of Special:Undelete and Special:RevisionDelete
* Fixed notice in Special:Upload, uninitialised $pageText
FIXME: current revision can be suppressed on undeletion causing an unauthenticated unsuppress. Comments indicate this is a known issue. I fixed the parser cache pollution in this case but not the rest.
2009-06-01 11:37:06 +00:00
|
|
|
'action' => $revdel->getLocalURL( array(
|
|
|
|
|
'type' => 'revision',
|
|
|
|
|
'target' => $this->mTitle->getPrefixedDbKey()
|
|
|
|
|
) ),
|
|
|
|
|
'method' => 'post',
|
|
|
|
|
'id' => 'mw-history-revdeleteform',
|
2009-04-11 17:38:21 +00:00
|
|
|
'style' => 'visibility:hidden;float:right;'
|
|
|
|
|
)
|
|
|
|
|
);
|
In Special:RevisionDelete:
* Refactored to remove massive duplication
* Removed page parameter and associated contextPage member variable, doesn't seem to do anything.
* Put ID lists into a single ids parameter and member variable instead of having one for each type.
* Fixed inappropriate call of Title::newFromUrl(), always wrong
* Don't pretend to use the return value from functions that don't return anything, this reduces readability.
* Use the table names for deleteKey/typeName values, they look more like English
* Use protected not private
* Remove requirement for log type to be specified in the target
* Use POST for RevisionDelete entry forms, to avoid URL size limits and issues with non-PATH_INFO URLs
* Don't purge all pages that use the given file
* LocalFile::purgeCache() already calls purgeHistory,() no need to do it again. But do call purgeDescription().
* Removed token from unhide=1 links, unnecessary
* Tokens are necessary on file streaming links, added them
* Fixed private data leakage due to incorrect use of LocalRepo::newFromArchiveName(). Non-existent placeholder file was returned which meant that $oimage->userCan(File::DELETED_FILE) was always true. Pass the archive name to tryShowFile() instead of the storage key.
* Using ls_field='oi_timestamp' is not correct, oi_timestamp refers to the timestamp of the revision in question, whereas the key that is stored is the timestamp of the previous revision (i.e. the timestamp in oi_archive_name). oi_archive_name would be more correct, although only half the field is used.
Elsewhere:
* Added missing message filehist-missing
* Fixed double asterisk in Status::getWikiText()
* Fixed escaping of the target parameter to Special:RevisionDelete from ImagePage
* Deleted FileStore.php. Deprecated in filerepo refactor except for get()/export() but somehow resurrected by RevisionDelete. Hopefully this will be the end of it. New interfaces will be added for wfStreamFile() in a later commit.
* Added convenience function File::getStorageKey(), factored out of Special:Undelete
* Added convenience function Revision::newFromArchiveRow(), factored out of Special:Undelete and Special:RevisionDelete
* Fixed notice in Special:Upload, uninitialised $pageText
FIXME: current revision can be suppressed on undeletion causing an unauthenticated unsuppress. Comments indicate this is a known issue. I fixed the parser cache pollution in this case but not the rest.
2009-06-01 11:37:06 +00:00
|
|
|
$s .= Xml::hidden( 'ids', '', array('id'=>'revdel-oldid') );
|
2009-04-11 17:38:21 +00:00
|
|
|
$s .= Xml::submitButton( wfMsg( 'showhideselectedversions' ) );
|
|
|
|
|
$s .= Xml::closeElement( 'form' );
|
|
|
|
|
}
|
|
|
|
|
$s .= Xml::openElement( 'form', array( 'action' => $wgScript,
|
|
|
|
|
'id' => 'mw-history-compare' ) );
|
2009-04-11 23:05:13 +00:00
|
|
|
$s .= Xml::hidden( 'title', $this->mTitle->getPrefixedDbKey() );
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $wgEnableHtmlDiff ) {
|
2008-08-21 00:45:13 +00:00
|
|
|
$s .= $this->submitButton( wfMsg( 'visualcomparison'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'name' => 'htmldiff',
|
|
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-visualcomparison' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
|
|
|
|
$s .= $this->submitButton( wfMsg( 'wikicodecomparison'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
2008-11-08 19:41:38 +00:00
|
|
|
} else {
|
2008-08-21 00:45:13 +00:00
|
|
|
$s .= $this->submitButton( wfMsg( 'compareselectedversions'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
|
|
|
|
}
|
2005-08-12 16:14:20 +00:00
|
|
|
$s .= '<ul id="pagehistory">' . "\n";
|
2003-12-21 12:01:29 +00:00
|
|
|
return $s;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-11 17:00:12 +00:00
|
|
|
/**
|
|
|
|
|
* Creates end of history list with a submit button
|
|
|
|
|
*
|
|
|
|
|
* @return string HTML output
|
|
|
|
|
*/
|
2005-03-31 11:40:05 +00:00
|
|
|
function endHistoryList() {
|
2008-08-21 00:45:13 +00:00
|
|
|
global $wgEnableHtmlDiff;
|
2005-03-31 11:40:05 +00:00
|
|
|
$s = '</ul>';
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $wgEnableHtmlDiff ) {
|
2008-08-21 00:45:13 +00:00
|
|
|
$s .= $this->submitButton( wfMsg( 'visualcomparison'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'name' => 'htmldiff',
|
|
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-visualcomparison' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
|
|
|
|
$s .= $this->submitButton( wfMsg( 'wikicodecomparison'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
2008-11-08 19:41:38 +00:00
|
|
|
} else {
|
2008-08-21 00:45:13 +00:00
|
|
|
$s .= $this->submitButton( wfMsg( 'compareselectedversions'),
|
2008-11-08 19:41:38 +00:00
|
|
|
array(
|
2009-04-11 17:38:21 +00:00
|
|
|
'class' => 'historysubmit',
|
|
|
|
|
'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
|
|
|
|
|
'title' => wfMsg( 'tooltip-compareselectedversions' ),
|
2008-11-08 19:41:38 +00:00
|
|
|
)
|
2008-08-21 00:45:13 +00:00
|
|
|
);
|
|
|
|
|
}
|
2004-08-28 17:34:54 +00:00
|
|
|
$s .= '</form>';
|
2003-12-21 12:01:29 +00:00
|
|
|
return $s;
|
|
|
|
|
}
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2007-12-11 17:00:12 +00:00
|
|
|
/**
|
|
|
|
|
* Creates a submit button
|
|
|
|
|
*
|
2008-08-21 00:45:13 +00:00
|
|
|
* @param array $attributes attributes
|
2007-12-11 17:00:12 +00:00
|
|
|
* @return string HTML output for the submit button
|
|
|
|
|
*/
|
2008-08-21 00:45:13 +00:00
|
|
|
function submitButton($message, $attributes = array() ) {
|
2007-12-11 17:00:12 +00:00
|
|
|
# Disable submit button if history has 1 revision only
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $this->linesonpage > 1 ) {
|
2008-08-21 00:45:13 +00:00
|
|
|
return Xml::submitButton( $message , $attributes );
|
2007-12-20 02:40:02 +00:00
|
|
|
} else {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2005-03-31 11:40:05 +00:00
|
|
|
}
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2006-11-19 17:16:34 +00:00
|
|
|
/**
|
|
|
|
|
* Returns a row from the history printout.
|
|
|
|
|
*
|
|
|
|
|
* @todo document some more, and maybe clean up the code (some params redundant?)
|
|
|
|
|
*
|
2008-03-15 21:20:41 +00:00
|
|
|
* @param Row $row The database row corresponding to the previous line.
|
|
|
|
|
* @param mixed $next The database row corresponding to the next line.
|
2006-11-19 17:16:34 +00:00
|
|
|
* @param int $counter Apparently a counter of what row number we're at, counted from the top row = 1.
|
|
|
|
|
* @param $notificationtimestamp
|
|
|
|
|
* @param bool $latest Whether this row corresponds to the page's latest revision.
|
|
|
|
|
* @param bool $firstInList Whether this row corresponds to the first displayed on this history page.
|
|
|
|
|
* @return string HTML output for the row
|
|
|
|
|
*/
|
2009-03-26 22:24:09 +00:00
|
|
|
function historyLine( $row, $next, $counter = '', $notificationtimestamp = false,
|
|
|
|
|
$latest = false, $firstInList = false )
|
|
|
|
|
{
|
2007-03-09 18:26:33 +00:00
|
|
|
global $wgUser, $wgLang;
|
2006-03-16 19:04:25 +00:00
|
|
|
$rev = new Revision( $row );
|
2006-06-11 04:48:27 +00:00
|
|
|
$rev->setTitle( $this->mTitle );
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2006-03-16 19:04:25 +00:00
|
|
|
$curlink = $this->curLink( $rev, $latest );
|
|
|
|
|
$lastlink = $this->lastLink( $rev, $next, $counter );
|
|
|
|
|
$arbitrary = $this->diffButtons( $rev, $firstInList, $counter );
|
|
|
|
|
$link = $this->revLink( $rev );
|
2009-01-28 19:08:18 +00:00
|
|
|
$classes = array();
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
$s = "($curlink) ($lastlink) $arbitrary";
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-03-16 19:04:25 +00:00
|
|
|
if( $wgUser->isAllowed( 'deleterevision' ) ) {
|
2009-04-11 17:38:21 +00:00
|
|
|
// Hide JS by default for non-JS browsing
|
2009-04-16 04:51:43 +00:00
|
|
|
$hidden = array( 'style' => 'display:none' );
|
2009-04-11 17:38:21 +00:00
|
|
|
// If revision was hidden from sysops
|
2009-04-06 01:43:38 +00:00
|
|
|
if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
|
2009-04-11 17:38:21 +00:00
|
|
|
$del = Xml::check( 'deleterevisions', false,
|
|
|
|
|
$hidden + array('disabled' => 'disabled') );
|
|
|
|
|
$del .= Xml::tags( 'span', array( 'class'=>'mw-revdelundel-link' ),
|
|
|
|
|
'(' . $this->message['rev-delundel'] . ')' );
|
|
|
|
|
// Otherwise, show the link...
|
2006-03-16 19:04:25 +00:00
|
|
|
} else {
|
2009-07-19 19:59:12 +00:00
|
|
|
$id = $rev->getId();
|
|
|
|
|
$jsCall = "updateShowHideForm($id,this.checked)";
|
2009-04-11 17:38:21 +00:00
|
|
|
$del = Xml::check( 'showhiderevisions', false,
|
2009-07-19 19:59:12 +00:00
|
|
|
$hidden + array(
|
|
|
|
|
'onchange' => $jsCall,
|
|
|
|
|
'id' => "mw-revdel-$id" ) );
|
In Special:RevisionDelete:
* Refactored to remove massive duplication
* Removed page parameter and associated contextPage member variable, doesn't seem to do anything.
* Put ID lists into a single ids parameter and member variable instead of having one for each type.
* Fixed inappropriate call of Title::newFromUrl(), always wrong
* Don't pretend to use the return value from functions that don't return anything, this reduces readability.
* Use the table names for deleteKey/typeName values, they look more like English
* Use protected not private
* Remove requirement for log type to be specified in the target
* Use POST for RevisionDelete entry forms, to avoid URL size limits and issues with non-PATH_INFO URLs
* Don't purge all pages that use the given file
* LocalFile::purgeCache() already calls purgeHistory,() no need to do it again. But do call purgeDescription().
* Removed token from unhide=1 links, unnecessary
* Tokens are necessary on file streaming links, added them
* Fixed private data leakage due to incorrect use of LocalRepo::newFromArchiveName(). Non-existent placeholder file was returned which meant that $oimage->userCan(File::DELETED_FILE) was always true. Pass the archive name to tryShowFile() instead of the storage key.
* Using ls_field='oi_timestamp' is not correct, oi_timestamp refers to the timestamp of the revision in question, whereas the key that is stored is the timestamp of the previous revision (i.e. the timestamp in oi_archive_name). oi_archive_name would be more correct, although only half the field is used.
Elsewhere:
* Added missing message filehist-missing
* Fixed double asterisk in Status::getWikiText()
* Fixed escaping of the target parameter to Special:RevisionDelete from ImagePage
* Deleted FileStore.php. Deprecated in filerepo refactor except for get()/export() but somehow resurrected by RevisionDelete. Hopefully this will be the end of it. New interfaces will be added for wfStreamFile() in a later commit.
* Added convenience function File::getStorageKey(), factored out of Special:Undelete
* Added convenience function Revision::newFromArchiveRow(), factored out of Special:Undelete and Special:RevisionDelete
* Fixed notice in Special:Upload, uninitialised $pageText
FIXME: current revision can be suppressed on undeletion causing an unauthenticated unsuppress. Comments indicate this is a known issue. I fixed the parser cache pollution in this case but not the rest.
2009-06-01 11:37:06 +00:00
|
|
|
$query = array(
|
|
|
|
|
'type' => 'revision',
|
|
|
|
|
'target' => $this->mTitle->getPrefixedDbkey(),
|
|
|
|
|
'ids' => $rev->getId() );
|
2009-04-11 17:38:21 +00:00
|
|
|
$del .= $this->mSkin->revDeleteLink( $query,
|
|
|
|
|
$rev->isDeleted( Revision::DELETED_RESTRICTED ) );
|
2006-03-16 19:04:25 +00:00
|
|
|
}
|
2009-01-20 00:16:35 +00:00
|
|
|
$s .= " $del ";
|
2003-12-21 12:01:29 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-02-05 06:12:31 +00:00
|
|
|
$s .= " $link";
|
2008-03-11 17:36:46 +00:00
|
|
|
$s .= " <span class='history-user'>" . $this->mSkin->revUserTools( $rev, true ) . "</span>";
|
2008-03-09 21:08:42 +00:00
|
|
|
|
2009-02-09 22:27:25 +00:00
|
|
|
if( $rev->isMinor() ) {
|
2009-07-29 22:15:52 +00:00
|
|
|
$s .= ' ' . Xml::element( 'abbr', array( 'class' => 'minor' ), wfMsg( 'minoreditletter') );
|
2004-05-18 12:36:13 +00:00
|
|
|
}
|
2007-03-08 03:07:58 +00:00
|
|
|
|
2009-02-09 22:27:25 +00:00
|
|
|
if( !is_null( $size = $rev->getSize() ) && !$rev->isDeleted( Revision::DELETED_TEXT ) ) {
|
2008-07-14 19:10:47 +00:00
|
|
|
$s .= ' ' . $this->mSkin->formatRevisionSize( $size );
|
2007-03-08 03:07:58 +00:00
|
|
|
}
|
|
|
|
|
|
2008-03-09 21:08:42 +00:00
|
|
|
$s .= $this->mSkin->revComment( $rev, false, true );
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $notificationtimestamp && ($row->rev_timestamp >= $notificationtimestamp) ) {
|
2005-08-12 16:14:20 +00:00
|
|
|
$s .= ' <span class="updatedmarker">' . wfMsgHtml( 'updatedmarker' ) . '</span>';
|
2004-12-18 03:47:11 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-07-07 00:17:51 +00:00
|
|
|
$tools = array();
|
2008-12-31 21:16:36 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
if( !is_null( $next ) && is_object( $next ) ) {
|
2008-12-31 21:16:36 +00:00
|
|
|
if( $latest && $this->mTitle->userCan( 'rollback' ) && $this->mTitle->userCan( 'edit' ) ) {
|
2009-05-26 12:29:16 +00:00
|
|
|
$tools[] = '<span class="mw-rollback-link">'.
|
|
|
|
|
$this->mSkin->buildRollbackLink( $rev ).'</span>';
|
2007-07-12 14:25:48 +00:00
|
|
|
}
|
2008-12-31 21:16:36 +00:00
|
|
|
|
2009-05-26 12:29:16 +00:00
|
|
|
if( $this->mTitle->quickUserCan( 'edit' )
|
|
|
|
|
&& !$rev->isDeleted( Revision::DELETED_TEXT )
|
|
|
|
|
&& !$next->rev_deleted & Revision::DELETED_TEXT )
|
2008-11-08 19:41:38 +00:00
|
|
|
{
|
2008-08-26 20:06:57 +00:00
|
|
|
# Create undo tooltip for the first (=latest) line only
|
|
|
|
|
$undoTooltip = $latest
|
|
|
|
|
? array( 'title' => wfMsg( 'tooltip-undo' ) )
|
|
|
|
|
: array();
|
|
|
|
|
$undolink = $this->mSkin->link(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
wfMsgHtml( 'editundo' ),
|
|
|
|
|
$undoTooltip,
|
|
|
|
|
array( 'action' => 'edit', 'undoafter' => $next->rev_id, 'undo' => $rev->getId() ),
|
|
|
|
|
array( 'known', 'noclasses' )
|
2007-12-27 18:05:40 +00:00
|
|
|
);
|
|
|
|
|
$tools[] = "<span class=\"mw-history-undo\">{$undolink}</span>";
|
|
|
|
|
}
|
2007-07-06 06:52:52 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2007-07-11 17:45:25 +00:00
|
|
|
if( $tools ) {
|
2009-02-09 09:13:30 +00:00
|
|
|
$s .= ' (' . $wgLang->pipeList( $tools ) . ')';
|
2007-07-11 17:45:25 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2009-01-28 19:08:18 +00:00
|
|
|
# Tags
|
|
|
|
|
list($tagSummary, $newClasses) = ChangeTags::formatSummaryRow( $row->ts_tags, 'history' );
|
|
|
|
|
$classes = array_merge( $classes, $newClasses );
|
|
|
|
|
$s .= " $tagSummary";
|
|
|
|
|
|
2008-05-23 09:03:49 +00:00
|
|
|
wfRunHooks( 'PageHistoryLineEnding', array( $this, &$row , &$s ) );
|
2003-12-21 12:01:29 +00:00
|
|
|
|
2009-01-28 19:08:18 +00:00
|
|
|
$classes = implode( ' ', $classes );
|
|
|
|
|
|
|
|
|
|
return "<li class=\"$classes\">$s</li>\n";
|
2003-12-21 12:01:29 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
|
|
|
|
/**
|
2008-08-21 00:45:13 +00:00
|
|
|
* Create a link to view this revision of the page
|
|
|
|
|
* @param Revision $rev
|
|
|
|
|
* @returns string
|
|
|
|
|
*/
|
2006-03-16 19:04:25 +00:00
|
|
|
function revLink( $rev ) {
|
2006-03-18 01:06:57 +00:00
|
|
|
global $wgLang;
|
2006-03-16 19:04:25 +00:00
|
|
|
$date = $wgLang->timeanddate( wfTimestamp(TS_MW, $rev->getTimestamp()), true );
|
2009-05-22 09:35:48 +00:00
|
|
|
$date = htmlspecialchars( $date );
|
2009-05-19 19:19:41 +00:00
|
|
|
if( !$rev->isDeleted( Revision::DELETED_TEXT ) ) {
|
2009-06-07 15:02:12 +00:00
|
|
|
$link = $this->mSkin->link(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
$date,
|
|
|
|
|
array(),
|
|
|
|
|
array( 'oldid' => $rev->getId() ),
|
|
|
|
|
array( 'known', 'noclasses' )
|
|
|
|
|
);
|
2005-03-31 11:40:05 +00:00
|
|
|
} else {
|
2009-05-19 19:19:41 +00:00
|
|
|
$link = "<span class=\"history-deleted\">$date</span>";
|
2005-03-31 11:40:05 +00:00
|
|
|
}
|
2006-03-16 19:04:25 +00:00
|
|
|
return $link;
|
2005-03-31 11:40:05 +00:00
|
|
|
}
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2008-04-14 07:45:50 +00:00
|
|
|
/**
|
2008-08-21 00:45:13 +00:00
|
|
|
* Create a diff-to-current link for this revision for this page
|
|
|
|
|
* @param Revision $rev
|
|
|
|
|
* @param Bool $latest, this is the latest revision of the page?
|
|
|
|
|
* @returns string
|
|
|
|
|
*/
|
2006-03-16 19:04:25 +00:00
|
|
|
function curLink( $rev, $latest ) {
|
2008-03-09 02:27:03 +00:00
|
|
|
$cur = $this->message['cur'];
|
2009-03-26 22:24:09 +00:00
|
|
|
if( $latest || !$rev->userCan( Revision::DELETED_TEXT ) ) {
|
2005-03-31 11:40:05 +00:00
|
|
|
return $cur;
|
|
|
|
|
} else {
|
2009-06-07 15:02:12 +00:00
|
|
|
return $this->mSkin->link(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
$cur,
|
|
|
|
|
array(),
|
|
|
|
|
array(
|
|
|
|
|
'diff' => $this->mTitle->getLatestRevID(),
|
|
|
|
|
'oldid' => $rev->getId()
|
|
|
|
|
),
|
|
|
|
|
array( 'known', 'noclasses' )
|
|
|
|
|
);
|
2005-03-31 11:40:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2008-04-14 07:45:50 +00:00
|
|
|
/**
|
2008-08-21 00:45:13 +00:00
|
|
|
* Create a diff-to-previous link for this revision for this page.
|
|
|
|
|
* @param Revision $prevRev, the previous revision
|
|
|
|
|
* @param mixed $next, the newer revision
|
|
|
|
|
* @param int $counter, what row on the history list this is
|
|
|
|
|
* @returns string
|
|
|
|
|
*/
|
2008-03-15 21:20:41 +00:00
|
|
|
function lastLink( $prevRev, $next, $counter ) {
|
2008-03-09 02:27:03 +00:00
|
|
|
$last = $this->message['last'];
|
2008-03-15 21:20:41 +00:00
|
|
|
# $next may either be a Row, null, or "unkown"
|
|
|
|
|
$nextRev = is_object($next) ? new Revision( $next ) : $next;
|
|
|
|
|
if( is_null($next) ) {
|
2006-07-07 03:28:48 +00:00
|
|
|
# Probably no next row
|
|
|
|
|
return $last;
|
2008-03-15 21:20:41 +00:00
|
|
|
} elseif( $next === 'unknown' ) {
|
2006-07-07 03:28:48 +00:00
|
|
|
# Next row probably exists but is unknown, use an oldid=prev link
|
2009-06-07 15:02:12 +00:00
|
|
|
return $this->mSkin->link(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
$last,
|
|
|
|
|
array(),
|
|
|
|
|
array(
|
|
|
|
|
'diff' => $prevRev->getId(),
|
|
|
|
|
'oldid' => 'prev'
|
|
|
|
|
),
|
|
|
|
|
array( 'known', 'noclasses' )
|
|
|
|
|
);
|
2009-03-26 22:24:09 +00:00
|
|
|
} elseif( !$prevRev->userCan(Revision::DELETED_TEXT) || !$nextRev->userCan(Revision::DELETED_TEXT) ) {
|
2005-03-31 11:40:05 +00:00
|
|
|
return $last;
|
|
|
|
|
} else {
|
2009-06-07 15:02:12 +00:00
|
|
|
return $this->mSkin->link(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
$last,
|
|
|
|
|
array(),
|
|
|
|
|
array(
|
|
|
|
|
'diff' => $prevRev->getId(),
|
|
|
|
|
'oldid' => $next->rev_id
|
|
|
|
|
),
|
|
|
|
|
array( 'known', 'noclasses' )
|
|
|
|
|
);
|
2005-03-31 11:40:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2007-12-04 12:22:23 +00:00
|
|
|
/**
|
|
|
|
|
* Create radio buttons for page history
|
|
|
|
|
*
|
|
|
|
|
* @param object $rev Revision
|
|
|
|
|
* @param bool $firstInList Is this version the first one?
|
|
|
|
|
* @param int $counter A counter of what row number we're at, counted from the top row = 1.
|
|
|
|
|
* @return string HTML output for the radio buttons
|
|
|
|
|
*/
|
2006-03-16 19:04:25 +00:00
|
|
|
function diffButtons( $rev, $firstInList, $counter ) {
|
2009-02-09 07:42:54 +00:00
|
|
|
if( $this->linesonpage > 1 ) {
|
2009-07-19 19:59:12 +00:00
|
|
|
$id = $rev->getId();
|
|
|
|
|
$radio = array( 'type' => 'radio', 'value' => $id );
|
2005-08-12 16:14:20 +00:00
|
|
|
/** @todo: move title texts to javascript */
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $firstInList ) {
|
2009-02-09 07:42:54 +00:00
|
|
|
$first = Xml::element( 'input',
|
2009-07-19 19:59:12 +00:00
|
|
|
array_merge( $radio, array(
|
|
|
|
|
'style' => 'visibility:hidden',
|
|
|
|
|
'name' => 'oldid',
|
|
|
|
|
'id' => 'mw-oldid-null' ) )
|
2009-02-09 07:42:54 +00:00
|
|
|
);
|
2005-03-31 11:40:05 +00:00
|
|
|
$checkmark = array( 'checked' => 'checked' );
|
|
|
|
|
} else {
|
2009-02-09 07:42:54 +00:00
|
|
|
# Check visibility of old revisions
|
2009-03-26 22:24:09 +00:00
|
|
|
if( !$rev->userCan( Revision::DELETED_TEXT ) ) {
|
2009-02-09 07:42:54 +00:00
|
|
|
$radio['disabled'] = 'disabled';
|
|
|
|
|
$checkmark = array(); // We will check the next possible one
|
|
|
|
|
} else if( $counter == 2 || !$this->mOldIdChecked ) {
|
2005-03-31 11:40:05 +00:00
|
|
|
$checkmark = array( 'checked' => 'checked' );
|
2009-07-19 19:59:12 +00:00
|
|
|
$this->mOldIdChecked = $id;
|
2005-03-31 11:40:05 +00:00
|
|
|
} else {
|
|
|
|
|
$checkmark = array();
|
|
|
|
|
}
|
2009-07-19 19:59:12 +00:00
|
|
|
$first = Xml::element( 'input',
|
|
|
|
|
array_merge( $radio, $checkmark, array(
|
|
|
|
|
'name' => 'oldid',
|
|
|
|
|
'id' => "mw-oldid-$id" ) ) );
|
2005-03-31 11:40:05 +00:00
|
|
|
$checkmark = array();
|
|
|
|
|
}
|
2009-07-19 19:59:12 +00:00
|
|
|
$second = Xml::element( 'input',
|
|
|
|
|
array_merge( $radio, $checkmark, array(
|
|
|
|
|
'name' => 'diff',
|
|
|
|
|
'id' => "mw-diff-$id" ) ) );
|
2005-03-31 11:40:05 +00:00
|
|
|
return $first . $second;
|
|
|
|
|
} else {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2005-08-12 16:14:20 +00:00
|
|
|
/**
|
2006-07-07 03:28:48 +00:00
|
|
|
* Fetch an array of revisions, specified by a given limit, offset and
|
2008-04-14 07:45:50 +00:00
|
|
|
* direction. This is now only used by the feeds. It was previously
|
2006-07-07 03:28:48 +00:00
|
|
|
* used by the main UI but that's now handled by the pager.
|
2005-08-12 16:14:20 +00:00
|
|
|
*/
|
2005-06-29 03:37:57 +00:00
|
|
|
function fetchRevisions($limit, $offset, $direction) {
|
2007-01-22 23:50:42 +00:00
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $direction == PageHistory::DIR_PREV )
|
2008-10-28 21:25:09 +00:00
|
|
|
list($dirs, $oper) = array("ASC", ">=");
|
2006-06-06 12:28:44 +00:00
|
|
|
else /* $direction == PageHistory::DIR_NEXT */
|
2008-10-28 21:25:09 +00:00
|
|
|
list($dirs, $oper) = array("DESC", "<=");
|
2005-06-29 03:37:57 +00:00
|
|
|
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $offset )
|
2008-10-28 21:25:09 +00:00
|
|
|
$offsets = array("rev_timestamp $oper '$offset'");
|
2005-08-12 16:14:20 +00:00
|
|
|
else
|
2008-10-28 21:25:09 +00:00
|
|
|
$offsets = array();
|
2005-06-29 03:37:57 +00:00
|
|
|
|
|
|
|
|
$page_id = $this->mTitle->getArticleID();
|
|
|
|
|
|
2008-10-28 21:25:09 +00:00
|
|
|
return $dbr->select( 'revision',
|
|
|
|
|
Revision::selectFields(),
|
|
|
|
|
array_merge(array("rev_page=$page_id"), $offsets),
|
|
|
|
|
__METHOD__,
|
|
|
|
|
array( 'ORDER BY' => "rev_timestamp $dirs",
|
2005-08-12 16:14:20 +00:00
|
|
|
'USE INDEX' => 'page_timestamp', 'LIMIT' => $limit)
|
2008-07-27 18:59:46 +00:00
|
|
|
);
|
2005-06-29 03:37:57 +00:00
|
|
|
}
|
|
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
/**
|
|
|
|
|
* Output a subscription feed listing recent edits to this page.
|
|
|
|
|
* @param string $type
|
|
|
|
|
*/
|
|
|
|
|
function feed( $type ) {
|
2008-07-15 16:00:22 +00:00
|
|
|
global $wgFeedClasses, $wgRequest, $wgFeedLimit;
|
2008-11-08 19:41:38 +00:00
|
|
|
if( !FeedUtils::checkFeedOutput($type) ) {
|
2006-05-28 03:47:28 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
$feed = new $wgFeedClasses[$type](
|
2009-06-07 15:02:12 +00:00
|
|
|
$this->mTitle->getPrefixedText() . ' - ' .
|
|
|
|
|
wfMsgForContent( 'history-feed-title' ),
|
|
|
|
|
wfMsgForContent( 'history-feed-description' ),
|
|
|
|
|
$this->mTitle->getFullUrl( array( 'action' => 'history' ) )
|
|
|
|
|
);
|
2006-05-28 03:47:28 +00:00
|
|
|
|
2008-07-15 16:00:22 +00:00
|
|
|
// Get a limit on number of feed entries. Provide a sane default
|
|
|
|
|
// of 10 if none is defined (but limit to $wgFeedLimit max)
|
|
|
|
|
$limit = $wgRequest->getInt( 'limit', 10 );
|
|
|
|
|
if( $limit > $wgFeedLimit || $limit < 1 ) {
|
|
|
|
|
$limit = 10;
|
|
|
|
|
}
|
2008-08-21 00:45:13 +00:00
|
|
|
$items = $this->fetchRevisions($limit, 0, PageHistory::DIR_NEXT);
|
2008-07-15 16:00:22 +00:00
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
$feed->outHeader();
|
|
|
|
|
if( $items ) {
|
|
|
|
|
foreach( $items as $row ) {
|
|
|
|
|
$feed->outItem( $this->feedItem( $row ) );
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$feed->outItem( $this->feedEmpty() );
|
|
|
|
|
}
|
|
|
|
|
$feed->outFooter();
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
function feedEmpty() {
|
|
|
|
|
global $wgOut;
|
|
|
|
|
return new FeedItem(
|
2008-11-08 19:45:26 +00:00
|
|
|
wfMsgForContent( 'nohistory' ),
|
|
|
|
|
$wgOut->parse( wfMsgForContent( 'history-feed-empty' ) ),
|
|
|
|
|
$this->mTitle->getFullUrl(),
|
|
|
|
|
wfTimestamp( TS_MW ),
|
|
|
|
|
'',
|
2009-07-28 11:11:46 +00:00
|
|
|
$this->mTitle->getTalkPage()->getFullUrl()
|
|
|
|
|
);
|
2006-05-28 03:47:28 +00:00
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-05-28 03:47:28 +00:00
|
|
|
/**
|
|
|
|
|
* Generate a FeedItem object from a given revision table row
|
|
|
|
|
* Borrows Recent Changes' feed generation functions for formatting;
|
|
|
|
|
* includes a diff to the previous revision (if any).
|
|
|
|
|
*
|
|
|
|
|
* @param $row
|
|
|
|
|
* @return FeedItem
|
|
|
|
|
*/
|
|
|
|
|
function feedItem( $row ) {
|
|
|
|
|
$rev = new Revision( $row );
|
2006-06-11 04:48:27 +00:00
|
|
|
$rev->setTitle( $this->mTitle );
|
2009-07-28 11:11:46 +00:00
|
|
|
$text = FeedUtils::formatDiffRow(
|
|
|
|
|
$this->mTitle,
|
|
|
|
|
$this->mTitle->getPreviousRevisionID( $rev->getId() ),
|
|
|
|
|
$rev->getId(),
|
|
|
|
|
$rev->getTimestamp(),
|
|
|
|
|
$rev->getComment()
|
|
|
|
|
);
|
2006-05-28 03:47:28 +00:00
|
|
|
if( $rev->getComment() == '' ) {
|
|
|
|
|
global $wgContLang;
|
2009-06-01 21:22:56 +00:00
|
|
|
$ts = $rev->getTimestamp();
|
2006-05-28 03:47:28 +00:00
|
|
|
$title = wfMsgForContent( 'history-feed-item-nocomment',
|
2009-06-01 21:22:56 +00:00
|
|
|
$rev->getUserText(),
|
|
|
|
|
$wgContLang->timeanddate( $ts ),
|
|
|
|
|
$wgContLang->date( $ts ),
|
|
|
|
|
$wgContLang->time( $ts ) );
|
2006-05-28 03:47:28 +00:00
|
|
|
} else {
|
2009-07-28 11:11:46 +00:00
|
|
|
$title = $rev->getUserText() . wfMsgForContent( 'colon-separator' ) .
|
|
|
|
|
FeedItem::stripComment( $rev->getComment() );
|
2006-05-28 03:47:28 +00:00
|
|
|
}
|
|
|
|
|
return new FeedItem(
|
2008-11-08 19:45:26 +00:00
|
|
|
$title,
|
|
|
|
|
$text,
|
2009-06-07 15:02:12 +00:00
|
|
|
$this->mTitle->getFullUrl( array(
|
|
|
|
|
'diff' => $rev->getId(),
|
|
|
|
|
'oldid' => 'prev'
|
|
|
|
|
) ),
|
2008-11-08 19:45:26 +00:00
|
|
|
$rev->getTimestamp(),
|
|
|
|
|
$rev->getUserText(),
|
2009-07-28 11:11:46 +00:00
|
|
|
$this->mTitle->getTalkPage()->getFullUrl()
|
|
|
|
|
);
|
2006-05-28 03:47:28 +00:00
|
|
|
}
|
2006-07-07 03:28:48 +00:00
|
|
|
}
|
|
|
|
|
|
2007-04-20 08:55:14 +00:00
|
|
|
/**
|
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
|
|
|
* @ingroup Pager
|
2007-04-20 08:55:14 +00:00
|
|
|
*/
|
2006-07-07 03:28:48 +00:00
|
|
|
class PageHistoryPager extends ReverseChronologicalPager {
|
2008-11-08 19:41:38 +00:00
|
|
|
public $mLastRow = false, $mPageHistory, $mTitle;
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2009-01-28 19:08:18 +00:00
|
|
|
function __construct( $pageHistory, $year='', $month='', $tagFilter = '' ) {
|
2006-07-07 03:28:48 +00:00
|
|
|
parent::__construct();
|
|
|
|
|
$this->mPageHistory = $pageHistory;
|
2008-11-08 19:41:38 +00:00
|
|
|
$this->mTitle =& $this->mPageHistory->mTitle;
|
2009-01-28 19:08:18 +00:00
|
|
|
$this->tagFilter = $tagFilter;
|
2008-08-01 22:59:06 +00:00
|
|
|
$this->getDateCond( $year, $month );
|
2006-07-07 03:28:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getQueryInfo() {
|
2008-05-23 16:47:39 +00:00
|
|
|
$queryInfo = array(
|
2008-07-17 12:09:58 +00:00
|
|
|
'tables' => array('revision'),
|
2009-01-28 19:08:18 +00:00
|
|
|
'fields' => array_merge( Revision::selectFields(), array('ts_tags') ),
|
2008-07-17 12:09:58 +00:00
|
|
|
'conds' => array('rev_page' => $this->mPageHistory->mTitle->getArticleID() ),
|
2009-01-28 19:08:18 +00:00
|
|
|
'options' => array( 'USE INDEX' => array('revision' => 'page_timestamp') ),
|
|
|
|
|
'join_conds' => array( 'tag_summary' => array( 'LEFT JOIN', 'ts_rev_id=rev_id' ) ),
|
2006-07-07 03:28:48 +00:00
|
|
|
);
|
2009-03-31 13:01:05 +00:00
|
|
|
ChangeTags::modifyDisplayQuery( $queryInfo['tables'],
|
|
|
|
|
$queryInfo['fields'],
|
|
|
|
|
$queryInfo['conds'],
|
|
|
|
|
$queryInfo['join_conds'],
|
|
|
|
|
$queryInfo['options'],
|
|
|
|
|
$this->tagFilter );
|
2008-05-23 16:47:39 +00:00
|
|
|
wfRunHooks( 'PageHistoryPager::getQueryInfo', array( &$this, &$queryInfo ) );
|
|
|
|
|
return $queryInfo;
|
2006-07-07 03:28:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getIndexField() {
|
|
|
|
|
return 'rev_timestamp';
|
|
|
|
|
}
|
2005-08-12 16:14:20 +00:00
|
|
|
|
2006-07-07 03:28:48 +00:00
|
|
|
function formatRow( $row ) {
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $this->mLastRow ) {
|
2008-04-13 15:05:32 +00:00
|
|
|
$latest = $this->mCounter == 1 && $this->mIsFirst;
|
2006-07-07 03:28:48 +00:00
|
|
|
$firstInList = $this->mCounter == 1;
|
2008-04-14 07:45:50 +00:00
|
|
|
$s = $this->mPageHistory->historyLine( $this->mLastRow, $row, $this->mCounter++,
|
2008-11-08 19:41:38 +00:00
|
|
|
$this->mTitle->getNotificationTimestamp(), $latest, $firstInList );
|
2006-07-07 03:28:48 +00:00
|
|
|
} else {
|
|
|
|
|
$s = '';
|
|
|
|
|
}
|
|
|
|
|
$this->mLastRow = $row;
|
|
|
|
|
return $s;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
|
2006-07-07 03:28:48 +00:00
|
|
|
function getStartBody() {
|
|
|
|
|
$this->mLastRow = false;
|
|
|
|
|
$this->mCounter = 1;
|
|
|
|
|
return '';
|
|
|
|
|
}
|
2005-08-12 16:14:20 +00:00
|
|
|
|
2006-07-07 03:28:48 +00:00
|
|
|
function getEndBody() {
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $this->mLastRow ) {
|
2008-04-13 15:05:32 +00:00
|
|
|
$latest = $this->mCounter == 1 && $this->mIsFirst;
|
2006-07-07 03:28:48 +00:00
|
|
|
$firstInList = $this->mCounter == 1;
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $this->mIsBackwards ) {
|
2006-07-07 03:28:48 +00:00
|
|
|
# Next row is unknown, but for UI reasons, probably exists if an offset has been specified
|
2008-11-08 19:41:38 +00:00
|
|
|
if( $this->mOffset == '' ) {
|
2006-07-07 03:28:48 +00:00
|
|
|
$next = null;
|
|
|
|
|
} else {
|
|
|
|
|
$next = 'unknown';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
# The next row is the past-the-end row
|
|
|
|
|
$next = $this->mPastTheEndRow;
|
|
|
|
|
}
|
2008-04-14 07:45:50 +00:00
|
|
|
$s = $this->mPageHistory->historyLine( $this->mLastRow, $next, $this->mCounter++,
|
2008-11-08 19:41:38 +00:00
|
|
|
$this->mTitle->getNotificationTimestamp(), $latest, $firstInList );
|
2006-07-07 03:28:48 +00:00
|
|
|
} else {
|
|
|
|
|
$s = '';
|
|
|
|
|
}
|
|
|
|
|
return $s;
|
|
|
|
|
}
|
2003-12-21 12:01:29 +00:00
|
|
|
}
|