r104595 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r104594‎ | r104595 | r104596 >
Date:21:26, 29 November 2011
Author:gregchiasson
Status:deferred
Tags:
Comment:
JS and API for first cut of AFTv5 Feedback page. Changes to rollups, with goal of getting select/option rollups in place soonish, but committing now per PM.
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.css (added) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js (added) (history)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.css
@@ -0,0 +1,2 @@
 2+/* css here */
 3+div.aft5-feedback { border:1px solid red; }
Property changes on: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.css
___________________________________________________________________
Added: svn:eol-style
14 + native
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js
@@ -0,0 +1,70 @@
 2+( function ( $ ) {
 3+ $.articleFeedbackv5special = {};
 4+
 5+ // TODO: Pass this in from the PHP side. Add it to mwConfig or w/e?
 6+ //$.articleFeedbackv5special.page = mw.config.get( 'wgPageId' );
 7+ $.articleFeedbackv5special.page = 0;
 8+console.log('oage id is ' + hackPageId);
 9+ $.articleFeedbackv5special.filter = 'visible';
 10+ $.articleFeedbackv5special.sort = 'newest';
 11+ $.articleFeedbackv5special.limit = 5;
 12+ $.articleFeedbackv5special.offset = 0;
 13+
 14+ $.articleFeedbackv5special.apiUrl = mw.config.get( 'wgScriptPath' )
 15+ + '/api.php';
 16+
 17+
 18+ $.articleFeedbackv5special.setBinds = function() {
 19+ $( '#aft5-filter' ).bind( 'change', function(e) {
 20+ $.articleFeedbackv5special.filter = $(this).val();
 21+ $.articleFeedbackv5special.loadFeedback();
 22+ return false;
 23+ } );
 24+ $( '#aft5-sort' ).bind( 'change', function(e) {
 25+ $.articleFeedbackv5special.sort = $(this).val();
 26+ $.articleFeedbackv5special.loadFeedback();
 27+ return false;
 28+ } );
 29+ $( '#aft5-more' ).bind( 'click', function(e) {
 30+ $.articleFeedbackv5special.offset +=
 31+ $.articleFeedbackv5special.limit;
 32+ $.articleFeedbackv5special.loadFeedback();
 33+ return false;
 34+ } );
 35+ // TODO: need to handle: upvote, downvote, hide, flag as abuse
 36+ // PROTIP use 'live' instead of 'bind' because dynamic loading.
 37+ }
 38+
 39+ $.articleFeedbackv5special.loadFeedback = function () {
 40+
 41+ $.ajax( {
 42+ 'url' : $.articleFeedbackv5special.apiUrl,
 43+ 'type' : 'GET',
 44+ 'dataType': 'json',
 45+ 'data' : {
 46+ 'afpageid': $.articleFeedbackv5special.page,
 47+ 'affilter': $.articleFeedbackv5special.filter,
 48+ 'afsort' : $.articleFeedbackv5special.sort,
 49+ 'aflimit' : $.articleFeedbackv5special.limit,
 50+ 'afoffset': $.articleFeedbackv5special.offset,
 51+ 'action' : 'query',
 52+ 'format' : 'json',
 53+ 'list' : 'articlefeedbackv5-view-feedback',
 54+ 'maxage' : 0,
 55+ },
 56+ 'success': function ( data ) {
 57+ // TODO check output and error if needed
 58+ $( '#aft5-show-feedback' ).html(
 59+$( '#aft5-show-feedback' ).html() + data.query['articlefeedbackv5-view-feedback'].feedback
 60+ );
 61+ }
 62+ // TODO have a callback for failures.
 63+ } );
 64+ return false;
 65+ }
 66+} )( jQuery );
 67+
 68+$( document ).ready( function() {
 69+ $.articleFeedbackv5special.setBinds();
 70+ $.articleFeedbackv5special.loadFeedback();
 71+} );
