Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql |
— | — | @@ -46,9 +46,21 @@ |
47 | 47 | -- Flag a message as being hidden or being deleted |
48 | 48 | af_is_deleted boolean NOT NULL DEFAULT FALSE, |
49 | 49 | 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, |
50 | 58 | -- Keep track of number of activities (hide/show/flag/unflag) |
51 | 59 | -- should be equivalent to counting rows in logging table |
52 | 60 | 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 |
53 | 65 | ) /*$wgDBTableOptions*/; |
54 | 66 | CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_id, af_user_anon_token, af_id); |
55 | 67 | CREATE INDEX /*i*/af_revision_id ON /*_*/aft_article_feedback (af_revision_id); |
Index: trunk/extensions/ArticleFeedbackv5/sql/alter.sql |
— | — | @@ -127,5 +127,12 @@ |
128 | 128 | CREATE INDEX /*_*/af_net_helpfulness_af_id ON /*_*/aft_article_feedback (af_id, af_net_helpfulness); |
129 | 129 | |
130 | 130 | -- 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; |
131 | 136 | 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 @@ |
2 | 2 | DELETE FROM aft_article_filter_count; |
3 | 3 | |
| 4 | +-- all includes oversighted and hidden |
4 | 5 | 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 |
8 | 14 | 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; |
9 | 17 | |
| 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 |
10 | 26 | 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 |
11 | 35 | 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 @@ |
65 | 65 | 'articlefeedbackv5-special-filter-visible' => 'All visible ($1)', |
66 | 66 | 'articlefeedbackv5-special-filter-invisible' => 'Hidden ($1)', |
67 | 67 | '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)', |
68 | 71 | 'articlefeedbackv5-special-sort-age' => 'Date', |
69 | 72 | 'articlefeedbackv5-special-sort-helpful' => 'Helpful', |
70 | 73 | 'articlefeedbackv5-special-sort-rating' => 'Rating', |
— | — | @@ -342,8 +345,6 @@ |
343 | 346 | |
344 | 347 | /* Activity Pane phrases */ |
345 | 348 | 'articlefeedbackv5-activity-pane-header' => 'Activity Log', |
346 | | - 'articlefeedbackv5-activity-help-item' => '?', |
347 | | - 'articlefeedbackv5-activity-close-item' => 'X', |
348 | 349 | 'articlefeedbackv5-activity-feedback-info' => 'Feedback Post #$1 by', |
349 | 350 | 'articlefeedbackv5-activity-feedback-date' => 'Posted on $1', |
350 | 351 | 'articlefeedbackv5-activity-permalink' => 'permalink', |
— | — | @@ -383,6 +384,29 @@ |
384 | 385 | Best wishes, and thank you, |
385 | 386 | The {{SITENAME}} team', |
386 | 387 | |
| 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 | + |
387 | 411 | ); |
388 | 412 | |
389 | 413 | /** Message documentation (Message documentation) |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiFlagFeedbackArticleFeedbackv5.php |
— | — | @@ -5,6 +5,7 @@ |
6 | 6 | * @package ArticleFeedback |
7 | 7 | * @subpackage Api |
8 | 8 | * @author Greg Chiasson <greg@omniti.com> |
| 9 | + * @author Elizabeth M Smith <elizabeth@omniti.com> |
9 | 10 | */ |
10 | 11 | |
11 | 12 | /** |
— | — | @@ -19,79 +20,259 @@ |
20 | 21 | } |
21 | 22 | |
22 | 23 | /** |
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. |
24 | 31 | */ |
25 | 32 | 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 |
26 | 40 | $params = $this->extractRequestParams(); |
27 | 41 | $pageId = $params['pageid']; |
28 | 42 | $feedbackId = $params['feedbackid']; |
29 | 43 | $flag = $params['flagtype']; |
30 | 44 | $notes = $params['note']; |
31 | 45 | $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; |
37 | 46 | $where = array( 'af_id' => $feedbackId ); |
38 | 47 | |
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(); |
41 | 51 | |
| 52 | + // load feedback record, bail if we don't have one |
| 53 | + $record = $this->fetchRecord( $dbw, $feedbackId ); |
| 54 | + |
42 | 55 | if ( $record === false || !$record->af_id ) { |
43 | 56 | // no-op, because this is already broken |
44 | 57 | $error = 'articlefeedbackv5-invalid-feedback-id'; |
45 | | - } elseif ( in_array( $flag, $flags ) ) { |
46 | 58 | |
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; |
56 | 94 | } |
| 95 | + |
| 96 | + } elseif ( 'hide' == $flag ) { |
| 97 | + |
| 98 | + // increase means "hide this" |
57 | 99 | 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 | + |
59 | 108 | } 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' ); |
61 | 116 | } |
| 117 | + |
62 | 118 | } elseif( 'resetoversight' === $flag) { |
63 | | - // special case, oversight request count becomes 0 |
| 119 | + |
| 120 | + $activity = 'decline'; |
| 121 | + // oversight request count becomes 0 |
64 | 122 | $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 | + } |
65 | 130 | |
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) { |
71 | 132 | |
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. |
75 | 140 | 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 | + } |
82 | 187 | } 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'; |
89 | 190 | } |
| 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 | + |
90 | 270 | } else { |
91 | 271 | $error = 'articlefeedbackv5-invalid-feedback-flag'; |
92 | 272 | } |
93 | 273 | |
94 | | - if ( !$error ) { |
95 | | - $dbw = wfGetDB( DB_MASTER ); |
| 274 | + // we were valid |
| 275 | + if ( !isset($error) ) { |
| 276 | + |
96 | 277 | $success = $dbw->update( |
97 | 278 | 'aft_article_feedback', |
98 | 279 | $update, |
— | — | @@ -99,84 +280,48 @@ |
100 | 281 | __METHOD__ |
101 | 282 | ); |
102 | 283 | |
103 | | - // If the query worked... |
104 | | - if( $success ) { |
| 284 | + // Update the filter count rollups. |
| 285 | + ApiArticleFeedbackv5Utils::updateFilterCounts( $dbw, $pageId, $filters ); |
105 | 286 | |
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 |
108 | 288 | |
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)) { |
114 | 291 | 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 | | - } |
148 | 292 | } |
149 | 293 | |
150 | | - // Conditional formatting for abuse flag |
151 | | - global $wgArticleFeedbackv5AbusiveThreshold, |
152 | | - $wgArticleFeedbackv5HideAbuseThreshold; |
| 294 | + // TODO: handle implicit hide/show logging |
153 | 295 | |
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--; |
162 | 309 | } |
163 | 310 | |
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); |
168 | 314 | |
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. |
175 | 321 | $dbw->update( |
176 | 322 | '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( |
179 | 325 | 'af_id' => $params['feedbackid'], |
180 | | - "af_abuse_count >= ". intval( $wgArticleFeedbackv5HideAbuseThreshold ) |
181 | 326 | ), |
182 | 327 | __METHOD__ |
183 | 328 | ); |
— | — | @@ -198,17 +343,91 @@ |
199 | 344 | ); |
200 | 345 | } |
201 | 346 | |
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( |
205 | 357 | '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'), |
207 | 370 | array( 'af_id' => $id ) |
208 | 371 | ); |
209 | 372 | return $record; |
210 | 373 | } |
211 | 374 | |
212 | 375 | /** |
| 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 | + /** |
213 | 432 | * Gets the allowed parameters |
214 | 433 | * |
215 | 434 | * @return array the params info, indexed by allowed key |
— | — | @@ -229,7 +448,7 @@ |
230 | 449 | ApiBase::PARAM_REQUIRED => true, |
231 | 450 | ApiBase::PARAM_ISMULTI => false, |
232 | 451 | ApiBase::PARAM_TYPE => array( |
233 | | - 'abuse', 'hide', 'helpful', 'unhelpful', 'delete', 'undelete', 'unhide', 'oversight', 'unoversight', 'resetoversight' ) |
| 452 | + 'abuse', 'hide', 'helpful', 'unhelpful', 'delete', 'oversight', 'resetoversight' ) |
234 | 453 | ), |
235 | 454 | 'direction' => array( |
236 | 455 | ApiBase::PARAM_REQUIRED => false, |
— | — | @@ -294,172 +513,6 @@ |
295 | 514 | } |
296 | 515 | |
297 | 516 | /** |
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 | | - /** |
464 | 517 | * Gets the version info |
465 | 518 | * |
466 | 519 | * @return string the SVN version info |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php |
— | — | @@ -50,7 +50,7 @@ |
51 | 51 | $this->dieUsage( 'ArticleFeedback is not enabled on this page', 'invalidpage' ); |
52 | 52 | } |
53 | 53 | |
54 | | - $dbr = wfGetDB( DB_SLAVE ); |
| 54 | + $dbw = wfGetDB( DB_MASTER ); |
55 | 55 | $pageId = $params['pageid']; |
56 | 56 | $bucket = $params['bucket']; |
57 | 57 | $revisionId = $params['revid']; |
— | — | @@ -97,8 +97,12 @@ |
98 | 98 | return; |
99 | 99 | } |
100 | 100 | |
| 101 | + // all write actions should be done under the same transaction |
| 102 | + // or counts will be messed up |
| 103 | + $dbw->begin(); |
| 104 | + |
101 | 105 | // Save the response data |
102 | | - $ratingIds = $this->saveUserRatings( $userAnswers, $bucket, $params ); |
| 106 | + $ratingIds = $this->saveUserRatings( $dbw, $userAnswers, $bucket, $params ); |
103 | 107 | $ctaId = $ratingIds['cta_id']; |
104 | 108 | $feedbackId = $ratingIds['feedback_id']; |
105 | 109 | $this->saveUserProperties( $feedbackId ); |
— | — | @@ -107,9 +111,12 @@ |
108 | 112 | // don't bother updating the rollups if this is a different one. |
109 | 113 | if( $bucket == 1 ) { |
110 | 114 | $this->updateRollupTables( $pageId, $revisionId, $userAnswers ); |
111 | | - $this->updateFilterCounts( $pageId, $userAnswers ); |
| 115 | + $this->updateFilterCounts( $dbw, $pageId, $userAnswers ); |
112 | 116 | } |
113 | 117 | |
| 118 | + // at this point we're done doing db writes, if we haven't rolled back, commit |
| 119 | + $dbw->commit(); |
| 120 | + |
114 | 121 | // If we have an email address, capture it |
115 | 122 | if ( $params['email'] ) { |
116 | 123 | $this->captureEmail ( $params['email'], FormatJson::encode( |
— | — | @@ -274,24 +281,22 @@ |
275 | 282 | return false; |
276 | 283 | } |
277 | 284 | |
278 | | - public function updateFilterCounts( $pageId, $answers ) { |
279 | | - $has_comment = false; |
| 285 | + public function updateFilterCounts( $dbw, $pageId, $answers ) { |
280 | 286 | |
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 |
283 | 293 | foreach ( $answers as $a ) { |
284 | 294 | if ( $a['aa_response_text'] !== null ) { |
285 | | - $has_comment = true; |
| 295 | + $filters['comment'] = 1; |
| 296 | + break; |
286 | 297 | } |
287 | 298 | } |
288 | 299 | |
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 ); |
296 | 301 | } |
297 | 302 | |
298 | 303 | /** |
— | — | @@ -558,9 +563,9 @@ |
559 | 564 | * @param int $bucket the bucket id |
560 | 565 | * @return int the cta id |
561 | 566 | */ |
562 | | - private function saveUserRatings( $data, $bucket, $params ) { |
| 567 | + private function saveUserRatings( $dbw, $data, $bucket, $params ) { |
563 | 568 | global $wgUser, $wgArticleFeedbackv5LinkBuckets; |
564 | | - $dbw = wfGetDB( DB_MASTER ); |
| 569 | + |
565 | 570 | $ctaId = $this->getCTAId( $data, $bucket ); |
566 | 571 | $revId = $params['revid']; |
567 | 572 | $bucket = $params['bucket']; |
— | — | @@ -597,8 +602,15 @@ |
598 | 603 | $links = array_flip( array_keys( $wgArticleFeedbackv5LinkBuckets['buckets'] ) ); |
599 | 604 | $linkId = isset( $links[$linkName] ) ? $links[$linkName] : 0; |
600 | 605 | |
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 | + } |
602 | 613 | |
| 614 | + |
603 | 615 | $dbw->insert( 'aft_article_feedback', array( |
604 | 616 | 'af_page_id' => $params['pageid'], |
605 | 617 | 'af_revision_id' => $revId, |
— | — | @@ -608,6 +620,7 @@ |
609 | 621 | 'af_user_anon_token' => $token, |
610 | 622 | 'af_bucket_id' => $bucket, |
611 | 623 | 'af_link_id' => $linkId, |
| 624 | + 'af_has_comment' => $has_comment, |
612 | 625 | ) ); |
613 | 626 | |
614 | 627 | $feedbackId = $dbw->insertID(); |
— | — | @@ -623,7 +636,6 @@ |
624 | 637 | array( 'af_id' => $feedbackId ), |
625 | 638 | __METHOD__ |
626 | 639 | ); |
627 | | - $dbw->commit(); |
628 | 640 | |
629 | 641 | return array( |
630 | 642 | 'cta_id' => ( $ctaId ? $ctaId : 0 ), |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php |
— | — | @@ -288,6 +288,9 @@ |
289 | 289 | case 'invisible': |
290 | 290 | $where[] = 'af_is_hidden IS TRUE'; |
291 | 291 | break; |
| 292 | + case 'unhidden': |
| 293 | + $where[] = 'af_is_unhidden IS TRUE'; |
| 294 | + break; |
292 | 295 | case 'abusive': |
293 | 296 | $where[] = 'af_abuse_count > 0'; |
294 | 297 | break; |
— | — | @@ -303,6 +306,12 @@ |
304 | 307 | case 'deleted': |
305 | 308 | $where[] = 'af_is_deleted IS TRUE'; |
306 | 309 | break; |
| 310 | + case 'undeleted': |
| 311 | + $where[] = 'af_is_undeleted IS TRUE'; |
| 312 | + break; |
| 313 | + case 'declined': |
| 314 | + $where[] = 'af_is_declined'; |
| 315 | + break; |
307 | 316 | default: |
308 | 317 | break; |
309 | 318 | } |
— | — | @@ -751,7 +760,11 @@ |
752 | 761 | ApiBase::PARAM_REQUIRED => false, |
753 | 762 | ApiBase::PARAM_ISMULTI => false, |
754 | 763 | 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' ) |
756 | 769 | ), |
757 | 770 | 'filtervalue' => array( |
758 | 771 | ApiBase::PARAM_REQUIRED => false, |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5Utils.php |
— | — | @@ -151,40 +151,22 @@ |
152 | 152 | } |
153 | 153 | |
154 | 154 | /** |
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 |
157 | 158 | * |
158 | 159 | * @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 |
160 | 162 | */ |
161 | | - public static function incrementFilterCounts( $pageId, $filterNames ) { |
162 | | - ApiArticleFeedbackv5Utils::updateFilterCounts( $pageId, $filterNames, false ); |
163 | | - } |
| 163 | + public static function updateFilterCounts( $dbw, $pageId, $filters ) { |
164 | 164 | |
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 ) { |
177 | 165 | // Don't do anything unless we have filters to process. |
178 | | - if( !$filters ) { |
| 166 | + if( empty( $filters ) || count($filters) < 1 ) { |
179 | 167 | return; |
180 | 168 | } |
181 | | - if( !count( $filters ) ) { |
182 | | - return; |
183 | | - } |
184 | 169 | |
185 | | - $dbw = wfGetDB( DB_MASTER ); |
186 | | - $dbw->begin(); |
187 | | - |
188 | | - foreach ( $filters as $filter ) { |
| 170 | + foreach ( $filters as $filter => $direction) { |
189 | 171 | $rows[] = array( |
190 | 172 | 'afc_page_id' => $pageId, |
191 | 173 | 'afc_filter_name' => $filter, |
— | — | @@ -201,9 +183,9 @@ |
202 | 184 | array( 'IGNORE' ) |
203 | 185 | ); |
204 | 186 | |
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'; |
206 | 189 | |
207 | | - foreach ( $filters as $filter ) { |
208 | 190 | # Update each row with the new count. |
209 | 191 | $dbw->update( |
210 | 192 | 'aft_article_filter_count', |
— | — | @@ -216,8 +198,6 @@ |
217 | 199 | ); |
218 | 200 | |
219 | 201 | } |
220 | | - |
221 | | - $dbw->commit(); |
222 | 202 | } |
223 | 203 | |
224 | 204 | /** |
— | — | @@ -246,6 +226,10 @@ |
247 | 227 | // to build our permalink, use the feedback entry key |
248 | 228 | $title = SpecialPage::getTitleFor( 'ArticleFeedbackv5', "$title/$itemId" ); |
249 | 229 | |
| 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 | + |
250 | 234 | $log = new LogPage( 'articlefeedbackv5' ); |
251 | 235 | // comments become the notes section from the feedback |
252 | 236 | $log->addEntry( $type, $title, $notes ); |
Index: trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php |
— | — | @@ -36,17 +36,16 @@ |
37 | 37 | $showHidden = $wgUser->isAllowed( 'aftv5-see-hidden-feedback' ); |
38 | 38 | $showDeleted = $wgUser->isAllowed( 'aftv5-see-deleted-feedback' ); |
39 | 39 | |
40 | | - if ( $showHidden ) { |
| 40 | + if ( $showDeleted ) { |
41 | 41 | array_push( $this->filters, |
42 | | - 'unhelpful', 'abusive', 'invisible' |
| 42 | + 'unhelpful', 'abusive', 'invisible', 'unhidden', 'needsoversight', 'deleted', 'undeleted', 'declined' |
43 | 43 | ); |
44 | | - # removing the 'needsoversight' filter, per Fabrice |
| 44 | + } elseif ( $showHidden ) { |
| 45 | + array_push( $this->filters, |
| 46 | + 'unhelpful', 'abusive', 'invisible', 'unhidden', 'needsoversight', 'undeleted', 'declined' |
| 47 | + ); |
45 | 48 | } |
46 | 49 | |
47 | | - if ( $showDeleted ) { |
48 | | - $this->filters[] = 'deleted'; |
49 | | - } |
50 | | - |
51 | 50 | // NOTE: The 'all' option actually displays different things |
52 | 51 | // based on the users role, which is handled in the filter: |
53 | 52 | // - deleter's all is actually everything |