r103079 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103078‎ | r103079 | r103080 >
Date:23:43, 14 November 2011
Author:rsterbin
Status:deferred
Tags:
Comment:
View ratings now works:
- Moved call to $.articleFeedbackv5.buckets[5].loadAggregateRatings() from the
form-building stage (which would be called once, immediately upon page
load) to the toggle event itself, with a new property
$.articleFeedbackv5.buckets[5].loadAggregate to keep track of whether it
needs to be loaded (once on toggle to view, and again only if the user had
submitted the form between toggles)
- Changed the API call to a custom one, rather than using afsubaction to
switch between the two uses (new class ApiViewRatingsArticleFeedbackv5)
- Updated the API call so that it sends rating rollup data already in the
correct format and removed the data munging from the success callback
- Removed ratings view code from ApiQueryArticleFeedbackv5 and cleaned it
up to follow coding standards

Temporary fix for the error overlay covering the whole article:
- New method $.articleFeedbackv5.buckets[5].markShowstopperError()
- Updated loadAggregates to use it, although eventually we may want to
downgrade to a non-showstopper sort of error (after all, viewing ratings
isn't critical)

Renamed some css class prefixes I missed last time
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiQueryArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php (added) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedback/ext.articleFeedback.css (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedback/ext.articleFeedback.dashboard.css (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedback/jquery.articleFeedback.js (modified) (history)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedback/jquery.articleFeedback.js
@@ -131,6 +131,15 @@
132132 */
133133 showOptions: 'show' === mw.user.bucket( 'ext.articleFeedback-options', mw.config.get( 'wgArticleFeedbackv5Options' ) ),
134134
 135+ /**
 136+ * Whether we need to load the aggregate ratings the next time the
 137+ * button is clicked. This is initially set to true, turned to
 138+ * false after the first time, then turned back to true on form
 139+ * submission, in case the user wants to go back and see the ratings with
 140+ * theirs included.
 141+ */
 142+ loadAggregate: true,
 143+
135144 // }}}
136145 // {{{ buildForm
137146
@@ -301,9 +310,6 @@
302311 $block.find( '.articleFeedbackv5-options' ).hide();
303312 }
304313
305 - // Grab the results in the background
306 - $.articleFeedbackv5.currentBucket().loadAggregateRatings();
307 -
308314 return $block;
309315 },
310316
@@ -368,6 +374,10 @@
369375 // Set up form/report switch behavior
370376 $block.find( '.articleFeedbackv5-switch' )
371377 .click( function ( e ) {
 378+ if ( $(this).attr( 'rel' ) == 'report' && $.articleFeedbackv5.currentBucket().loadAggregate ) {
 379+ $.articleFeedbackv5.currentBucket().loadAggregateRatings();
 380+ $.articleFeedbackv5.currentBucket().loadAggregate = false;
 381+ }
372382 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-visibleWith-' + $(this).attr( 'rel' ) )
373383 .show();
374384 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-switch' )
@@ -535,56 +545,43 @@
536546 * the label's CSS class
537547 */
538548 loadAggregateRatings: function () {
539 - var usecache = !( !$.articleFeedbackv5.anonymous || $.articleFeedbackv5.alreadySubmitted );
540 -
541549 $.ajax( {
542550 'url': $.articleFeedbackv5.apiUrl,
543551 'type': 'GET',
544552 'dataType': 'json',
545 - 'cache': usecache,
546553 'data': {
547554 'action': 'query',
548555 'format': 'json',
549 - 'list': 'articlefeedbackv5',
550 - 'afsubaction': 'showratings',
 556+ 'list': 'articlefeedbackv5-view-ratings',
551557 'afpageid': $.articleFeedbackv5.pageId,
552 - 'afanontoken': usecache ? $.articleFeedbackv5.userId : '',
553 - 'afuserrating': Number( !usecache ),
 558+ 'afanontoken': $.articleFeedbackv5.userId,
554559 'maxage': 0,
555 - 'smaxage': usecache ? 0 : mw.config.get( 'wgArticleFeedbackSMaxage' )
 560+ 'smaxage': mw.config.get( 'wgArticleFeedbackSMaxage' )
556561 },
557562 'success': function ( data ) {
558563 // Get data
559564 if (
560565 !( 'query' in data )
561 - || !( 'articlefeedbackv5' in data.query )
562 - || !$.isArray( data.query.articlefeedbackv5 )
563 - || !data.query.articlefeedbackv5.length
 566+ || !( 'articlefeedbackv5-view-ratings' in data.query )
 567+ || !( 'rollup' in data.query['articlefeedbackv5-view-ratings'] )
564568 ) {
565569 mw.log( 'ArticleFeedback invalid response error.' );
566 - if ($.articleFeedbackv5.debug && 'error' in data && 'info' in data.error) {
567 - console.log( data.error.info );
568 - $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error-message' ).html( data.error.info.replace( "\n", '<br />' ) );
 570+ var msg = 'ArticleFeedback invalid response error.';
 571+ if ( 'error' in data && 'info' in data.error ) {
 572+ msg = data.error.info;
 573+ } else {
 574+ console.log(data);
569575 }
570 - $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error' ).show();
 576+ $.articleFeedbackv5.currentBucket().markShowstopperError( msg );
571577 return;
572578 }
573 - $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error' ).show();
574 - var feedback = data.query.articlefeedbackv5[0];
 579+ var rollup = data.query['articlefeedbackv5-view-ratings'].rollup;
575580
576 - // Index rating data by rating ID
577 - var ratings = {};
578 - if ( typeof feedback.ratings === 'object' && feedback.ratings !== null ) {
579 - for ( var i = 0; i < feedback.ratings.length; i++ ) {
580 - ratings[feedback.ratings[i].ratingid] = feedback.ratings[i];
581 - }
582 - }
583 -
584581 // Ratings
585582 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-rating' ).each( function () {
586583 var name = $(this).attr( 'rel' );
587584 var info = $.articleFeedbackv5.currentBucket().ratingInfo;
588 - var rating = name in info && info[name] in ratings ? ratings[info[name]] : null;
 585+ var rating = name in info && info[name] in rollup ? rollup[info[name]] : null;
589586 if (
590587 rating !== null
591588 && 'total' in rating
@@ -597,7 +594,7 @@
598595 $(this).find( '.articleFeedbackv5-rating-meter div' )
599596 .css( 'width', Math.round( average * 21 ) + 'px' );
600597 $(this).find( '.articleFeedbackv5-rating-count' )
601 - .text( mw.msg( 'articlefeedbackv5-report-ratings', rating.countall ) );
 598+ .text( mw.msg( 'articlefeedbackv5-report-ratings', rating.count ) );
602599 } else {
603600 // Special case for no ratings
604601 $(this).find( '.articleFeedbackv5-rating-average' )
@@ -626,6 +623,7 @@
627624 },
628625 'error': function () {
629626 mw.log( 'Report loading error' );
 627+ $.articleFeedbackv5.currentBucket().markShowstopperError( 'Report loading error' );
630628 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error' ).show();
631629 }
632630 } );
@@ -727,6 +725,31 @@
728726 },
729727
730728 // }}}
 729+ // {{{ markShowstopperError
 730+
 731+ /**
 732+ * Marks a showstopper error
 733+ *
 734+ * @param string message the message to display, if in dev
 735+ */
 736+ markShowstopperError: function ( message ) {
 737+ console.log( message );
 738+ if ($.articleFeedbackv5.debug && message) {
 739+ $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error-message' ).html( message.replace( "\n", '<br />' ) );
 740+ }
 741+ var veil = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-error' );
 742+ var box = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-panel' );
 743+ // TODO: Make this smarter -- on ubuntu/ff at least, using the
 744+ // offset puts it about 100px down from where it should be;
 745+ // this math corrects for it, but will most likely be wrong on
 746+ // other browsers
 747+ veil.css('top', box.find('.articleFeedbackv5-ui').offset().top / 2 + 10);
 748+ veil.css('width', box.width());
 749+ veil.css('height', box.height());
 750+ veil.show();
 751+ },
 752+
 753+ // }}}
731754 // {{{ setSuccessState
732755
733756 /**
@@ -750,9 +773,10 @@
751774 */
752775 onSubmit: function () {
753776
 777+ $.articleFeedbackv5.currentBucket().loadAggregate = true;
754778
755779 /////////////////////////////////////////////////////////////////////////////////
756 -// BOOKMARK
 780+// TODO: Email capture
757781 /////////////////////////////////////////////////////////////////////////////////
758782
759783 // 'submit': function () {
Index: trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedback/ext.articleFeedback.dashboard.css
@@ -1,33 +1,33 @@
2 -.articleFeedback-table {
 2+.articleFeedbackv5-table {
33 border: solid 1px #cccccc;
44 margin-bottom: 2em;
55 }
66
7 -.articleFeedback-table caption {
 7+.articleFeedbackv5-table caption {
88 text-align: left;
99 font-size: 1.6em;
1010 margin-bottom: 0.5em;
1111 }
1212
13 -.articleFeedback-table th {
 13+.articleFeedbackv5-table th {
1414 padding-left: 0.75em;
1515 padding-top: 0.25em;
1616 padding-bottom: 0.25em;
1717 text-align: left;
1818 }
1919
20 -.articleFeedback-table td {
 20+.articleFeedbackv5-table td {
2121 padding: 0.25em 0.75em;
2222 border-top: solid 1px #eeeeee;
2323 }
2424
25 -.articleFeedback-table td.articleFeedback-table-column-page,
26 -.articleFeedback-table td.articleFeedback-table-column-category {
 25+.articleFeedbackv5-table td.articleFeedbackv5-table-column-page,
 26+.articleFeedbackv5-table td.articleFeedbackv5-table-column-category {
2727 text-align: left;
2828 }
2929
30 -.articleFeedback-table td.articleFeedback-table-column-rating,
31 -.articleFeedback-table td.articleFeedback-table-column-average {
 30+.articleFeedbackv5-table td.articleFeedbackv5-table-column-rating,
 31+.articleFeedbackv5-table td.articleFeedbackv5-table-column-average {
3232 text-align: right;
3333 }
3434
@@ -37,34 +37,34 @@
3838 * later if found useful.
3939 */
4040 /*
41 -.articleFeedback-table-column-score-0,
42 -.articleFeedback-table-column-score-1 {
 41+.articleFeedbackv5-table-column-score-0,
 42+.articleFeedbackv5-table-column-score-1 {
4343 background-color: #ffcccc;
4444 }
4545
4646
47 -.articleFeedback-table-column-score-2,
48 -.articleFeedback-table-column-bad {
 47+.articleFeedbackv5-table-column-score-2,
 48+.articleFeedbackv5-table-column-bad {
4949 background-color: #ffcc99;
5050 }
5151
52 -.articleFeedback-table-column-score-3 {
 52+.articleFeedbackv5-table-column-score-3 {
5353 background-color: #ffff99;
5454 }
5555
56 -.articleFeedback-table-column-score-4,
57 -.articleFeedback-table-column-good {
 56+.articleFeedbackv5-table-column-score-4,
 57+.articleFeedbackv5-table-column-good {
5858 background-color: #99ff99;
5959 }
60 -.articleFeedback-table-column-score-5 {
 60+.articleFeedbackv5-table-column-score-5 {
6161 background-color: #55ff55;
6262 }
6363 */
6464
65 -.articleFeedback-table-column-bad {
 65+.articleFeedbackv5-table-column-bad {
6666 background-color: #ffcc99;
6767 }
6868
69 -.articleFeedback-table-column-good {
 69+.articleFeedbackv5-table-column-good {
7070 background-color: #99ff99;
71 -}
\ No newline at end of file
 71+}
Index: trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedback/ext.articleFeedback.css
@@ -1,16 +1,16 @@
22 /*
33 * Styles for Article Feedback Extension
44 */
5 -#articleFeedback-dialog {
 5+#articleFeedbackv5-dialog {
66 padding: 2em;
77 padding-top: 1em;
88 }
99
10 -.articleFeedback-survey-disclaimer {
 10+.articleFeedbackv5-survey-disclaimer {
1111 font-weight: normal; /* Override bold */
1212 font-style: italic;
1313 }
1414
15 -.articleFeedback-survey-disclaimer a {
 15+.articleFeedbackv5-survey-disclaimer a {
1616 color: #0645AD; /* Override blackish color set by JUI */
1717 }
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php
@@ -1,10 +1,10 @@
22 <?php
33 /**
44 * Article Feedback extension
5 - *
 5+ *
66 * @file
77 * @ingroup Extensions
8 - *
 8+ *
99 * @author Trevor Parscal <trevor@wikimedia.org>
1010 * @license GPL v2 or later
1111 * @version 0.1.0
@@ -78,14 +78,14 @@
7979 *
8080 * Since the dashboard is powered by a SpecialPage, we cannot rel on the built-in
8181 * MW talk page for this, so we must expose our own page - internally or externally.
82 - *
83 - * This value will be passed into an i18n message which will parse the URL as an
 82+ *
 83+ * This value will be passed into an i18n message which will parse the URL as an
8484 * external link using wikitext, so this must be a full URL.
8585 * @var string
8686 */
8787 $wgArticleFeedbackv5DashboardTalkPage = "http://www.mediawiki.org/wiki/Talk:Article_feedback";
8888
89 -# TODO: What's up with the surveys, then?
 89+# TODO: What's up with the surveys, then?
9090 // Would ordinarily call this articlefeedback but survey names are 16 chars max
9191 $wgPrefSwitchSurveys['articlerating'] = array(
9292 'updatable' => false,
@@ -148,13 +148,14 @@
149149
150150 // Autoloading
151151 $dir = dirname( __FILE__ ) . '/';
152 -$wgAutoloadClasses['ApiQueryArticleFeedbackv5'] = $dir . 'api/ApiQueryArticleFeedbackv5.php';
153 -$wgAutoloadClasses['ApiArticleFeedbackv5Utils'] = $dir . 'api/ApiArticleFeedbackv5Utils.php';
154 -$wgAutoloadClasses['ApiArticleFeedbackv5'] = $dir . 'api/ApiArticleFeedbackv5.php';
155 -$wgAutoloadClasses['ArticleFeedbackv5Hooks'] = $dir . 'ArticleFeedbackv5.hooks.php';
156 -$wgAutoloadClasses['SpecialArticleFeedbackv5'] = $dir . 'SpecialArticleFeedbackv5.php';
157 -$wgExtensionMessagesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.i18n.php';
158 -$wgExtensionAliasesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.alias.php';
 152+$wgAutoloadClasses['ApiQueryArticleFeedbackv5'] = $dir . 'api/ApiQueryArticleFeedbackv5.php';
 153+$wgAutoloadClasses['ApiArticleFeedbackv5Utils'] = $dir . 'api/ApiArticleFeedbackv5Utils.php';
 154+$wgAutoloadClasses['ApiArticleFeedbackv5'] = $dir . 'api/ApiArticleFeedbackv5.php';
 155+$wgAutoloadClasses['ApiViewRatingsArticleFeedbackv5'] = $dir . 'api/ApiViewRatingsArticleFeedbackv5.php';
 156+$wgAutoloadClasses['ArticleFeedbackv5Hooks'] = $dir . 'ArticleFeedbackv5.hooks.php';
 157+$wgAutoloadClasses['SpecialArticleFeedbackv5'] = $dir . 'SpecialArticleFeedbackv5.php';
 158+$wgExtensionMessagesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.i18n.php';
 159+$wgExtensionAliasesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.alias.php';
159160
160161 // Hooks
161162 $wgHooks['LoadExtensionSchemaUpdates'][] = 'ArticleFeedbackv5Hooks::loadExtensionSchemaUpdates';
@@ -167,6 +168,7 @@
168169
169170 // API Registration
170171 $wgAPIListModules['articlefeedbackv5'] = 'ApiQueryArticleFeedbackv5';
 172+$wgAPIListModules['articlefeedbackv5-view-ratings'] = 'ApiViewRatingsArticleFeedbackv5';
171173 $wgAPIModules['articlefeedbackv5'] = 'ApiArticleFeedbackv5';
172174
173175 // Special Page
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php
@@ -0,0 +1,206 @@
 2+<?php
 3+/**
 4+ * ApiViewRatingsArticleFeedbackv5 class
 5+ *
 6+ * @package ArticleFeedback
 7+ * @subpackage Api
 8+ * @author Greg Chiasson <greg@omniti.com>
 9+ * @author Reha Sterbin <reha@omniti.com>
 10+ * @version $Id$
 11+ */
 12+
 13+/**
 14+ * This class pulls the aggregated ratings for display in Bucket #5
 15+ *
 16+ * @package ArticleFeedback
 17+ * @subpackage Api
 18+ */
 19+class ApiViewRatingsArticleFeedbackv5 extends ApiQueryBase {
 20+
 21+ /**
 22+ * Constructor
 23+ */
 24+ public function __construct( $query, $moduleName ) {
 25+ parent::__construct( $query, $moduleName, 'af' );
 26+ }
 27+
 28+ /**
 29+ * Execute the API call: Pull the aggregated ratings
 30+ */
 31+ public function execute() {
 32+ $params = $this->extractRequestParams();
 33+ global $wgArticleFeedbackv5RatingTypes;
 34+
 35+ $params = $this->extractRequestParams();
 36+ $result = $this->getResult();
 37+ $result_path = array( 'query', $this->getModuleName() );
 38+ $revisionId = ApiArticleFeedbackv5Utils::getRevisionId( $params['pageid'] );
 39+ $pageId = $params['pageid'];
 40+ $rollup = $this->fetchPageRollup( $pageId );
 41+
 42+ $result->addValue( $result_path, 'pageid', $params['pageid'] );
 43+ $result->addValue( $result_path, 'status', 'current' );
 44+
 45+ $info = array();
 46+ foreach ( $rollup as $row ) {
 47+ $info[$row->field_id] = array(
 48+ 'ratingdesc' => $row->field_name,
 49+ 'ratingid' => (int) $row->field_id,
 50+ 'total' => (int) $row->points,
 51+ 'count' => (int) $row->reviews,
 52+ );
 53+ }
 54+ $result->addValue( $result_path, 'rollup', $info );
 55+
 56+ $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'aa' );
 57+ }
 58+
 59+ /**
 60+ * Pulls the page rollup row
 61+ *
 62+ * @param $pageId int the page id
 63+ * @return array the rollup row
 64+ */
 65+ public function fetchPageRollup( $pageId ) {
 66+ return $this->fetchRollup( $pageId, 0, 'page' );
 67+ }
 68+
 69+ /**
 70+ * Pulls the revision rollup row
 71+ *
 72+ * @param $pageId int the page id
 73+ * @param $revisionLimit int [optional] go back only to this revision
 74+ * @return array the rollup row
 75+ */
 76+ public function fetchRevisionRollup( $pageId, $revisionLimit = 0 ) {
 77+ return $this->fetchRollup( $pageId, $revisionLimit, 'revision' );
 78+ }
 79+
 80+ /**
 81+ * Pulls a rollup row
 82+ *
 83+ * @param $pageId int the page id
 84+ * @param $revisionLimit int go back only to this revision
 85+ * @param $type string the type of row to fetch ('page' or 'revision')
 86+ * @return array the rollup row
 87+ */
 88+ private function fetchRollup( $pageId, $revisionLimit, $type ) {
 89+ $dbr = wfGetDB( DB_SLAVE );
 90+ $where = array();
 91+
 92+ if ( $type == 'page' ) {
 93+ $table = 'article_feedback_ratings_rollup';
 94+ $prefix = 'aap';
 95+ } else {
 96+ $table = 'article_revision_feedback_ratings_rollup';
 97+ $prefix = 'afr';
 98+ $where[] = 'afr_revision_id >= ' . $revisionLimit;
 99+ }
 100+ $where[$prefix . '_page_id'] = $pageId;
 101+ $where[] = $prefix . '_rating_id = aaf_id';
 102+
 103+ $rows = $dbr->select(
 104+ array( 'aft_' . $table, 'aft_article_field' ),
 105+ array(
 106+ 'aaf_name AS field_name',
 107+ $prefix . '_rating_id AS field_id',
 108+ 'SUM(' . $prefix . '_total) AS points',
 109+ 'SUM(' . $prefix . '_count) AS reviews',
 110+ ),
 111+ $where,
 112+ __METHOD__,
 113+ array(
 114+ 'GROUP BY' => $prefix . '_rating_id, aaf_name'
 115+ )
 116+ );
 117+
 118+ return $rows;
 119+ }
 120+
 121+ /**
 122+ * Gets the allowed parameters
 123+ *
 124+ * @return array the params info, indexed by allowed key
 125+ */
 126+ public function getAllowedParams() {
 127+ return array(
 128+ 'userrating' => 0,
 129+ 'anontoken' => null,
 130+ 'userid' => null,
 131+ 'subaction' => array(
 132+ ApiBase::PARAM_REQUIRED => false,
 133+ ApiBase::PARAM_ISMULTI => false,
 134+ ApiBase::PARAM_TYPE => array( 'showratings', 'newform' ),
 135+ ),
 136+ 'revid' => array(
 137+ ApiBase::PARAM_REQUIRED => false,
 138+ ApiBase::PARAM_ISMULTI => false,
 139+ ApiBase::PARAM_TYPE => 'integer',
 140+ ),
 141+ 'pageid' => array(
 142+ ApiBase::PARAM_REQUIRED => true,
 143+ ApiBase::PARAM_ISMULTI => false,
 144+ ApiBase::PARAM_TYPE => 'integer',
 145+ )
 146+ );
 147+ }
 148+
 149+ /**
 150+ * Gets the parameter descriptions
 151+ *
 152+ * @return array the descriptions, indexed by allowed key
 153+ */
 154+ public function getParamDescription() {
 155+ return array(
 156+ 'pageid' => 'Page ID to get feedback ratings for',
 157+ 'revid' => 'Rev ID to get feedback ratings for',
 158+ 'anontoken' => 'Token for anonymous users',
 159+ );
 160+ }
 161+
 162+ /**
 163+ * Gets the api descriptions
 164+ *
 165+ * @return array the description as the first element in an array
 166+ */
 167+ public function getDescription() {
 168+ return array(
 169+ 'List article feedback ratings for a specified page'
 170+ );
 171+ }
 172+
 173+ /**
 174+ * Gets any possible errors
 175+ *
 176+ * @return array the errors
 177+ */
 178+ public function getPossibleErrors() {
 179+ return array_merge( parent::getPossibleErrors(), array(
 180+ array( 'missingparam', 'anontoken' ),
 181+ array( 'code' => 'invalidtoken', 'info' => 'The anontoken is not 32 characters' ),
 182+ )
 183+ );
 184+ }
 185+
 186+ /**
 187+ * Gets an example
 188+ *
 189+ * @return array the example as the first element in an array
 190+ */
 191+ protected function getExamples() {
 192+ return array(
 193+ 'api.php?action=query&list=articlefeedbackv5-view-ratings&afpageid=1',
 194+ );
 195+ }
 196+
 197+ /**
 198+ * Gets the version info
 199+ *
 200+ * @return string the SVN version info
 201+ */
 202+ public function getVersion() {
 203+ return __CLASS__ . ': $Id$';
 204+ }
 205+
 206+}
 207+
Property changes on: trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php
___________________________________________________________________
Added: svn:eol-style
1208 + native
Added: svn:keywords
2209 + "Author Date Id HeadURL Revision"
Index: trunk/extensions/ArticleFeedbackv5/api/ApiQueryArticleFeedbackv5.php
@@ -1,198 +1,155 @@
22 <?php
3 -# This file loads the data and all. The other one saves it.
 3+/**
 4+ * ApiQueryArticleFeedbackv5 class
 5+ *
 6+ * @package ArticleFeedback
 7+ * @subpackage Api
 8+ * @author Greg Chiasson <greg@omniti.com>
 9+ * @author Reha Sterbin <reha@omniti.com>
 10+ * @version $Id$
 11+ */
 12+
 13+/**
 14+ * This class loads data. The other one saves it.
 15+ *
 16+ * @package ArticleFeedback
 17+ * @subpackage Api
 18+ */
419 class ApiQueryArticleFeedbackv5 extends ApiQueryBase {
 20+
 21+ /**
 22+ * Constructor
 23+ */
524 public function __construct( $query, $moduleName ) {
625 parent::__construct( $query, $moduleName, 'af' );
726 }
827
9 - # split these two off into their own modules, instead of doing this.
 28+ /**
 29+ * Execute the API call: initialize a brand new request
 30+ *
 31+ * JS passes in a page id and, sometimes, a revision id. Return back the
 32+ * correct bucket id.
 33+ *
 34+ * NB: This call used to return a feedback id and any associated answers as
 35+ * well as the bucket id (each user was allowed one rating/comment saved
 36+ * per page per revision); it no longer does, as per the 11/10 meeting --
 37+ * instead, we'll store everything the user submits.
 38+ */
1039 public function execute() {
 40+ $params = $this->extractRequestParams();
 41+ global $wgArticleFeedbackv5RatingTypes, $wgUser;
1142 $params = $this->extractRequestParams();
12 - global $wgArticleFeedbackv5RatingTypes;
13 -
14 - if($params['subaction'] == 'showratings') {
15 - $this->executeFetchRatings();
16 - } else {
17 - $this->executeNewForm();
18 - }
19 - }
20 -
21 - # Initialize a brand new request
22 - protected function executeNewForm() {
23 - global $wgUser;
24 - $params = $this->extractRequestParams();
2543 $bucket = $this->getBucket();
2644 $result = $this->getResult();
2745
28 - if(!$params['revid']) {
29 - $params['revid'] = ApiArticleFeedbackv5Utils::getRevisionId($params['pageid']);
 46+ if ( !$params['revid'] ) {
 47+ $params['revid'] = ApiArticleFeedbackv5Utils::getRevisionId( $params['pageid'] );
3048 }
31 -
32 - if(!$params['pageid'] || !$params['revid']) {
 49+ if ( !$params['pageid'] || !$params['revid'] ) {
3350 return null;
3451 }
3552
 53+ $this->logHit( $params['pageid'], $params['revid'], $bucket );
3654
37 - $this->logHit($params['pageid'], $params['revid'], $bucket);
 55+ $result->addValue( 'form', 'pageId', $params['pageid'] );
 56+ $result->addValue( 'form', 'bucketId', $bucket );
3857
39 - $result->addValue('form', 'pageId', $params['pageid']);
40 - $result->addValue('form', 'bucketId', $bucket);
41 - # Not doing this, per 11/10 meeting, for scalability reasons.
42 - #$feedbackId = $this->getFeedbackId($params, $bucket);
43 - #$result->addValue('form', 'feedbackId', $feedbackId);
 58+ // $feedbackId = $this->getFeedbackId($params, $bucket);
 59+ // $result->addValue('form', 'feedbackId', $feedbackId);
4460 }
4561
46 - protected function executeFetchRatings() {
47 - $params = $this->extractRequestParams();
48 - $result = $this->getResult();
49 - $revisionLimit = ApiArticleFeedbackv5Utils::getRevisionId( $params['pageid'] );
50 - $bucket = $this->getBucket();
51 - $pageId = $params['pageid'];
52 - $rows = $this->fetchRevisionRollup($pageId, $revisionLimit);
53 - $historical = $this->fetchPageRollup($pageId);
54 - $ratings = array(
55 - 'pageid' => $params['pageid'],
56 - 'ratings' => array(),
57 - 'status' => 'current'
58 - );
59 -
60 - foreach ( $rows as $row ) {
61 - $overall = 0;
62 - foreach($historical as $ancient) {
63 - if($ancient->aaf_name == $row->aaf_name) {
64 - $overall = $ancient->reviews;
65 - }
66 - }
67 - $ratings['ratings'][] = array(
68 - 'ratingdesc' => $row->field_name,
69 - 'ratingid' => (int) $row->field_id,
70 - 'total' => (int) $row->points,
71 - 'count' => (int) $row->reviews,
72 - 'countall' => (int) $overall
73 - );
74 - }
75 -
76 - foreach ( $ratings as $r ) {
77 - $result->addValue(
78 - array('query', $this->getModuleName()), null, $r
79 - );
80 - }
81 -
82 - $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'aa' );
83 - }
84 -
 62+ /**
 63+ * Determine into which bucket this request should fall
 64+ *
 65+ * @TODO Base this on last 2 digits of IP address per requirements; when we
 66+ * have markup, we can add other buckets
 67+ *
 68+ * @return int the bucket id
 69+ */
8570 protected function getBucket() {
86 - #TODO base this on last 2 digits of IP address per requirements
8771 return 5;
8872 }
8973
90 - private function logHit($page, $revision, $bucket) {
 74+ /**
 75+ * Log that this bucket was served for this page and revision
 76+ *
 77+ * @param $page int the page id
 78+ * @param $revision int the revision id
 79+ * @param $bucket int the bucket id
 80+ */
 81+ private function logHit( $page, $revision, $bucket ) {
9182 $dbr = wfGetDB( DB_SLAVE );
9283 $dbw = wfGetDB( DB_MASTER );
93 - $date = date('Y-m-d');
 84+ $date = date( 'Y-m-d' );
9485
95 - if(!$page && !$revision) {
96 - return;
 86+ if ( !$page && !$revision ) {
 87+ return;
9788 }
9889
99 - # Select hit counter row
 90+ // Select hit counter row
10091 $hits = $dbr->selectField(
101 - 'aft_article_hits',
102 - 'aah_hits',
103 - array(
104 - 'aah_page_id' => $page,
105 - 'aah_date' => $date,
106 - 'aah_bucket_id' => $bucket,
107 - )
108 - );
109 -
110 - # If there's a row, update it.
111 - if($hits) {
112 - $dbw->update(
11392 'aft_article_hits',
114 - array( 'aah_hits' => ($hits + 1) ),
 93+ 'aah_hits',
11594 array(
116 - 'aah_page_id' => $page,
117 - 'aah_date' => $date,
118 - 'aah_bucket_id' => $bucket,
 95+ 'aah_page_id' => $page,
 96+ 'aah_date' => $date,
 97+ 'aah_bucket_id' => $bucket,
11998 )
12099 );
121 - } else {
122 - # Otherwise, there's no row, insert one.
123 - $dbw->insert('aft_article_hits', array(
124 - 'aah_page_id' => $page,
125 - 'aah_date' => $date,
126 - 'aah_bucket_id' => $bucket,
127 - 'aah_hits' => 1
128 - ));
129 - }
130 - }
131100
132 - public function fetchPageRollup($pageId, $revisionLimit = 0) {
133 - return $this->fetchRollup($pageId, $revisionLimit, 'page');
134 - }
135 -
136 - public function fetchRevisionRollup($pageId, $revisionLimit = 0) {
137 - return $this->fetchRollup($pageId, $revisionLimit, 'revision');
138 - }
139 -
140 - private function fetchRollup($pageId, $revisionLimit, $type) {
141 - $dbr = wfGetDB( DB_SLAVE );
142 - $where = array();
143 -
144 - if($type == 'page') {
145 - $table = 'article_feedback_ratings_rollup';
146 - $prefix = 'aap';
 101+ // If there's a row, update it.
 102+ if ( $hits ) {
 103+ $dbw->update(
 104+ 'aft_article_hits',
 105+ array( 'aah_hits' => ( $hits + 1 ) ),
 106+ array(
 107+ 'aah_page_id' => $page,
 108+ 'aah_date' => $date,
 109+ 'aah_bucket_id' => $bucket,
 110+ )
 111+ );
147112 } else {
148 - $table = 'article_revision_feedback_ratings_rollup';
149 - $prefix = 'afr';
150 - $where[] = 'afr_revision_id >= '.$revisionLimit;
 113+ // Otherwise, there's no row, insert one.
 114+ $dbw->insert('aft_article_hits', array(
 115+ 'aah_page_id' => $page,
 116+ 'aah_date' => $date,
 117+ 'aah_bucket_id' => $bucket,
 118+ 'aah_hits' => 1
 119+ ));
151120 }
152 - $where[$prefix.'_page_id'] = $pageId;
153 - $where[] = $prefix.'_rating_id = aaf_id';
154 -
155 - $rows = $dbr->select(
156 - array( 'aft_'.$table, 'aft_article_field' ),
157 - array(
158 - 'aaf_name AS field_name',
159 - $prefix.'_rating_id AS field_id',
160 - 'SUM('.$prefix.'_total) AS points',
161 - 'SUM('.$prefix.'_count) AS reviews',
162 - ),
163 - $where,
164 - __METHOD__,
165 - array(
166 - 'GROUP BY' => $prefix.'_rating_id, aaf_name'
167 - )
168 - );
169 -
170 - return $rows;
171121 }
172122
173 - # Mostly deprecated
174 - # Gets the user's feedback for this page. Only works on userids,
175 - # NOT IP adderesses. Idea being that IPs can move, and we don't want
176 - # your comments being shown to a different person who took your IP.
177 - # ALSO take revision limit into account.
178 - protected function getUserRatings($feedbackId) {
 123+ /**
 124+ * Gets the user's feedback for this page.
 125+ *
 126+ * Only works on userids, NOT IP adderesses. Idea being that IPs can move,
 127+ * and we don't want your comments being shown to a different person who
 128+ * took your IP. ALSO take revision limit into account.
 129+ *
 130+ * NB: Mostly deprecated; do not use in new code.
 131+ *
 132+ * @param $feedbackId the feedback id
 133+ * @return array the previous answers
 134+ */
 135+ protected function getUserRatings( $feedbackId ) {
179136 global $wgUser;
180137 $dbr = wfGetDB( DB_SLAVE );
181138 $feedback = array();
182139 $rows = $dbr->select(
183140 array('aft_article_answer', 'aft_article_field',
184 - 'aft_article_feedback'),
 141+ 'aft_article_feedback'),
185142 array('aaaa_response_rating', 'aaaa_response_text',
186 - 'aaaa_response_bool', 'aaaa_response_option_id',
187 - 'aaf_name', 'aaf_data_type'),
 143+ 'aaaa_response_bool', 'aaaa_response_option_id',
 144+ 'aaf_name', 'aaf_data_type'),
188145 array(
189 - 'aa_revision >= '.$this->getRevisionLimit(),
 146+ 'aa_revision >= ' . $this->getRevisionLimit(),
190147 'aaaa_feedback_id' => $feedbackId,
191148 'aa_user_id' => $wgUser->getId(),
192149 'aa_is_submitted' => 1,
193150 )
194151 );
195152
196 - foreach($rows as $row) {
 153+ foreach ( $rows as $row ) {
197154 $method = 'response_'.$row->aaf_data_type;
198155 $feeedback[] = array(
199156 'name' => $row->aaf_name,
@@ -203,10 +160,11 @@
204161 }
205162
206163 /**
207 - * Get the revision number of the oldest revision still being counted in totals.
 164+ * Get the revision number of the oldest revision still being counted in
 165+ * totals
208166 *
209 - * @param $pageId Integer: ID of page to check revisions for
210 - * @return Integer: Oldest valid revision number or 0 of all revisions are valid
 167+ * @param $pageId int ID of page to check revisions for
 168+ * @return int oldest valid revision number or 0 of all revisions are valid
211169 */
212170 protected function getRevisionLimit( $pageId ) {
213171 global $wgArticleFeedbackv5RatingLifetime;
@@ -228,6 +186,12 @@
229187 return 0;
230188 }
231189
 190+ /**
 191+ * Gets the cache mode
 192+ *
 193+ * @param $params array the params passed in
 194+ * @return string the cache mode ('anon-public-user-private' or 'public')
 195+ */
232196 public function getCacheMode( $params ) {
233197 if ( $params['userrating'] ) {
234198 return 'anon-public-user-private';
@@ -236,6 +200,12 @@
237201 }
238202 }
239203
 204+ /**
 205+ * TODO
 206+ * Gets the allowed parameters
 207+ *
 208+ * @return array the params info, indexed by allowed key
 209+ */
240210 public function getAllowedParams() {
241211 return array(
242212 'userrating' => 0,
@@ -243,7 +213,7 @@
244214 'subaction' => array(
245215 ApiBase::PARAM_REQUIRED => false,
246216 ApiBase::PARAM_ISMULTI => false,
247 - ApiBase::PARAM_TYPE => array('showratings','newform'),
 217+ ApiBase::PARAM_TYPE => array( 'showratings', 'newform' ),
248218 ),
249219 'revid' => array(
250220 ApiBase::PARAM_REQUIRED => false,
@@ -258,7 +228,12 @@
259229 );
260230 }
261231
262 - # TODO
 232+ /**
 233+ * TODO
 234+ * Gets the parameter descriptions
 235+ *
 236+ * @return array the descriptions, indexed by allowed key
 237+ */
263238 public function getParamDescription() {
264239 return array(
265240 'pageid' => 'Page ID to get feedback ratings for',
@@ -267,14 +242,24 @@
268243 );
269244 }
270245
271 - # TODO
 246+ /**
 247+ * TODO
 248+ * Gets the api descriptions
 249+ *
 250+ * @return array the description as the first element in an array
 251+ */
272252 public function getDescription() {
273253 return array(
274254 'List article feedback ratings for a specified page'
275255 );
276256 }
277257
278 - # TODO
 258+ /**
 259+ * TODO
 260+ * Gets any possible errors
 261+ *
 262+ * @return array the errors
 263+ */
279264 public function getPossibleErrors() {
280265 return array_merge( parent::getPossibleErrors(), array(
281266 array( 'missingparam', 'anontoken' ),
@@ -283,15 +268,27 @@
284269 );
285270 }
286271
287 - # TODO
 272+ /**
 273+ * TODO
 274+ * Gets an example
 275+ *
 276+ * @return array the example as the first element in an array
 277+ */
288278 protected function getExamples() {
289279 return array(
290280 'api.php?action=query&list=articlefeedbackv5&afpageid=1',
291281 );
292282 }
293283
294 - # TODO
 284+ /**
 285+ * TODO
 286+ * Gets the version info
 287+ *
 288+ * @return string the SVN version info
 289+ */
295290 public function getVersion() {
296291 return __CLASS__ . ': $Id$';
297292 }
 293+
298294 }
 295+

Status & tagging log