r103439 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103438‎ | r103439 | r103440 >
Date:03:19, 17 November 2011
Author:rsterbin
Status:deferred
Tags:
Comment:
Updated ratings info collection and display:
- sql/ArticleFeedbackv5.sql:
- Insert statements for aft_article_field now include the bucket id
- Added inserts for the expertise detail fields of bucket 5 and for
bucket 1
- ArticleFeedbackv5.php:
- Updated to add $wgArticleFeedbackv5Bucket5RatingCategories --
basically just the names from aft_article_field with bucket id 5 and
data type rating, but pulling from the database wouldn't give us order
- ArticleFeedbackv5.hooks.php:
- Updated resourceLoaderRegisterModules() and
resourceLoaderGetConfigVars() to use
$wgArticleFeedbackv5Bucket5RatingCategories rather than
$wgArticleFeedbackv5RatingTypes and
$wgArticleFeedbackv5RatingTypesFlipped
- jquery.articleFeedbackv5.js:
- Replaced wgArticleFeedbackv5RatingTypesFlipped with
wgArticleFeedbackv5Bucket5RatingCategories
- Updated all uses to take into account the fact that it's a regular
index array rather than an associative one
- Bucket 5 no longer uses the so-called rating id (really just an
index); instead it uses the name throughout
- ext.articleFeedbackv5.js:
Removed old use of wgArticleFeedbackv5RatingTypesFlipped
- ApiViewRatingsArticleFeedbackv5:
- Updated execute() to send the aggregate data indexed by field name
rather than id
- Now only pulls aggregate data for bucket 5 (later versions may want
to pass in the bucket id instead of having it hardcoded)

Submit now works properly:
- jquery.articleFeedbackv5.js:
- Fixed collection of form data -- the fact that $('input:checked') is
not equivalent to $('input[checked]'), so radio buttons selected via
jquery and checkboxes selected manually must use different selectors
- Added a value to the "yes" radio button
- If you submit bucket 1 with the default text in the comment box, it
now sends an empty string rather than the default text
- ApiArticleFeedbackv5:
- Now makes use of ApiArticleFeedbackv5Utils::getFields() to collect
the appropriate answer fields
- Corrected for coding style and added doc blocks
- ApiArticleFeedbackv5Utils:
- Updated getFields() to pull the bucket id as well
- Updated isFeedbackEnabled() to return booleans rather than ints
- Corrected for coding style and added doc blocks

Bug fix: Corrected the message tag for empty ratings
Bug fix: View ratings no longer shows an incorrect average
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5Utils.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedbackv5/ext.articleFeedbackv5.js (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql (modified) (history)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql
@@ -97,12 +97,12 @@
9898 ) /*$wgDBTableOptions*/;
9999
100100 CREATE TABLE IF NOT EXISTS /*_*/aft_article_revision_feedback_select_rollup (
101 - arfsr_page_id integer unsigned NOT NULL,
102 - arfsr_revision_id integer unsigned NOT NULL,
103 - arfsr_option_id integer unsigned NOT NULL,
104 - arfsr_total integer unsigned NOT NULL,
105 - arfsr_count integer unsigned NOT NULL,
106 - PRIMARY KEY (arfsr_revision_id, arfsr_option_id)
 101+ arfsr_page_id integer unsigned NOT NULL,
 102+ arfsr_revision_id integer unsigned NOT NULL,
 103+ arfsr_option_id integer unsigned NOT NULL,
 104+ arfsr_total integer unsigned NOT NULL,
 105+ arfsr_count integer unsigned NOT NULL,
 106+ PRIMARY KEY (arfsr_revision_id, arfsr_option_id)
107107 ) /*$wgDBTableOptions*/;
108108
109109 -- Mostyl taken from avtV4
@@ -118,9 +118,15 @@
119119
120120 -- TODO: Add indices
121121
122 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('trustworthy', 'rating');
123 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('objective', 'rating');
124 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('complete', 'rating');
125 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('wellwritten', 'rating');
126 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('expertise', 'boolean');
127 -INSERT INTO aft_article_field(afi_name, afi_data_type) VALUES ('comment', 'text');
 122+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('found', 'boolean', 1);
 123+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('comment', 'text', 1);
 124+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('trustworthy', 'rating', 5);
 125+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('objective', 'rating', 5);
 126+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('complete', 'rating', 5);
 127+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('wellwritten', 'rating', 5);
 128+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('expertise-general', 'boolean', 5);
 129+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('expertise-studies', 'boolean', 5);
 130+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('expertise-profession', 'boolean', 5);
 131+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('expertise-hobby', 'boolean', 5);
 132+INSERT INTO aft_article_field(afi_name, afi_data_type, afi_bucket_id) VALUES ('expertise-other', 'boolean', 5);
 133+
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js
@@ -151,7 +151,7 @@
152152 <div class="form-item" rel="yes" id="articleFeedbackv5-bucket1-toggle-wrapper-yes">\
153153 <label for="articleFeedbackv5-bucket1-toggle-yes"><html:msg key="bucket1-toggle-found-yes-full" /></label>\
154154 <span class="articleFeedbackv5-button-placeholder"><html:msg key="bucket1-toggle-found-yes" value="yes" /></span>\
155 - <input type="radio" name="toggle" id="articleFeedbackv5-bucket1-toggle-yes" class="query-button" />\
 155+ <input type="radio" name="toggle" id="articleFeedbackv5-bucket1-toggle-yes" class="query-button" value="yes" />\