Property changes on: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js
___________________________________________________________________
Added: svn:eol-style
172 + native
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php
@@ -187,13 +187,14 @@
188188
189189 // Autoloading
190190 $dir = dirname( __FILE__ ) . '/';
191 -$wgAutoloadClasses['ApiArticleFeedbackv5Utils'] = $dir . 'api/ApiArticleFeedbackv5Utils.php';
192 -$wgAutoloadClasses['ApiArticleFeedbackv5'] = $dir . 'api/ApiArticleFeedbackv5.php';
193 -$wgAutoloadClasses['ApiViewRatingsArticleFeedbackv5'] = $dir . 'api/ApiViewRatingsArticleFeedbackv5.php';
194 -$wgAutoloadClasses['ArticleFeedbackv5Hooks'] = $dir . 'ArticleFeedbackv5.hooks.php';
195 -$wgAutoloadClasses['SpecialArticleFeedbackv5'] = $dir . 'SpecialArticleFeedbackv5.php';
196 -$wgExtensionMessagesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.i18n.php';
197 -$wgExtensionAliasesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.alias.php';
 191+$wgAutoloadClasses['ApiArticleFeedbackv5Utils'] = $dir . 'api/ApiArticleFeedbackv5Utils.php';
 192+$wgAutoloadClasses['ApiArticleFeedbackv5'] = $dir . 'api/ApiArticleFeedbackv5.php';
 193+$wgAutoloadClasses['ApiViewRatingsArticleFeedbackv5'] = $dir . 'api/ApiViewRatingsArticleFeedbackv5.php';
 194+$wgAutoloadClasses['ApiViewFeedbackArticleFeedbackv5'] = $dir . 'api/ApiViewFeedbackArticleFeedbackv5.php';
 195+$wgAutoloadClasses['ArticleFeedbackv5Hooks'] = $dir . 'ArticleFeedbackv5.hooks.php';
 196+$wgAutoloadClasses['SpecialArticleFeedbackv5'] = $dir . 'SpecialArticleFeedbackv5.php';
 197+$wgExtensionMessagesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.i18n.php';
 198+$wgExtensionAliasesFiles['ArticleFeedbackv5'] = $dir . 'ArticleFeedbackv5.alias.php';
198199
199200 // Hooks
200201 $wgHooks['LoadExtensionSchemaUpdates'][] = 'ArticleFeedbackv5Hooks::loadExtensionSchemaUpdates';
@@ -207,10 +208,10 @@
208209 $wgHooks['ArticleSaveComplete'][] = 'ArticleFeedbackv5Hooks::trackEdit';
209210
210211 // API Registration
211 -$wgAPIListModules['articlefeedbackv5-view-ratings'] = 'ApiViewRatingsArticleFeedbackv5';
212 -$wgAPIModules['articlefeedbackv5'] = 'ApiArticleFeedbackv5';
 212+$wgAPIListModules['articlefeedbackv5-view-ratings'] = 'ApiViewRatingsArticleFeedbackv5';
 213+$wgAPIListModules['articlefeedbackv5-view-feedback'] = 'ApiViewFeedbackArticleFeedbackv5';
 214+$wgAPIModules['articlefeedbackv5'] = 'ApiArticleFeedbackv5';
