From 0ce798bd16b43de8d33e7bd045ee775cb2285cb9 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 5 Dec 2006 01:11:12 +0000 Subject: [PATCH] Restore Special:Contributions to its state as of 17964 New version doesn't keep all features; keep it off trunk until complete --- RELEASE-NOTES | 3 - includes/QueryPage.php | 2 - includes/SpecialContributions.php | 665 ++++++++++++++---------- includes/SpecialNewbieContributions.php | 107 ---- includes/SpecialPage.php | 1 - languages/messages/MessagesEn.php | 16 +- languages/messages/MessagesFi.php | 12 +- 7 files changed, 398 insertions(+), 408 deletions(-) delete mode 100644 includes/SpecialNewbieContributions.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 03cab3e65c..81c69e6531 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -242,9 +242,6 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * {{REVISIONTIMESTAMP}} now uses site local timezone instead of user timezone to ensure consistent behavior * {{REVISIONTIMESTAMP}} and friends should now work on non-MySQL backends -* Special:Contributions has been rewritten to inherit from QueryPage -* New special page Special:NewbieContributions, with a (deprecated) - redirect from Special:Contributions/newbies for backwards compatibility * (bug 7671) Observe canonical media namespace prefix in Linker::formatComment * Added js variable wgCurRevisionId to the output * (bug 8141) Cleanup of Parser::doTableStuff, patch by AzaTht diff --git a/includes/QueryPage.php b/includes/QueryPage.php index b8fedc4dff..850365c58b 100644 --- a/includes/QueryPage.php +++ b/includes/QueryPage.php @@ -14,7 +14,6 @@ $wgQueryPages = array( array( 'AncientPagesPage', 'Ancientpages' ), array( 'BrokenRedirectsPage', 'BrokenRedirects' ), array( 'CategoriesPage', 'Categories' ), - array( 'ContributionsPage', 'Contributions' ), array( 'DeadendPagesPage', 'Deadendpages' ), array( 'DisambiguationsPage', 'Disambiguations' ), array( 'DoubleRedirectsPage', 'DoubleRedirects' ), @@ -28,7 +27,6 @@ $wgQueryPages = array( array( 'MostlinkedPage', 'Mostlinked' ), array( 'MostrevisionsPage', 'Mostrevisions' ), array( 'NewPagesPage', 'Newpages' ), - array( 'NewbieContributionsPage', 'NewbieContributions' ), array( 'ShortPagesPage', 'Shortpages' ), array( 'UncategorizedCategoriesPage', 'Uncategorizedcategories' ), array( 'UncategorizedPagesPage', 'Uncategorizedpages' ), diff --git a/includes/SpecialContributions.php b/includes/SpecialContributions.php index 933d7eebf3..34de8e0aa2 100644 --- a/includes/SpecialContributions.php +++ b/includes/SpecialContributions.php @@ -1,344 +1,435 @@ user = User::newFromName( $username, false ); +/** @package MediaWiki */ +class ContribsFinder { + var $username, $offset, $limit, $namespace; + var $dbr; + + function ContribsFinder( $username ) { + $this->username = $username; + $this->namespace = false; + $this->dbr =& wfGetDB( DB_SLAVE ); } - function openList( $offset ) { - return "'; + + function setLimit( $limit ) { + $this->limit = $limit; } - - /** - * @return string Name of this special page. - */ - function getName() { - return 'Contributions'; + + function setOffset( $offset ) { + $this->offset = $offset; + } + + function getEditLimit( $dir ) { + list( $index, $usercond ) = $this->getUserCond(); + $nscond = $this->getNamespaceCond(); + $use_index = $this->dbr->useIndexClause( $index ); + list( $revision, $page) = $this->dbr->tableNamesN( 'revision', 'page' ); + $sql = "SELECT rev_timestamp " . + " FROM $page,$revision $use_index " . + " WHERE rev_page=page_id AND $usercond $nscond" . + " ORDER BY rev_timestamp $dir LIMIT 1"; + + $res = $this->dbr->query( $sql, __METHOD__ ); + $row = $this->dbr->fetchObject( $res ); + if ( $row ) { + return $row->rev_timestamp; + } else { + return false; + } } - /** - * Not expensive, won't work with the query cache anyway. - */ - function isExpensive() { return false; } + function getEditLimits() { + return array( + $this->getEditLimit( "ASC" ), + $this->getEditLimit( "DESC" ) + ); + } - /** - * Should we? - */ - function isSyndicated() { return false; } + function getUserCond() { + $condition = ''; - /** - * Get target user name. May be overridden in subclasses. - * @return string username - */ - function getUsername() { - return $this->user->getName(); + if ( $this->username == 'newbies' ) { + $max = $this->dbr->selectField( 'user', 'max(user_id)', false, 'make_sql' ); + $condition = '>' . (int)($max - $max / 100); + } + + if ( $condition == '' ) { + $condition = ' rev_user_text=' . $this->dbr->addQuotes( $this->username ); + $index = 'usertext_timestamp'; + } else { + $condition = ' rev_user '.$condition ; + $index = 'user_timestamp'; + } + return array( $index, $condition ); } - /** - * @return array Extra URL params for self-links. - */ - function linkParameters() { - $params['target'] = $this->getUsername(); + function getNamespaceCond() { + if ( $this->namespace !== false ) + return ' AND page_namespace = ' . (int)$this->namespace; + return ''; + } - if ( isset($this->namespace) ) - $params['namespace'] = $this->namespace; + function getPreviousOffsetForPaging() { + list( $index, $usercond ) = $this->getUserCond(); + $nscond = $this->getNamespaceCond(); - if ( $this->botmode ) - $params['bot'] = 1; + $use_index = $this->dbr->useIndexClause( $index ); + list( $page, $revision ) = $this->dbr->tableNamesN( 'page', 'revision' ); - return $params; + $sql = "SELECT rev_timestamp FROM $page, $revision $use_index " . + "WHERE page_id = rev_page AND rev_timestamp > '" . $this->offset . "' AND " . + $usercond . $nscond; + $sql .= " ORDER BY rev_timestamp ASC"; + $sql = $this->dbr->limitResult( $sql, $this->limit, 0 ); + $res = $this->dbr->query( $sql ); + + $numRows = $this->dbr->numRows( $res ); + if ( $numRows ) { + $this->dbr->dataSeek( $res, $numRows - 1 ); + $row = $this->dbr->fetchObject( $res ); + $offset = $row->rev_timestamp; + } else { + $offset = false; + } + $this->dbr->freeResult( $res ); + return $offset; } - /** - * Build the list of links to be shown in the subtitle. - * @return string Link list for "contribsub" UI message. - */ - function getTargetUserLinks() { - global $wgSysopUserBans, $wgLang, $wgUser; + function getFirstOffsetForPaging() { + list( $index, $usercond ) = $this->getUserCond(); + $use_index = $this->dbr->useIndexClause( $index ); + list( $page, $revision ) = $this->dbr->tableNamesN( 'page', 'revision' ); + $nscond = $this->getNamespaceCond(); + $sql = "SELECT rev_timestamp FROM $page, $revision $use_index " . + "WHERE page_id = rev_page AND " . + $usercond . $nscond; + $sql .= " ORDER BY rev_timestamp ASC"; + $sql = $this->dbr->limitResult( $sql, $this->limit, 0 ); + $res = $this->dbr->query( $sql ); + + $numRows = $this->dbr->numRows( $res ); + if ( $numRows ) { + $this->dbr->dataSeek( $res, $numRows - 1 ); + $row = $this->dbr->fetchObject( $res ); + $offset = $row->rev_timestamp; + } else { + $offset = false; + } + $this->dbr->freeResult( $res ); + return $offset; + } - $skin = $wgUser->getSkin(); + /* private */ function makeSql() { + $offsetQuery = ''; + + list( $page, $revision ) = $this->dbr->tableNamesN( 'page', 'revision' ); + list( $index, $userCond ) = $this->getUserCond(); + + if ( $this->offset ) + $offsetQuery = "AND rev_timestamp <= '{$this->offset}'"; + + $nscond = $this->getNamespaceCond(); + $use_index = $this->dbr->useIndexClause( $index ); + $sql = "SELECT + page_namespace,page_title,page_is_new,page_latest, + rev_id,rev_page,rev_text_id,rev_timestamp,rev_comment,rev_minor_edit,rev_user,rev_user_text, + rev_deleted + FROM $page,$revision $use_index + WHERE page_id=rev_page AND $userCond $nscond $offsetQuery + ORDER BY rev_timestamp DESC"; + $sql = $this->dbr->limitResult( $sql, $this->limit, 0 ); + return $sql; + } - $username = $this->getUsername(); - $userpage = $this->user->getUserPage(); - $userlink = $skin->makeLinkObj( $userpage, $username ); + function find() { + $contribs = array(); + $res = $this->dbr->query( $this->makeSql(), __METHOD__ ); + while ( $c = $this->dbr->fetchObject( $res ) ) + $contribs[] = $c; + $this->dbr->freeResult( $res ); + return $contribs; + } +}; - // talk page link - $tools[] = $skin->makeLinkObj( $userpage->getTalkPage(), $wgLang->getNsText( NS_TALK ) ); +/** + * Special page "user contributions". + * Shows a list of the contributions of a user. + * + * @return none + * @param $par String: (optional) user name of the user for which to show the contributions + */ +function wfSpecialContributions( $par = null ) { + global $wgUser, $wgOut, $wgLang, $wgRequest; - // block or block log link - $id = $this->user->getId(); - if ( ( $id != 0 && $wgSysopUserBans ) || ( $id == 0 && User::isIP( $username ) ) ) { - if( $wgUser->isAllowed( 'block' ) ) - $tools[] = $skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Blockip', $username ), - wfMsgHtml( 'blocklink' ) ); - else - $tools[] = $skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Log' ), - htmlspecialchars( LogPage::logName( 'block' ) ), - 'type=block&page=' . $userpage->getPrefixedUrl() ); - } + $target = isset( $par ) ? $par : $wgRequest->getVal( 'target' ); + if ( !strlen( $target ) ) { + $wgOut->showErrorPage( 'notargettitle', 'notargettext' ); + return; + } + + $nt = Title::newFromURL( $target ); + if ( !$nt ) { + $wgOut->showErrorPage( 'notargettitle', 'notargettext' ); + return; + } + + $options = array(); + + list( $options['limit'], $options['offset']) = wfCheckLimits(); + $options['offset'] = $wgRequest->getVal( 'offset' ); + /* Offset must be an integral. */ + if ( !strlen( $options['offset'] ) || !preg_match( '/^[0-9]+$/', $options['offset'] ) ) + $options['offset'] = ''; - // other logs link - $tools[] = $skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Log' ), - wfMsgHtml( 'log' ), - 'user=' . $userpage->getPartialUrl() ); + $title = SpecialPage::getTitleFor( 'Contributions' ); + $options['target'] = $target; - return $userlink . ' (' . implode( ' | ', $tools ) . ')'; - } + $nt =& Title::makeTitle( NS_USER, $nt->getDBkey() ); + $finder = new ContribsFinder( ( $target == 'newbies' ) ? 'newbies' : $nt->getText() ); + $finder->setLimit( $options['limit'] ); + $finder->setOffset( $options['offset'] ); - /** - * Generate "For User (...)" message in subtitle. Calls - * getTargetUserLinks() for most of the work. - * @return string - */ - function getSubtitleForTarget() { - return wfMsgHtml( 'contribsub', $this->getTargetUserLinks() ); + if ( ( $ns = $wgRequest->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { + $options['namespace'] = intval( $ns ); + $finder->setNamespace( $options['namespace'] ); + } else { + $options['namespace'] = ''; } - /** - * If the user has deleted contributions and we are allowed to - * view them, generate a link to Special:DeletedContributions. - * @return string - */ - function getDeletedContributionsLink() { - global $wgUser; - - if( !$wgUser->isAllowed( 'deletedhistory' ) ) - return ''; - - $dbr = wfGetDB( DB_SLAVE ); - $n = $dbr->selectField( 'archive', 'count(*)', array( 'ar_user_text' => $this->getUsername() ), __METHOD__ ); - - if ( $n == 0 ) - return ''; - - $msg = wfMsg( ( $wgUser->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted' ), - $wgUser->getSkin()->makeKnownLinkObj( - SpecialPage::getTitleFor( 'DeletedContributions', $this->getUsername() ), - wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $n ) ) ); - - return "

$msg

"; - } - - /** - * Construct and output the page subtitle. - */ - function outputSubtitle() { - global $wgOut; - $subtitle = $this->getSubtitleForTarget(); - // $subtitle .= $this->getDeletedContributionsLink(); NOT YET... - $wgOut->setSubtitle( $subtitle ); - } - - /** - * Construct the namespace selector form. - * @return string - */ - function getNamespaceForm() { - $title = $this->getTitle(); - - $ns = $this->namespace; - if ( !isset($ns) ) - $ns = ''; - - $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $title->getLocalUrl() ) ); - $form .= wfMsgHtml( 'namespace' ) . ' '; - $form .= Xml::namespaceSelector( $ns, '' ) . ' '; - $form .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ); - $form .= Xml::hidden( 'offset', $this->offset ); - $form .= Xml::hidden( 'limit', $this->limit ); - $form .= Xml::hidden( 'target', $this->getUsername() ); - if ( $this->botmode ) - $form .= Xml::hidden( 'bot', 1 ); - $form .= ''; - - return '

' . $form . '

'; - } - - /** - * Build the page header. Also calls outputSubtitle(). - * @return string - */ - function getPageHeader() { - $this->outputSubtitle(); - return $this->getNamespaceForm(); - } - - /** - * Construct the WHERE clause of the SQL SELECT statement for - * this query. - * @return string - */ - function makeSQLCond( $dbr ) { - $cond = ' page_id = rev_page'; - $cond .= ' AND rev_user_text = ' . $dbr->addQuotes( $this->getUsername() ); - - if ( isset($this->namespace) ) - $cond .= ' AND page_namespace = ' . (int)$this->namespace; - - return $cond; - } - - /** - * Construct the SQL SELECT statement for this query. - * @return string - */ - function getSQL() { - $dbr = wfGetDB( DB_SLAVE ); - - list( $page, $revision ) = $dbr->tableNamesN( 'page', 'revision' ); - - // XXX: the username and userid fields aren't used for much here, - // but some subclasses rely on them more than we do. - - return "SELECT 'Contributions' as type, - page_namespace AS namespace, - page_title AS title, - rev_timestamp AS value, - rev_user AS userid, - rev_user_text AS username, - rev_minor_edit AS is_minor, - page_latest AS cur_id, - rev_id AS rev_id, - rev_comment AS comment, - rev_deleted AS deleted - FROM $page, $revision - WHERE " . $this->makeSQLCond( $dbr ); - } - - /** - * Get user links for output row, for subclasses that may want - * such functionality. - * - * @param $skin Skin to use - * @param $row Result row - * @return string - */ - function getRowUserLinks( $skin, $row ) { return ''; } - - /** - * Format a row, providing the timestamp, links to the - * page/diff/history and a comment - * - * @param $skin Skin to use - * @param $row Result row - * @return string - */ - function formatResult( $skin, $row ) { - global $wgLang, $wgContLang, $wgUser; - - $dm = $wgContLang->getDirMark(); - - /* - * Cache UI messages in a static array so we don't - * have to regenerate them for each row. - */ - static $messages; - if( !isset( $messages ) ) { - foreach( explode( ' ', 'uctop diff newarticle rollbacklink diff hist minoreditletter' ) as $msg ) - $messages[$msg] = wfMsgExt( $msg, array( 'escape') ); + if ( $wgUser->isAllowed( 'rollback' ) && $wgRequest->getBool( 'bot' ) ) { + $options['bot'] = '1'; + } + + if ( $wgRequest->getText( 'go' ) == 'prev' ) { + $offset = $finder->getPreviousOffsetForPaging(); + if ( $offset !== false ) { + $options['offset'] = $offset; + $prevurl = $title->getLocalURL( wfArrayToCGI( $options ) ); + $wgOut->redirect( $prevurl ); + return; } + } - $page = Title::makeTitle( $row->namespace, $row->title ); + if ( $wgRequest->getText( 'go' ) == 'first' && $target != 'newbies') { + $offset = $finder->getFirstOffsetForPaging(); + if ( $offset !== false ) { + $options['offset'] = $offset; + $prevurl = $title->getLocalURL( wfArrayToCGI( $options ) ); + $wgOut->redirect( $prevurl ); + return; + } + } - /* - * HACK: We need a revision object, so we make a very - * heavily stripped-down one. All we really need are - * the comment, the title and the deletion bitmask. - */ - $rev = new Revision( array( - 'comment' => $row->comment, - 'deleted' => $row->deleted, - 'user_text' => $row->username, - 'user' => $row->userid, - ) ); - $rev->setTitle( $page ); + if ( $target == 'newbies' ) { + $wgOut->setSubtitle( wfMsgHtml( 'sp-contributions-newbies-sub') ); + } else { + $wgOut->setSubtitle( wfMsgHtml( 'contribsub', contributionsSub( $nt ) ) ); + } - $ts = wfTimestamp( TS_MW, $row->value ); - $time = $wgLang->timeAndDate( $ts, true ); - $hist = $skin->makeKnownLinkObj( $page, $messages['hist'], 'action=history' ); + $id = User::idFromName( $nt->getText() ); + wfRunHooks( 'SpecialContributionsBeforeMainOutput', $id ); - if ( $rev->userCan( Revision::DELETED_TEXT ) ) - $diff = $skin->makeKnownLinkObj( $page, $messages['diff'], 'diff=prev&oldid=' . $row->rev_id ); - else - $diff = $messages['diff']; + $wgOut->addHTML( contributionsForm( $options) ); - if( $row->is_minor ) - $mflag = '' . $messages['minoreditletter'] . ' '; - else - $mflag = ''; + $contribs = $finder->find(); - $link = $skin->makeKnownLinkObj( $page ); - $comment = $skin->revComment( $rev ); + if ( count( $contribs ) == 0) { + $wgOut->addWikiText( wfMsg( 'nocontribs' ) ); + return; + } - $user = $this->getRowUserLinks( $skin, $row ); // for subclasses + list( $early, $late ) = $finder->getEditLimits(); + $lastts = count( $contribs ) ? $contribs[count( $contribs ) - 1]->rev_timestamp : 0; + $atstart = ( !count( $contribs ) || $late == $contribs[0]->rev_timestamp ); + $atend = ( !count( $contribs ) || $early == $lastts ); + + // These four are defaults + $newestlink = wfMsgHtml( 'sp-contributions-newest' ); + $oldestlink = wfMsgHtml( 'sp-contributions-oldest' ); + $newerlink = wfMsgHtml( 'sp-contributions-newer', $options['limit'] ); + $olderlink = wfMsgHtml( 'sp-contributions-older', $options['limit'] ); + + if ( !$atstart ) { + $stuff = $title->escapeLocalURL( wfArrayToCGI( array( 'offset' => '' ), $options ) ); + $newestlink = "$newestlink"; + $stuff = $title->escapeLocalURL( wfArrayToCGI( array( 'go' => 'prev' ), $options ) ); + $newerlink = "$newerlink"; + } - $notes = ''; + if ( !$atend ) { + $stuff = $title->escapeLocalURL( wfArrayToCGI( array( 'go' => 'first' ), $options ) ); + $oldestlink = "$oldestlink"; + $stuff = $title->escapeLocalURL( wfArrayToCGI( array( 'offset' => $lastts ), $options ) ); + $olderlink = "$olderlink"; + } - if( $row->rev_id == $row->cur_id ) { - $notes .= ' ' . $messages['uctop'] . ''; + if ( $target == 'newbies' ) { + $firstlast ="($newestlink)"; + } else { + $firstlast = "($newestlink | $oldestlink)"; + } - if( $wgUser->isAllowed( 'rollback' ) ) - $notes .= ' ' . $skin->generateRollback( $rev ); - } - - if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { - $time = '' . $time . ''; - $notes .= ' ' . wfMsgHtml( 'deletedrev' ); + $urls = array(); + foreach ( array( 20, 50, 100, 250, 500 ) as $num ) { + $stuff = $title->escapeLocalURL( wfArrayToCGI( array( 'limit' => $num ), $options ) ); + $urls[] = "".$wgLang->formatNum( $num ).""; + } + $bits = implode( $urls, ' | ' ); + + $prevnextbits = $firstlast .' '. wfMsgHtml( 'viewprevnext', $newerlink, $olderlink, $bits ); + + $wgOut->addHTML( "

{$prevnextbits}

\n" ); + + $wgOut->addHTML( "\n" ); + $wgOut->addHTML( "

{$prevnextbits}

\n" ); +} + +/** + * Generates the subheading with links + * @param $nt @see Title object for the target + */ +function contributionsSub( $nt ) { + global $wgSysopUserBans, $wgLang, $wgUser; + + $sk = $wgUser->getSkin(); + $id = User::idFromName( $nt->getText() ); + + if ( 0 == $id ) { + $ul = $nt->getText(); + } else { + $ul = $sk->makeLinkObj( $nt, htmlspecialchars( $nt->getText() ) ); + } + $talk = $nt->getTalkPage(); + if( $talk ) { + # Talk page link + $tools[] = $sk->makeLinkObj( $talk, $wgLang->getNsText( NS_TALK ) ); + if( ( $id != 0 && $wgSysopUserBans ) || ( $id == 0 && User::isIP( $nt->getText() ) ) ) { + # Block link + if( $wgUser->isAllowed( 'block' ) ) + $tools[] = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'Blockip', $nt->getDBkey() ), wfMsgHtml( 'blocklink' ) ); + # Block log link + $tools[] = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'Log' ), htmlspecialchars( LogPage::logName( 'block' ) ), 'type=block&page=' . $nt->getPrefixedUrl() ); } - - return "{$time} ({$hist}) ({$diff}) {$mflag} {$dm}{$link}{$user} {$comment}{$notes}"; + # Other logs link + $tools[] = $sk->makeKnownLinkObj( SpecialPage::getTitleFor( 'Log' ), wfMsgHtml( 'log' ), 'user=' . $nt->getPartialUrl() ); + $ul .= ' (' . implode( ' | ', $tools ) . ')'; } + return $ul; } /** - * Show the special page. + * Generates the namespace selector form with hidden attributes. + * @param $options Array: the options to be included. */ -function wfSpecialContributions( $par = null ) { - global $wgRequest, $wgUser, $wgOut; +function contributionsForm( $options ) { + global $wgScript, $wgTitle; + + $options['title'] = $wgTitle->getPrefixedText(); + + $f = "
\n"; + foreach ( $options as $name => $value ) { + if( $name === 'namespace') continue; + $f .= "\t" . wfElement( 'input', array( + 'name' => $name, + 'type' => 'hidden', + 'value' => $value ) ) . "\n"; + } - $username = ( isset($par) ? $par : $wgRequest->getVal( 'target' ) ); + $f .= '

' . wfMsgHtml( 'namespace' ) . ' ' . + HTMLnamespaceselector( $options['namespace'], '' ) . + wfElement( 'input', array( + 'type' => 'submit', + 'value' => wfMsg( 'allpagessubmit' ) ) + ) . + "

\n"; - // compatibility hack - if ( $username == 'newbies' ) { - $wgOut->redirect( SpecialPage::getTitleFor( 'NewbieContributions' )->getFullURL() ); - return; + return $f; +} + +/** + * Generates each row in the contributions list. + * + * Contributions which are marked "top" are currently on top of the history. + * For these contributions, a [rollback] link is shown for users with sysop + * privileges. The rollback link restores the most recent version that was not + * written by the target user. + * + * @todo This would probably look a lot nicer in a table. + */ +function ucListEdit( $sk, $row ) { + $fname = 'ucListEdit'; + wfProfileIn( $fname ); + + global $wgLang, $wgUser, $wgRequest; + static $messages; + if( !isset( $messages ) ) { + foreach( explode( ' ', 'uctop diff newarticle rollbacklink diff hist minoreditletter' ) as $msg ) { + $messages[$msg] = wfMsgExt( $msg, array( 'escape') ); + } } - $page = new ContributionsPage( $username ); + $rev = new Revision( $row ); + + $page = Title::makeTitle( $row->page_namespace, $row->page_title ); + $link = $sk->makeKnownLinkObj( $page ); + $difftext = $topmarktext = ''; + if( $row->rev_id == $row->page_latest ) { + $topmarktext .= '' . $messages['uctop'] . ''; + if( !$row->page_is_new ) { + $difftext .= '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=0' ) . ')'; + } else { + $difftext .= $messages['newarticle']; + } + + if( $wgUser->isAllowed( 'rollback' ) ) { + $topmarktext .= ' '.$sk->generateRollback( $rev ); + } - if( !$page->user ) { - $wgOut->showErrorPage( 'notargettitle', 'notargettext' ); - return; } - // hook for Contributionseditcount extension - if ( $page->user && $page->user->isLoggedIn() ) - wfRunHooks( 'SpecialContributionsBeforeMainOutput', $page->user->getId() ); - - $page->namespace = $wgRequest->getIntOrNull( 'namespace' ); - $page->botmode = ( $wgUser->isAllowed( 'rollback' ) && $wgRequest->getBool( 'bot' ) ); + if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { + if ( $rev->userCan( Revision::DELETED_TEXT ) ) { + $difftext .= '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=prev&oldid='.$row->rev_id ) . ')'; + } else { + $difftext .= '(' . $messages['diff'] . ')'; + } + } + $histlink='('.$sk->makeKnownLinkObj( $page, $messages['hist'], 'action=history' ) . ')'; + + $comment = $sk->revComment( $rev ); + $d = $wgLang->timeanddate( wfTimestamp( TS_MW, $row->rev_timestamp ), true ); - list( $limit, $offset ) = wfCheckLimits(); - return $page->doQuery( $offset, $limit ); + if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { + $d = '' . $d . ''; + } + + if( $row->rev_minor_edit ) { + $mflag = '' . $messages['minoreditletter'] . ' '; + } else { + $mflag = ''; + } + + $ret = "{$d} {$histlink} {$difftext} {$mflag} {$link} {$comment} {$topmarktext}"; + if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { + $ret .= ' ' . wfMsgHtml( 'deletedrev' ); + } + $ret = "
  • $ret
  • \n"; + wfProfileOut( $fname ); + return $ret; } ?> diff --git a/includes/SpecialNewbieContributions.php b/includes/SpecialNewbieContributions.php deleted file mode 100644 index 7e8e948cbe..0000000000 --- a/includes/SpecialNewbieContributions.php +++ /dev/null @@ -1,107 +0,0 @@ - no subtitle. - */ - function getSubtitleForTarget() { - return ''; - } - - /** - * No target user => no deleted contribs link. - */ - function getDeletedContributionsLink() { - return ''; - } - - /** - * Construct the WHERE clause of the SQL SELECT statement for - * this query. - * @return string - */ - function makeSQLCond( $dbr ) { - $cond = ' page_id = rev_page'; - - $max = $dbr->selectField( 'user', 'max(user_id)', false, 'make_sql' ); - $cond .= ' AND rev_user > ' . (int)($max - $max / 100); - - if ( isset($this->namespace) ) - $cond .= ' AND page_namespace = ' . (int)$this->namespace; - - return $cond; - } - - /** - * Do a batch existence check for any user and user talk pages - * that will be shown in the list. - */ - function preprocessResults( $dbr, $res ) { - $linkBatch = new LinkBatch(); - while( $row = $dbr->fetchObject( $res ) ) { - $linkBatch->add( NS_USER, $row->username ); - $linkBatch->add( NS_USER_TALK, $row->username ); - } - $linkBatch->execute(); - - // Seek to start - if( $dbr->numRows( $res ) > 0 ) - $dbr->dataSeek( $res, 0 ); - } - - /** - * Get user links for output row. - * - * @param $skin Skin to use - * @param $row Result row - * @return string User links - */ - function getRowUserLinks( $skin, $row ) { - $user = ' . . ' . $skin->userLink( $row->userid, $row->username ) - . $skin->userToolLinks( $row->userid, $row->username ); - return $user; - } -} - -/** - * Show the special page. - */ -function wfSpecialNewbieContributions( $par = null ) { - global $wgRequest, $wgUser, $wgOut; - - $page = new NewbieContributionsPage(); - - $page->namespace = $wgRequest->getIntOrNull( 'namespace' ); - $page->botmode = ( $wgUser->isAllowed( 'rollback' ) && $wgRequest->getBool( 'bot' ) ); - - list( $limit, $offset ) = wfCheckLimits(); - return $page->doQuery( $offset, $limit ); -} - -?> diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php index 92aa4cbf45..e8db18b742 100644 --- a/includes/SpecialPage.php +++ b/includes/SpecialPage.php @@ -114,7 +114,6 @@ class SpecialPage 'Ipblocklist' => array( 'SpecialPage', 'Ipblocklist' ), 'Specialpages' => array( 'UnlistedSpecialPage', 'Specialpages' ), 'Contributions' => array( 'UnlistedSpecialPage', 'Contributions' ), - 'NewbieContributions' => array( 'SpecialPage', 'NewbieContributions' ), 'Emailuser' => array( 'UnlistedSpecialPage', 'Emailuser' ), 'Whatlinkshere' => array( 'UnlistedSpecialPage', 'Whatlinkshere' ), 'Recentchangeslinked' => array( 'UnlistedSpecialPage', 'Recentchangeslinked' ), diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index f1860b2482..5e7a573f74 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -380,7 +380,6 @@ $specialPageAliases = array( 'Ipblocklist' => array( 'Ipblocklist' ), 'Specialpages' => array( 'Specialpages' ), 'Contributions' => array( 'Contributions' ), - 'NewbieContributions' => array( 'NewbieContributions' ), 'Emailuser' => array( 'Emailuser' ), 'Whatlinkshere' => array( 'Whatlinkshere' ), 'Recentchangeslinked' => array( 'Recentchangeslinked' ), @@ -1755,11 +1754,19 @@ Consult the [[Special:Log/delete|deletion log]] for a record of recent deletions 'contributions' => 'User contributions', 'mycontris' => 'My contributions', 'contribsub' => "For $1", +'nocontribs' => 'No changes were found matching these criteria.', +'ucnote' => "Below are this user's last $1 changes in the last $2 days.", +'uclinks' => "View the last $1 changes; view the last $2 days.", 'uctop' => ' (top)' , +'newbies' => 'newbies', -# Newbie contributions -# -'newbiecontributions' => 'Newbie contributions', +'sp-newimages-showfrom' => 'Show new images starting from $1', + +'sp-contributions-newest' => 'Newest', +'sp-contributions-oldest' => 'Oldest', +'sp-contributions-newer' => 'Newer $1', +'sp-contributions-older' => 'Older $1', +'sp-contributions-newbies-sub' => 'For newbies', # What links here @@ -2161,7 +2168,6 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\');', 'newimages-summary' => '', 'showhidebots' => '($1 bots)', 'noimages' => 'Nothing to see.', -'sp-newimages-showfrom' => 'Show new images starting from $1', # short names for language variants used for language conversion links. # to disable showing a particular link, set it to 'disable', e.g. diff --git a/languages/messages/MessagesFi.php b/languages/messages/MessagesFi.php index b9bddc4ad3..da698149f0 100644 --- a/languages/messages/MessagesFi.php +++ b/languages/messages/MessagesFi.php @@ -1137,11 +1137,17 @@ Palaute ja lisäapu osoitteessa: 'contributions' => 'Käyttäjän muokkaukset', 'mycontris' => 'Muokkaukset', 'contribsub' => 'Käyttäjän $1 muokkaukset', +'nocontribs' => 'Näihin ehtoihin sopivia muokkauksia ei löytynyt.', +'ucnote' => 'Alla on \'\'\'$1\'\'\' viimeisintä tämän käyttäjän tekemää muokkausta viimeisten \'\'\'$2\'\'\' päivän aikana.', +'uclinks' => 'Katso $1 viimeisintä muokkausta; katso $2 viimeisintä päivää.', 'uctop' => ' (uusin)' , +'newbies' => 'tulokkaat', -# Newbie contributions -# -'newbiecontributions' => 'Uusien tulokkaiden muokkaukset', +'sp-contributions-newest' => 'Uusimmat', +'sp-contributions-oldest' => 'Vanhimmat', +'sp-contributions-newer' => '← $1 uudempaa', +'sp-contributions-older' => '$1 vanhempaa →', +'sp-contributions-newbies-sub' => 'Uusien tulokkaiden muokkaukset', # What links here # -- 2.20.1