r105448 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105447‎ | r105448 | r105449 >
Date:18:37, 7 December 2011
Author:gregchiasson
Status:resolved (Comments)
Tags:
Comment:
Making long-delayed schema updates to AFTv5, per Roan's feedback in the CodeReview.
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.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)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql
@@ -11,15 +11,15 @@
1212 DROP TABLE IF EXISTS /*_*/aft_article_hits;
1313 DROP TABLE IF EXISTS /*_*/aft_article_feedback_properties;
1414
 15+-- Stores feedback records: "user X submitted feedback on page Y, at time Z"
1516 CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback (
1617 -- Row ID (primary key)
1718 af_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
1819 -- Foreign key to page.page_id
1920 af_page_id integer unsigned NOT NULL,
20 - -- User Id (0 if anon)
 21+ -- User Id (0 if anon), and ip address
2122 af_user_id integer NOT NULL,
22 - -- Username or IP address
23 - af_user_text varbinary(255) NOT NULL,
 23+ af_user_ip varchar(32) NOT NULL,
2424 -- Unique token for anonymous users (to facilitate ratings from multiple users on the same IP)
2525 af_user_anon_token varbinary(32) NOT NULL DEFAULT '',
2626 -- Foreign key to revision.rev_id
@@ -31,49 +31,77 @@
3232 af_cta_id integer unsigned NOT NULL DEFAULT 0,
3333 -- Which link the user clicked on to get to the widget. Default of 0 is "none".
3434 af_link_id integer unsigned NOT NULL DEFAULT 0,
35 - af_created timestamp NULL DEFAULT CURRENT_TIMESTAMP,
36 - af_modified timestamp NULL
 35+ -- Creation timetamp
 36+ af_created binary(14) NOT NULL DEFAULT ''
3737 ) /*$wgDBTableOptions*/;
38 -CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_text, af_user_anon_token, af_id);
 38+CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_id, af_user_anon_token, af_id);
3939 CREATE INDEX /*i*/af_revision_id ON /*_*/aft_article_feedback (af_revision_id);
4040 -- Create an index on the article_feedback.af_timestamp field
4141 CREATE INDEX /*i*/article_feedback_timestamp ON /*_*/aft_article_feedback (af_created);
4242 CREATE INDEX /*i*/af_page_id ON /*_*/aft_article_feedback (af_page_id, af_created);
4343
 44+-- Allows for organizing fields into fieldsets, for reporting or rendering.
 45+-- A group is just a name and an ID.
4446 CREATE TABLE IF NOT EXISTS /*_*/aft_article_field_group (
4547 afg_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
4648 afg_name varchar(255) NOT NULL UNIQUE
4749 ) /*$wgDBTableOptions*/;
4850
 51+-- Stores article fields, zero or more of which are used by each feedback widget
 52+-- We already used af_ as a prefix above, so this is afi_ instead
4953 CREATE TABLE IF NOT EXISTS /*_*/aft_article_field (
5054 afi_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
5155 afi_name varchar(255) NOT NULL,
 56+ -- Allowed data types - relates directly to which aa_response_* field gets
 57+ -- set in aft_article_answer, and where we check for answers when fetching
5258 afi_data_type ENUM('text', 'boolean', 'rating', 'option_id'),
5359 -- FKey to article_field_groups.group_id
5460 afi_group_id integer unsigned NULL,
 61+ -- Which 'bucket' this field should be rendered in.
5562 afi_bucket_id integer unsigned NOT NULL
5663 ) /*$wgDBTableOptions*/;
5764
 65+-- Stores options for multi-value feedback fields (ie, select boxes)
5866 CREATE TABLE IF NOT EXISTS /*_*/aft_article_field_option (
5967 afo_option_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
 68+ -- foreign key to aft_article_field.afi_id
6069 afo_field_id integer unsigned NOT NULL,
6170 afo_name varchar(255) NOT NULL
6271 ) /*$wgDBTableOptions*/;
6372
 73+-- Stores individual answers for each feedback record - for a given feedback
 74+-- record, what did the user answer for each individual question/input on
 75+-- the form with which they were presented.
6476 CREATE TABLE IF NOT EXISTS /*_*/aft_article_answer (
6577 -- FKEY to article_feedback.af_id)
6678 aa_feedback_id integer unsigned NOT NULL,
6779 -- FKEY to article_field.afi_id)
6880 aa_field_id integer unsigned NOT NULL,
 81+ -- Only one of these four columns will be non-null, based on the afi_data_type
 82+ -- of the aa_field_id related to this record.
