r52215 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r52214‎ | r52215 | r52216 >
Date:22:12, 20 June 2009
Author:aaron
Status:resolved (Comments)
Tags:
Comment:
bug 19107 Tag filter for pending changes
Modified paths:
  • /trunk/extensions/FlaggedRevs/FlaggedRevs.php (modified) (history)
  • /trunk/extensions/FlaggedRevs/language/ProblemChanges.i18n.php (added) (history)
  • /trunk/extensions/FlaggedRevs/specialpages/ProblemChanges_body.php (added) (history)

Diff [purge]

Index: trunk/extensions/FlaggedRevs/FlaggedRevs.php
@@ -336,6 +336,10 @@
337337 $wgAutoloadClasses['OldReviewedPages'] = $dir . 'specialpages/OldReviewedPages_body.php';
338338 $wgExtensionMessagesFiles['OldReviewedPages'] = $langDir . 'OldReviewedPages.i18n.php';
339339 $wgSpecialPageGroups['OldReviewedPages'] = 'quality';
 340+# Load "suspicious changes" pages list
 341+$wgAutoloadClasses['ProblemChanges'] = $dir . 'specialpages/ProblemChanges_body.php';
 342+$wgExtensionMessagesFiles['ProblemChanges'] = $langDir . 'ProblemChanges.i18n.php';
 343+$wgSpecialPageGroups['ProblemChanges'] = 'quality';
340344 # Load reviewed pages list
341345 $wgAutoloadClasses['ReviewedPages'] = $dir . 'specialpages/ReviewedPages_body.php';
342346 $wgExtensionMessagesFiles['ReviewedPages'] = $langDir . 'ReviewedPages.i18n.php';
@@ -509,6 +513,7 @@
510514 $list['Stabilization'] = $wgSpecialPages['Stabilization'] = 'Stabilization';
511515 $list['UnreviewedPages'] = $wgSpecialPages['UnreviewedPages'] = 'UnreviewedPages';
512516 $list['OldReviewedPages'] = $wgSpecialPages['OldReviewedPages'] = 'OldReviewedPages';
 517+ $list['ProblemChanges'] = $wgSpecialPages['ProblemChanges'] = 'ProblemChanges';
513518 $list['ReviewedPages'] = $wgSpecialPages['ReviewedPages'] = 'ReviewedPages';
514519 $list['StablePages'] = $wgSpecialPages['StablePages'] = 'StablePages';
515520 $list['UnstablePages'] = $wgSpecialPages['UnstablePages'] = 'UnstablePages';
Index: trunk/extensions/FlaggedRevs/language/ProblemChanges.i18n.php
@@ -0,0 +1,15 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for FlaggedRevs extension, section ProblemChanges
 5+ *
 6+ * @addtogroup Extensions
 7+ */
 8+
 9+$messages = array();
 10+
 11+$messages['en'] = array(
 12+ 'problemchanges' => 'Review tagged changes',
 13+ 'problemchanges-legend' => 'List reviewed pages with tagged edits pending review',
 14+ 'problemchanges-none' => 'There are currently no pages meeting these criteria',
 15+ 'problemchanges-category' => 'Category:',
 16+);
