r112038 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r112037‎ | r112038 | r112039 >
Date:20:28, 21 February 2012
Author:emsmith
Status:resolved (Comments)
Tags:scaptrap, schema 
Comment:
bug 34090 - added additional counts for filters including unhidden, undeleted (unoversighted) and oversight declined, stored a flag for "has a comment" in the main feedback table to avoid a join or extra query for comment status when doing filtering and count updating, moved the truncation of logging into the logging utility method, rewrote most of the flagging api, simplifying the filtering utility method, moved all of the hiding count adjustements into a single helper method, added auto hide/unhide to requesting oversight (threshold is always one request), and added auto hide (but NOT unhide) to oversight functionality - so oversight will autohide, unoversight will NOT autounhide, altered the filter count update script to rollup/adjust for the new filter values, added the new filters to the feedback page, made sure all flagging activity and feedback saving activity is done inside a single transaction so counts are not updated if changes are not made to the feedback table (and vice versa - no successful count updates, no feedback changes) - this should help to keep the counts in sync with the data in the table
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5Utils.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiFlagFeedbackArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/sql/alter.sql (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/sql/filter_count.sql (modified) (history)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql
@@ -46,9 +46,21 @@
4747 -- Flag a message as being hidden or being deleted
4848 af_is_deleted boolean NOT NULL DEFAULT FALSE,
4949 af_is_hidden boolean NOT NULL DEFAULT FALSE,
 50+ -- Keep track of items that have been unhidden, undeleted (unoversighted)
 51+ -- or had oversight declined - note this is cleared when the item is
 52+ -- rehidden, reoversighted, or has oversight requested again
 53+ af_is_unhidden boolean NOT NULL DEFAULT FALSE,
 54+ af_is_undeleted boolean NOT NULL DEFAULT FALSE,
 55+ af_is_declined boolean NOT NULL DEFAULT FALSE,
 56+ -- keep track of "this has a comment" for filtering purposes (avoids a join)
 57+ af_has_comment boolean NOT NULL DEFAULT FALSE,
5058 -- Keep track of number of activities (hide/show/flag/unflag)
5159 -- should be equivalent to counting rows in logging table
5260 af_activity_count integer unsigned NOT NULL DEFAULT 0
 61+ -- for some of the filtering, we need to know "unhidden"
 62+ -- to do this we have to keep track of "has ever been hidden
 63+ -- same with "has ever been oversighted, has ever had oversight requested"
 64+ -- these go on and never go back off, really
5365 ) /*$wgDBTableOptions*/;
5466 CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_id, af_user_anon_token, af_id);
5567 CREATE INDEX /*i*/af_revision_id ON /*_*/aft_article_feedback (af_revision_id);
Index: trunk/extensions/ArticleFeedbackv5/sql/alter.sql
@@ -127,5 +127,12 @@
128128 CREATE INDEX /*_*/af_net_helpfulness_af_id ON /*_*/aft_article_feedback (af_id, af_net_helpfulness);
129129
130130 -- Added 2/14 (emsmith)
 131+ALTER TABLE /*_*/aft_article_feedback CHANGE COLUMN af_needs_oversight af_oversight_count integer unsigned NOT NULL DEFAULT 0;
 132+ALTER TABLE /*_*/aft_article_feedback ADD COLUMN af_has_comment BOOLEAN NOT NULL DEFAULT FALSE;
 133+ALTER TABLE /*_*/aft_article_feedback ADD COLUMN af_is_unhidden BOOLEAN NOT NULL DEFAULT FALSE;
 134+ALTER TABLE /*_*/aft_article_feedback ADD COLUMN af_is_undeleted BOOLEAN NOT NULL DEFAULT FALSE;
 135+ALTER TABLE /*_*/aft_article_feedback ADD COLUMN af_is_declined BOOLEAN NOT NULL DEFAULT FALSE;
131136 ALTER TABLE /*_*/aft_article_feedback ADD COLUMN af_activity_count integer unsigned NOT NULL DEFAULT 0;
132 -ALTER TABLE /*_*/aft_article_feedback CHANGE COLUMN af_needs_oversight af_oversight_count integer unsigned NOT NULL DEFAULT 0;
 137+
 138+-- set has_comment appropriately
 139+UPDATE aft_article_feedback, aft_article_answer SET af_has_comment = TRUE WHERE af_bucket_id = 1 AND af_id = aa_feedback_id AND aa_response_text IS NOT NULL;
Index: trunk/extensions/ArticleFeedbackv5/sql/filter_count.sql
@@ -1,12 +1,35 @@
22 DELETE FROM aft_article_filter_count;
33
 4+-- all includes oversighted and hidden
45 INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'all', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 GROUP BY af_page_id;
5 -INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'needsoversight', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_oversight_count > 0 GROUP BY af_page_id;
6 -INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'invisible', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_hidden IS TRUE GROUP BY af_page_id;
7 -INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'visible', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
 6+
 7+-- notdeleted includes all but oversighted
 8+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'notdeleted', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_deleted IS FALSE GROUP BY af_page_id;
 9+
 10+-- has text in the comment
 11+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'comment', COUNT(*) FROM aft_article_feedback, aft_article_answer WHERE af_bucket_id = 1 AND af_id = aa_feedback_id AND aa_response_text IS NOT NULL AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
 12+
 13+-- oversighted
814 INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'deleted', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_deleted IS TRUE GROUP BY af_page_id;
 15+--unoversighted
 16+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'undeleted', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_deleted IS FALSE AND af_is_undeleted IS TRUE GROUP BY af_page_id;
917
 18+-- visible (all not hidden)
 19+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'visible', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
 20+-- invisible (hidden)
 21+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'invisible', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_hidden IS TRUE GROUP BY af_page_id;
 22+-- once was hidden, now is visible (unhidden)
 23+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'unhidden', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_hidden IS FALSE AND af_is_unhidden IS TRUE GROUP BY af_page_id;
 24+
 25+-- abusive - not hidden/deleted and has flag count
1026 INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'abusive', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_abuse_count > 0 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
 27+
 28+-- needs oversight - has at least one oversight request
 29+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'needsoversight', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_oversight_count > 0 GROUP BY af_page_id;
 30+
 31+-- declined - had oversight declined
 32+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'declined', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND af_is_declined IS TRUE GROUP BY af_page_id;
 33+
 34+-- helpful and unhelpful counts
1135 INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'helpful', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND CONVERT(af_helpful_count, SIGNED) - CONVERT(af_unhelpful_count, SIGNED) > 0 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
12 -INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'unhelpful', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND CONVERT(af_helpful_count, SIGNED) - CONVERT(af_unhelpful_count, SIGNED) < 0 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
13 -INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'comment', COUNT(*) FROM aft_article_feedback, aft_article_answer WHERE af_bucket_id = 1 AND af_id = aa_feedback_id AND aa_response_text IS NOT NULL AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
 36+INSERT INTO aft_article_filter_count(afc_page_id, afc_filter_name, afc_filter_count) SELECT af_page_id, 'unhelpful', COUNT(*) FROM aft_article_feedback WHERE af_bucket_id = 1 AND CONVERT(af_helpful_count, SIGNED) - CONVERT(af_unhelpful_count, SIGNED) < 0 AND af_is_hidden IS FALSE AND af_is_deleted IS FALSE GROUP BY af_page_id;