6983 aa_response_rating integer NULL,
7084 aa_response_text text NULL,
7185 aa_response_boolean boolean NULL,
7286 -- FKey to article_field_options.afo_option_id)
7387 aa_response_option_id integer unsigned NULL,
 88+ -- Only allow one answer per field per feedback ID.
7489 PRIMARY KEY (aa_feedback_id, aa_field_id)
7590 ) /*$wgDBTableOptions*/;
7691
 92+/*
 93+These next four are rollup tables used by the articlefeedback special page.
 94+The revision tables store per-revision numers, as we (in meetings with WMF)
 95+agreed that per-revision numbers could be useful in reporting, though
 96+they aren't currently used on the feedback page. The page-level ones only
 97+count back to wgArticleFeedbackv5RatingLifetime, so they're a rolling window.
 98+
 99+There are tables for ratings and select (ratings includes booleans as well),
 100+because while the vaue of the rating/boolean is important (Rated 3/5), for
 101+selects we only want the count for each input, not the value of that input or
 102+the sum of the values (which will be numerical option_ids, not meaningful
 103+rating values). The queries were sufficiently different that we deemed multiple
 104+tables worthwhile.
 105+*/
77106 CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback_ratings_rollup (
78107 arr_page_id integer unsigned NOT NULL,
79108 arr_rating_id integer unsigned NOT NULL,
@@ -108,7 +136,7 @@
109137 PRIMARY KEY (arfsr_revision_id, arfsr_option_id)
110138 ) /*$wgDBTableOptions*/;
111139
 140+-- Directly taken from AFTv4
112141 CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback_properties (
113142 -- Keys to article_feedback.aa_id
114143 afp_feedback_id integer unsigned NOT NULL,
Index: trunk/extensions/ArticleFeedbackv5/sql/alter.sql
@@ -24,3 +24,9 @@
2525
2626 ALTER TABLE aft_article_feedback ADD COLUMN af_abuse_count integer unsigned NOT NULL DEFAULT 0;
2727 ALTER TABLE aft_article_feedback ADD COLUMN af_hide_count integer unsigned NOT NULL DEFAULT 0;
 28+
 29+ALTER TABLE aft_article_feedback ADD COLUMN af_user_ip varchar(32);
 30+UPDATE aft_article_feedback SET af_user_ip = af_user_text WHERE af_user_text REGEXP '[0-9\.]+';
 31+ALTER TABLE aft_article_feedback DROP COLUMN af_user_text;
 32+ALTER TABLE aft_article_feedback DROP COLUMN af_modified;
 33+ALTER TABLE aft_article_feedback MODIFY COLUMN af_created binary(14) NOT NULL DEFAULT '';
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php
@@ -158,7 +158,6 @@
159159 */
160160 $wgArticleFeedbackv5LearnToEdit = "http://en.wikipedia.org/wiki/Wikipedia:Tutorial";
161161
162 -# TODO: What's up with the surveys, then?
163162 // Would ordinarily call this articlefeedback but survey names are 16 chars max
164163 $wgPrefSwitchSurveys['articlerating'] = array(
165164 'updatable' => false,
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php
@@ -315,6 +315,7 @@
316316 $link = $params['link'];
317317 $token = ApiArticleFeedbackv5Utils::getAnonToken( $params );
318318 $timestamp = $dbw->timestamp();
 319+ $ip = wfGetIP();
319320
320321 # make sure we have a page/user
321322 if ( !$params['pageid'] || !$wgUser) {
@@ -332,7 +333,7 @@
333334 'af_revision_id' => $revId,
334335 'af_created' => $timestamp,
335336 'af_user_id' => $wgUser->getId(),
336 - 'af_user_text' => $wgUser->getName(),
 337+ 'af_user_ip' => $ip,
337338 'af_user_anon_token' => $token,
338339 'af_bucket_id' => $bucket,
339340 'af_link_id' => $link,
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php
@@ -129,18 +129,22 @@
130130
131131 $rows = $dbr->select(
132132 array( 'aft_article_feedback', 'aft_article_answer',
133 - 'aft_article_field', 'aft_article_field_option'
 133+ 'aft_article_field', 'aft_article_field_option',
 134+ 'user'
134135 ),
135136 array( 'af_id', 'af_bucket_id', 'afi_name', 'afo_name',
136137 'aa_response_text', 'aa_response_boolean',
137138 'aa_response_rating', 'aa_response_option_id',
138 - 'afi_data_type', 'af_created', 'af_user_text',
139 - 'af_hide_count', 'af_abuse_count'
 139+ 'afi_data_type', 'af_created', 'user_name',
 140+ 'af_user_ip', 'af_hide_count', 'af_abuse_count'
140141 ),
141142 array( 'af_id' => $ids ),
142143 __METHOD__,
143144 array( 'ORDER BY' => $order ),
144145 array(
 146+ 'user' => array(
 147+ 'LEFT JOIN', 'user_id = af_user_id'
 148+ ),
145149 'aft_article_field' => array(
146150 'LEFT JOIN', 'afi_id = aa_field_id'
147151 ),
@@ -154,20 +158,21 @@
155159 )
156160 );
157161
158 - foreach($rows as $row) {
159 - if(!array_key_exists($row->af_id, $rv)) {
160 - $rv[$row->af_id] = array();
 162+ foreach( $rows as $row ) {
 163+ if( !array_key_exists( $row->af_id, $rv ) ) {
 164+ $rv[$row->af_id] = array();
161165 $rv[$row->af_id][0] = $row;
 166+ $rv[$row->af_id][0]->user_name = $row->user_name ? $row->user_name : $row->af_user_ip;
162167 }
163168 $rv[$row->af_id][$row->afi_name] = $row;
164169 }
165 -
 170+
166171 return $rv;
167172 }
168173
169174 private function getFilterCriteria( $filter ) {
170175 $where = array();
171 - switch($filter) {
 176+ switch( $filter ) {
172177 case 'all':
173178 $where = array();
174179 break;
@@ -208,7 +213,7 @@
209214 }
210215
211216 private function renderBucket1( $record ) {
212 - $name = $record[0]->af_user_text;
 217+ $name = $record[0]->user_name;
213218 if( $record['found']->aa_response_boolean ) {
214219 $found = wfMsg(
215220 'articlefeedbackv5-form1-header-found',
@@ -227,7 +232,7 @@
228233 }
229234
230235 private function renderBucket2( $record ) {
231 - $name = $record[0]->af_user_text;
 236+ $name = $record[0]->user_name;
232237 $type = $record['tag']->afo_name;
233238 return wfMsg( 'articlefeedbackv5-form2-header', $name, $type )
234239 .'<blockquote>'.$record['comment']->aa_response_text
@@ -235,7 +240,7 @@
236241 }
237242
238243 private function renderBucket3( $record ) {
239 - $name = $record[0]->af_user_text;
 244+ $name = $record[0]->user_name;
240245 $rating = $record['rating']->aa_response_rating;
241246 return wfMsg( 'articlefeedbackv5-form3-header', $name, $rating )
242247 .'<blockquote>'.$record['comment']->aa_response_text
@@ -247,8 +252,8 @@
248253 }
249254
250255 private function renderBucket5( $record ) {
251 - $name = $record[0]->af_user_text;
252 - $rv = wfMsg( 'articlefeedbackv5-form5-header', $name );
 256+ $name = $record[0]->user_name;
 257+ $rv = wfMsg( 'articlefeedbackv5-form5-header', $name );
253258 $rv .= '<ul>';
254259 foreach( $record as $key => $answer ) {
255260 if( $answer->afi_data_type == 'rating' && $key != '0' ) {

Follow-up revisions

RevisionCommit summaryAuthorDate
r105901AFTv5 - fix a privacy issue introduced by r105448 - apparently we only want t...gregchiasson16:32, 12 December 2011

Comments

#Comment by Catrope (talk | contribs)   15:55, 12 December 2011
-			'af_user_text'       => $wgUser->getName(),
+			'af_user_ip'         => $ip,

This means you're putting the user's IP address in the table unconditionally, even if the user is logged in. Please don't do this. We're not completely against tracking this information, but the IP address of logged-in users is considered private information that we don't share with the outside world. By storing it in the af_ table you're 'tainting' it so it can't be made available to the public without being censored. I suggest you just don't store this information (and set user_ip to NULL if user_id != 0) so as to make publishing the data easier.

OK otherwise. Marking fixme for the privacy issue.

Status & tagging log