213215
214216 // Special Page
215217 $wgSpecialPages['ArticleFeedbackv5'] = 'SpecialArticleFeedbackv5';
216218 $wgSpecialPageGroups['ArticleFeedbackv5'] = 'other';
217 -
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php
@@ -143,7 +143,6 @@
144144 * @param $revision int the revision id
145145 */
146146 public function updateRollupTables( $page, $revision ) {
147 -# Select rollup doesn't work yet
148147 # foreach( array( 'rating', 'boolean', 'select' ) as $type ) {
149148 foreach( array( 'rating', 'boolean' ) as $type ) {
150149 $this->updateRollup( $page, $revision, $type );
@@ -158,19 +157,40 @@
159158 * @param $type string the type (rating, select, or boolean)
160159 */
161160 private function updateRollup($pageId, $revId, $type) {
162 - global $wgArticleFeedbackv5RatingLifetime;
163 - $dbr = wfGetDB( DB_SLAVE );
164 - $dbw = wfGetDB( DB_MASTER );
165 - $limit = ApiArticleFeedbackv5Utils::getRevisionLimit( $pageId );
166 -
167161 # sanity check
168162 if ( $type != 'rating' && $type != 'select' && $type != 'boolean' ) {
169163 return 0;
170164 }
171165
 166+ global $wgArticleFeedbackv5RatingLifetime;
 167+ $dbr = wfGetDB( DB_SLAVE );
 168+ $dbw = wfGetDB( DB_MASTER );
 169+ $limit = ApiArticleFeedbackv5Utils::getRevisionLimit( $pageId );
 170+ $page_data = array();
 171+ $rev_data = array();
 172+ $rev_table = 'aft_article_revision_feedback_'
 173+ . ( $type == 'select' ? 'select' : 'ratings' )
 174+ . '_rollup';
 175+ $page_table = 'aft_article_feedback_'
 176+ . ( $type == 'select' ? 'select' : 'ratings' )
 177+ . '_rollup';
 178+
 179+ if ( $type == 'select' ) {
 180+ $page_prefix = 'afsr_';
 181+ $rev_prefix = 'arfsr_';
 182+ $select = array( 'aa_field_id', 'aa_response_option_id', 'COUNT(aa_response_option_id) AS earned' );
 183+ $group = array( 'GROUP BY' => 'aa_response_option_id' );
 184+ } else {
 185+ $page_prefix = 'arr_';
 186+ $rev_prefix = 'afrr_';
 187+ $select = array( 'aa_field_id', "SUM(aa_response_$type) AS earned", 'COUNT(*) AS submits' );
 188+ $group = array( 'GROUP BY' => 'aa_field_id' );
 189+
 190+ }
 191+
172192 $rows = $dbr->select(
173193 array( 'aft_article_answer', 'aft_article_feedback', 'aft_article_field' ),
174 - array( 'aa_field_id', "SUM(aa_response_$type) AS earned", 'COUNT(*) AS submits' ),
 194+ $select,
175195 array(
176196 'afi_data_type' => $type,
177197 'af_page_id' => $pageId,
@@ -179,24 +199,9 @@
180200 "af_revision_id >= $limit",
181201 ),
182202 __METHOD__,
183 - array( 'GROUP BY' => 'aa_field_id' )
 203+ $group
184204 );
185205
186 - if ( $type == 'select' ) {
187 - $page_prefix = 'afsr_';
188 - $rev_prefix = 'arfsr_';
189 - } else {
190 - $page_prefix = 'arr_';
191 - $rev_prefix = 'afrr_';
192 - }
193 - $page_data = array();
194 - $rev_data = array();
195 - $rev_table = 'aft_article_revision_feedback_'
196 - . ( $type == 'select' ? 'select' : 'ratings' )
197 - . '_rollup';
198 - $page_table = 'aft_article_feedback_'
199 - . ( $type == 'select' ? 'select' : 'ratings' )
200 - . '_rollup';
201206
202207 foreach ( $rows as $row ) {
203208 if ( !array_key_exists( $row->aa_field_id, $page_data ) ) {
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewRatingsArticleFeedbackv5.php
@@ -98,7 +98,7 @@
9999 }
100100 $where[$prefix . '_page_id'] = $pageId;
101101 $where[] = $prefix . '_rating_id = afi_id';
102 - $where['afi_bucket_id'] = 5; // TODO: Pass this in
 102+# $where['afi_bucket_id'] = 5; // TODO: Pass this in
103103
104104 $rows = $dbr->select(
105105 array( 'aft_' . $table, 'aft_article_field' ),
Index: trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php
@@ -1,564 +1,109 @@
22 <?php
3 -/**
4 - * SpecialPage for ArticleFeedback extension
5 - *
6 - * @file
7 - * @ingroup Extensions
8 - */
9 -
103 class SpecialArticleFeedbackv5 extends SpecialPage {
 4+ private $api;
115
12 - /* Methods */
13 -
146 public function __construct() {
15 - parent::__construct( 'ArticleFeedback' );
 7+ parent::__construct( 'ArticleFeedbackv5' );
168 }
179
18 - public function execute( $par ) {
19 - global $wgOut, $wgLang, $wgArticleFeedbackDashboard, $wgArticleFeedbackDashboardTalkPage;
20 -
21 - $wgOut->addModules( 'ext.articleFeedback.dashboard' );
22 - $this->setHeaders();
23 - if ( $wgArticleFeedbackDashboard ) {
24 - // fetch the highest and lowest rated articles
25 - $highs_lows = $this->getDailyHighsAndLows();
26 -
27 - // determine the highest rated articles
28 - $highs = $this->getDailyHighs( $highs_lows );
29 -
30 - // .. and the lowest rated articles
31 - $lows = $this->getDailyLows( $highs_lows );
32 -
33 - // provide some messaging above high/low tables
34 - $wgOut->addWikiMsg( 'articleFeedback-copy-above-highlow-tables', $wgArticleFeedbackDashboardTalkPage );
35 -
36 - //render daily highs table
37 - $this->renderDailyHighsAndLows( $highs, wfMsg( 'articleFeedback-table-caption-dailyhighs', $wgLang->date( time() )));
38 -
39 - //render daily lows table
40 - $this->renderDailyHighsAndLows( $lows, wfMsg( 'articleFeedback-table-caption-dailylows', $wgLang->date( time() )));
41 -
42 - /*
43 - This functionality does not exist yet.
44 - $this->renderWeeklyMostChanged();*/
45 - $this->renderProblems();
46 -
47 - $wgOut->addWikiMsg( 'articlefeedback-dashboard-bottom' );
48 - } else {
49 - $wgOut->addWikiText( 'This page has been disabled.' );
50 - }
51 - }
52 -
53 - /* Protected Methods */
54 -
55 - /**
56 - * Returns an HTML table containing data from a given two dimensional array.
57 - *
58 - * @param $headings Array: List of rows, each a list of column data (values will be escaped)
59 - * @param $rows Array: List of rows, each a list of either calss/column data pairs (values will
60 - * be escaped), or arrays containing attr, text and html fields, used to set attributes, text or
61 - * HTML content of the cell
62 - * @param $attribs Array: List of HTML attributes to apply to the table
63 - * @return String: HTML table code
64 - */
65 - protected function renderTable( $caption, array $headings, array $rows, $id = null ) {
 10+ public function execute( $title ) {
6611 global $wgOut;
 12+ $pageId = $this->pageIdFromTitle( $title );
6713
68 - $table = Html::openElement( 'table', array(
69 - 'class' => 'articleFeedback-table sortable', 'id' => $id
70 - ) );
71 - // Caption
72 - $table .= Html::element( 'caption', array(), $caption );
73 - // Head
74 - $table .= Html::openElement( 'thead' );
75 - $table .= Html::openElement( 'tr' );
76 - foreach ( $headings as $heading ) {
77 - $table .= Html::element( 'th', array(), $heading );
 14+ if( !$pageId ) {
 15+ # Probably this is bad.
 16+ print "That ain't no good kind of page.";
 17+ die();
7818 }
79 - $table .= Html::closeElement( 'tr' );
80 - $table .= Html::closeElement( 'thead' );
81 - // Body
82 - $table .= Html::openElement( 'tbody' );
83 - foreach ( $rows as $row ) {
84 - $table .= Html::openElement( 'tr' );
85 - foreach ( $row as $column ) {
86 - $attr = array();
87 - if ( is_array( $column ) ) {
88 - if ( isset( $column['attr'] ) && is_array( $column['attr'] ) ) {
89 - $attr = $column['attr'];
90 - }
91 - if ( isset( $column['text'] ) ) {
92 - $table .= Html::element( 'td', $attr, $column['text'] );
93 - } elseif ( isset( $column['html'] ) ) {
94 - $table .= Html::rawElement( 'td', $attr, $column['html'] );
95 - } else {
96 - $table .= Html::element( 'td', $attr );
97 - }
98 - } else {
99 - $table .= Html::rawElement( 'td', $attr, $column );
100 - }
101 - }
102 - $table .= Html::closeElement( 'tr' );
103 - }
104 - $table .= Html::closeElement( 'tbody' );
105 - $table .= Html::closeElement( 'table' );
106 - $wgOut->addHtml( $table );
107 - }
10819
109 - /**
110 - * Renders daily highs and lows
111 - *
112 - * @return String: HTML table of daily highs and lows
113 - */
114 - protected function renderDailyHighsAndLows( $pages, $caption ) {
115 - global $wgUser;
 20+ $wgOut->setPagetitle( "Feedback for $title" );
 21+# $wgOut->addModules( 'jquery.articleFeedbackv5.special' );
11622
117 - // Pre-fill page ID cache
118 - $ids = array();
119 - foreach ( $pages as $page ) {
120 - $ids[] = $page['page'];
121 - }
122 - self::populateTitleCache( $ids );
123 -
124 - $categories = self::getCategories();
 23+ $this->api = $this->getApi();
 24+ $output = '';
 25+ $ratings = $this->api->fetchOverallRating( $pageId );
 26+ $found = $ratings['found'];
 27+ $rating = $ratings['rating'];
12528
126 - $rows = array();
127 - if ( $pages ) {
128 - foreach ( $pages as $page ) {
129 - $row = array();
130 - $pageTitle = self::getTitleFromID( $page['page'] );
131 - if ( !$pageTitle ) {
132 - continue;
133 - }
134 - $row['page'] = $wgUser->getSkin()->link( $pageTitle, $pageTitle->getPrefixedText() );
135 - foreach ( $categories as $catid => $catmsg ) {
136 - if ( isset( $page['ratings'][$catid] ) ) {
137 - $number = $this->formatNumber( $page['ratings'][$catid] );
138 - $class = round( $page['ratings'][$catid] );
139 - } else {
140 - $number = wfMsg( 'articlefeedback-table-noratings' );
141 - $class = 'none';
142 - }
143 - $row[] = array(
144 - 'text' => $number,
145 - 'attr' => array(
146 - 'class' => 'articleFeedback-table-column-rating ' .
147 - 'articleFeedback-table-column-score-' . $class
148 - )
149 - );
150 - }
151 - $row[] = array(
152 - 'text' => $this->formatNumber( $page['average'] ),
153 - 'attr' => array(
154 - 'class' => 'articleFeedback-table-column-average ' .
155 - 'articleFeedback-table-column-score-' . round( $page['average'] )
156 - )
157 - );
158 - $rows[] = $row;
159 - }
160 - }
 29+ $output .= "[[Wikipedia:$title|Go to Article]]
 30+ | [[Wikipedia:$title|Discussion page]]
 31+ | [[Wikipedia:$title|What's this?]]\n";
16132
162 - $this->renderTable(
163 - $caption,
164 - array_merge(
165 - array( wfMsg( 'articleFeedback-table-heading-page' ) ),
166 - $categories,
167 - array( wfMsg( 'articleFeedback-table-heading-average' ) )
168 - ),
169 - $rows,
170 - 'articleFeedback-table-highsandlows'
171 - );
172 - }
173 -
174 - /**
175 - * Renders weekly most changed
176 - *
177 - * @return String: HTML table of weekly most changed
178 - */
179 - protected function renderWeeklyMostChanged() {
180 - global $wgUser;
181 -
182 - $categories = self::getCategories();
183 -
184 - $rows = array();
185 - foreach ( $this->getWeeklyMostChanged() as $page ) {
186 - $row = array();
187 - $pageTitle = Title::newFromText( $page['page'] );
188 - $row['page'] = $wgUser->getSkin()->link( $pageTitle, $pageTitle->getPrefixedText() );
189 - foreach ( $categories as $catid => $catmsg ) {
190 - if ( isset( $page['changes'][$catid] ) ) {
191 - $number = $this->formatNumber( $page['changes'][$catid] );
192 - } else {
193 - $number = wfMsg( 'articlefeedback-table-noratings' );
194 - }
195 - $row[] = array(
196 - 'text' => $number,
197 - 'attr' => array(
198 - 'class' => 'articleFeedback-table-column-changes'
199 - )
200 - );
201 - }
202 - $rows[] = $row;
 33+ if( $found ) {
 34+ $output .= " $found% of users found what they were looking for. ";
20335 }
204 - $this->renderTable(
205 - wfMsg( 'articleFeedback-table-caption-weeklymostchanged' ),
206 - array_merge(
207 - array( wfMsg( 'articleFeedback-table-heading-page' ) ),
208 - $categories
209 - ),
210 - $rows,
211 - 'articleFeedback-table-weeklymostchanged'
212 - );
213 - }
21436
215 - /**
216 - * Renders problem articles table
217 - *
218 - * @return String: HTML table of recent lows
219 - */
220 - protected function renderProblems() {
221 - global $wgUser;
222 -
223 - $problems = $this->getProblems();
224 - $categories = self::getCategories();
225 -
226 - // Pre-fill page ID cache
227 - $ids = array();
228 - foreach ( $problems as $page ) {
229 - $ids[] = $page['page'];
 37+ if( $rating ) {
 38+ $output .= " Rating: $rating/5 ";
23039 }
231 - self::populateTitleCache( $ids );
23240
233 - $rows = array();
234 - foreach ( $problems as $page ) {
235 - $row = array();
236 - $pageTitle = self::getTitleFromID( $page['page'] );
237 - if ( !$pageTitle ) {
238 - continue;
239 - }
240 - $row['page'] = $wgUser->getSkin()->link( $pageTitle, $pageTitle->getPrefixedText() );
241 - foreach ( $categories as $catid => $catmsg ) {
242 - if ( isset( $page['ratings'][$catid] ) ) {
243 - $number = $this->formatNumber( $page['ratings'][$catid] );
244 - $class = round( $page['ratings'][$catid] );
245 - } else {
246 - $number = wfMsg( 'articlefeedback-table-noratings' );
247 - $class = 'none';
248 - }
249 - $row[] = array(
250 - 'text' => $number,
251 - 'attr' => array(
252 - 'class' => 'articleFeedback-table-column-rating ' .
253 - 'articleFeedback-table-column-score-' . $class
254 - )
255 - );
256 - }
257 - $row[] = array(
258 - 'text' => $this->formatNumber( $page['average'] ),
259 - 'attr' => array(
260 - 'class' => 'articleFeedback-table-column-average ' .
261 - 'articleFeedback-table-column-score-' . round( $page['average'] )
262 - )
263 - );
264 - $rows[] = $row;
265 - }
266 - $this->renderTable(
267 - wfMsg( 'articleFeedback-table-caption-recentlows' ),
268 - array_merge(
269 - array( wfMsg( 'articleFeedback-table-heading-page' ) ),
270 - $categories,
271 - array( wfMsg( 'articleFeedback-table-heading-average' ) )
272 - ),
273 - $rows,
274 - 'articleFeedback-table-recentlows'
275 - );
276 - }
 41+ $output .= "\n== Feedback ==\n";
27742
278 - /**
279 - * Gets a list of articles which were rated exceptionally low
280 - */
281 - protected function getProblems() {
282 - global $wgMemc;
283 - // check if we've got results in the cache
284 - $key = wfMemcKey( 'article_feedback_stats_problems' );
285 - $cache = $wgMemc->get( $key );
286 - if ( is_array( $cache )) {
287 - $problems = $cache;
288 - } else {
289 - $dbr = wfGetDB( DB_SLAVE );
290 - $typeID = self::getStatsTypeId( 'problems' );
291 - // first find the freshest timestamp
292 - $row = $dbr->selectRow(
293 - 'article_feedback_stats',
294 - array( 'afs_ts' ),
295 - array( 'afs_stats_type_id' => $typeID ),
296 - __METHOD__,
297 - array( "ORDER BY" => "afs_ts DESC", "LIMIT" => 1 )
298 - );
299 -
300 - // if we have no results, just return
301 - if ( !$row || !$row->afs_ts ) {
302 - return array();
 43+/*
 44+ $feedback = $this->api->fetchFeedback( $pageId );
 45+ foreach($feedback as $record) {
 46+ # add a table or something
 47+ $output .= " \n record: ".$record[0]->af_id;
 48+ foreach($record as $answer) {
 49+ $func = 'aa_response_'.$answer->afi_data_type;
 50+ $output .= " \n ".$answer->afi_name.': '
 51+ .$answer->$func;
30352 }
304 -
305 - // select ratings with that ts
306 - $result = $dbr->select(
307 - 'article_feedback_stats',
308 - array(
309 - 'afs_page_id',
310 - 'afs_orderable_data',
311 - 'afs_data'
312 - ),
313 - array(
314 - 'afs_ts' => $row->afs_ts,
315 - 'afs_stats_type_id' => $typeID
316 - ),
317 - __METHOD__,
318 - array( "ORDER BY" => "afs_orderable_data" )
319 - );
320 - $problems = $this->buildProblems( $result );
321 - $wgMemc->set( $key, $problems, 86400 );
 53+ $output .= " \n ----------- ";
 54+
32255 }
 56+*/
32357
324 - return $problems;
325 - }
 58+ $wgOut->addWikiText( $output );
32659
327 - /**
328 - * Gets a list of articles which were rated exceptionally high or low.
329 - *
330 - * - Based on average of all rating categories
331 - * - Gets 50 highest rated and 50 lowest rated
332 - * - Only consider articles with 10+ ratings in the last 24 hours
333 - *
334 - * This data should be updated daily, ideally though a scheduled batch job
335 - */
336 - protected function getDailyHighsAndLows() {
337 - global $wgMemc;
338 - // check if we've got results in the cache
339 - $key = wfMemcKey( 'article_feedback_stats_highs_lows' );
340 - $cache = $wgMemc->get( $key );
341 - if ( is_array( $cache )) {
342 - $highs_lows = $cache;
343 - } else {
344 - $dbr = wfGetDB( DB_SLAVE );
345 - $typeID = self::getStatsTypeId( 'highs_and_lows' );
346 - // first find the freshest timestamp
347 - $row = $dbr->selectRow(
348 - 'article_feedback_stats',
349 - array( 'afs_ts' ),
350 - array( 'afs_stats_type_id' => $typeID ),
351 - __METHOD__,
352 - array( "ORDER BY" => "afs_ts DESC", "LIMIT" => 1 )
353 - );
354 -
355 - // if we have no results, just return
356 - if ( !$row || !$row->afs_ts ) {
357 - return array();
358 - }
359 -
360 - // select ratings with that ts
361 - $result = $dbr->select(
362 - 'article_feedback_stats',
363 - array(
364 - 'afs_page_id',
365 - 'afs_orderable_data',
366 - 'afs_data'
367 - ),
368 - array(
369 - 'afs_ts' => $row->afs_ts,
370 - 'afs_stats_type_id' => $typeID,
371 - ),
372 - __METHOD__,
373 - array( "ORDER BY" => "afs_orderable_data" )
374 - );
375 - $highs_lows = $this->buildHighsAndLows( $result );
376 - $wgMemc->set( $key, $highs_lows, 86400 );
377 - }
378 -
379 - return $highs_lows;
380 - }
381 -
382 - /**
383 - * Determine the 'highest' rated articles
384 - *
385 - * Divides the number of ratings in half to determine the range of
386 - * articles to consider 'highest'. In the event of an odd number
387 - * of articles, (determined by checking for modulus of # of ratings / 2),
388 - * round up, giving preference to the 'highs' so
389 - * everyone feels warm and fuzzy about having more 'highs', as
390 - * it were...
391 - *
392 - * @param array Pre-orderd from highest to lowest
393 - * @return array Containing the... highest rated article data
394 - */
395 - protected function getDailyHighs( $highs_lows ) {
396 - $num_ratings = count( $highs_lows );
397 - if ( $num_ratings % 2 ) {
398 - $num_highs = round( $num_ratings / 2 );
399 - } else {
400 - $num_highs = $num_ratings / 2;
401 - }
402 - $highs = array_slice( $highs_lows, -$num_highs, $num_highs );
403 -
404 - // Sort descending
405 - return array_reverse( $highs );
406 - }
407 -
408 - /**
409 - * Determine the 'lowest' rated articles
410 - *
411 - * @see getDailyHighs() However, if we are dealing with an odd number of
412 - * ratings, round up and then subtract 1 since we are giving preference
413 - * to the 'highs' when dealing with an odd number of ratings. We do this
414 - * rather than rely on PHP's rounding 'modes' for compaitibility with
415 - * PHP < 5.3
416 - * @param array Pre-orderd from lowest to highest
417 - * @return array Containing the... lowest rated article data
418 - */
419 - protected function getDailyLows( $highs_lows ) {
420 - $num_ratings = count( $highs_lows );
421 - if ( $num_ratings % 2 ) {
422 - $num_lows = round( $num_ratings / 2 ) - 1;
423 - } else {
424 - $num_lows = $num_ratings / 2;
425 - }
426 - return array_slice( $highs_lows, 0, $num_lows );
427 - }
428 -
429 - /**
430 - * Build data store of highs/lows for use when rendering table
431 - * @param object Database result or array of rows
432 - * @return array
433 - */
434 - public static function buildHighsAndLows( $result ) {
435 - $highs_lows = array();
436 - foreach ( $result as $row ) {
437 - if ( is_array( $row ) ) {
438 - $row = (object)$row;
439 - }
440 - $highs_lows[] = array(
441 - 'page' => $row->afs_page_id,
442 - 'ratings' => FormatJson::decode( $row->afs_data, true ),
443 - 'average' => $row->afs_orderable_data
444 - );
445 - }
446 - return $highs_lows;
447 - }
448 -
449 - /**
450 - * Build data store of problems for use when rendering table
451 - * @param object Database result or array of rows
452 - * @return array
453 - */
454 - public static function buildProblems( $result ) {
455 - $problems = array();
456 - foreach( $result as $row ) {
457 - if ( is_array( $row ) ) {
458 - $row = (object)$row;
459 - }
460 - $problems[] = array(
461 - 'page' => $row->afs_page_id,
462 - 'ratings' => FormatJson::decode( $row->afs_data, true ),
463 - 'average' => $row->afs_orderable_data
464 - );
465 - }
466 - return $problems;
467 - }
468 -
469 - /**
470 - * Get the stats type id for a given stat type
471 - * @param string $stats_type
472 - */
473 - public static function getStatsTypeId( $stats_type ) {
474 - global $wgMemc;
475 - $key = wfMemcKey( 'article_feedback_stats_type_' . $stats_type );
476 - $cache = $wgMemc->get( $key );
477 - if ( $cache ) {
478 - return $cache;
479 - }
480 -
481 - $dbr = wfGetDB( DB_SLAVE );
482 - $row = $dbr->selectRow(
483 - 'article_feedback_stats_types',
484 - array( 'afst_id' ),
485 - array( 'afst_type' => $stats_type ),
486 - __METHOD__,
487 - array( )
 60+ $wgOut->addHTML(<<<EOH
 61+<!-- This is a terrible, terrible hack. I'm taking it out as soon as I stop
 62+ being an idiot and sort this ResourceLoader thing out -->
 63+<script> var hackPageId = $pageId; </script>
 64+<script src="http://wikidev.int.omniti.net/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js"></script>
 65+<!--
 66+Show only: <select id="aft5-filter">
 67+<option>visible</option>
 68+<option>all</option>
 69+</select>
 70+<br/>
 71+Sort:
 72+<select id="aft5-sort">
 73+<option>newest</option>
 74+<option>oldest</option>
 75+</select>
 76+-->
 77+<br>
 78+<span id="aft5-showing">
 79+Showing 0 posts (of 0)
 80+</span>
 81+<br>
 82+<div style="border:1px solid red;" id="aft5-show-feedback">Loading...</div>
 83+<a href="#" id="aft5-more">More</a>
 84+EOH
48885 );
489 - $wgMemc->set( $key, $row->afst_id );
490 - return $row->afst_id;
 86+ # "more" link to load the next 50 and append it.
49187 }
49288
493 - /**
494 - * Gets a list of articles which have quickly changing ratings.
495 - *
496 - * - Based on any rating category
497 - * - Gets 50 most improved and 50 most worsened
498 - * - Only consider articles with 100+ ratings in the last 7 days
499 - *
500 - * This data should be updated daily, ideally though a scheduled batch job
501 - */
502 - protected function getWeeklyMostChanged() {
503 - return array(
504 - array(
505 - 'page' => 'Main Page',
506 - // List of differences for each rating in the past 7 days
507 - 'changes' => array(
508 - 1 => 1,
509 - 2 => 2,
510 - 3 => 0,
511 - 4 => 0,
512 - ),
513 - ),
514 - array(
515 - 'page' => 'Test Article',
516 - 'changes' => array(
517 - 1 => 0,
518 - 2 => 0,
519 - 3 => 1,
520 - 4 => 2,
521 - ),
522 - )
523 - );
524 - }
525 -
526 - /* Protected Static Members */
527 -
528 - protected static $categories;
529 - protected static $titleCache = array();
530 -
531 - /* Protected Static Methods */
532 -
53389 protected static function formatNumber( $number ) {
53490 global $wgLang;
535 -
53691 return $wgLang->formatNum( number_format( $number, 2 ) );
53792 }
53893
539 - protected static function getCategories() {
540 - global $wgArticleFeedbackRatingTypes;
541 -
542 - if ( !isset( self::$categories ) ) {
543 - foreach ( $wgArticleFeedbackRatingTypes as $id => $rating ) {
544 - self::$categories[$id] = wfMsg( "articlefeedback-field-$rating-label" );
545 - }
546 - }
547 - return self::$categories;
 94+ protected function pageIdFromTitle( $title ) {
 95+ $dbr = wfGetDB( DB_SLAVE );
 96+ return $dbr->selectField(
 97+ 'page',
 98+ 'page_id',
 99+ array( 'page_title' => $title )
 100+ );
548101 }
549102
550 - protected static function getTitleFromID( $id ) {
551 - // There's no caching in Title::newFromId() so we hack our own around it
552 - if ( !isset( self::$titleCache[$id] ) ) {
553 - self::$titleCache[$id] = Title::newFromId( $id );
554 - }
555 - return self::$titleCache[$id];
 103+ private function getApi() {
 104+ $q = new ApiQuery(
 105+ 'ApiQuery', 'articlefeedbackv5-view-feedback' );
 106+ $api = new ApiViewFeedbackArticleFeedbackv5(
 107+ $q, 'articlefeedbackv5-view-feedback' );
 108+ return $api;
556109 }
557 -
558 - protected static function populateTitleCache( $ids ) {
559 - $toQuery = array_diff( $ids, array_keys( self::$titleCache ) );
560 - $titles = Title::newFromIds( $toQuery );
561 - foreach ( $titles as $title ) {
562 - self::$titleCache[$title->getArticleID()] = $title;
563 - }
564 - }
565110 }
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php
@@ -115,6 +115,10 @@
116116 'jquery.clickTracking',
117117 ),
118118 ),
 119+ 'jquery.articleFeedbackv5.special' => array(
 120+ 'scripts ' => 'jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js',
 121+ 'styles' => 'jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.css',
 122+ ),
119123 );
120124
121125 public static function addFeedbackLink($template, &$content_actions) {
@@ -122,7 +126,7 @@
123127 $content_actions['namespaces'][] = array(
124128 'class' => false or 'selected',
125129 'text' => 'Feedback',
126 - 'href' => '/wiki-dev/index.php/Feedback:Greg', #TODO
 130+ 'href' => '/wiki-dev/index.php/Special:ArticleFeedbackv5', #TODO
127131 'context' => 'feedback'
128132 );
129133 return true;
@@ -194,6 +198,7 @@
195199 $resources['messages'][] = $prefix . $field . '-tooltip-5';
196200 }
197201 }
 202+
198203 $resourceLoader->register(
199204 $name, new ResourceLoaderFileModule( $resources, $localpath, $remotepath )
200205 );

Status & tagging log