Index: trunk/extensions/FlaggedRevs/specialpages/ProblemChanges_body.php
@@ -0,0 +1,373 @@
 2+<?php
 3+if ( !defined( 'MEDIAWIKI' ) ) {
 4+ echo "FlaggedRevs extension\n";
 5+ exit( 1 );
 6+}
 7+
 8+class ProblemChanges extends SpecialPage
 9+{
 10+ public function __construct() {
 11+ parent::__construct( 'ProblemChanges' );
 12+ $this->includable( true );
 13+ wfLoadExtensionMessages( 'ProblemChanges' );
 14+ wfLoadExtensionMessages( 'OldReviewedPages' );
 15+ wfLoadExtensionMessages( 'FlaggedRevs' );
 16+ }
 17+
 18+ public function execute( $par ) {
 19+ global $wgRequest, $wgUser, $wgOut;
 20+ $this->setHeaders();
 21+ $this->skin = $wgUser->getSkin();
 22+ $this->level = $wgRequest->getInt( 'level', -1 );
 23+ $this->tag = trim( $wgRequest->getVal( 'tagfilter' ) );
 24+ $this->category = trim( $wgRequest->getVal( 'category' ) );
 25+ $feedType = $wgRequest->getVal( 'feed' );
 26+ if( $feedType ) {
 27+ return $this->feed( $feedType );
 28+ }
 29+ $this->setSyndicated();
 30+ $this->showList( $par );
 31+ }
 32+
 33+ protected function setSyndicated() {
 34+ global $wgOut, $wgRequest;
 35+ $queryParams = array(
 36+ 'level' => $wgRequest->getIntOrNull( 'level' ),
 37+ 'tag' => $wgRequest->getVal( 'tag' ),
 38+ 'category' => $wgRequest->getVal( 'category' ),
 39+ );
 40+ $wgOut->setSyndicated( true );
 41+ $wgOut->setFeedAppendQuery( wfArrayToCGI( $queryParams ) );
 42+ }
 43+
 44+ public function showList( $par ) {
 45+ global $wgOut, $wgScript, $wgUser, $wgFlaggedRevsNamespaces;
 46+ $limit = $this->parseParams( $par );
 47+ $pager = new ProblemChangesPager( $this, $this->level, $this->category, $this->tag );
 48+ // Apply limit if transcluded
 49+ $pager->mLimit = $limit ? $limit : $pager->mLimit;
 50+ // Viewing the page normally...
 51+ if( !$this->including() ) {
 52+ $action = htmlspecialchars( $wgScript );
 53+ $tagForm = ChangeTags::buildTagFilterSelector( $this->tag );
 54+ $wgOut->addHTML(
 55+ "<form action=\"$action\" method=\"get\">\n" .
 56+ '<fieldset><legend>' . wfMsg('problemchanges-legend') . '</legend>' .
 57+ Xml::hidden( 'title', $this->getTitle()->getPrefixedDBKey() )
 58+ );
 59+ $form =
 60+ ( FlaggedRevs::qualityVersions() ?
 61+ "<span style='white-space: nowrap;'>" .
 62+ FlaggedRevsXML::getLevelMenu( $this->level, 'revreview-filter-stable' ) . '</span> '
 63+ : ""
 64+ );
 65+ if( count($tagForm) ) {
 66+ $form .= Xml::tags( 'td', array( 'class' => 'mw-label' ), $tagForm[0] );
 67+ $form .= Xml::tags( 'td', array( 'class' => 'mw-input' ), $tagForm[1] );
 68+ }
 69+ $form .= '<br/>' .
 70+ Xml::label( wfMsg("problemchanges-category"), 'wpCategory' ) . '&nbsp;' .
 71+ Xml::input( 'category', 30, $this->category, array('id' => 'wpCategory') ) . ' ';
 72+ $form .= Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . "\n" .
 73+ "</fieldset></form>";
 74+ # Add filter options
 75+ $wgOut->addHTML( $form );
 76+ # Add list output (skip if no tag given)
 77+ $num = strlen($this->tag) && $pager->getNumRows();
 78+ if( $num ) {
 79+ $wgOut->addHTML( $pager->getNavigationBar() );
 80+ $wgOut->addHTML( $pager->getBody() );
 81+ $wgOut->addHTML( $pager->getNavigationBar() );
 82+ } else if( strlen($this->tag) ) {
 83+ $wgOut->addHTML( wfMsgExt('problemchanges-none', array('parse') ) );
 84+ }
 85+ // If this page is transcluded...
 86+ } else {
 87+ if( strlen($this->tag) && $pager->getNumRows() ) {
 88+ $wgOut->addHTML( $pager->getBody() );
 89+ } else if( strlen($this->tag) ) {
 90+ $wgOut->addHTML( wfMsgExt('problemchanges-none', array('parse') ) );
 91+ }
 92+ }
 93+ }
 94+
 95+ protected function parseParams( $par ) {
 96+ global $wgLang;
 97+ $bits = preg_split( '/\s*,\s*/', trim( $par ) );
 98+ $limit = false;
 99+ foreach( $bits as $bit ) {
 100+ if( is_numeric( $bit ) )
 101+ $limit = intval( $bit );
 102+ $m = array();
 103+ if( preg_match( '/^limit=(\d+)$/', $bit, $m ) )
 104+ $limit = intval($m[1]);
 105+ if( preg_match( '/^category=(.+)$/', $bit, $m ) )
 106+ $this->category = $m[1];
 107+ if( preg_match( '/^tagfilter=(.+)$/', $bit, $m ) )
 108+ $this->tag = $m[1];
 109+ }
 110+ return $limit;
 111+ }
 112+
 113+ /**
 114+ * Output a subscription feed listing recent edits to this page.
 115+ * @param string $type
 116+ */
 117+ protected function feed( $type ) {
 118+ global $wgFeed, $wgFeedClasses, $wgRequest;
 119+ if( !$wgFeed ) {
 120+ global $wgOut;
 121+ $wgOut->addWikiMsg( 'feed-unavailable' );
 122+ return;
 123+ }
 124+ if( !isset( $wgFeedClasses[$type] ) ) {
 125+ global $wgOut;
 126+ $wgOut->addWikiMsg( 'feed-invalid' );
 127+ return;
 128+ }
 129+ $feed = new $wgFeedClasses[$type](
 130+ $this->feedTitle(),
 131+ wfMsg( 'tagline' ),
 132+ $this->getTitle()->getFullUrl() );
 133+
 134+ $pager = new ProblemChangesPager( $this, $this->category );
 135+ $limit = $wgRequest->getInt( 'limit', 50 );
 136+ global $wgFeedLimit;
 137+ $pager->mLimit = min( $wgFeedLimit, $limit );
 138+
 139+ $feed->outHeader();
 140+ if( $pager->getNumRows() > 0 ) {
 141+ while( $row = $pager->mResult->fetchObject() ) {
 142+ $feed->outItem( $this->feedItem( $row ) );
 143+ }
 144+ }
 145+ $feed->outFooter();
 146+ }
 147+
 148+ protected function feedTitle() {
 149+ global $wgContLanguageCode, $wgSitename;
 150+ $page = SpecialPage::getPage( 'problemchanges' );
 151+ $desc = $page->getDescription();
 152+ return "$wgSitename - $desc [$wgContLanguageCode]";
 153+ }
 154+
 155+ protected function feedItem( $row ) {
 156+ $title = Title::MakeTitle( $row->page_namespace, $row->page_title );
 157+ if( $title ) {
 158+ $date = $row->pending_since;
 159+ $comments = $title->getTalkPage()->getFullURL();
 160+ $curRev = Revision::newFromTitle( $title );
 161+ return new FeedItem(
 162+ $title->getPrefixedText(),
 163+ FeedUtils::formatDiffRow( $title, $row->stable, $curRev->getId(),
 164+ $row->pending_since, $curRev->getComment() ),
 165+ $title->getFullURL(),
 166+ $date,
 167+ $curRev->getUserText(),
 168+ $comments
 169+ );
 170+ } else {
 171+ return NULL;
 172+ }
 173+ }
 174+
 175+ public function formatRow( $row ) {
 176+ global $wgLang, $wgUser, $wgMemc;
 177+
 178+ $title = Title::makeTitle( $row->page_namespace, $row->page_title );
 179+ $link = $this->skin->makeKnownLinkObj( $title );
 180+ $css = $stxt = $review = $quality = $underReview = '';
 181+ $review = $this->skin->makeKnownLinkObj( $title, wfMsg('oldreviewed-diff'),
 182+ "diff=cur&oldid={$row->stable}&reviewform=1&diffonly=0" );
 183+ # Show quality level if there are several
 184+ if( FlaggedRevs::qualityVersions() ) {
 185+ $quality = $row->quality ?
 186+ wfMsgHtml('revreview-lev-quality') : wfMsgHtml('revreview-lev-sighted');
 187+ $quality = " <b>[{$quality}]</b>";
 188+ }
 189+ # Is anybody watching?
 190+ if( !$this->including() && $wgUser->isAllowed( 'unreviewedpages' ) ) {
 191+ $uw = UnreviewedPages::usersWatching( $title );
 192+ $watching = $uw
 193+ ? wfMsgExt('oldreviewedpages-watched','parsemag',$uw,$uw)
 194+ : wfMsgHtml('oldreviewedpages-unwatched');
 195+ $watching = " {$watching}";
 196+ } else {
 197+ $uw = -1;
 198+ $watching = ''; // leave out data
 199+ }
 200+ # Get how long the first unreviewed edit has been waiting...
 201+ if( $row->pending_since ) {
 202+ static $currentTime;
 203+ $currentTime = wfTimestamp( TS_UNIX ); // now
 204+ $firstPendingTime = wfTimestamp( TS_UNIX, $row->pending_since );
 205+ $hours = ($currentTime - $firstPendingTime)/3600;
 206+ // After three days, just use days
 207+ if( $hours > (3*24) ) {
 208+ $days = round($hours/24,0);
 209+ $age = wfMsgExt('oldreviewedpages-days',array('parsemag'),$days);
 210+ // If one or more hours, use hours
 211+ } elseif( $hours >= 1 ) {
 212+ $hours = round($hours,0);
 213+ $age = wfMsgExt('oldreviewedpages-hours',array('parsemag'),$hours);
 214+ } else {
 215+ $age = wfMsg('oldreviewedpages-recent'); // hot off the press :)
 216+ }
 217+ // Oh-noes!
 218+ $css = self::getLineClass( $hours, $uw );
 219+ $css = $css ? " class='$css'" : "";
 220+ } else {
 221+ $age = ""; // wtf?
 222+ }
 223+ $key = wfMemcKey( 'stableDiffs', 'underReview', $row->stable, $row->page_latest );
 224+ # Show if a user is looking at this page
 225+ if( ($val = $wgMemc->get($key)) ) {
 226+ $underReview = " <b class='fr-under-review'>".wfMsgHtml('oldreviewedpages-viewing').'</b>';
 227+ }
 228+
 229+ return( "<li{$css}>{$link} {$stxt} ({$review}) <i>{$age}</i>{$quality}{$watching}{$underReview}</li>" );
 230+ }
 231+
 232+ /**
 233+ * Get the timestamp of the next revision
 234+ *
 235+ * @param integer $revision Revision ID. Get the revision that was after this one.
 236+ * @param integer $page, page ID
 237+ */
 238+ protected function getNextRevisionTimestamp( $revision, $page ) {
 239+ $dbr = wfGetDB( DB_SLAVE );
 240+ return $dbr->selectField( 'revision', 'rev_timestamp',
 241+ array(
 242+ 'rev_page' => $page,
 243+ 'rev_id > ' . intval( $revision )
 244+ ),
 245+ __METHOD__,
 246+ array( 'ORDER BY' => 'rev_id' )
 247+ );
 248+ }
 249+
 250+ protected static function getLineClass( $hours, $uw ) {
 251+ if( $uw == 0 )
 252+ return 'fr-unreviewed-unwatched';
 253+ else
 254+ return "";
 255+ }
 256+}
 257+
 258+/**
 259+ * Query to list out outdated reviewed pages
 260+ */
 261+class ProblemChangesPager extends AlphabeticPager {
 262+ public $mForm, $mConds;
 263+ private $category, $namespace, $tag;
 264+
 265+ function __construct( $form, $level=-1, $category='', $tag='' )
 266+ {
 267+ $this->mForm = $form;
 268+ # Must be a content page...
 269+ global $wgFlaggedRevsNamespaces;
 270+ $this->namespace = $wgFlaggedRevsNamespaces;
 271+ # Sanity check level: 0 = sighted; 1 = quality; 2 = pristine
 272+ $this->level = ($level >= 0 && $level <= 2) ? $level : -1;
 273+ $this->tag = $tag;
 274+ $this->category = $category ? str_replace(' ','_',$category) : NULL;
 275+ parent::__construct();
 276+ // Don't get to expensive
 277+ $this->mLimitsShown = array( 20, 50, 100 );
 278+ $this->mLimit = min( $this->mLimit, 100 );
 279+ }
 280+
 281+ function formatRow( $row ) {
 282+ return $this->mForm->formatRow( $row );
 283+ }
 284+
 285+ function getDefaultDirections() {
 286+ return false;
 287+ }
 288+
 289+ function getQueryInfo() {
 290+ global $wgUser;
 291+ $conds = $this->mConds;
 292+ $tables = array( 'page', 'revision', 'change_tag' );
 293+ $fields = array('page_namespace','page_title','page_latest');
 294+ # Show outdated "stable" versions
 295+ if( $this->level < 0 ) {
 296+ $fields[] = 'fp_stable AS stable';
 297+ $fields[] = 'fp_quality AS quality';
 298+ $fields[] = 'fp_pending_since AS pending_since';
 299+ $conds[] = 'fp_pending_since IS NOT NULL';
 300+ $conds[] = 'page_id = fp_page_id';
 301+ # Find revisions that are tagged as such
 302+ $conds[] = 'rev_page = page_id';
 303+ $conds[] = 'rev_id > fp_stable';
 304+ $conds[] = 'ct_rev_id = rev_id';
 305+ $conds['ct_tag'] = $this->tag;
 306+ $useIndex = array('flaggedpages' => 'fp_pending_since',
 307+ 'change_tag' => 'change_tag_rev_tag ');
 308+ # Filter by category
 309+ if( $this->category ) {
 310+ array_unshift($tables,'categorylinks'); // order matters
 311+ $conds[] = 'cl_from = fp_page_id';
 312+ $conds['cl_to'] = $this->category;
 313+ $useIndex['categorylinks'] = 'cl_from';
 314+ }
 315+ array_unshift($tables,'flaggedpages'); // order matters
 316+ $this->mIndexField = 'fp_pending_since';
 317+ $groupBy = 'fp_pending_since,fp_page_id';
 318+ # Show outdated version for a specific review level
 319+ } else {
 320+ $fields[] = 'fpp_rev_id AS stable';
 321+ $fields[] = 'fpp_quality AS quality';
 322+ $fields[] = 'fpp_pending_since AS pending_since';
 323+ $conds[] = 'fpp_pending_since IS NOT NULL';
 324+ $conds[] = 'page_id = fpp_page_id';
 325+ # Find revisions that are tagged as such
 326+ $conds[] = 'rev_page = page_id';
 327+ $conds[] = 'rev_id > fpp_rev_id';
 328+ $conds[] = 'rev_id = ct_rev_id';
 329+ $conds['ct_tag'] = $this->tag;
 330+ $useIndex = array('flaggedpage_pending' => 'fpp_quality_pending',
 331+ 'change_tag' => 'change_tag_rev_tag ');
 332+ # Filter by review level
 333+ $conds['fpp_quality'] = $this->level;
 334+ # Filter by category
 335+ if( $this->category ) {
 336+ array_unshift($tables,'categorylinks'); // order matters
 337+ $conds[] = 'cl_from = fpp_page_id';
 338+ $conds['cl_to'] = $this->category;
 339+ $useIndex['categorylinks'] = 'cl_from';
 340+ }
 341+ array_unshift($tables,'flaggedpage_pending'); // order matters
 342+ $this->mIndexField = 'fpp_pending_since';
 343+ $groupBy = 'fpp_pending_since,fpp_page_id';
 344+ }
 345+ $fields[] = $this->mIndexField; // Pager needs this
 346+ $conds['page_namespace'] = $this->namespace; // sanity check NS
 347+ return array(
 348+ 'tables' => $tables,
 349+ 'fields' => $fields,
 350+ 'conds' => $conds,
 351+ 'options' => array( 'USE INDEX' => $useIndex, 'GROUP BY' => $groupBy, 'STRAIGHT_JOIN' )
 352+ );
 353+ }
 354+
 355+ function getIndexField() {
 356+ return $this->mIndexField;
 357+ }
 358+
 359+ function getStartBody() {
 360+ wfProfileIn( __METHOD__ );
 361+ # Do a link batch query
 362+ $lb = new LinkBatch();
 363+ while( $row = $this->mResult->fetchObject() ) {
 364+ $lb->add( $row->page_namespace, $row->page_title );
 365+ }
 366+ $lb->execute();
 367+ wfProfileOut( __METHOD__ );
 368+ return '<ul>';
 369+ }
 370+
 371+ function getEndBody() {
 372+ return '</ul>';
 373+ }
 374+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r52219Follow-up to r52215:...siebrand22:44, 20 June 2009
r52220Update Translate with FlaggedRevs - ProblemChanges (r52215)siebrand22:46, 20 June 2009

Comments

#Comment by Siebrand (talk | contribs)   19:37, 21 June 2009

You need to properly configure your svn client to add "eol-style native", Aaron. See Subversion/auto-props. Thanks.

Status & tagging log