Index: trunk/extensions/ArticleFeedbackv5/sql/ArticleFeedbackv5.sql |
— | — | @@ -140,6 +140,17 @@ |
141 | 141 | PRIMARY KEY (arfsr_page_id, arfsr_field_id, arfsr_revision_id, arfsr_option_id) |
142 | 142 | ) /*$wgDBTableOptions*/; |
143 | 143 | |
| 144 | +-- Exists to provide counts on filters for the feedback page, and toggle the "more" button" |
| 145 | +CREATE TABLE IF NOT EXISTS /*_*/aft_article_filter_count ( |
| 146 | + -- Keys to page.page_id |
| 147 | + afc_page_id integer unsigned NOT NULL, |
| 148 | + -- The name of the filter (must be matched by the fitler select on feedback page) |
| 149 | + afc_filter_name varchar(64) NOT NULL, |
| 150 | + -- Number of aft_article_feedback records that match this filter. |
| 151 | + afc_filter_count integer unsigned NOT NULL, |
| 152 | + PRIMARY KEY (afc_page_id, afc_filter_name) |
| 153 | +); |
| 154 | + |
144 | 155 | -- Directly taken from AFTv4 |
145 | 156 | CREATE TABLE IF NOT EXISTS /*_*/aft_article_feedback_properties ( |
146 | 157 | -- Keys to article_feedback.aa_id |
Index: trunk/extensions/ArticleFeedbackv5/sql/alter.sql |
— | — | @@ -48,3 +48,11 @@ |
49 | 49 | |
50 | 50 | -- added 12/16 (Roan) |
51 | 51 | ALTER TABLE aft_article_feedback MODIFY COLUMN af_user_ip varchar(32) NULL; |
| 52 | + |
| 53 | +-- added 1/13 (greg) |
| 54 | +CREATE TABLE IF NOT EXISTS /*_*/aft_article_filter_count ( |
| 55 | + afc_page_id integer unsigned NOT NULL, |
| 56 | + afc_filter_name varchar(64) NOT NULL, |
| 57 | + afc_filter_count integer unsigned NOT NULL, |
| 58 | + PRIMARY KEY (afc_page_id, afc_filter_name) |
| 59 | +); |
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php |
— | — | @@ -42,12 +42,14 @@ |
43 | 43 | 'articlefeedbackv5-error-flagging' => 'Error flagging feedback.', |
44 | 44 | |
45 | 45 | // Article Feedback special page. |
| 46 | + 'articlefeedbackv5-error-loading-feedback' => 'Error loading article feedback.', |
46 | 47 | 'articlefeedbackv5-form-tools-label' => 'Tools', |
47 | 48 | 'articlefeedbackv5-form-helpful-label' => 'Is this feedback helpful?', |
48 | 49 | 'articlefeedbackv5-special-add-feedback' => 'Add your feedback', |
49 | | - 'articlefeedbackv5-special-filter-visible' => 'Visible', |
50 | | - 'articlefeedbackv5-special-filter-invisible' => 'Invisible', |
51 | | - 'articlefeedbackv5-special-filter-all' => 'All', |
| 50 | + 'articlefeedbackv5-special-filter-comment' => 'Comments only ($1)', |
| 51 | + 'articlefeedbackv5-special-filter-visible' => 'Visible ($1)', |
| 52 | + 'articlefeedbackv5-special-filter-invisible' => 'Invisible ($1)', |
| 53 | + 'articlefeedbackv5-special-filter-all' => 'All ($1)', |
52 | 54 | 'articlefeedbackv5-special-sort-newest' => 'Newest first', |
53 | 55 | 'articlefeedbackv5-special-sort-oldest' => 'Oldest first', |
54 | 56 | 'articlefeedbackv5-special-sort-label-before' => 'Order by:', |
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.css |
— | — | @@ -1,2 +1,2 @@ |
2 | 2 | /* css here */ |
3 | | -div.aft5-feedback { border:1px solid red; } |
| 3 | +div.articleFeedbackv5-feedback { border:1px solid #CCC; background:#EEE; margin-top:10px; } |
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.special.js |
— | — | @@ -50,12 +50,12 @@ |
51 | 51 | /** |
52 | 52 | * The number of responses to display per data pull |
53 | 53 | */ |
54 | | - $.articleFeedbackv5special.limit = 25; |
| 54 | + $.articleFeedbackv5special.limit = 5; |
55 | 55 | |
56 | 56 | /** |
57 | 57 | * The index at which to start the pull |
58 | 58 | */ |
59 | | - $.articleFeedbackv5special.offset = 0; |
| 59 | + $.articleFeedbackv5special.continue = null; |
60 | 60 | |
61 | 61 | /** |
62 | 62 | * The url to which to send the request |
— | — | @@ -69,27 +69,26 @@ |
70 | 70 | * Binds events for each of the controls |
71 | 71 | */ |
72 | 72 | $.articleFeedbackv5special.setBinds = function() { |
73 | | - $( '#aft5-filter' ).bind( 'change', function( e ) { |
| 73 | + $( '#articleFeedbackv5-filter' ).bind( 'change', function( e ) { |
74 | 74 | $.articleFeedbackv5special.filter = $(this).val(); |
75 | 75 | $.articleFeedbackv5special.loadFeedback( true ); |
76 | 76 | return false; |
77 | 77 | } ); |
78 | | - $( '.aft5-sort-link' ).bind( 'click', function( e ) { |
79 | | - $.articleFeedbackv5special.sort = $.articleFeedbackv5special.stripID( this, 'articlefeedbackv5-special-sort-' ); |
| 78 | + $( '.articleFeedbackv5-sort-link' ).bind( 'click', function( e ) { |
| 79 | + $.articleFeedbackv5special.sort = $.articleFeedbackv5special.stripID( this, 'articleFeedbackv5-special-sort-' ); |
80 | 80 | $.articleFeedbackv5special.loadFeedback( true ); |
81 | 81 | return false; |
82 | 82 | } ); |
83 | | - $( '#aft5-show-more' ).bind( 'click', function( e ) { |
84 | | - $.articleFeedbackv5special.offset += $.articleFeedbackv5special.limit; |
| 83 | + $( '#articleFeedbackv5-show-more' ).bind( 'click', function( e ) { |
85 | 84 | $.articleFeedbackv5special.loadFeedback( false ); |
86 | 85 | return false; |
87 | 86 | } ); |
88 | | - $( '.aft5-abuse-link' ).live( 'click', function( e ) { |
89 | | - $.articleFeedbackv5special.abuseFeedback( $.articleFeedbackv5special.stripID( this, 'aft5-abuse-link-' ) ); |
| 87 | + $( '.articleFeedbackv5-abuse-link' ).live( 'click', function( e ) { |
| 88 | + $.articleFeedbackv5special.abuseFeedback( $.articleFeedbackv5special.stripID( this, 'articleFeedbackv5-abuse-link-' ) ); |
90 | 89 | return false; |
91 | 90 | } ); |
92 | | - $( '.aft5-hide-link' ).live( 'click', function( e ) { |
93 | | - $.articleFeedbackv5special.hideFeedback( $.articleFeedbackv5special.stripID( this, 'aft5-hide-link-' ) ); |
| 91 | + $( '.articleFeedbackv5-hide-link' ).live( 'click', function( e ) { |
| 92 | + $.articleFeedbackv5special.hideFeedback( $.articleFeedbackv5special.stripID( this, 'articleFeedbackv5-hide-link-' ) ); |
94 | 93 | return false; |
95 | 94 | } ); |
96 | 95 | } |
— | — | @@ -156,10 +155,10 @@ |
157 | 156 | } |
158 | 157 | } |
159 | 158 | } |
160 | | - $( '#aft5-' + type + '-link-' + id ).text( mw.msg( msg ) ); |
| 159 | + $( '#articleFeedbackv5-' + type + '-link-' + id ).text( mw.msg( msg ) ); |
161 | 160 | }, |
162 | 161 | 'error': function ( data ) { |
163 | | - $( '#aft5-' + type + '-link-' + id ).text( mw.msg( 'articlefeedbackv5-error-flagging' ) ); |
| 162 | + $( '#articleFeedbackv5-' + type + '-link-' + id ).text( mw.msg( 'articlefeedbackv5-error-flagging' ) ); |
164 | 163 | } |
165 | 164 | } ); |
166 | 165 | return false; |
— | — | @@ -187,11 +186,11 @@ |
188 | 187 | 'type' : 'GET', |
189 | 188 | 'dataType': 'json', |
190 | 189 | 'data' : { |
191 | | - 'afvfpageid': $.articleFeedbackv5special.page, |
192 | | - 'afvffilter': $.articleFeedbackv5special.filter, |
193 | | - 'afvfsort' : $.articleFeedbackv5special.sort, |
194 | | - 'afvflimit' : $.articleFeedbackv5special.limit, |
195 | | - 'afvfoffset': $.articleFeedbackv5special.offset, |
| 190 | + 'afvfpageid' : $.articleFeedbackv5special.page, |
| 191 | + 'afvffilter' : $.articleFeedbackv5special.filter, |
| 192 | + 'afvfsort' : $.articleFeedbackv5special.sort, |
| 193 | + 'afvflimit' : $.articleFeedbackv5special.limit, |
| 194 | + 'afvfcontinue': $.articleFeedbackv5special.continue, |
196 | 195 | 'action' : 'query', |
197 | 196 | 'format' : 'json', |
198 | 197 | 'list' : 'articlefeedbackv5-view-feedback', |
— | — | @@ -200,17 +199,18 @@ |
201 | 200 | 'success': function ( data ) { |
202 | 201 | if ( 'articlefeedbackv5-view-feedback' in data ) { |
203 | 202 | if ( resetContents ) { |
204 | | - $( '#aft5-show-feedback' ).html( data['articlefeedbackv5-view-feedback'].feedback); |
| 203 | + $( '#articleFeedbackv5-show-feedback' ).html( data['articlefeedbackv5-view-feedback'].feedback); |
205 | 204 | } else { |
206 | | - $( '#aft5-show-feedback' ).append( data['articlefeedbackv5-view-feedback'].feedback); |
| 205 | + $( '#articleFeedbackv5-show-feedback' ).append( data['articlefeedbackv5-view-feedback'].feedback); |
207 | 206 | } |
208 | | - $( '#aft5-feedback-count-total' ).text( data['articlefeedbackv5-view-feedback'].count ); |
| 207 | + $( '#articleFeedbackv5-feedback-count-total' ).text( data['articlefeedbackv5-view-feedback'].count ); |
| 208 | + $.articleFeedbackv5special.continue = data['articlefeedbackv5-view-feedback'].continue; |
209 | 209 | } else { |
210 | | - $( '#aft5-show-feedback' ).text( mw.msg( 'articlefeedbackv5-error-loading-feedback' ) ); |
| 210 | + $( '#articleFeedbackv5-show-feedback' ).text( mw.msg( 'articlefeedbackv5-error-loading-feedback' ) ); |
211 | 211 | } |
212 | 212 | }, |
213 | 213 | 'error': function ( data ) { |
214 | | - $( '#aft5-show-feedback' ).text( mw.msg( 'articlefeedbackv5-error-loading-feedback' ) ); |
| 214 | + $( '#articleFeedbackv5-show-feedback' ).text( mw.msg( 'articlefeedbackv5-error-loading-feedback' ) ); |
215 | 215 | } |
216 | 216 | } ); |
217 | 217 | |
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.php |
— | — | @@ -257,11 +257,11 @@ |
258 | 258 | $wgHooks['ArticleSaveComplete'][] = 'ArticleFeedbackv5Hooks::trackEditSuccess'; |
259 | 259 | |
260 | 260 | // API Registration |
261 | | -// $wgAPIListModules['articlefeedbackv5-view-ratings'] = 'ApiViewRatingsArticleFeedbackv5'; |
262 | | -// $wgAPIListModules['articlefeedbackv5-view-feedback'] = 'ApiViewFeedbackArticleFeedbackv5'; |
263 | | -// $wgAPIModules['articlefeedbackv5-flag-feedback'] = 'ApiFlagFeedbackArticleFeedbackv5'; |
| 261 | +$wgAPIListModules['articlefeedbackv5-view-ratings'] = 'ApiViewRatingsArticleFeedbackv5'; |
| 262 | +$wgAPIListModules['articlefeedbackv5-view-feedback'] = 'ApiViewFeedbackArticleFeedbackv5'; |
| 263 | +$wgAPIModules['articlefeedbackv5-flag-feedback'] = 'ApiFlagFeedbackArticleFeedbackv5'; |
264 | 264 | $wgAPIModules['articlefeedbackv5'] = 'ApiArticleFeedbackv5'; |
265 | 265 | |
266 | 266 | // Special Page |
267 | | -// $wgSpecialPages['ArticleFeedbackv5'] = 'SpecialArticleFeedbackv5'; |
268 | | -// $wgSpecialPageGroups['ArticleFeedbackv5'] = 'other'; |
| 267 | +$wgSpecialPages['ArticleFeedbackv5'] = 'SpecialArticleFeedbackv5'; |
| 268 | +$wgSpecialPageGroups['ArticleFeedbackv5'] = 'other'; |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php |
— | — | @@ -46,9 +46,9 @@ |
47 | 47 | $bucket = $params['bucket']; |
48 | 48 | $revisionId = $params['revid']; |
49 | 49 | $error = null; |
50 | | - $user_answers = array(); |
| 50 | + $userAnswers = array(); |
51 | 51 | $fields = ApiArticleFeedbackv5Utils::getFields(); |
52 | | - $email_data = array( |
| 52 | + $emailData = array( |
53 | 53 | 'ratingData' => array(), |
54 | 54 | 'pageID' => $pageId, |
55 | 55 | 'bucketId' => $bucket |
— | — | @@ -78,8 +78,8 @@ |
79 | 79 | foreach ( array( 'rating', 'text', 'boolean', 'option_id' ) as $t ) { |
80 | 80 | $data["aa_response_$t"] = $t == $type ? $value : null; |
81 | 81 | } |
82 | | - $user_answers[] = $data; |
83 | | - $email_data['ratingData'][$field_name] = $value; |
| 82 | + $userAnswers[] = $data; |
| 83 | + $emailData['ratingData'][$field_name] = $value; |
84 | 84 | } |
85 | 85 | } |
86 | 86 | if ( $error ) { |
— | — | @@ -88,16 +88,17 @@ |
89 | 89 | } |
90 | 90 | |
91 | 91 | // Save the response data |
92 | | - $ratingIds = $this->saveUserRatings( $user_answers, $bucket, $params ); |
| 92 | + $ratingIds = $this->saveUserRatings( $userAnswers, $bucket, $params ); |
93 | 93 | $ctaId = $ratingIds['cta_id']; |
94 | 94 | $feedbackId = $ratingIds['feedback_id']; |
95 | 95 | $this->saveUserProperties( $feedbackId ); |
96 | | - $this->updateRollupTables( $pageId, $revisionId, $user_answers ); |
| 96 | + $this->updateRollupTables( $pageId, $revisionId, $userAnswers ); |
| 97 | + $this->updateFilterCounts( $pageId, $userAnswers ); |
97 | 98 | |
98 | 99 | // If we have an email address, capture it |
99 | 100 | if ( $params['email'] ) { |
100 | 101 | $this->captureEmail ( $params['email'], FormatJson::encode( |
101 | | - $email_data |
| 102 | + $emailData |
102 | 103 | ) ); |
103 | 104 | } |
104 | 105 | |
— | — | @@ -254,7 +255,66 @@ |
255 | 256 | return false; |
256 | 257 | } |
257 | 258 | |
| 259 | + public function updateFilterCounts( $pageId, $answers ) { |
| 260 | + $has_comment = false; |
| 261 | + |
| 262 | + # Does this record have a comment attached? |
| 263 | + # Defined as an answer of type 'text'. |
| 264 | + foreach( $answers as $a ) { |
| 265 | + if( $a['aa_response_text'] !== null ) { |
| 266 | + $has_comment = true; |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + # Update the overall number of records for this page. |
| 271 | + $this->updateFilterCount( $pageId, 'all' ); |
| 272 | + # If the feedbackrecord had a comment, update that fitler count. |
| 273 | + if( $has_comment ) { |
| 274 | + $this->updateFilterCount( $pageId, 'comment' ); |
| 275 | + } |
| 276 | + } |
| 277 | + |
258 | 278 | /** |
| 279 | + * Update the feedback count rollup table |
| 280 | + * |
| 281 | + * @param $pageId int the page id |
| 282 | + * @param $filterName string the name of the filter to update |
| 283 | + */ |
| 284 | + private function updateFilterCount( $pageId, $filterName ) { |
| 285 | + $dbw = wfGetDB( DB_MASTER ); |
| 286 | + |
| 287 | + $dbw->begin(); |
| 288 | + |
| 289 | + # Try to insert the record, but ignore failures. |
| 290 | + # Ensures the count row exists. |
| 291 | + $dbw->insert( |
| 292 | + 'aft_article_filter_counts', |
| 293 | + array( |
| 294 | + 'afc_page_id' => $pageId, |
| 295 | + 'afc_filter_name' => $filterName, |
| 296 | + 'afc_filter_count' => 0 |
| 297 | + ), |
| 298 | + __METHOD__, |
| 299 | + array( 'IGNORE' ) |
| 300 | + ); |
| 301 | + |
| 302 | + # Update the count row, incrementing the count. |
| 303 | + $dbw->update( |
| 304 | + 'aft_article_filter_counts', |
| 305 | + array( |
| 306 | + 'afc_filter_count = afc_filter_count + 1' |
| 307 | + ), |
| 308 | + array( |
| 309 | + 'afc_page_id' => $pageId, |
| 310 | + 'afc_filter_name' => $filterName |
| 311 | + ), |
| 312 | + __METHOD__ |
| 313 | + ); |
| 314 | + |
| 315 | + $dbw->commit(); |
| 316 | + } |
| 317 | + |
| 318 | + /** |
259 | 319 | * Update the rollup tables |
260 | 320 | * |
261 | 321 | * @param $page int the page id |
Index: trunk/extensions/ArticleFeedbackv5/api/ApiViewFeedbackArticleFeedbackv5.php |
— | — | @@ -27,48 +27,52 @@ |
28 | 28 | */ |
29 | 29 | public function execute() { |
30 | 30 | $params = $this->extractRequestParams(); |
31 | | - $html = ''; |
32 | 31 | $result = $this->getResult(); |
33 | 32 | $pageId = $params['pageid']; |
| 33 | + $html = ''; |
34 | 34 | $length = 0; |
35 | | - $count = $this->fetchFeedbackCount( |
36 | | - $params['pageid'], $params['filter'] ); |
| 35 | + $count = $this->fetchFeedbackCount( $params['pageid'], $params['filter'] ); |
37 | 36 | $feedback = $this->fetchFeedback( |
38 | 37 | $params['pageid'], |
39 | 38 | $params['filter'], |
40 | 39 | $params['sort'], |
41 | 40 | $params['limit'], |
42 | | - $params['offset'] |
| 41 | + ( $params['continue'] !== 'null' ? $params['continue'] : null ) |
43 | 42 | ); |
44 | 43 | |
45 | 44 | foreach ( $feedback as $record ) { |
46 | 45 | $html .= $this->renderFeedback( $record ); |
47 | 46 | $length++; |
48 | 47 | } |
| 48 | + $tmp = end($feedback); |
| 49 | + if( $tmp ) { |
| 50 | + $continue = $tmp[0]->af_id; |
| 51 | + } |
49 | 52 | |
50 | 53 | $result->addValue( $this->getModuleName(), 'length', $length ); |
51 | 54 | $result->addValue( $this->getModuleName(), 'count', $count ); |
52 | 55 | $result->addValue( $this->getModuleName(), 'feedback', $html ); |
| 56 | + if ( $continue ) { |
| 57 | + $result->addValue( $this->getModuleName(), 'continue', $continue ); |
| 58 | + } |
53 | 59 | } |
54 | 60 | |
55 | 61 | public function fetchFeedbackCount( $pageId, $filter ) { |
56 | | - $dbr = wfGetDB( DB_SLAVE ); |
57 | | - $where = $this->getFilterCriteria( $filter ); |
| 62 | + $dbr = wfGetDB( DB_SLAVE ); |
58 | 63 | |
59 | | - $where['af_page_id'] = $pageId; |
60 | | - |
61 | | - # Until this is done properly, just don't do anything. |
62 | | - return 0; |
63 | | - |
64 | | -# return $dbr->selectField( |
65 | | -# array( 'aft_article_feedback' ), |
66 | | -# array( 'COUNT(*) AS count' ), |
67 | | -# $where |
68 | | -# ); |
| 64 | + return $dbr->selectField( |
| 65 | + array( 'aft_article_filter_count' ), |
| 66 | + array( 'afc_filter_count' ), |
| 67 | + array( |
| 68 | + 'afc_page_id' => $pageId, |
| 69 | + 'afc_filter_name' => $filter |
| 70 | + ), |
| 71 | + __METHOD__ |
| 72 | + ); |
69 | 73 | } |
70 | 74 | |
71 | 75 | public function fetchFeedback( $pageId, |
72 | | - $filter = 'visible', $order = 'newest', $limit = 25, $offset = 0 ) { |
| 76 | + $filter = 'visible', $order = 'newest', $limit = 25, $continue = null ) { |
73 | 77 | $dbr = wfGetDB( DB_SLAVE ); |
74 | 78 | $ids = array(); |
75 | 79 | $rows = array(); |
— | — | @@ -77,18 +81,25 @@ |
78 | 82 | $order; |
79 | 83 | |
80 | 84 | # Newest first is the only option right now. |
| 85 | + # TODO: The SQL needs to handle all sorts of weird cases. |
81 | 86 | switch( $order ) { |
82 | 87 | case 'oldest': |
83 | | - $order = 'af_id ASC'; |
| 88 | + $order = 'af_id ASC'; |
| 89 | + $continueSql = 'af_id > '; |
84 | 90 | break; |
85 | 91 | case 'newest': |
86 | 92 | default: |
87 | | - $order = 'af_id DESC'; |
| 93 | + $order = 'af_id DESC'; |
| 94 | + $continueSql = 'af_id < '; |
88 | 95 | break; |
89 | 96 | } |
90 | 97 | |
91 | 98 | $where['af_page_id'] = $pageId; |
92 | 99 | |
| 100 | + if( $continue !== null ) { |
| 101 | + $where[] = "$continueSql $continue"; |
| 102 | + } |
| 103 | + |
93 | 104 | /* I'd really love to do this in one big query, but MySQL |
94 | 105 | doesn't support LIMIT inside IN() subselects, and since |
95 | 106 | we don't know the number of answers for each feedback |
— | — | @@ -98,7 +109,6 @@ |
99 | 110 | 'aft_article_feedback', 'af_id', $where, __METHOD__, |
100 | 111 | array( |
101 | 112 | 'LIMIT' => $limit, |
102 | | - 'OFFSET' => $offset, |
103 | 113 | 'ORDER BY' => $order |
104 | 114 | ) |
105 | 115 | ); |
— | — | @@ -187,28 +197,32 @@ |
188 | 198 | $id = $record[0]->af_id; |
189 | 199 | |
190 | 200 | # TODO: permalinks |
191 | | - return Html::openElement( 'div', array( 'id' => 'aft5-feedback' ) ) |
| 201 | + return Html::openElement( 'div', array( 'class' => 'articleFeedbackv5-feedback' ) ) |
192 | 202 | . Html::openElement( 'p' ) |
193 | | - . Html::element( 'a', array( 'class' => 'aft5-comment-name', 'href' => 'profilepage or whatever' ), $id ) |
194 | | - . Html::element( 'span', array( 'class' => 'aft5-comment-timestamp' ), $record[0]->af_created ) |
| 203 | + . Html::element( 'a', array( 'class' => 'articleFeedbackv5-comment-name', 'href' => 'profilepage or whatever' ), $id ) |
| 204 | + . Html::element( 'span', array( 'class' => 'articleFeedbackv5-comment-timestamp' ), $record[0]->af_created ) |
195 | 205 | . Html::closeElement( 'p' ) |
196 | 206 | . wfMessage( 'articlefeedbackv5-form-optionid', $record[0]->af_bucket_id )->escaped() |
197 | 207 | . $content |
| 208 | + |
| 209 | + . Html::openElement( 'div', array( 'class' => 'articleFeedbackv5-feedback-rate' ) ) |
198 | 210 | . wfMessage( 'articlefeedbackv5-form-helpful-label' )->escaped() |
199 | | - . Html::openElement( 'div', array( 'id' => 'aft5-feedback-tools' ) ) |
| 211 | + . Html::closeElement( 'div' ) |
| 212 | + |
| 213 | + . Html::openElement( 'div', array( 'class' => 'articleFeedbackv5-feedback-tools' ) ) |
200 | 214 | . Html::element( 'h3', array(), wfMessage( 'articlefeedbackv5-form-tools-label' )->text() ) |
201 | 215 | . Html::openElement( 'ul' ) |
202 | 216 | . ( $can_flag ? Html::rawElement( 'li', array(), Html::element( 'a', array( |
203 | | - 'id' => "aft5-hide-link-$id", |
204 | | - 'class' => 'aft5-hide-link' |
| 217 | + 'id' => "articleFeedbackv5-hide-link-$id", |
| 218 | + 'class' => 'articleFeedbackv5-hide-link' |
205 | 219 | ), wfMessage( 'articlefeedbackv5-form-hide', $record[0]->af_hide_count )->text() ) ) : '' ) |
206 | 220 | . ( $can_hide ? Html::rawElement( 'li', array(), Html::element( 'a', array( |
207 | | - 'id' => "aft5-abuse-link-$id", |
208 | | - 'class' => 'aft5-abuse-link' |
| 221 | + 'id' => "articleFeedbackv5-abuse-link-$id", |
| 222 | + 'class' => 'articleFeedbackv5-abuse-link' |
209 | 223 | ), wfMessage( 'articlefeedbackv5-form-abuse', $record[0]->af_abuse_count )->text() ) ) : '' ) |
210 | 224 | . ( $can_delete ? Html::rawElement( 'li', array(), Html::element( 'a', array( |
211 | | - 'id' => "aft5-delete-link-$id", |
212 | | - 'class' => 'aft5-delete-link' |
| 225 | + 'id' => "articleFeedbackv5-delete-link-$id", |
| 226 | + 'class' => 'articleFeedbackv5-delete-link' |
213 | 227 | ), wfMessage( 'articlefeedbackv5-form-delete' )->text() ) ) : '' ) |
214 | 228 | . Html::closeElement( 'ul' ) |
215 | 229 | . Html::closeElement( 'div' ) |
— | — | @@ -312,17 +326,17 @@ |
313 | 327 | ApiBase::PARAM_REQUIRED => false, |
314 | 328 | ApiBase::PARAM_ISMULTI => false, |
315 | 329 | ApiBase::PARAM_TYPE => array( |
316 | | - 'all', 'invisible', 'visible' ) |
| 330 | + 'all', 'invisible', 'visible', 'comment' ) |
317 | 331 | ), |
318 | 332 | 'limit' => array( |
319 | 333 | ApiBase::PARAM_REQUIRED => false, |
320 | 334 | ApiBase::PARAM_ISMULTI => false, |
321 | 335 | ApiBase::PARAM_TYPE => 'integer' |
322 | 336 | ), |
323 | | - 'offset' => array( |
| 337 | + 'continue' => array( |
324 | 338 | ApiBase::PARAM_REQUIRED => false, |
325 | 339 | ApiBase::PARAM_ISMULTI => false, |
326 | | - ApiBase::PARAM_TYPE => 'integer' |
| 340 | + ApiBase::PARAM_TYPE => 'string' |
327 | 341 | ), |
328 | 342 | ); |
329 | 343 | } |
— | — | @@ -334,11 +348,11 @@ |
335 | 349 | */ |
336 | 350 | public function getParamDescription() { |
337 | 351 | return array( |
338 | | - 'pageid' => 'Page ID to get feedback ratings for', |
339 | | - 'sort' => 'Key to sort records by', |
340 | | - 'filter' => 'What filtering to apply to list', |
341 | | - 'limit' => 'Number of records to show', |
342 | | - 'offset' => 'How many to skip (for pagination)', |
| 352 | + 'pageid' => 'Page ID to get feedback ratings for', |
| 353 | + 'sort' => 'Key to sort records by', |
| 354 | + 'filter' => 'What filtering to apply to list', |
| 355 | + 'limit' => 'Number of records to show', |
| 356 | + 'continue' => 'Offset from which to continue', |
343 | 357 | ); |
344 | 358 | } |
345 | 359 | |
Index: trunk/extensions/ArticleFeedbackv5/SpecialArticleFeedbackv5.php |
— | — | @@ -15,6 +15,12 @@ |
16 | 16 | * @subpackage Special |
17 | 17 | */ |
18 | 18 | class SpecialArticleFeedbackv5 extends SpecialPage { |
| 19 | + private $filters = array( |
| 20 | + 'visible', |
| 21 | + 'invisible', |
| 22 | + 'all', |
| 23 | + 'comment' |
| 24 | + ); |
19 | 25 | |
20 | 26 | /** |
21 | 27 | * Constructor |
— | — | @@ -29,8 +35,9 @@ |
30 | 36 | * @param $param string the parameter passed in the url |
31 | 37 | */ |
32 | 38 | public function execute( $param ) { |
33 | | - $out = $this->getOutput(); |
| 39 | + $out = $this->getOutput(); |
34 | 40 | $title = Title::newFromText( $param ); |
| 41 | + |
35 | 42 | if ( $title ) { |
36 | 43 | $pageId = $title->getArticleID(); |
37 | 44 | } else { |
— | — | @@ -39,8 +46,8 @@ |
40 | 47 | } |
41 | 48 | |
42 | 49 | $ratings = $this->fetchOverallRating( $pageId ); |
43 | | - $found = isset( $ratings['found'] ) ? $ratings['found'] : null; |
44 | | - $rating = isset( $ratings['rating'] ) ? $ratings['rating'] : null; |
| 50 | + $found = isset( $ratings['found'] ) ? $ratings['found'] : null; |
| 51 | + $rating = isset( $ratings['rating'] ) ? $ratings['rating'] : null; |
45 | 52 | |
46 | 53 | $out->setPagetitle( |
47 | 54 | $this->msg( 'articlefeedbackv5-special-pagetitle', $title )->escaped() |
— | — | @@ -53,7 +60,7 @@ |
54 | 61 | $out->addHTML( |
55 | 62 | Html::openElement( |
56 | 63 | 'div', |
57 | | - array( 'id' => 'aft5-header-links' ) |
| 64 | + array( 'id' => 'articleFeedbackv5-header-links' ) |
58 | 65 | ) |
59 | 66 | . Linker::link( |
60 | 67 | Title::newFromText( $param ), |
— | — | @@ -76,11 +83,11 @@ |
77 | 84 | $out->addHTML( |
78 | 85 | Html::openElement( |
79 | 86 | 'div', |
80 | | - array( 'id' => 'aft5-showing-count-wrap' ) |
| 87 | + array( 'id' => 'articleFeedbackv5-showing-count-wrap' ) |
81 | 88 | ) |
82 | 89 | . $this->msg( |
83 | 90 | 'articlefeedbackv5-special-showing', |
84 | | - Html::element( 'span', array( 'id' => 'aft-feedback-count-total' ), '0' ) |
| 91 | + Html::element( 'span', array( 'id' => 'articleFeedbackv5-feedback-count-total' ), '0' ) |
85 | 92 | ) |
86 | 93 | . Html::closeElement( 'div' ) |
87 | 94 | ); |
— | — | @@ -89,7 +96,7 @@ |
90 | 97 | $out->addHtml( |
91 | 98 | Html::openElement( |
92 | 99 | 'div', |
93 | | - array( 'id' => 'aft5-percent-found-wrap' ) |
| 100 | + array( 'id' => 'articleFeedbackv5-percent-found-wrap' ) |
94 | 101 | ) |
95 | 102 | . $this->msg( 'articlefeedbackv5-percent-found', $found )->escaped() |
96 | 103 | . Html::closeElement( 'div' ) |
— | — | @@ -105,7 +112,6 @@ |
106 | 113 | $out->addJsConfigVars( 'afPageId', $pageId ); |
107 | 114 | $out->addModules( 'jquery.articleFeedbackv5.special' ); |
108 | 115 | |
109 | | - |
110 | 116 | $sortLabels = array(); |
111 | 117 | $sortOpts = array( 'newest', 'oldest' ); |
112 | 118 | foreach ( $sortOpts as $sort ) { |
— | — | @@ -113,24 +119,28 @@ |
114 | 120 | 'a', |
115 | 121 | array( |
116 | 122 | 'href' => '#', |
117 | | - 'id' => 'articlefeedbackv5-special-sort-' . $sort, |
118 | | - 'class' => 'aft5-sort-link' |
| 123 | + 'id' => 'articleFeedbackv5-special-sort-' . $sort, |
| 124 | + 'class' => 'articleFeedbackv5-sort-link' |
119 | 125 | ), |
120 | 126 | $this->msg( 'articlefeedbackv5-special-sort-' . $sort )->text() |
121 | 127 | ); |
122 | 128 | } |
123 | 129 | |
124 | | - $filterSelect = new XmlSelect( false, 'aft5-filter' ); |
125 | | - $filterSelect->addOptions( $this->selectMsg( array( |
126 | | - 'articlefeedbackv5-special-filter-visible' => 'visible', |
127 | | - 'articlefeedbackv5-special-filter-invisible' => 'invisible', |
128 | | - 'articlefeedbackv5-special-filter-all' => 'all', |
129 | | - ) ) ); |
| 130 | + $opts = array(); |
| 131 | + $counts = $this->getFilterCounts( $pageId ); |
| 132 | + foreach( $this->filters as $filter ) { |
| 133 | + $count = isset($counts[$filter]) ? $counts[$filter] : 0; |
| 134 | + $key = $this->msg( 'articlefeedbackv5-special-filter-'.$filter, $count )->escaped(); |
| 135 | + $opts[ (string) $key ] = $filter; |
| 136 | + } |
130 | 137 | |
| 138 | + $filterSelect = new XmlSelect( false, 'articleFeedbackv5-filter' ); |
| 139 | + $filterSelect->addOptions( $opts ); |
| 140 | + |
131 | 141 | $out->addHTML( |
132 | 142 | Html::openElement( |
133 | 143 | 'div', |
134 | | - array( 'id' => 'aft5-sort-filter-controls' ) |
| 144 | + array( 'id' => 'articleFeedbackv5-sort-filter-controls' ) |
135 | 145 | ) |
136 | 146 | . $this->msg( 'articlefeedbackv5-special-sort-label-before' )->escaped() |
137 | 147 | . implode( $this->msg( 'pipe-separator' )->escaped(), $sortLabels ) |
— | — | @@ -143,7 +153,7 @@ |
144 | 154 | 'a', |
145 | 155 | array( |
146 | 156 | 'href' => '#', |
147 | | - 'id' => 'articlefeedbackv5-special-add-feedback', |
| 157 | + 'id' => 'articleFeedbackv5-special-add-feedback', |
148 | 158 | ), |
149 | 159 | $this->msg( 'articlefeedbackv5-special-add-feedback' )->text() |
150 | 160 | ) |
— | — | @@ -154,15 +164,14 @@ |
155 | 165 | Html::element( |
156 | 166 | 'div', |
157 | 167 | array( |
158 | | - 'id' => 'aft5-show-feedback', |
159 | | - 'style' => 'border:1px solid red;' |
160 | | - ), '' |
| 168 | + 'id' => 'articleFeedbackv5-show-feedback', |
| 169 | + ) |
161 | 170 | ) |
162 | 171 | . Html::element( |
163 | 172 | 'a', |
164 | 173 | array( |
165 | 174 | 'href' => '#', |
166 | | - 'id' => 'aft5-show-more' |
| 175 | + 'id' => 'articleFeedbackv5-show-more' |
167 | 176 | ), |
168 | 177 | $this->msg( 'articlefeedbackv5-special-more' )->text() |
169 | 178 | ) |
— | — | @@ -220,5 +229,27 @@ |
221 | 230 | return $rv; |
222 | 231 | } |
223 | 232 | |
| 233 | + private function getFilterCounts( $pageId ) { |
| 234 | + $rv = array(); |
| 235 | + $dbr = wfGetDB( DB_SLAVE ); |
| 236 | + $rows = $dbr->select( |
| 237 | + 'aft_article_filter_count', |
| 238 | + array( |
| 239 | + 'afc_filter_name', |
| 240 | + 'afc_filter_count' |
| 241 | + ), |
| 242 | + array( |
| 243 | + 'afc_page_id' => $pageId |
| 244 | + ), |
| 245 | + array(), |
| 246 | + __METHOD__ |
| 247 | + ); |
| 248 | + |
| 249 | + foreach( $rows as $row ) { |
| 250 | + $rv[ $row->afc_filter_name ] = $row->afc_filter_count; |
| 251 | + } |
| 252 | + |
| 253 | + return $rv; |
| 254 | + } |
224 | 255 | } |
225 | 256 | |