156156 </div>\
157157 <div class="form-item" rel="no" id="articleFeedbackv5-bucket1-toggle-wrapper-no">\
158158 <label for="articleFeedbackv5-bucket1-toggle-no"><html:msg key="bucket1-toggle-found-no-full" /></label>\
@@ -238,7 +238,7 @@
239239 $other_wrap.find( 'span' ).removeClass( 'articleFeedbackv5-button-placeholder-active' );
240240 // check/uncheck radio buttons
241241 $wrap.find( 'input' ).attr( 'checked', 'checked' );
242 - $other_wrap.find( 'input' ).attr( 'checked', '' );
 242+ $other_wrap.find( 'input' ).removeAttr( 'checked' );
243243 // set default comment message
244244 var $txt = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-comment textarea' );
245245 var def_msg_yes = mw.msg( 'articlefeedbackv5-bucket1-question-comment-yes' );
@@ -254,7 +254,7 @@
255255 $block.find( '.articleFeedbackv5-comment textarea' )
256256 .focus( function () {
257257 var def_msg = '';
258 - var val = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input:checked' ).val();
 258+ var val = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input[checked]' ).val();
259259 if ( val == 'yes' ) {
260260 def_msg = mw.msg( 'articlefeedbackv5-bucket1-question-comment-yes' );
261261 } else if ( val == 'no' ) {
@@ -266,7 +266,7 @@
267267 } )
268268 .blur( function () {
269269 var def_msg = '';
270 - var val = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input:checked' ).val();
 270+ var val = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input[checked]' ).val();
271271 if ( val == 'yes' ) {
272272 def_msg = mw.msg( 'articlefeedbackv5-bucket1-question-comment-yes' );
273273 } else if ( val == 'no' ) {
@@ -318,8 +318,14 @@
319319 */
320320 getFormData: function () {
321321 var data = {};
322 - data.toggle = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input:checked' ).val() == 'yes' ? true : false;
 322+ var $check = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input[checked]' );
 323+ data.found = $check.val() == 'yes' ? 1 : 0;
323324 data.comment = $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-comment textarea' ).val();
 325+ var def_msg_yes = mw.msg( 'articlefeedbackv5-bucket1-question-comment-yes' );
 326+ var def_msg_no = mw.msg( 'articlefeedbackv5-bucket1-question-comment-no' );
 327+ if ( data.comment == def_msg_yes || data.comment == def_msg_no ) {
 328+ data.comment = '';
 329+ }
324330 return data;
325331 },
326332
@@ -335,7 +341,7 @@
336342 localValidation: function ( formdata ) {
337343 var error = {};
338344 var ok = true;
339 - if ( $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input:checked' ).length < 1 ) {
 345+ if ( $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-bucket1-toggle input[checked]' ).length < 1 ) {
340346 error.toggle = 'Please select an option';
341347 ok = false;
342348 }
@@ -393,7 +399,7 @@
394400 * The ratings right now are coming from the config, but they really
395401 * can't be configured. Eventually, these should just be hardcoded.
396402 */
397 - ratingInfo: mw.config.get( 'wgArticleFeedbackv5RatingTypesFlipped' ),
 403+ ratingInfo: mw.config.get( 'wgArticleFeedbackv5Bucket5RatingCategories' ),
398404
399405 /**
400406 * Only certain users can see the expertise checkboxes and email
@@ -465,7 +471,7 @@
466472 var rating_tpl = '\
467473 <div class="articleFeedbackv5-rating">\
468474 <div class="articleFeedbackv5-label"></div>\
469 - <input type="hidden" />\
 475+ <input type="hidden" name="" />\
470476 <div class="articleFeedbackv5-rating-labels articleFeedbackv5-visibleWith-form">\
471477 <div class="articleFeedbackv5-rating-label" rel="1"></div>\
472478 <div class="articleFeedbackv5-rating-label" rel="2"></div>\
@@ -489,7 +495,9 @@
490496
491497 // Add the ratings from the options
492498 $block.find( '.articleFeedbackv5-ratings' ).each( function () {
493 - for ( var key in $.articleFeedbackv5.currentBucket().ratingInfo ) {
 499+ var info = $.articleFeedbackv5.currentBucket().ratingInfo;
 500+ for ( var i in info ) {
 501+ var key = info[i];
494502 var tip_msg = 'articlefeedbackv5-bucket5-' + key + '-tip';
495503 var label_msg = 'articlefeedbackv5-bucket5-' + key + '-label';
496504 var $rtg = $( rating_tpl ).attr( 'rel', key );
@@ -561,8 +569,7 @@
562570 // Name the hidden rating fields
563571 $block.find( '.articleFeedbackv5-rating' )
564572 .each( function () {
565 - var name = $.articleFeedbackv5.currentBucket().ratingInfo[$(this).attr( 'rel' )];
566 - $(this).find( 'input:hidden' ) .attr( 'name', 'r' + name );
 573+ $(this).find( 'input:hidden' ) .attr( 'name', $(this).attr( 'rel' ) );
567574 } );
568575
569576 // Hide the additional options, if the user's in a bucket that
@@ -841,8 +848,7 @@
842849 // Ratings
843850 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-rating' ).each( function () {
844851 var name = $(this).attr( 'rel' );
845 - var info = $.articleFeedbackv5.currentBucket().ratingInfo;
846 - var rating = name in info && info[name] in rollup ? rollup[info[name]] : null;
 852+ var rating = name in rollup ? rollup[name] : null;
847853 if (
848854 rating !== null
849855 && 'total' in rating
@@ -863,7 +869,7 @@
864870 $(this).find( '.articleFeedbackv5-rating-meter div' )
865871 .css( 'width', 0 );
866872 $(this).find( '.articleFeedbackv5-rating-count' )
867 - .text( mw.msg( 'articlefeedbackv5-report-empty' ) );
 873+ .text( mw.msg( 'articlefeedbackv5-bucket5-report-empty' ) );
868874 }
869875 } );
870876
@@ -902,15 +908,14 @@
903909 getFormData: function () {
904910 var data = {};
905911 var info = $.articleFeedbackv5.currentBucket().ratingInfo;
906 - for ( var key in info ) {
907 - var id = info[key];
908 - data['r' + id] = $.articleFeedbackv5.$holder.find( 'input[name="r' + id + '"]' ).val();
 912+ for ( var i in info ) {
 913+ var key = info[i];
 914+ data[key] = $.articleFeedbackv5.$holder.find( 'input[name="' + key + '"]' ).val();
909915 }
910 - var expertise = [];
911916 $.articleFeedbackv5.$holder.find( '.articleFeedbackv5-expertise input:checked' ).each( function () {
912 - expertise.push( $(this).val() );
 917+ console.log($(this).is(':checked'));
 918+ data['expertise-' + $( this ).val()] = 1;
913919 } );
914 - data.expertise = expertise.join( '|' );
915920 return data;
916921 },
917922
@@ -1486,9 +1491,3 @@
14871492
14881493 } )( jQuery );
14891494
1490 -
1491 -
1492 -
1493 -
1494 -
1495 -
Index: trunk/extensions/ArticleFeedbackv5/modules/ext.articleFeedbackv5/ext.articleFeedbackv5.js
@@ -213,7 +213,6 @@
214214 } )();
215215
216216 var config = {
217 - 'ratings': mw.config.get( 'wgArticleFeedbackv5RatingTypesFlipped' ),
218217 'pitches': {
219218 'survey': {
220219 'weight': 1,
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php
@@ -47,6 +47,9 @@
4848 // default message.
4949 $wgArticleFeedbackv5Debug = true;
5050
 51+// The rating categories for bucket 5 -- these MUST match the field names in the database.
 52+$wgArticleFeedbackv5Bucket5RatingCategories = array( 'trustworthy', 'objective', 'complete', 'wellwritten' );
 53+
5154 // Bucket settings for display options
5255 $wgArticleFeedbackv5DisplayBuckets = array(
5356 // Users can fall into one of several display buckets (these are defined in
@@ -73,7 +76,6 @@
7477 'tracked' => true
7578 );
7679
77 -
7880 // Bucket settings for tracking users
7981 $wgArticleFeedbackv5Tracking = array(
8082 // Not all users need to be tracked, but we do want to track some users over time - these
@@ -209,3 +211,4 @@
210212 // Special Page
211213 $wgSpecialPages['ArticleFeedbackv5'] = 'SpecialArticleFeedbackv5';
212214 $wgSpecialPageGroups['ArticleFeedbackv5'] = 'other';
 215+
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php
@@ -1,17 +1,36 @@
22 <?php
3 -# This file saves the data and all. The other one loads it.
 3+/**
 4+ * ApiArticleFeedbackv5 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 saves the ratings
 15+ *
 16+ * @package ArticleFeedback
 17+ * @subpackage Api
 18+ */
419 class ApiArticleFeedbackv5 extends ApiBase {
 20+
 21+ /**
 22+ * Constructor
 23+ */
524 public function __construct( $query, $moduleName ) {
625 parent::__construct( $query, $moduleName, '' );
726 }
827
 28+ /**
 29+ * Execute the API call: Save the form values
 30+ */
931 public function execute() {
1032 global $wgUser, $wgArticleFeedbackv5SMaxage;
1133 $params = $this->extractRequestParams();
1234
13 -error_log('saving form');
14 -error_log(print_r($params,1));
15 -
1635 // Anon token check
1736 $token = ApiArticleFeedbackv5Utils::getAnonToken( $params );
1837
@@ -20,40 +39,44 @@
2140 # $this->dieUsage( 'ArticleFeedback is not enabled on this page', 'invalidpage' );
2241 # }
2342
24 - $feedbackId = $this->getFeedbackId($params);
 43+ $feedbackId = $this->getFeedbackId( $params );
2544 $dbr = wfGetDB( DB_SLAVE );
26 - $keys = array();
27 - foreach($params as $key => $unused) { $keys[] = $key; }
28 - $user_answers = array();
2945 $pageId = $params['pageid'];
3046 $bucket = $params['bucket'];
3147 $revisionId = $params['revid'];
32 - $answers = $dbr->select(
33 - 'aft_article_field',
34 - array('afi_id', 'afi_name', 'afi_data_type'),
35 - array('afi_name' => $keys),
36 - __METHOD__
37 - );
3848
39 - foreach($answers as $answer) {
40 - $type = $answer->afi_data_type;
41 - $value = $params[$answer->afi_name];
42 - if($value && $this->validateParam($value, $type)) {
43 - $user_answers[] = array(
44 - 'aa_feedback_id' => $feedbackId,
45 - 'aa_field_id' => $answer->afi_id,
46 - "aa_response_$type" => $value
47 - );
 49+ $user_answers = array();
 50+ $fields = ApiArticleFeedbackv5Utils::getFields();
 51+ foreach ( $fields as $field ) {
 52+ if ( $field->afi_bucket_id != $bucket ) {
 53+ continue;
4854 }
 55+ if ( isset( $params[$field->afi_name] ) ) {
 56+ $value = $params[$field->afi_name];
 57+ $type = $field->afi_data_type;
 58+ if ( $value === '' ) {
 59+ continue;
 60+ }
 61+ if ( $this->validateParam( $value, $type ) ) {
 62+ $data = array(
 63+ 'aa_feedback_id' => $feedbackId,
 64+ 'aa_field_id' => $field->afi_id,
 65+ );
 66+ foreach ( array( 'rating', 'text', 'boolean', 'option_id' ) as $t ) {
 67+ $data["aa_response_$t"] = $t == $type ? $value : null;
 68+ }
 69+ $user_answers[] = $data;
 70+ } else {
 71+ // TODO: ERROR
 72+ }
 73+ }
4974 }
50 -error_log('user answers are');
51 -error_log(print_r($user_answers,1));
5275
53 - $ctaId = $this->saveUserRatings($user_answers, $feedbackId, $bucket);
54 - $this->updateRollupTables($pageId, $revisionId);
 76+ $ctaId = $this->saveUserRatings( $user_answers, $feedbackId, $bucket );
 77+ $this->updateRollupTables( $pageId, $revisionId );
5578
56 - $squidUpdate = new SquidUpdate(array(
57 - wfAppendQuery(wfScript('api'), array(
 79+ $squidUpdate = new SquidUpdate( array(
 80+ wfAppendQuery( wfScript( 'api' ), array(
5881 'action' => 'query',
5982 'format' => 'json',
6083 'list' => 'articlefeedback',
@@ -62,83 +85,100 @@
6386 'afuserrating' => 0,
6487 'maxage' => 0,
6588 'smaxage' => $wgArticleFeedbackv5SMaxage
66 - ))
67 - ));
 89+ ) )
 90+ ) );
6891 $squidUpdate->doUpdate();
6992
70 - wfRunHooks('ArticleFeedbackChangeRating', array($params));
 93+ wfRunHooks( 'ArticleFeedbackChangeRating', array( $params ) );
7194
72 - $this->getResult()->addValue(null, $this->getModuleName(),
73 - array('result' => 'Success')
 95+ $this->getResult()->addValue(
 96+ null,
 97+ $this->getModuleName(),
 98+ array( 'result' => 'Success' )
7499 );
75100 }
76101
77 - protected function validateParam($value, $type) {
 102+ /**
 103+ * Validates a value against a field type
 104+ *
 105+ * @param $value mixed the value
 106+ * @param $type string the field type
 107+ * @return bool whether this is okay
 108+ */
 109+ protected function validateParam( $value, $type ) {
78110 # rating: int between 1 and 5 (inclusive)
79111 # boolean: 1 or 0
80112 # option: option exists
81113 # text: none (maybe xss encode)
82 - switch($type) {
 114+ switch ( $type ) {
83115 case 'rating':
84 - if(preg_match('/^(1|2|3|4|5)$/', $value)) {
85 - return 1;
 116+ if ( preg_match( '/^(1|2|3|4|5)$/', $value ) ) {
 117+ return true;
86118 }
87119 break;
88120 case 'boolean':
89 - if(preg_match('/^(1|0)$/', $value)) {
90 - return 1;
 121+ if ( preg_match( '/^(1|0)$/', $value ) ) {
 122+ return true;
91123 }
92124 break;
93125 case 'option':
94126 # TODO: check for option existance.
 127+ break;
95128 case 'text':
96 - return 1;
97 - break;
 129+ return true;
98130 default:
99 - return 0;
100 - break;
 131+ return false;
101132 }
102 -
103 - return 0;
 133+ return false;
104134 }
105135
106 - public function updateRollupTables($page, $revision) {
 136+ /**
 137+ * Update the rollup tables
 138+ *
 139+ * @param $page int the page id
 140+ * @param $revision int the revision id
 141+ */
 142+ public function updateRollupTables( $page, $revision ) {
 143+# Select rollup doesn't work yet
107144 # foreach( array( 'rating', 'boolean', 'select' ) as $type ) {
108 -# foreach( array( 'rating', 'boolean' ) as $type ) {
109 - foreach( array( 'rating' ) as $type ) {
 145+ foreach( array( 'rating', 'boolean' ) as $type ) {
110146 $this->updateRollup( $page, $revision, $type );
111147 }
112148 }
113149
114 - # TODO: This breaks on the select/option_id type.
 150+ /**
 151+ * Update the rollup tables
 152+ *
 153+ * @param $page int the page id
 154+ * @param $revision int the revision id
 155+ * @param $type string the type (rating, select, or boolean)
 156+ */
115157 private function updateRollup($pageId, $revId, $type) {
116158 global $wgArticleFeedbackv5RatingLifetime;
117159 $dbr = wfGetDB( DB_SLAVE );
118160 $dbw = wfGetDB( DB_MASTER );
119 - $limit = ApiArticleFeedbackv5Utils::getRevisionLimit($pageId);
 161+ $limit = ApiArticleFeedbackv5Utils::getRevisionLimit( $pageId );
120162
121163 # sanity check
122 - if( $type != 'rating' && $type != 'select'
123 - && $type != 'boolean' ) { return 0; }
 164+ if ( $type != 'rating' && $type != 'select' && $type != 'boolean' ) {
 165+ return 0;
 166+ }
124167
125168 $rows = $dbr->select(
126 - array( 'aft_article_answer', 'aft_article_feedback',
127 - 'aft_article_field' ),
128 - array( 'aa_field_id',
129 - "SUM(aa_response_$type) AS earned",
130 - 'COUNT(*) AS submits'),
 169+ array( 'aft_article_answer', 'aft_article_feedback', 'aft_article_field' ),
 170+ array( 'aa_field_id', "SUM(aa_response_$type) AS earned", 'COUNT(*) AS submits' ),
131171 array(
132172 'afi_data_type' => $type,
133173 'af_page_id' => $pageId,
134174 'aa_feedback_id = af_id',
135175 'afi_id = aa_field_id',
136 - "af_revision_id >= $limit"
 176+ "af_revision_id >= $limit",
137177 ),
138178 __METHOD__,
139179 array( 'GROUP BY' => 'aa_field_id' )
140180 );
141181
142 - if( $type == 'select' ) {
 182+ if ( $type == 'select' ) {
143183 $page_prefix = 'afsr_';
144184 $rev_prefix = 'arfsr_';
145185 } else {
@@ -148,76 +188,74 @@
149189 $page_data = array();
150190 $rev_data = array();
151191 $rev_table = 'aft_article_revision_feedback_'
152 - .( $type == 'select' ? 'select' : 'ratings' ).'_rollup';
 192+ . ( $type == 'select' ? 'select' : 'ratings' )
 193+ . '_rollup';
153194 $page_table = 'aft_article_feedback_'
154 - .( $type == 'select' ? 'select' : 'ratings' ).'_rollup';
 195+ . ( $type == 'select' ? 'select' : 'ratings' )
 196+ . '_rollup';
155197
156 - foreach($rows as $row) {
157 - if($type == 'rating') {
158 - $points = $row->submits * 5;
159 - } else {
160 - $points = $row->submits;
161 - }
162 -
163 - if(!array_key_exists($row->aa_field_id, $page_data)) {
 198+ foreach ( $rows as $row ) {
 199+ if ( !array_key_exists( $row->aa_field_id, $page_data ) ) {
164200 $page_data[$row->aa_field_id] = array(
165 - $page_prefix.'page_id' => $pageId,
166 - $page_prefix.'total' => 0,
167 - $page_prefix.'count' => 0,
168 - $page_prefix.($type == 'select' ? 'option' : 'rating').'_id' => $row->aa_field_id
 201+ $page_prefix . 'page_id' => $pageId,
 202+ $page_prefix . 'total' => 0,
 203+ $page_prefix . 'count' => 0,
 204+ $page_prefix . ($type == 'select' ? 'option' : 'rating') . '_id' => $row->aa_field_id
169205 );
170206 }
171207
172208 $rev_data[] = array(
173 - $rev_prefix.'page_id' => $pageId,
174 - $rev_prefix.'revision_id' => $revId,
175 - $rev_prefix.'total' => $row->earned,
176 - $rev_prefix.'count' => $points,
177 - $rev_prefix.($type == 'select' ? 'option' : 'rating').'_id' => $row->aa_field_id
 209+ $rev_prefix . 'page_id' => $pageId,
 210+ $rev_prefix . 'revision_id' => $revId,
 211+ $rev_prefix . 'total' => $row->earned,
 212+ $rev_prefix . 'count' => $points,
 213+ $rev_prefix . ($type == 'select' ? 'option' : 'rating') . '_id' => $row->aa_field_id
178214 );
179215 $page_data[$row->aa_field_id][$page_prefix.'total'] += $row->earned;
180 - $page_data[$row->aa_field_id][$page_prefix.'count'] += $points;
 216+ $page_data[$row->aa_field_id][$page_prefix.'count'] += $row->submits;
181217 }
182218
183 - # Hack becuse you can't use array keys or insert barfs.
184 - $tmp = array();
185 - foreach($page_data as $p) {
186 - $tmp[] = $p;
187 - }
188 - $page_data = $tmp;
189 -
190219 $dbw->begin();
191220 $dbw->delete( $rev_table, array(
192 - $rev_prefix.'page_id' => $pageId,
193 - $rev_prefix.'revision_id' => $revId,
 221+ $rev_prefix . 'page_id' => $pageId,
 222+ $rev_prefix . 'revision_id' => $revId,
 223+ $rev_prefix . 'rating_id' => array_keys( $page_data ),
194224 ) );
195 - $dbw->insert( $rev_table, $rev_data );
 225+ $dbw->insert( $rev_table, $rev_data );
196226 $dbw->delete( $page_table, array(
197 - $page_prefix.'page_id' => $pageId,
 227+ $page_prefix . 'page_id' => $pageId,
 228+ $page_prefix . 'rating_id' => array_keys( $page_data ),
198229 ) );
199 - $dbw->insert( $page_table, $page_data );
 230+ $dbw->insert( $page_table, array_values ( $page_data ) );
200231
201232 $dbw->commit();
202233 }
203234
 235+ /**
 236+ * Gets the feedback id
 237+ *
 238+ * @param $params array the parameters
 239+ * @return int the feedback id
 240+ */
204241 public function getFeedbackId($params) {
205242 global $wgUser;
206243 $dbw = wfGetDB( DB_MASTER );
207244 $revId = $params['revid'];
208245 $bucket = $params['revid'];
209 - $token = ApiArticleFeedbackv5Utils::getAnonToken($params);
 246+ $token = ApiArticleFeedbackv5Utils::getAnonToken( $params );
210247 $timestamp = $dbw->timestamp();
211248
212249 # make sure we have a page/user
213 - if(!$params['pageid'] || !$wgUser) { return null; }
 250+ if ( !$params['pageid'] || !$wgUser) {
 251+ return null;
 252+ }
214253
215254 # Fetch this if it wasn't passed in
216 - if(!$revId) {
 255+ if ( !$revId ) {
217256 $revId = ApiArticleFeedbackv5Utils::getRevisionId($params['pageid']);
218 -error_log('rev id?');
219257 }
220258
221 - $dbw->insert('aft_article_feedback', array(
 259+ $dbw->insert( 'aft_article_feedback', array(
222260 'af_page_id' => $params['pageid'],
223261 'af_revision_id' => $revId,
224262 'af_created' => $timestamp,
@@ -225,17 +263,22 @@
226264 'af_user_text' => $wgUser->getName(),
227265 'af_user_anon_token' => $token,
228266 'af_bucket_id' => $bucket,
229 - ));
 267+ ) );
230268
231269 return $dbw->insertID();
232270 }
233271
234272 /**
235273 * Inserts the user's rating for a specific revision
 274+ *
 275+ * @param array $data the data
 276+ * @param int $feedbackId the feedback id
 277+ * @param int $bucket the bucket id
 278+ * @return int the cta id
236279 */
237 - private function saveUserRatings($data, $feedbackId, $bucket) {
238 - $dbw = wfGetDB(DB_MASTER);
239 - $ctaId = $this->getCTAId($data, $bucket);
 280+ private function saveUserRatings( $data, $feedbackId, $bucket ) {
 281+ $dbw = wfGetDB( DB_MASTER );
 282+ $ctaId = $this->getCTAId( $data, $bucket );
240283
241284 $dbw->begin();
242285 $dbw->insert( 'aft_article_answer', $data, __METHOD__ );
@@ -250,10 +293,22 @@
251294 return $ctaId;
252295 }
253296
 297+ /**
 298+ * Picks a CTA to send the user to
 299+ *
 300+ * @param $answers array the user's answers
 301+ * @param $bucket int the bucket id
 302+ * @return int the cta id
 303+ */
254304 public function getCTAId($answers, $bucket) {
255 - return 1; # Hard-code this for now.
 305+ return 1; # Hard-code this for now.
256306 }
257307
 308+ /**
 309+ * Gets the allowed parameters
 310+ *
 311+ * @return array the params info, indexed by allowed key
 312+ */
258313 public function getAllowedParams() {
259314 $ret = array(
260315 'pageid' => array(
@@ -276,7 +331,7 @@
277332 );
278333
279334 $fields = ApiArticleFeedbackv5Utils::getFields();
280 - foreach( $fields as $field ) {
 335+ foreach ( $fields as $field ) {
281336 $ret[$field->afi_name] = array(
282337 ApiBase::PARAM_TYPE => 'string',
283338 ApiBase::PARAM_REQUIRED => false,
@@ -287,27 +342,45 @@
288343 return $ret;
289344 }
290345
 346+ /**
 347+ * Gets the parameter descriptions
 348+ *
 349+ * @return array the descriptions, indexed by allowed key
 350+ */
291351 public function getParamDescription() {
292 - $fields = ApiArticleFeedbackv5Utils::getFields();
293 - $ret = array(
 352+ $ret = array(
294353 'pageid' => 'Page ID to submit feedback for',
295354 'revid' => 'Revision ID to submit feedback for',
296355 'anontoken' => 'Token for anonymous users',
297356 'bucket' => 'Which rating widget was shown to the user',
298 - 'expertise' => 'What kinds of expertise does the user claim to have',
299357 );
300 -
301 - foreach( $fields as $f ) {
302 - $ret[$f->afi_name] = 'Optional feedback field, only appears on certain "buckets".';
 358+ $fields = ApiArticleFeedbackv5Utils::getFields();
 359+ foreach ( $fields as $f ) {
 360+ $ret[$f->afi_name] = 'Optional feedback field, only appears on certain "buckets".';
303361 }
304 -
305362 return $ret;
306363 }
307364
 365+ /**
 366+ * Returns whether this API call is post-only
 367+ *
 368+ * @return bool
 369+ */
308370 public function mustBePosted() { return true; }
309371
 372+ /**
 373+ * Returns whether this is a write call
 374+ *
 375+ * @return bool
 376+ */
310377 public function isWriteMode() { return true; }
311378
 379+ /**
 380+ * TODO
 381+ * Gets a list of possible errors
 382+ *
 383+ * @return bool
 384+ */
312385 public function getPossibleErrors() {
313386 return array_merge( parent::getPossibleErrors(), array(
314387 array( 'missingparam', 'anontoken' ),
@@ -316,19 +389,37 @@
317390 ) );
318391 }
319392
 393+ /**
 394+ * Gets a description
 395+ *
 396+ * @return string
 397+ */
320398 public function getDescription() {
321399 return array(
322400 'Submit article feedback'
323401 );
324402 }
325403
 404+ /**
 405+ * TODO
 406+ * Gets a list of examples
 407+ *
 408+ * @return array
 409+ */
326410 protected function getExamples() {
327411 return array(
328412 'api.php?action=articlefeedbackv5'
329413 );
330414 }
331415
 416+ /**
 417+ * Gets the version info
 418+ *
 419+ * @return string the SVN version info
 420+ */
332421 public function getVersion() {
333422 return __CLASS__ . ': $Id$';
334423 }
 424+
335425 }
 426+
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5Utils.php
@@ -1,9 +1,33 @@
22 <?php
3 -# ApiArticleFeedback and ApiQueryArticleFeedback don't descend from the same
4 -# parent, which is why these are all static methods instead of just a parent
5 -# class with inheritable methods. I don't get it either.
 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: ApiViewRatingsArticleFeedbackv5.php 103335 2011-11-16 16:25:53Z gregchiasson $
 11+ */
 12+
 13+/**
 14+ * Utility methods used by api calls
 15+ *
 16+ * ApiArticleFeedback and ApiQueryArticleFeedback don't descend from the same
 17+ * parent, which is why these are all static methods instead of just a parent
 18+ * class with inheritable methods. I don't get it either.
 19+ *
 20+ * @package ArticleFeedback
 21+ * @subpackage Api
 22+ */
623 class ApiArticleFeedbackv5Utils {
7 - public static function getAnonToken($params) {
 24+
 25+ /**
 26+ * Gets the anonymous token from the params
 27+ *
 28+ * @param $params array the params
 29+ * @return string the token, or null if the user is not anonymous
 30+ */
 31+ public static function getAnonToken( $params ) {
832 global $wgUser;
933 $token = null;
1034 if ( $wgUser->isAnon() ) {
@@ -17,11 +41,16 @@
1842 } else {
1943 $token = '';
2044 }
21 -
2245 return $token;
2346 }
2447
25 - public static function isFeedbackEnabled($params) {
 48+ /**
 49+ * Returns whether feedback is enabled for this page
 50+ *
 51+ * @param $params array the params
 52+ * @return bool
 53+ */
 54+ public static function isFeedbackEnabled( $params ) {
2655 global $wgArticleFeedbackNamespaces;
2756 $title = Title::newFromID( $params['pageid'] );
2857 if (
@@ -33,11 +62,17 @@
3463 || $title->isRedirect()
3564 ) {
3665 // ...then feedback diabled
37 - return 0;
 66+ return false;
3867 }
39 - return 1;
 68+ return true;
4069 }
4170
 71+ /**
 72+ * Returns the revision limit for a page
 73+ *
 74+ * @param $pageId int the page id
 75+ * @return int the revision limit
 76+ */
4277 public static function getRevisionLimit( $pageId ) {
4378 global $wgArticleFeedbackv5RatingLifetime;
4479 $dbr = wfGetDB( DB_SLAVE );
@@ -51,11 +86,16 @@
5287 'OFFSET' => $wgArticleFeedbackv5RatingLifetime - 1
5388 )
5489 );
55 -
56 - return $revision ? intval($revision) : 0;
 90+ return $revision ? intval( $revision ) : 0;
5791 }
5892
59 - public static function getRevisionId($pageId) {
 93+ /**
 94+ * Gets the most recent revision id for a page id
 95+ *
 96+ * @param $pageId int the page id
 97+ * @return int the revision id
 98+ */
 99+ public static function getRevisionId( $pageId ) {
60100 $dbr = wfGetDB( DB_SLAVE );
61101 $revId = $dbr->selectField(
62102 'revision', 'rev_id',
@@ -70,14 +110,21 @@
71111 return $revId;
72112 }
73113
74 - # TODO: use memcache
 114+ /**
 115+ * Gets the known feedback fields
 116+ *
 117+ * TODO: use memcache
 118+ *
 119+ * @return array the rows in the aft_article_field table
 120+ */
75121 public static function getFields() {
76122 $dbr = wfGetDB( DB_SLAVE );
77123 $rv = $dbr->select(
78124 'aft_article_field',
79 - array( 'afi_name', 'afi_id', 'afi_data_type' )
 125+ array( 'afi_name', 'afi_id', 'afi_data_type', 'afi_bucket_id' )
80126 );
81 -
82127 return $rv;
83128 }
 129+
84130 }
 131+
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php
@@ -43,7 +43,7 @@
4444
4545 $info = array();
4646 foreach ( $rollup as $row ) {
47 - $info[$row->field_id] = array(
 47+ $info[$row->field_name] = array(
4848 'ratingdesc' => $row->field_name,
4949 'ratingid' => (int) $row->field_id,
5050 'total' => (int) $row->points,
@@ -98,6 +98,7 @@
9999 }
100100 $where[$prefix . '_page_id'] = $pageId;
101101 $where[] = $prefix . '_rating_id = afi_id';
 102+ $where['afi_bucket_id'] = 5; // TODO: Pass this in
102103
103104 $rows = $dbr->select(
104105 array( 'aft_' . $table, 'aft_article_field' ),
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php
@@ -174,25 +174,24 @@
175175 * ResourceLoaderRegisterModules hook
176176 */
177177 public static function resourceLoaderRegisterModules( &$resourceLoader ) {
178 - global $wgExtensionAssetsPath;
 178+ global $wgExtensionAssetsPath,
 179+ $wgArticleFeedbackv5Bucket5RatingCategories;
 180+
179181 $localpath = dirname( __FILE__ ) . '/modules';
180182 $remotepath = "$wgExtensionAssetsPath/ArticleFeedbackv5/modules";
181183
182184 foreach ( self::$modules as $name => $resources ) {
183185 if ( $name == 'jquery.articleFeedbackv5' ) {
184186 // Bucket 5: labels and tooltips
185 - $fields = ApiArticleFeedbackv5Utils::getFields();
186187 $prefix = 'articlefeedbackv5-bucket5-';
187 - foreach( $fields as $field ) {
188 - if($fielf->afi_data_type == 'rating') {
189 - $resources['messages'][] = $prefix . $field->afi_name . '-label';
190 - $resources['messages'][] = $prefix . $field->afi_name . '-tip';
191 - $resources['messages'][] = $prefix . $field->afi_name . '-tooltip-1';
192 - $resources['messages'][] = $prefix . $field->afi_name . '-tooltip-2';
193 - $resources['messages'][] = $prefix . $field->afi_name . '-tooltip-3';
194 - $resources['messages'][] = $prefix . $field->afi_name . '-tooltip-4';
195 - $resources['messages'][] = $prefix . $field->afi_name . '-tooltip-5';
196 - }
 188+ foreach ( $wgArticleFeedbackv5Bucket5RatingCategories as $field ) {
 189+ $resources['messages'][] = $prefix . $field . '-label';
 190+ $resources['messages'][] = $prefix . $field . '-tip';
 191+ $resources['messages'][] = $prefix . $field . '-tooltip-1';
 192+ $resources['messages'][] = $prefix . $field . '-tooltip-2';
 193+ $resources['messages'][] = $prefix . $field . '-tooltip-3';
 194+ $resources['messages'][] = $prefix . $field . '-tooltip-4';
 195+ $resources['messages'][] = $prefix . $field . '-tooltip-5';
197196 }
198197 }
199198 $resourceLoader->register(
@@ -211,6 +210,7 @@
212211 $wgArticleFeedbackv5BlacklistCategories,
213212 $wgArticleFeedbackv5LotteryOdds,
214213 $wgArticleFeedbackv5Debug,
 214+ $wgArticleFeedbackv5Bucket5RatingCategories,
215215 $wgArticleFeedbackv5DisplayBuckets,
216216 $wgArticleFeedbackv5Tracking,
217217 $wgArticleFeedbackv5Options,
@@ -220,18 +220,13 @@
221221 $vars['wgArticleFeedbackv5BlacklistCategories'] = $wgArticleFeedbackv5BlacklistCategories;
222222 $vars['wgArticleFeedbackv5LotteryOdds'] = $wgArticleFeedbackv5LotteryOdds;
223223 $vars['wgArticleFeedbackv5Debug'] = $wgArticleFeedbackv5Debug;
 224+ $vars['wgArticleFeedbackv5Bucket5RatingCategories'] = $wgArticleFeedbackv5Bucket5RatingCategories;
224225 $vars['wgArticleFeedbackv5DisplayBuckets'] = $wgArticleFeedbackv5DisplayBuckets;
225226 $vars['wgArticleFeedbackv5Tracking'] = $wgArticleFeedbackv5Tracking;
226227 $vars['wgArticleFeedbackv5Options'] = $wgArticleFeedbackv5Options;
227228 $vars['wgArticleFeedbackv5Namespaces'] = $wgArticleFeedbackv5Namespaces;
228229 $vars['wgArticleFeedbackv5WhatsThisPage'] = wfMsgForContent( 'articlefeedbackv5-bucket5-form-panel-explanation-link' );
229230 $vars['wgArticleFeedbackv5TermsPage'] = wfMsgForContent( 'articlefeedbackv5-transparency-terms-url' );
230 -
231 - $fields = ApiArticleFeedbackv5Utils::getFields();
232 - foreach( $fields as $field ) {
233 - $vars['wgArticleFeedbackv5RatingTypes'][] = $field->afi_name;
234 - $vars['wgArticleFeedbackv5RatingTypesFlipped'][$field->afi_name] = $field->afi_id;
235 - }
236231 return true;
237232 }
238233

Status & tagging log