\ No newline at end of file
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php
@@ -64,6 +64,9 @@
6565 'articlefeedbackv5-special-filter-visible' => 'All visible ($1)',
6666 'articlefeedbackv5-special-filter-invisible' => 'Hidden ($1)',
6767 'articlefeedbackv5-special-filter-deleted' => 'Oversighted ($1)',
 68+ 'articlefeedbackv5-special-filter-undeleted' => 'Un-oversighted ($1)',
 69+ 'articlefeedbackv5-special-filter-declined' => 'Oversight Declined ($1)',
 70+ 'articlefeedbackv5-special-filter-unhidden' => 'Un-hidden ($1)',
6871 'articlefeedbackv5-special-sort-age' => 'Date',
6972 'articlefeedbackv5-special-sort-helpful' => 'Helpful',
7073 'articlefeedbackv5-special-sort-rating' => 'Rating',
@@ -342,8 +345,6 @@
343346
344347 /* Activity Pane phrases */
345348 'articlefeedbackv5-activity-pane-header' => 'Activity Log',
346 - 'articlefeedbackv5-activity-help-item' => '?',
347 - 'articlefeedbackv5-activity-close-item' => 'X',
348349 'articlefeedbackv5-activity-feedback-info' => 'Feedback Post #$1 by',
349350 'articlefeedbackv5-activity-feedback-date' => 'Posted on $1',
350351 'articlefeedbackv5-activity-permalink' => 'permalink',
@@ -383,6 +384,29 @@
384385 Best wishes, and thank you,
385386 The {{SITENAME}} team',
386387
 388+ 'articlefeedbackv5-emailcapture-request-oversight' => 'Hello!
 389+
 390+A request for oversight has been made by
 391+
 392+$1 : $2
 393+
 394+on feedback item
 395+
 396+$3 : $4
 397+
 398+for page
 399+
 400+$5 : $6
 401+
 402+Please visit
 403+
 404+$7
 405+
 406+to decline or approve this oversight request.
 407+
 408+Thank you,
 409+The {{SITENAME}} team',
 410+
387411 );
388412
389413 /** Message documentation (Message documentation)
Index: trunk/extensions/ArticleFeedbackv5/api/ApiFlagFeedbackArticleFeedbackv5.php
@@ -5,6 +5,7 @@
66 * @package ArticleFeedback
77 * @subpackage Api
88 * @author Greg Chiasson <greg@omniti.com>
 9+ * @author Elizabeth M Smith <elizabeth@omniti.com>
910 */
1011
1112 /**
@@ -19,79 +20,259 @@
2021 }
2122
2223 /**
23 - * Execute the API call: Pull the requested feedback
 24+ * Execute the API call
 25+ *
 26+ * This single api call covers all cases where flags are being applied to
 27+ * a piece of feedback
 28+ *
 29+ * A feedback request consists of
 30+ * 1.
2431 */
2532 public function execute() {
 33+
 34+ // default values for information to be filled in
 35+ $filters = array();
 36+ $update = array();
 37+ $results = array();
 38+
 39+ // get important values from our parameters
2640 $params = $this->extractRequestParams();
2741 $pageId = $params['pageid'];
2842 $feedbackId = $params['feedbackid'];
2943 $flag = $params['flagtype'];
3044 $notes = $params['note'];
3145 $direction = isset( $params['direction'] ) ? $params['direction'] : 'increase';
32 - $counters = array( 'abuse', 'helpful', 'unhelpful', 'oversight' );
33 - $flags = array( 'hide', 'delete' );
34 - $results = array();
35 - $helpful = null;
36 - $error = null;
3746 $where = array( 'af_id' => $feedbackId );
3847
39 - # load feedback record, bail if we don't have one
40 - $record = $this->fetchRecord( $feedbackId );
 48+ // we use ONE db connection that talks to master
 49+ $dbw = wfGetDB( DB_MASTER );
 50+ $dbw->begin();
4151
 52+ // load feedback record, bail if we don't have one
 53+ $record = $this->fetchRecord( $dbw, $feedbackId );
 54+
4255 if ( $record === false || !$record->af_id ) {
4356 // no-op, because this is already broken
4457 $error = 'articlefeedbackv5-invalid-feedback-id';
45 - } elseif ( in_array( $flag, $flags ) ) {
4658
47 - $count = null;
48 - switch( $flag ) {
49 - case 'hide':
50 - $field = 'af_is_hidden';
51 - break;
52 - case 'delete':
53 - $field = 'af_is_deleted';
54 - break;
55 - default: return; # return error, ideally.
 59+ } elseif ( 'delete' == $flag ) {
 60+
 61+ // deleting means to "mark as oversighted" and "delete" it
 62+ // oversighting also auto-hides the item
 63+
 64+ // increase means "oversight this"
 65+ if( $direction == 'increase' ) {
 66+ $activity = 'oversight';
 67+
 68+ // delete
 69+ $update[] = "af_is_deleted = TRUE";
 70+ $update[] = "af_is_undeleted = FALSE";
 71+ // delete specific filters
 72+ $filters['deleted'] = 1;
 73+ $filters['notdeleted'] = -1;
 74+
 75+ // autohide if not hidden
 76+ if (false == $record->af_is_hidden ) {
 77+ $update[] = "af_is_hidden = TRUE";
 78+ $update[] = "af_is_unhidden = FALSE";
 79+ $filters = $this->changeFilterCounts( $record, $filters, 'hide' );
 80+ $implicit_hide = true; // for logging
 81+ }
 82+
 83+ } else {
 84+ // decrease means "unoversight this" but does NOT auto-unhide
 85+ $activity = 'unoversight';
 86+ $update[] = "af_is_deleted = FALSE";
 87+ $update[] = "af_is_undeleted = TRUE";
 88+ // increment "undeleted", decrement "deleted"
 89+ // NOTE: we do not touch visible, since hidden controls visiblity
 90+ $filters['deleted'] = -1;
 91+ $filters['undeleted'] = 1;
 92+ // increment "notdeleted" for count of everything but oversighted
 93+ $filters['notdeleted'] = 1;
5694 }
 95+
 96+ } elseif ( 'hide' == $flag ) {
 97+
 98+ // increase means "hide this"
5799 if( $direction == 'increase' ) {
58 - $update[] = "$field = TRUE";
 100+ $activity = 'hide';
 101+
 102+ // hide
 103+ $update[] = "af_is_hidden = TRUE";
 104+ $update[] = "af_is_unhidden = FALSE";
 105+
 106+ $filters = $this->changeFilterCounts( $record, $filters, 'hide' );
 107+
59108 } else {
60 - $update[] = "$field = FALSE";
 109+ // decrease means "unhide this"
 110+ $activity = 'unhide';
 111+
 112+ $update[] = "af_is_hidden = FALSE";
 113+ $update[] = "af_is_unhidden = TRUE";
 114+
 115+ $filters = $this->changeFilterCounts( $record, $filters, 'show' );
61116 }
 117+
62118 } elseif( 'resetoversight' === $flag) {
63 - // special case, oversight request count becomes 0
 119+
 120+ $activity = 'decline';
 121+ // oversight request count becomes 0
64122 $update[] = "af_oversight_count = 0";
 123+ // declined oversight is flagged
 124+ $update[] = "af_is_declined = TRUE";
 125+ $filters['declined'] = 1;
 126+ // if the oversight count was greater then 1
 127+ if(0 < $record->af_oversight_count) {
 128+ $filters['needsoversight'] = -1;
 129+ }
65130
66 - } elseif ( in_array( $flag, $counters ) ) {
67 - // Probably this doesn't need validation, since the API
68 - // will handle it, but if it's getting interpolated into
69 - // the SQL, I'm really wary not re-validating it.
70 - $field = 'af_' . $flag . '_count';
 131+ } elseif( 'abuse' === $flag) {
71132
72 - // Add another where condition to confirm that
73 - // the new flag value is at or above 0 (we use
74 - // unsigned ints, so negatives cause errors.
 133+ // Conditional formatting for abuse flag
 134+ global $wgArticleFeedbackv5AbusiveThreshold,
 135+ $wgArticleFeedbackv5HideAbuseThreshold;
 136+
 137+ $results['abuse_count'] = $record->af_abuse_count;
 138+
 139+ // Make the abuse count in the result reflect this vote.
75140 if( $direction == 'increase' ) {
76 - $update[] = "$field = $field + 1";
77 - // If this is already less than 0,
78 - // don't do anything - it'll just
79 - // throw a SQL error, so don't bother.
80 - // Incrementing from 0 is still valid.
81 - $where[] = "$field >= 0";
 141+ $results['abuse_count']++;
 142+ } else {
 143+ $results['abuse_count']--;
 144+ }
 145+ // no negative numbers
 146+ $results['abuse_count'] = max(0, $results['abuse_count']);
 147+
 148+ // Return a flag in the JSON, that turns the link red.
 149+ if( $results['abuse_count'] >= $wgArticleFeedbackv5AbusiveThreshold ) {
 150+ $results['abusive'] = 1;
 151+ }
 152+
 153+ // Adding a new abuse flag: abusive++
 154+ if($direction == 'increase') {
 155+ $activity = 'flag';
 156+ $filters['abusive'] = 1;
 157+ $update[] = "af_abuse_count = LEAST(af_abuse_count + 1, 1)";
 158+
 159+ // Auto-hide after threshold flags
 160+ if( $record->af_abuse_count > $wgArticleFeedbackv5HideAbuseThreshold
 161+ && false == $record->af_is_hidden ) {
 162+ // hide
 163+ $update[] = "af_is_hidden = TRUE";
 164+ $update[] = "af_is_unhidden = FALSE";
 165+
 166+ $filters = $this->changeFilterCounts( $record, $filters, 'hide' );
 167+ $results['abuse-hidden'] = 1;
 168+ $implicit_hide = true;
 169+ }
 170+ }
 171+
 172+ // Removing the last abuse flag: abusive--
 173+ elseif($direction == 'decrease') {
 174+ $activity = 'unflag';
 175+ $filters['abusive'] = -1;
 176+ $update[] = "af_abuse_count = GREATEST(af_abuse_count - 1, 0)";
 177+
 178+ // Un-hide if we don't have 5 flags anymore
 179+ if( $record->af_abuse_count == 5 && true == $record->af_is_hidden ) {
 180+ $update[] = "af_is_hidden = FALSE";
 181+ $update[] = "af_is_unhidden = TRUE";
 182+
 183+ $filters = $this->changeFilterCounts( $record, $filters, 'show' );
 184+
 185+ $implicit_unhide = true;
 186+ }
82187 } else {
83 - $update[] = "$field = $field - 1";
84 - // If this is already 0 or less,
85 - // don't decrement it, that would
86 - // throw an error.
87 - // Decrementing from 0 is not allowed.
88 - $where[] = "$field > 0";
 188+ // TODO: real error here?
 189+ $error = 'articlefeedbackv5-invalid-feedback-flag';
89190 }
 191+
 192+ // NOTE: this is actually request/unrequest oversight and works similar to abuse
 193+ } elseif( 'oversight' === $flag) {
 194+
 195+ if($direction == 'increase') {
 196+ $activity = 'request';
 197+ $filters['needsoversight'] = 1;
 198+ $update[] = "af_oversight_count = LEAST(af_oversight_count + 1, 1)";
 199+
 200+ // autohide if not hidden
 201+ if (false == $record->af_is_hidden ) {
 202+ $update[] = "af_is_hidden = TRUE";
 203+ $update[] = "af_is_unhidden = FALSE";
 204+ $filters = $this->changeFilterCounts( $record, $filters, 'hide' );
 205+ $implicit_hide = true; // for logging
 206+ }
 207+ }
 208+
 209+ elseif($direction == 'decrease' && $record->af_abuse_count > 0 ) {
 210+ $activity = 'unrequest';
 211+ $filters['needsoversight'] = -1;
 212+ $update[] = "af_oversight_count = GREATEST(af_oversight_count - 1, 0)";
 213+
 214+ // Un-hide if we don't have oversight flags anymore
 215+ if( $record->af_oversight_count == 1 && true == $record->af_is_hidden ) {
 216+ $update[] = "af_is_hidden = FALSE";
 217+ $update[] = "af_is_unhidden = TRUE";
 218+
 219+ $filters = $this->changeFilterCounts( $record, $filters, 'show' );
 220+
 221+ $implicit_unhide = true;
 222+ }
 223+ } else {
 224+ // TODO: real error here?
 225+ $error = 'articlefeedbackv5-invalid-feedback-flag';
 226+ }
 227+
 228+ // helpful and unhelpful flagging
 229+ } elseif( 'unhelpful' === $flag || 'helpful' === $flag) {
 230+
 231+ if ( 'unhelpful' === $flag ) {
 232+ $update[] = "af_unhelpful_count = af_unhelpful_count + 1";
 233+ } elseif ( 'helpful' === $flag ) {
 234+ $update[] = "af_helpful_count = af_helpful_count + 1";
 235+ }
 236+
 237+ // note that a net helpfulness of 0 is neither helpful nor unhelpful
 238+ $netHelpfulness = $record->af_net_helpfulness;
 239+
 240+ // increase helpful OR decrease unhelpful
 241+ if( ( ($flag == 'helpful' && $direction == 'increase' )
 242+ || ($flag == 'unhelpful' && $direction == 'decrease' ) )
 243+ ) {
 244+ // net was -1: no longer unhelpful
 245+ if( $netHelpfulness == -1 ) {
 246+ $filters['unhelpful'] = -1;
 247+ }
 248+
 249+ // net was 0: now helpful
 250+ if( $netHelpfulness == 0 ) {
 251+ $filters['helpful'] = 1;
 252+ }
 253+ }
 254+
 255+ // increase unhelpful OR decrease unhelpful
 256+ if( ( ($flag == 'unhelpful' && $direction == 'increase' )
 257+ || ($flag == 'helpful' && $direction == 'decrease' ) )
 258+ ) {
 259+ // net was 1: no longer helpful
 260+ if( $netHelpfulness == 1 ) {
 261+ $filters['helpful'] = -1;
 262+ }
 263+
 264+ // net was 0: now unhelpful
 265+ if( $netHelpfulness == 0 ) {
 266+ $filters['unhelpful'] = 1;
 267+ }
 268+ }
 269+
90270 } else {
91271 $error = 'articlefeedbackv5-invalid-feedback-flag';
92272 }
93273
94 - if ( !$error ) {
95 - $dbw = wfGetDB( DB_MASTER );
 274+ // we were valid
 275+ if ( !isset($error) ) {
 276+
96277 $success = $dbw->update(
97278 'aft_article_feedback',
98279 $update,
@@ -99,84 +280,48 @@
100281 __METHOD__
101282 );
102283
103 - // If the query worked...
104 - if( $success ) {
 284+ // Update the filter count rollups.
 285+ ApiArticleFeedbackv5Utils::updateFilterCounts( $dbw, $pageId, $filters );
105286
106 - // Log the feedback activity entry via the utils method
107 - $activity = $this->getActivity( $flag, $direction );
 287+ $dbw->commit(); // everything went well, so we commit our db changes
108288
109 - // Make sure our notes are not too long - we won't error, just hard substr it
110 - global $wgArticleFeedbackv5MaxActivityNoteLength;
111 -
112 - $notes = substr($notes, 0, $wgArticleFeedbackv5MaxActivityNoteLength);
113 -
 289+ // helpfulness counts are NOT logged, no activity is set
 290+ if (isset($activity)) {
114291 ApiArticleFeedbackv5Utils::logActivity( $activity , $pageId, $feedbackId, $notes );
115 -
116 - $this->updateCounts( $flag, $direction, $record, $pageId );
117 -
118 - // Update helpful/unhelpful display count after submission.
119 - if ( $flag == 'helpful' || $flag == 'unhelpful' ) {
120 - $helpful = $record->af_helpful_count;
121 - $unhelpful = $record->af_unhelpful_count;
122 -
123 - if( $flag == 'helpful' && $direction == 'increase' ) {
124 - $helpful++;
125 - } elseif ( $flag == 'helpful' && $direction == 'decrease' ) {
126 - $helpful--;
127 - } elseif ( $flag == 'unhelpful' && $direction == 'increase' ) {
128 - $unhelpful++;
129 - } elseif ( $flag == 'unhelpful' && $direction == 'decrease' ) {
130 - $unhelpful--;
131 - }
132 -
133 - $results['helpful'] = wfMessage(
134 - 'articlefeedbackv5-form-helpful-votes',
135 - $helpful, $unhelpful
136 - )->escaped();
137 -
138 - // Update net_helpfulness after flagging as helpful/unhelpful.
139 - $dbw->update(
140 - 'aft_article_feedback',
141 - array( 'af_net_helpfulness = CONVERT(af_helpful_count, SIGNED) - CONVERT(af_unhelpful_count, SIGNED)' ),
142 - array(
143 - 'af_id' => $params['feedbackid'],
144 - ),
145 - __METHOD__
146 - );
147 - }
148292 }
149293
150 - // Conditional formatting for abuse flag
151 - global $wgArticleFeedbackv5AbusiveThreshold,
152 - $wgArticleFeedbackv5HideAbuseThreshold;
 294+ // TODO: handle implicit hide/show logging
153295
154 - $results['abuse_count'] = $record->af_abuse_count;
155 -
156 - if( $flag == 'abuse' ) {
157 - // Make the abuse count in the result reflect this vote.
158 - if( $direction == 'increase' ) {
159 - $results['abuse_count']++;
160 - } else {
161 - $results['abuse_count']--;
 296+ // Update helpful/unhelpful display count after submission.
 297+ if ( $flag == 'helpful' || $flag == 'unhelpful' ) {
 298+ $helpful = $record->af_helpful_count;
 299+ $unhelpful = $record->af_unhelpful_count;
 300+
 301+ if( $flag == 'helpful' && $direction == 'increase' ) {
 302+ $helpful++;
 303+ } elseif ( $flag == 'helpful' && $direction == 'decrease' ) {
 304+ $helpful--;
 305+ } elseif ( $flag == 'unhelpful' && $direction == 'increase' ) {
 306+ $unhelpful++;
 307+ } elseif ( $flag == 'unhelpful' && $direction == 'decrease' ) {
 308+ $unhelpful--;
162309 }
163310
164 - // Return a flag in the JSON, that turns the link red.
165 - if( $results['abuse_count'] >= $wgArticleFeedbackv5AbusiveThreshold ) {
166 - $results['abusive'] = 1;
167 - }
 311+ // no negative numbers please
 312+ $helpful = max(0, $helpful);
 313+ $unhelpful = max(0, $unhelpful);
168314
169 - // Return a flag in the JSON, that knows to kill the row
170 - if( $results['abuse_count'] >= $wgArticleFeedbackv5HideAbuseThreshold ) {
171 - $results['abuse-hidden'] = 1;
172 - }
173 -
174 - // Hide the row if the abuse count is above our threshhold
 315+ $results['helpful'] = wfMessage(
 316+ 'articlefeedbackv5-form-helpful-votes',
 317+ $helpful, $unhelpful
 318+ )->escaped();
 319+
 320+ // Update net_helpfulness after flagging as helpful/unhelpful.
175321 $dbw->update(
176322 'aft_article_feedback',
177 - array( 'af_is_hidden = TRUE' ),
178 - array(
 323+ array( 'af_net_helpfulness = CONVERT(af_helpful_count, SIGNED) - CONVERT(af_unhelpful_count, SIGNED)' ),
 324+ array(
179325 'af_id' => $params['feedbackid'],
180 - "af_abuse_count >= ". intval( $wgArticleFeedbackv5HideAbuseThreshold )
181326 ),
182327 __METHOD__
183328 );
@@ -198,17 +343,91 @@
199344 );
200345 }
201346
202 - private function fetchRecord( $id ) {
203 - $dbr = wfGetDB( DB_SLAVE );
204 - $record = $dbr->selectRow(
 347+ /**
 348+ * Helper function to grab a record from the database with information
 349+ * about the current feedback row
 350+ *
 351+ * @param object $dbw connection to database
 352+ * @param int $id id of the feedback to fetch
 353+ * @return object database record
 354+ */
 355+ private function fetchRecord( $dbw, $id ) {
 356+ $record = $dbw->selectRow(
205357 'aft_article_feedback',
206 - array( 'af_id', 'af_abuse_count', 'af_is_hidden', 'af_helpful_count', 'af_unhelpful_count', 'af_is_deleted', 'af_net_helpfulness' ),
 358+ array(
 359+ 'af_id',
 360+ 'af_abuse_count',
 361+ 'af_is_hidden',
 362+ 'af_helpful_count',
 363+ 'af_unhelpful_count',
 364+ 'af_is_deleted',
 365+ 'af_net_helpfulness',
 366+ 'af_is_unhidden',
 367+ 'af_is_undeleted',
 368+ 'af_is_declined',
 369+ 'af_has_comment'),
207370 array( 'af_id' => $id )
208371 );
209372 return $record;
210373 }
211374
212375 /**
 376+ * Helper function to manipulate all flags when hiding/showing a piece of feedback
 377+ *
 378+ * @param object $record existing feedback database record
 379+ * @param array $filters existing filters
 380+ * @param string $action 'hide' or 'show'
 381+ * @return array the filter array with new filter choices added
 382+ */
 383+ protected function changeFilterCounts( $record, $filters, $action ) {
 384+ // only filters that hide shouldn't manipulate are
 385+ // all, deleted, undeleted, and notdeleted
 386+
 387+ // use -1 (decrement) for hide, 1 for increment (show) - default is hide
 388+ switch($action) {
 389+ case 'show':
 390+ $int = 1;
 391+ break;
 392+ default:
 393+ $int = -1;
 394+ break;
 395+ }
 396+
 397+ // visible, invisible, unhidden
 398+ $filters['visible'] = $int;
 399+ $filters['invisible'] = -$int; // opposite of int
 400+ if(true == $record->af_is_unhidden) {
 401+ $filters['unhidden'] = $int;
 402+ }
 403+
 404+ // comment
 405+ if(true == $record->af_has_comment) {
 406+ $filters['comment'] = $int;
 407+ }
 408+
 409+ // abusive
 410+ if( $record->af_abuse_count > 1 ) {
 411+ $filters['abusive'] = $int;
 412+ }
 413+ // helpful and unhelpful
 414+ if( $record->af_net_helpfulness > 1 ) {
 415+ $filters['helpful'] = $int;
 416+ } elseif( $record->af_net_helpfulness < 1 ) {
 417+ $filters['unhelpful'] = $int;
 418+ }
 419+
 420+ // needsoversight, declined
 421+ if($record->af_oversight_count > 0) {
 422+ $filters['needsoversight'] = $int;
 423+ }
 424+ if(true == $record->af_is_declined) {
 425+ $filters['declined'] = $int;
 426+ }
 427+
 428+ return $filters;
 429+ }
 430+
 431+ /**
213432 * Gets the allowed parameters
214433 *
215434 * @return array the params info, indexed by allowed key
@@ -229,7 +448,7 @@
230449 ApiBase::PARAM_REQUIRED => true,
231450 ApiBase::PARAM_ISMULTI => false,
232451 ApiBase::PARAM_TYPE => array(
233 - 'abuse', 'hide', 'helpful', 'unhelpful', 'delete', 'undelete', 'unhide', 'oversight', 'unoversight', 'resetoversight' )
 452+ 'abuse', 'hide', 'helpful', 'unhelpful', 'delete', 'oversight', 'resetoversight' )
234453 ),
235454 'direction' => array(
236455 ApiBase::PARAM_REQUIRED => false,
@@ -294,172 +513,6 @@
295514 }
296515
297516 /**
298 - * Figures out which filter counts to increment/decrement based on what
299 - * flag was clicked and which direction it was going.
300 - *
301 - * @param $action string type of flag sent to the form
302 - * @param $direction string type of direction sent to the form
303 - * @param $record object database object representing the feedback row
304 - * @param $pageId integer ID of the page to be updated.
305 - */
306 - protected function updateCounts( $action, $direction, $record, $pageId ) {
307 - $counts = array( 'increment' => array(), 'decrement' => array() );
308 - $netHelpfulness = $record->af_net_helpfulness;
309 -
310 - // Increment or decrement hide or delete filters.
311 - if( $action == 'hide' || $action == 'delete' ) {
312 - $count = $action == 'hide' ? 'invisible' : 'deleted';
313 -
314 - // If this is hiding/deleting, increment the visible count and
315 - // decrement the visible count.
316 - if( $direction == 'increase' ) {
317 - $counts['increment'][] = $count;
318 - $counts['decrement'][] = 'visible';
319 - }
320 - // For unhiding/undeleting, do the opposite.
321 - if( $direction == 'decrease' ) {
322 - $counts['increment'][] = 'visible';
323 - $counts['decrement'][] = $count;
324 - }
325 - }
326 -
327 - // Adding a new abuse flag: abusive++
328 - if( $action == 'abuse' && $direction == 'increase'
329 - && $record->af_abuse_count == 0 ) {
330 - $counts['increment'][] = 'abusive';
331 - // Auto-hide after 5 abuse flags.
332 - if( $record->af_abuse_count > 4 ) {
333 - $counts['increment'][] = 'invisible';
334 - $counts['decrement'][] = 'visible';
335 - }
336 - }
337 -
338 - // Removing the last abuse flag: abusive--
339 - if( $action == 'abuse' && $direction == 'decrease'
340 - && $record->af_abuse_count == 1 ) {
341 - $counts['decrement'][] = 'abusive';
342 - // Un-hide if we don't have 5 flags anymore
343 - if( $record->af_abuse_count == 5 ) {
344 - $counts['increment'][] = 'visible';
345 - $counts['decrement'][] = 'invisible';
346 - }
347 - }
348 -
349 - // note that a net helpfulness of 0 is neither helpful nor unhelpful
350 -
351 - // increase helpful OR decrease unhelpful
352 - if( ( ($action == 'helpful' && $direction == 'increase' )
353 - || ($action == 'unhelpful' && $direction == 'decrease' ) )
354 - ) {
355 - // net was -1: no longer unhelpful
356 - if( $netHelpfulness == -1 ) {
357 - $counts['decrement'][] = 'unhelpful';
358 - }
359 -
360 - // net was 0: now helpful
361 - if( $netHelpfulness == 0 ) {
362 - $counts['increment'][] = 'helpful';
363 - }
364 - }
365 -
366 - // increase unhelpful OR decrease unhelpful
367 - if( ( ($action == 'unhelpful' && $direction == 'increase' )
368 - || ($action == 'helpful' && $direction == 'decrease' ) )
369 - ) {
370 - // net was 1: no longer helpful
371 - if( $netHelpfulness == 1 ) {
372 - $counts['decrement'][] = 'helpful';
373 - }
374 -
375 - // net was 0: now unhelpful
376 - if( $netHelpfulness == 0 ) {
377 - $counts['increment'][] = 'unhelpful';
378 - }
379 - }
380 -
381 - // If someone hides or deletes an abusive/comment/helpful/unhelpful
382 - // comment, decrement the relevent counter.
383 - // If they unhide/undelete, increment that same counter.
384 - if( $action == 'delete' || $action == 'hide' ) {
385 - $dbr = wfGetDB( DB_SLAVE );
386 - $dir = $direction == 'increase' ? 'decrement' : 'increment';
387 - $comment = $dbr->select(
388 - array( 'aft_article_answer', 'aft_article_field' ),
389 - 'aa_response_text',
390 - array(
391 - 'aa_feedback_id' => $record->af_id,
392 - 'afi_data_type' => 'text',
393 - 'aa_field_id = afi_id'
394 - ),
395 - __METHOD__
396 - );
397 -
398 - if( $record->af_abuse_count > 1 ) {
399 - $counts[$dir][] = 'abusive';
400 - }
401 - if( $comment->numRows() > 0 ) {
402 - $counts[$dir][] = 'comment';
403 - }
404 - if( $netHelpfulness > 1 ) {
405 - $counts[$dir][] = 'helpful';
406 - }
407 - if( $netHelpfulness < 1 ) {
408 - $counts[$dir][] = 'unhelpful';
409 - }
410 - }
411 -
412 - // Update the filter count rollups.
413 - ApiArticleFeedbackv5Utils::incrementFilterCounts( $pageId, $counts['increment'] );
414 - ApiArticleFeedbackv5Utils::decrementFilterCounts( $pageId, $counts['decrement'] );
415 - }
416 -
417 - /**
418 - * Figures out which activity happened so it can be logged correctly
419 - *
420 - * @param $flag string type of flag sent to the form
421 - * @param $direction string type of direction sent to the form
422 - * @return string name of activity to log
423 - */
424 - protected function getActivity($flag, $direction) {
425 -
426 - // handle flag as abuse / remove abuse flag
427 - if ( 'abuse' == $flag && 'increase' == $direction) {
428 - return 'flag';
429 - } elseif ( 'abuse' == $flag && 'decrease' == $direction) {
430 - return 'unflag';
431 - }
432 -
433 - // handle hide as hidden, unhidden
434 - if ( 'hide' == $flag && 'increase' == $direction) {
435 - return 'hidden';
436 - } elseif ( 'hide' == $flag && 'decrease' == $direction) {
437 - return 'unhidden';
438 - }
439 -
440 - // handle delete as oversight, unoversight
441 - if ( 'delete' == $flag && 'increase' == $direction) {
442 - return 'oversight';
443 - } elseif ( 'delete' == $flag && 'decrease' == $direction) {
444 - return 'unoversight';
445 - }
446 -
447 - // handle oversight as request and unrequest oversighting
448 - if ( 'oversight' == $flag && 'increase' == $direction) {
449 - return 'request';
450 - } elseif ( 'oversight' == $flag && 'decrease' == $direction) {
451 - return 'unrequest';
452 - }
453 -
454 - // handle resetoversight
455 - if ( 'resetoversight' == $flag) {
456 - return 'decline';
457 - }
458 -
459 - // this is the default - we should never, ever get here, but just in case
460 - return 'flag';
461 - }
462 -
463 - /**
464517 * Gets the version info
465518 *
466519 * @return string the SVN version info
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php
@@ -50,7 +50,7 @@
5151 $this->dieUsage( 'ArticleFeedback is not enabled on this page', 'invalidpage' );
5252 }
5353
54 - $dbr = wfGetDB( DB_SLAVE );
 54+ $dbw = wfGetDB( DB_MASTER );
5555 $pageId = $params['pageid'];
5656 $bucket = $params['bucket'];
5757 $revisionId = $params['revid'];
@@ -97,8 +97,12 @@
9898 return;
9999 }
100100
 101+ // all write actions should be done under the same transaction
 102+ // or counts will be messed up
 103+ $dbw->begin();
 104+
101105 // Save the response data
102 - $ratingIds = $this->saveUserRatings( $userAnswers, $bucket, $params );
 106+ $ratingIds = $this->saveUserRatings( $dbw, $userAnswers, $bucket, $params );
103107 $ctaId = $ratingIds['cta_id'];
104108 $feedbackId = $ratingIds['feedback_id'];
105109 $this->saveUserProperties( $feedbackId );
@@ -107,9 +111,12 @@
108112 // don't bother updating the rollups if this is a different one.
109113 if( $bucket == 1 ) {
110114 $this->updateRollupTables( $pageId, $revisionId, $userAnswers );
111 - $this->updateFilterCounts( $pageId, $userAnswers );
 115+ $this->updateFilterCounts( $dbw, $pageId, $userAnswers );
112116 }
113117
 118+ // at this point we're done doing db writes, if we haven't rolled back, commit
 119+ $dbw->commit();
 120+
114121 // If we have an email address, capture it
115122 if ( $params['email'] ) {
116123 $this->captureEmail ( $params['email'], FormatJson::encode(
@@ -274,24 +281,22 @@
275282 return false;
276283 }
277284
278 - public function updateFilterCounts( $pageId, $answers ) {
279 - $has_comment = false;
 285+ public function updateFilterCounts( $dbw, $pageId, $answers ) {
280286
281 - # Does this record have a comment attached?
282 - # Defined as an answer of type 'text'.
 287+ // a new item should be in all and visible by default, increment those counters
 288+ $filters = array( 'all' => 1, 'visible' => 1, 'notdeleted' => 1);
 289+
 290+ // if this record has a comment attached then increment comment as well
 291+ // notice we do not need to walk the entire array, since any one hit
 292+ // counts - aa_response_text is "comment" in the values
283293 foreach ( $answers as $a ) {
284294 if ( $a['aa_response_text'] !== null ) {
285 - $has_comment = true;
 295+ $filters['comment'] = 1;
 296+ break;
286297 }
287298 }
288299
289 - $filters = array( 'all', 'visible' );
290 - # If the feedbackrecord had a comment, update that filter count.
291 - if ( $has_comment ) {
292 - $filters[] = 'comment';
293 - }
294 -
295 - ApiArticleFeedbackv5Utils::incrementFilterCounts( $pageId, $filters );
 300+ ApiArticleFeedbackv5Utils::updateFilterCounts( $dbw, $pageId, $filters );
296301 }
297302
298303 /**
@@ -558,9 +563,9 @@
559564 * @param int $bucket the bucket id
560565 * @return int the cta id
561566 */
562 - private function saveUserRatings( $data, $bucket, $params ) {
 567+ private function saveUserRatings( $dbw, $data, $bucket, $params ) {
563568 global $wgUser, $wgArticleFeedbackv5LinkBuckets;
564 - $dbw = wfGetDB( DB_MASTER );
 569+
565570 $ctaId = $this->getCTAId( $data, $bucket );
566571 $revId = $params['revid'];
567572 $bucket = $params['bucket'];
@@ -597,8 +602,15 @@
598603 $links = array_flip( array_keys( $wgArticleFeedbackv5LinkBuckets['buckets'] ) );
599604 $linkId = isset( $links[$linkName] ) ? $links[$linkName] : 0;
600605
601 - $dbw->begin();
 606+ $has_comment = false;
 607+ foreach ( $data as $a ) {
 608+ if ( $a['aa_response_text'] !== null ) {
 609+ $has_comment = true;
 610+ break;
 611+ }
 612+ }
602613
 614+
603615 $dbw->insert( 'aft_article_feedback', array(
604616 'af_page_id' => $params['pageid'],
605617 'af_revision_id' => $revId,
@@ -608,6 +620,7 @@
609621 'af_user_anon_token' => $token,
610622 'af_bucket_id' => $bucket,
611623 'af_link_id' => $linkId,
 624+ 'af_has_comment' => $has_comment,
612625 ) );
613626
614627 $feedbackId = $dbw->insertID();
@@ -623,7 +636,6 @@
624637 array( 'af_id' => $feedbackId ),
625638 __METHOD__
626639 );
627 - $dbw->commit();
628640
629641 return array(
630642 'cta_id' => ( $ctaId ? $ctaId : 0 ),
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php
@@ -288,6 +288,9 @@
289289 case 'invisible':
290290 $where[] = 'af_is_hidden IS TRUE';
291291 break;
 292+ case 'unhidden':
 293+ $where[] = 'af_is_unhidden IS TRUE';
 294+ break;
292295 case 'abusive':
293296 $where[] = 'af_abuse_count > 0';
294297 break;
@@ -303,6 +306,12 @@
304307 case 'deleted':
305308 $where[] = 'af_is_deleted IS TRUE';
306309 break;
 310+ case 'undeleted':
 311+ $where[] = 'af_is_undeleted IS TRUE';
 312+ break;
 313+ case 'declined':
 314+ $where[] = 'af_is_declined';
 315+ break;
307316 default:
308317 break;
309318 }
@@ -751,7 +760,11 @@
752761 ApiBase::PARAM_REQUIRED => false,
753762 ApiBase::PARAM_ISMULTI => false,
754763 ApiBase::PARAM_TYPE => array(
755 - 'all', 'notdeleted', 'invisible', 'visible', 'comment', 'id', 'helpful', 'unhelpful', 'abusive', 'deleted', 'needsoversight' )
 764+ 'all', 'notdeleted',
 765+ 'invisible', 'visible', 'unhidden',
 766+ 'comment', 'id',
 767+ 'helpful', 'unhelpful', 'abusive',
 768+ 'deleted', 'undeleted', 'needsoversight', 'declined' )
756769 ),
757770 'filtervalue' => array(
758771 ApiBase::PARAM_REQUIRED => false,
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5Utils.php
@@ -151,40 +151,22 @@
152152 }
153153
154154 /**
155 - * Increments the per-page-per-filter count rollups used on the feedback
156 - * page.
 155+ * Must pass in a useable database handle in a transaction - since all
 156+ * counts MUST be incremented in the same transaction as the data changing
 157+ * or the counts will be off
157158 *
158159 * @param $pageId int the ID of the page (page.page_id)
159 - * @param $filterNames array values are names of filters to increment
 160+ * @param $filters array an array of filter name => direction pairs
 161+ * direction 1 = increment, -1 = decrement
160162 */
161 - public static function incrementFilterCounts( $pageId, $filterNames ) {
162 - ApiArticleFeedbackv5Utils::updateFilterCounts( $pageId, $filterNames, false );
163 - }
 163+ public static function updateFilterCounts( $dbw, $pageId, $filters ) {
164164
165 - /**
166 - * decrements the per-page-per-filter count rollups used on the feedback
167 - * page.
168 - *
169 - * @param $pageId int the ID of the page (page.page_id)
170 - * @param $filterNames array values are names of filters to decrement
171 - */
172 - public static function decrementFilterCounts( $pageId, $filterNames ) {
173 - ApiArticleFeedbackv5Utils::updateFilterCounts( $pageId, $filterNames, true );
174 - }
175 -
176 - public function updateFilterCounts( $pageId, $filters, $decrement ) {
177165 // Don't do anything unless we have filters to process.
178 - if( !$filters ) {
 166+ if( empty( $filters ) || count($filters) < 1 ) {
179167 return;
180168 }
181 - if( !count( $filters ) ) {
182 - return;
183 - }
184169
185 - $dbw = wfGetDB( DB_MASTER );
186 - $dbw->begin();
187 -
188 - foreach ( $filters as $filter ) {
 170+ foreach ( $filters as $filter => $direction) {
189171 $rows[] = array(
190172 'afc_page_id' => $pageId,
191173 'afc_filter_name' => $filter,
@@ -201,9 +183,9 @@
202184 array( 'IGNORE' )
203185 );
204186
205 - $value = $decrement ? 'afc_filter_count - 1' : 'afc_filter_count + 1';
 187+ foreach ( $filters as $filter => $direction) {
 188+ $value = ($direction > 0) ? 'afc_filter_count + 1' : 'afc_filter_count - 1';
206189
207 - foreach ( $filters as $filter ) {
208190 # Update each row with the new count.
209191 $dbw->update(
210192 'aft_article_filter_count',
@@ -216,8 +198,6 @@
217199 );
218200
219201 }
220 -
221 - $dbw->commit();
222202 }
223203
224204 /**
@@ -246,6 +226,10 @@
247227 // to build our permalink, use the feedback entry key
248228 $title = SpecialPage::getTitleFor( 'ArticleFeedbackv5', "$title/$itemId" );
249229
 230+ // Make sure our notes are not too long - we won't error, just hard substr it
 231+ global $wgArticleFeedbackv5MaxActivityNoteLength;
 232+ $notes = substr($notes, 0, $wgArticleFeedbackv5MaxActivityNoteLength);
 233+
250234 $log = new LogPage( 'articlefeedbackv5' );
251235 // comments become the notes section from the feedback
252236 $log->addEntry( $type, $title, $notes );
Index: trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php
@@ -36,17 +36,16 @@
3737 $showHidden = $wgUser->isAllowed( 'aftv5-see-hidden-feedback' );
3838 $showDeleted = $wgUser->isAllowed( 'aftv5-see-deleted-feedback' );
3939
40 - if ( $showHidden ) {
 40+ if ( $showDeleted ) {
4141 array_push( $this->filters,
42 - 'unhelpful', 'abusive', 'invisible'
 42+ 'unhelpful', 'abusive', 'invisible', 'unhidden', 'needsoversight', 'deleted', 'undeleted', 'declined'
4343 );
44 - # removing the 'needsoversight' filter, per Fabrice
 44+ } elseif ( $showHidden ) {
 45+ array_push( $this->filters,
 46+ 'unhelpful', 'abusive', 'invisible', 'unhidden', 'needsoversight', 'undeleted', 'declined'
 47+ );
4548 }
4649
47 - if ( $showDeleted ) {
48 - $this->filters[] = 'deleted';
49 - }
50 -
5150 // NOTE: The 'all' option actually displays different things
5251 // based on the users role, which is handled in the filter:
5352 // - deleter's all is actually everything

Follow-up revisions

RevisionCommit summaryAuthorDate
r112039bug 34090 - fixed issue noted : if $feedback is false return nothing - not th...emsmith20:50, 21 February 2012
r112040r112038: Update ignore messagesraymond20:55, 21 February 2012
r112041bug 34090 - kill the -1 issue by never letting it get below 0emsmith21:08, 21 February 2012
r112115bug 34090 - no code changes, just fixing/adding keyword svn propertiesemsmith16:31, 22 February 2012
r112119bug 34090 - cast the naughty column so it can be signed, the greatest still k...emsmith16:57, 22 February 2012
r112142bug 34090 - toggle for atomic un/helpful changing (and elimination of an extr...emsmith20:37, 22 February 2012
r112147bug 34090 - note to self, watch the copy and paste errors...emsmith21:01, 22 February 2012
r112149bug 34090 - no upper limit, only lower limit - we can't get any worse then 0emsmith21:21, 22 February 2012
r112154bug 34090 - quick and dirty helper script to get missing documentation keysemsmith21:57, 22 February 2012
r112156bug 34090 - only send the activity header if continue < 1, make the more div ...emsmith22:14, 22 February 2012
r112161bug 34090 - fix limit and use old continue to determine if we do the headeremsmith23:15, 22 February 2012
r112218bug 34090 - make sure the name are right for hidden/unhidden logging (argh)emsmith16:44, 23 February 2012
r112225bug 34090 - unhidden and unoversight logic adjustmentsemsmith18:06, 23 February 2012
r112228bug 34090 - fix filter - needsoversight are always autohiddenemsmith19:16, 23 February 2012
r112230bug 34090 - let's try this again - needsoversight and declined will have hidd...emsmith19:38, 23 February 2012
r112232bug 34090 - hide and show shouldn't fiddle with oversight counts or declined ...emsmith19:48, 23 February 2012
r112599bug 34090 - follow up to r111211 - rename things to make them "less confusin...emsmith14:43, 28 February 2012
r112603bug 34090 - Add the logging of automated hide/show errors by the "Article Fee...emsmith15:21, 28 February 2012
r112604bug 34090 - can't believe there were no permissions checks in this - only del...emsmith15:38, 28 February 2012
r112610bug 34090 - change all sql updates to use escaping except for explicitly comm...emsmith16:22, 28 February 2012
r112611bug 34090 - take out implicit show and add returning user that hid/oversighte...emsmith17:02, 28 February 2012
r112627bug 34090 - follow up to r112599 - change to use getText since it's going int...emsmith18:53, 28 February 2012
r112825bug 34090 - insert custom attributes (sigh) for the user and formatted timest...emsmith18:14, 1 March 2012
r112830bug 34090 - follow up to r111474 - use truncate for choppingemsmith19:42, 1 March 2012
r113052bug 34090 - remaining backend feature in requirements, oversight email genera...emsmith18:04, 5 March 2012
r113062bug 34090 - follow up to r110520 1. change index 2. default of null for conti...emsmith18:54, 5 March 2012
r113073bug 34090 - follow up to r111472 part 1 - change to use getDbKey, check for b...emsmith19:48, 5 March 2012
r113082bug 34090 - follow up to r111471 - changed to use text()emsmith20:42, 5 March 2012
r113083bug 34090 - follow up to rr111472 part 2 - only use log_id for orderingemsmith20:48, 5 March 2012
r113104bug 34090 - follow up to rr111472 part 3 - totally redo the continue function...emsmith23:10, 5 March 2012
r113159bug 34090 - follow up to rr111472 part 4 and follow up to r111596 (same issue...emsmith17:37, 6 March 2012
r113160bug 34090 - follow up to rr111472 part 5 plural and number format action countemsmith17:48, 6 March 2012
r113161bug 34090 - follow up to rr111472 part 6 last of lego messagesemsmith17:53, 6 March 2012
r113163bug 34090 - two additional configuration settings (help url and admin user ur...emsmith18:02, 6 March 2012
r113193bug 34090 - followup to r113104 - only sort by timestamp (sorting by log id w...emsmith22:56, 6 March 2012
r113228bug 34090 - followup to r113160emsmith14:05, 7 March 2012
r113247bug 34090 - db issue, remove one of the sorts from the query, use the ids arr...emsmith16:52, 7 March 2012
r113269bug 34090 - followup to r113247emsmith19:01, 7 March 2012
r113273bug 34090 - add javascript level hiding on request oversight IF autohidden is...emsmith19:22, 7 March 2012
r113287bug 34090 - usernames and formatted timestamps into red lines for hidden/over...emsmith20:22, 7 March 2012
r113311bug 34090 - fixing the username bugs - apparently using the data- stuff with ...emsmith22:34, 7 March 2012
r113317bug 34090 - js and css voodoo to make the element with the red lines appear a...emsmith23:01, 7 March 2012
r113370bug 34090 - make different titles for masking appear if it's been hidden or o...emsmith16:43, 8 March 2012
r113371bug 34090 - fixes for oversighter view for hide/oversight panelsemsmith17:51, 8 March 2012
r113383bug 34090 - not entirely necessary, but keeps $2 from showing up in hiders pa...emsmith19:25, 8 March 2012
r113384bug 34090 - fix for double red line issues when hiding an oversighted post ha...emsmith19:28, 8 March 2012
r113390bug 34090 - adding translation for "automatic hider" useremsmith19:44, 8 March 2012
r113392bug 34090 - followup to r113287 - adjusted localization documentationemsmith20:03, 8 March 2012
r113393bug 34090 - followup to r113370 - adjusted localization documentationemsmith20:05, 8 March 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r111211bug 34090 - Added a log namespace and log types for the Article Feedback v5 e...emsmith22:53, 10 February 2012
r111472bug 34090 - Added an additional column in the main feedback table to keep a c...emsmith19:14, 14 February 2012
r111474bug 34090 - remove a todo - take the note from the flag submission and save i...emsmith19:57, 14 February 2012
r111552bug 34090 - split activity notes into their own config for maximum length (th...emsmith16:07, 15 February 2012
r111557bug 34090 - changed structure of the link classes and ids per the following f...emsmith16:47, 15 February 2012
r111570bug 34090 - request oversight is now a counter - so you can request/unrequest...emsmith19:53, 15 February 2012
r111573bug 34090 - removed the "header" portion of the html generation from the acti...emsmith20:18, 15 February 2012
r111645bug 34090 - updated the filter count update script to get requested oversight...emsmith15:45, 16 February 2012

Comments

#Comment by Raymond (talk | contribs)   20:49, 21 February 2012

Please add message documentation for the newly added messages. Thanks.

#Comment by Catrope (talk | contribs)   18:07, 6 March 2012

When this is deployed, the DB fields will need to be added, and the has_comment field will need to be populated.

#Comment by Elizabeth M Smith (talk | contribs)   18:08, 6 March 2012

alter.sql should have the lines needed to make those changes (including the update for the has_comment field)

#Comment by Catrope (talk | contribs)   18:11, 6 March 2012

It does, but it also includes other repopulation things that I don't want to run on the cluster. That comment was a reminder to myself that I need to include those things when I write an alter.sql redux for this deployment.

#Comment by Catrope (talk | contribs)   18:48, 6 March 2012
+ $update[] = "af_abuse_count = LEAST(af_abuse_count + 1, 1)";

Are you sure you meant to use LEAST here, not GREATEST? As written, this will set af_abuse_count to 1 no matter what its previous value is. It looks like this was fixed later.

Status & tagging log