https://www.mediawiki.org/wiki/Special:Code/MediaWiki/105448
Revision: 105448 Author: gregchiasson Date: 2011-12-07 18:37:05 +0000 (Wed, 07 Dec 2011) Log Message: ----------- Making long-delayed schema updates to AFTv5, per Roan's feedback in the CodeReview. Modified Paths: -------------- trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql trunk/extensions/ArticleFeedbackv5/sql/alter.sql Modified: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php =================================================================== --- trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php 2011-12-07 18:29:02 UTC (rev 105447) +++ trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php 2011-12-07 18:37:05 UTC (rev 105448) @@ -158,7 +158,6 @@ */ $wgArticleFeedbackv5LearnToEdit = "http://en.wikipedia.org/wiki/Wikipedia:Tutorial"; -# TODO: What's up with the surveys, then? // Would ordinarily call this articlefeedback but survey names are 16 chars max $wgPrefSwitchSurveys['articlerating'] = array( 'updatable' => false, Modified: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php =================================================================== --- trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php 2011-12-07 18:29:02 UTC (rev 105447) +++ trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php 2011-12-07 18:37:05 UTC (rev 105448) @@ -315,6 +315,7 @@ $link = $params['link']; $token = ApiArticleFeedbackv5Utils::getAnonToken( $params ); $timestamp = $dbw->timestamp(); + $ip = wfGetIP(); # make sure we have a page/user if ( !$params['pageid'] || !$wgUser) { @@ -332,7 +333,7 @@ 'af_revision_id' => $revId, 'af_created' => $timestamp, 'af_user_id' => $wgUser->getId(), - 'af_user_text' => $wgUser->getName(), + 'af_user_ip' => $ip, 'af_user_anon_token' => $token, 'af_bucket_id' => $bucket, 'af_link_id' => $link, Modified: trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php =================================================================== --- trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php 2011-12-07 18:29:02 UTC (rev 105447) +++ trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php 2011-12-07 18:37:05 UTC (rev 105448) @@ -129,18 +129,22 @@ $rows = $dbr->select( array( 'aft_article_feedback', 'aft_article_answer', - 'aft_article_field', 'aft_article_field_option' + 'aft_article_field', 'aft_article_field_option', + 'user' ), array( 'af_id', 'af_bucket_id', 'afi_name', 'afo_name', 'aa_response_text', 'aa_response_boolean', 'aa_response_rating', 'aa_response_option_id', - 'afi_data_type', 'af_created', 'af_user_text', - 'af_hide_count', 'af_abuse_count' + 'afi_data_type', 'af_created', 'user_name', + 'af_user_ip', 'af_hide_count', 'af_abuse_count' ), array( 'af_id' => $ids ), __METHOD__, array( 'ORDER BY' => $order ), array( + 'user' => array( + 'LEFT JOIN', 'user_id = af_user_id' + ), 'aft_article_field' => array( 'LEFT JOIN', 'afi_id = aa_field_id' ), @@ -154,20 +158,21 @@ ) ); - foreach($rows as $row) { - if(!array_key_exists($row->af_id, $rv)) { - $rv[$row->af_id] = array(); + foreach( $rows as $row ) { + if( !array_key_exists( $row->af_id, $rv ) ) { + $rv[$row->af_id] = array(); $rv[$row->af_id][0] = $row; + $rv[$row->af_id][0]->user_name = $row->user_name ? $row->user_name : $row->af_user_ip; } $rv[$row->af_id][$row->afi_name] = $row; } - + return $rv; } private function getFilterCriteria( $filter ) { $where = array(); - switch($filter) { + switch( $filter ) { case 'all': $where = array(); break; @@ -208,7 +213,7 @@ } private function renderBucket1( $record ) { - $name = $record[0]->af_user_text; + $name = $record[0]->user_name; if( $record['found']->aa_response_boolean ) { $found = wfMsg( 'articlefeedbackv5-form1-header-found', @@ -227,7 +232,7 @@ } private function renderBucket2( $record ) { - $name = $record[0]->af_user_text; + $name = $record[0]->user_name; $type = $record['tag']->afo_name; return wfMsg( 'articlefeedbackv5-form2-header', $name, $type ) .'<blockquote>'.$record['comment']->aa_response_text @@ -235,7 +240,7 @@ } private function renderBucket3( $record ) { - $name = $record[0]->af_user_text; + $name = $record[0]->user_name; $rating = $record['rating']->aa_response_rating; return wfMsg( 'articlefeedbackv5-form3-header', $name, $rating ) .'<blockquote>'.$record['comment']->aa_response_text @@ -247,8 +252,8 @@ } private function renderBucket5( $record ) { - $name = $record[0]->af_user_text; - $rv = wfMsg( 'articlefeedbackv5-form5-header', $name ); + $name = $record[0]->user_name; + $rv = wfMsg( 'articlefeedbackv5-form5-header', $name ); $rv .= '<ul>'; foreach( $record as $key => $answer ) { if( $answer->afi_data_type == 'rating' && $key != '0' ) { Modified: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql =================================================================== --- trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql 2011-12-07 18:29:02 UTC (rev 105447) +++ trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql 2011-12-07 18:37:05 UTC (rev 105448) @@ -11,15 +11,15 @@ DROP TABLE IF EXISTS /*_*/aft_article_hits; DROP TABLE IF EXISTS /*_*/aft_article_feedback_properties; +-- Stores feedback records: "user X submitted feedback on page Y, at time Z" CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback ( -- Row ID (primary key) af_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Foreign key to page.page_id af_page_id integer unsigned NOT NULL, - -- User Id (0 if anon) + -- User Id (0 if anon), and ip address af_user_id integer NOT NULL, - -- Username or IP address - af_user_text varbinary(255) NOT NULL, + af_user_ip varchar(32) NOT NULL, -- Unique token for anonymous users (to facilitate ratings from multiple users on the same IP) af_user_anon_token varbinary(32) NOT NULL DEFAULT '', -- Foreign key to revision.rev_id @@ -31,49 +31,77 @@ af_cta_id integer unsigned NOT NULL DEFAULT 0, -- Which link the user clicked on to get to the widget. Default of 0 is "none". af_link_id integer unsigned NOT NULL DEFAULT 0, - af_created timestamp NULL DEFAULT CURRENT_TIMESTAMP, - af_modified timestamp NULL + -- Creation timetamp + af_created binary(14) NOT NULL DEFAULT '' ) /*$wgDBTableOptions*/; -CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_text, af_user_anon_token, af_id); +CREATE INDEX /*i*/af_page_user_token_id ON /*_*/aft_article_feedback (af_page_id, af_user_id, af_user_anon_token, af_id); CREATE INDEX /*i*/af_revision_id ON /*_*/aft_article_feedback (af_revision_id); -- Create an index on the article_feedback.af_timestamp field CREATE INDEX /*i*/article_feedback_timestamp ON /*_*/aft_article_feedback (af_created); CREATE INDEX /*i*/af_page_id ON /*_*/aft_article_feedback (af_page_id, af_created); +-- Allows for organizing fields into fieldsets, for reporting or rendering. +-- A group is just a name and an ID. CREATE TABLE IF NOT EXISTS /*_*/aft_article_field_group ( afg_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, afg_name varchar(255) NOT NULL UNIQUE ) /*$wgDBTableOptions*/; --- We already used af_ above, so this is ArticleFIeld instead +-- Stores article fields, zero or more of which are used by each feedback widget +-- We already used af_ as a prefix above, so this is afi_ instead CREATE TABLE IF NOT EXISTS /*_*/aft_article_field ( afi_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, afi_name varchar(255) NOT NULL, + -- Allowed data types - relates directly to which aa_response_* field gets + -- set in aft_article_answer, and where we check for answers when fetching afi_data_type ENUM('text', 'boolean', 'rating', 'option_id'), -- FKey to article_field_groups.group_id afi_group_id integer unsigned NULL, + -- Which 'bucket' this field should be rendered in. afi_bucket_id integer unsigned NOT NULL ) /*$wgDBTableOptions*/; +-- Stores options for multi-value feedback fields (ie, select boxes) CREATE TABLE IF NOT EXISTS /*_*/aft_article_field_option ( afo_option_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + -- foreign key to aft_article_field.afi_id afo_field_id integer unsigned NOT NULL, afo_name varchar(255) NOT NULL ) /*$wgDBTableOptions*/; +-- Stores individual answers for each feedback record - for a given feedback +-- record, what did the user answer for each individual question/input on +-- the form with which they were presented. CREATE TABLE IF NOT EXISTS /*_*/aft_article_answer ( -- FKEY to article_feedback.af_id) aa_feedback_id integer unsigned NOT NULL, -- FKEY to article_field.afi_id) aa_field_id integer unsigned NOT NULL, + -- Only one of these four columns will be non-null, based on the afi_data_type + -- of the aa_field_id related to this record. aa_response_rating integer NULL, aa_response_text text NULL, aa_response_boolean boolean NULL, -- FKey to article_field_options.afo_option_id) aa_response_option_id integer unsigned NULL, + -- Only allow one answer per field per feedback ID. PRIMARY KEY (aa_feedback_id, aa_field_id) ) /*$wgDBTableOptions*/; +/* +These next four are rollup tables used by the articlefeedback special page. +The revision tables store per-revision numers, as we (in meetings with WMF) +agreed that per-revision numbers could be useful in reporting, though +they aren't currently used on the feedback page. The page-level ones only +count back to wgArticleFeedbackv5RatingLifetime, so they're a rolling window. + +There are tables for ratings and select (ratings includes booleans as well), +because while the vaue of the rating/boolean is important (Rated 3/5), for +selects we only want the count for each input, not the value of that input or +the sum of the values (which will be numerical option_ids, not meaningful +rating values). The queries were sufficiently different that we deemed multiple +tables worthwhile. +*/ CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback_ratings_rollup ( arr_page_id integer unsigned NOT NULL, arr_rating_id integer unsigned NOT NULL, @@ -108,7 +136,7 @@ PRIMARY KEY (arfsr_revision_id, arfsr_option_id) ) /*$wgDBTableOptions*/; --- Mostly taken from AFTv4 +-- Directly taken from AFTv4 CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback_properties ( -- Keys to article_feedback.aa_id afp_feedback_id integer unsigned NOT NULL, Modified: trunk/extensions/ArticleFeedbackv5/sql/alter.sql =================================================================== --- trunk/extensions/ArticleFeedbackv5/sql/alter.sql 2011-12-07 18:29:02 UTC (rev 105447) +++ trunk/extensions/ArticleFeedbackv5/sql/alter.sql 2011-12-07 18:37:05 UTC (rev 105448) @@ -24,3 +24,9 @@ ALTER TABLE aft_article_feedback ADD COLUMN af_abuse_count integer unsigned NOT NULL DEFAULT 0; ALTER TABLE aft_article_feedback ADD COLUMN af_hide_count integer unsigned NOT NULL DEFAULT 0; + +ALTER TABLE aft_article_feedback ADD COLUMN af_user_ip varchar(32); +UPDATE aft_article_feedback SET af_user_ip = af_user_text WHERE af_user_text REGEXP '[0-9\.]+'; +ALTER TABLE aft_article_feedback DROP COLUMN af_user_text; +ALTER TABLE aft_article_feedback DROP COLUMN af_modified; +ALTER TABLE aft_article_feedback MODIFY COLUMN af_created binary(14) NOT NULL DEFAULT ''; _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs