r98227 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98226‎ | r98227 | r98228 >
Date:16:13, 27 September 2011
Author:catrope
Status:ok
Tags:
Comment:
MoodBar: Rename SpecialMoodBarFeedback to SpecialFeedbackDashboard. This just renames the file, the next commit will clean this up
Modified paths:
  • /trunk/extensions/MoodBar/SpecialFeedbackDashboard.php (added) (history)
  • /trunk/extensions/MoodBar/SpecialMoodBarFeedback.php (deleted) (history)

Diff [purge]

Index: trunk/extensions/MoodBar/SpecialMoodBarFeedback.php
@@ -1,321 +0,0 @@
2 -<?php
3 -/**
4 - * Special:MoodBarFeedback. Special page for viewing moodbar comments.
5 - */
6 -class SpecialMoodBarFeedback extends SpecialPage {
7 - public function __construct() {
8 - parent::__construct( 'MoodBarFeedback' );
9 - }
10 -
11 - public function getDescription() {
12 - return wfMessage( 'moodbar-feedback-title' )->plain();
13 - }
14 -
15 - public function execute( $par ) {
16 - global $wgOut, $wgRequest;
17 -
18 - $limit = 20;
19 - $offset = false;
20 - $filterType = '';
21 - $id = intval( $par );
22 - if ( $id > 0 ) {
23 - // Special:MoodBarFeedback/123 is an ID/permalink view
24 - $filters = array( 'id' => $id );
25 - $filterType = 'id';
26 - } else {
27 - // Determine filters and offset from the query string
28 - $filters = array();
29 - $type = $wgRequest->getArray( 'type' );
30 - if ( $type ) {
31 - $filters['type'] = $type;
32 - }
33 - $username = strval( $wgRequest->getVal( 'username' ) );
34 - if ( $username !== '' ) {
35 - $filters['username'] = $username;
36 - }
37 - $offset = $wgRequest->getVal( 'offset', $offset );
38 - if ( count( $filters ) ) {
39 - $filterType = 'filtered';
40 - }
41 - }
42 - // Do the query
43 - $backwards = $wgRequest->getVal( 'dir' ) === 'prev';
44 - $res = $this->doQuery( $filters, $limit, $offset, $backwards );
45 -
46 - // Output HTML
47 - $wgOut->setPageTitle( wfMsg( 'moodbar-feedback-title' ) );
48 - $wgOut->addHTML( $this->buildForm( $filterType ) );
49 - $wgOut->addHTML( $this->buildList( $res ) );
50 - $wgOut->addModuleStyles( 'ext.moodBar.dashboard.styles' );
51 - $wgOut->addModules( 'ext.moodBar.dashboard' );
52 - }
53 -
54 - /**
55 - * Build the filter form. The state of each form element is preserved
56 - * using data in $wgRequest.
57 - * @param $filterType string Value to pass in the <form>'s data-filtertype attribute
58 - * @return string HTML
59 - */
60 - public function buildForm( $filterType ) {
61 - global $wgRequest, $wgMoodBarConfig;
62 - $filtersMsg = wfMessage( 'moodbar-feedback-filters' )->escaped();
63 - $typeMsg = wfMessage( 'moodbar-feedback-filters-type' )->escaped();
64 - $praiseMsg = wfMessage( 'moodbar-feedback-filters-type-happy' )->escaped();
65 - $confusionMsg = wfMessage( 'moodbar-feedback-filters-type-confused' )->escaped();
66 - $issuesMsg = wfMessage( 'moodbar-feedback-filters-type-sad' )->escaped();
67 - $usernameMsg = wfMessage( 'moodbar-feedback-filters-username' )->escaped();
68 - $setFiltersMsg = wfMessage( 'moodbar-feedback-filters-button' )->escaped();
69 - $whatIsMsg = wfMessage( 'moodbar-feedback-whatis' )->escaped();
70 - $whatIsURL = htmlspecialchars( $wgMoodBarConfig['infoUrl'] );
71 - $actionURL = htmlspecialchars( $this->getTitle()->getLinkURL() );
72 -
73 - $types = $wgRequest->getArray( 'type', array() );
74 - $happyCheckbox = Xml::check( 'type[]', in_array( 'happy', $types ),
75 - array( 'id' => 'fbd-filters-type-praise', 'value' => 'happy' ) );
76 - $confusedCheckbox = Xml::check( 'type[]', in_array( 'confused', $types ),
77 - array( 'id' => 'fbd-filters-type-confusion', 'value' => 'confused' ) );
78 - $sadCheckbox = Xml::check( 'type[]', in_array( 'sad', $types ),
79 - array( 'id' => 'fbd-filters-type-issues', 'value' => 'sad' ) );
80 - $usernameTextbox = Html::input( 'username', $wgRequest->getText( 'username' ), 'text',
81 - array( 'id' => 'fbd-filters-username', 'class' => 'fbd-filters-input' ) );
82 - $filterType = htmlspecialchars( $filterType );
83 -
84 - return <<<HTML
85 - <div id="fbd-filters">
86 - <form action="$actionURL" data-filtertype="$filterType">
87 - <h3 id="fbd-filters-title">$filtersMsg</h3>
88 - <fieldset id="fbd-filters-types">
89 - <legend class="fbd-filters-label">$typeMsg</legend>
90 - <ul>
91 - <li>
92 - $happyCheckbox
93 - <label for="fbd-filters-type-praise" id="fbd-filters-type-praise-label">$praiseMsg</label>
94 - </li>
95 - <li>
96 - $confusedCheckbox
97 - <label for="fbd-filters-type-confusion" id="fbd-filters-type-confusion-label">$confusionMsg</label>
98 - </li>
99 - <li>
100 - $sadCheckbox
101 - <label for="fbd-filters-type-issues" id="fbd-filters-type-issues-label">$issuesMsg</label>
102 - </li>
103 - </ul>
104 - </fieldset>
105 - <label for="fbd-filters-username" class="fbd-filters-label">$usernameMsg</label>
106 - $usernameTextbox
107 - <button type="submit" id="fbd-filters-set">$setFiltersMsg</button>
108 - </form>
109 - <a href="$whatIsURL" id="fbd-about">$whatIsMsg</a>
110 - </div>
111 -HTML;
112 - }
113 -
114 - /**
115 - * Format a single list item from a database row.
116 - * @param $row Database row object
117 - * @return string HTML
118 - */
119 - public static function formatListItem( $row ) {
120 - global $wgLang;
121 - $type = $row->mbf_type;
122 - $typeMsg = wfMessage( "moodbar-type-$type" )->escaped();
123 - $time = $wgLang->formatTimePeriod( wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $row->mbf_timestamp ),
124 - array( 'avoid' => 'avoidminutes', 'noabbrevs' => true )
125 - );
126 - $timeMsg = wfMessage( 'ago' )->params( $time )->escaped();
127 - $username = htmlspecialchars( $row->user_name === null ? $row->mbf_user_ip : $row->user_name );
128 - //$links = Linker::userToolLinks( $row->mbf_user_id, $username );
129 - $links = $GLOBALS['wgUser']->getSkin()->userToolLinks( $row->mbf_user_id, $username ); // 1.17wmf1 compat
130 - $comment = htmlspecialchars( $row->mbf_comment );
131 - $permalinkURL = htmlspecialchars( SpecialPage::getTitleFor( 'MoodBarFeedback', $row->mbf_id )->getLinkURL() );
132 - $permalinkText = wfMessage( 'moodbar-feedback-permalink' )->escaped();
133 - $continueData = wfTimestamp( TS_MW, $row->mbf_timestamp ) . '|' . intval( $row->mbf_id );
134 -
135 - return <<<HTML
136 - <li class="fbd-item" data-mbccontinue="$continueData">
137 - <div class="fbd-item-emoticon fbd-item-emoticon-$type">
138 - <span class="fbd-item-emoticon-label">$typeMsg</span>
139 - </div>
140 - <div class="fbd-item-time">$timeMsg</div>
141 - <h3 class="fbd-item-userName">
142 - <a href="#">$username</a>
143 - <sup class="fbd-item-userLinks">
144 - $links
145 - </sup>
146 - </h3>
147 - <div class="fbd-item-message">$comment</div>
148 - <div class="fbd-item-permalink">(<a href="$permalinkURL">$permalinkText</a>)</div>
149 - <div style="clear:both"></div>
150 - </li>
151 -HTML;
152 - }
153 -
154 - /**
155 - * Build a comment list from a query result
156 - * @param $res array Return value of doQuery()
157 - * @return string HTML
158 - */
159 - public function buildList( $res ) {
160 - global $wgRequest;
161 - $list = '';
162 - foreach ( $res['rows'] as $row ) {
163 - $list .= self::formatListItem( $row );
164 - }
165 -
166 - if ( $list === '' ) {
167 - return '<div id="fbd-list">' . wfMessage( 'moodbar-feedback-noresults' )->escaped() . '</div>';
168 - } else {
169 - // FIXME: We also need to show the More link (hidden) if there were no results
170 - $olderRow = $res['olderRow'];
171 - $newerRow = $res['newerRow'];
172 - $html = "<ul id=\"fbd-list\">$list</ul>";
173 -
174 - // Output the "More" link
175 - $moreText = wfMessage( 'moodbar-feedback-more' )->escaped();
176 - $attribs = array( 'id' => 'fbd-list-more' );
177 - if ( !$olderRow ) {
178 - // There are no more rows. Hide the More link
179 - // We still need to output it because the JS may need it later
180 - $attribs['style'] = 'display: none;';
181 - }
182 - $html .= Html::rawElement( 'div', $attribs, '<a href="#">' . $moreText . '</a>' );
183 -
184 - // Paging links for no-JS clients
185 - $olderURL = $newerURL = false;
186 - if ( $olderRow ) {
187 - $olderOffset = wfTimestamp( TS_MW, $olderRow->mbf_timestamp ) . '|' . intval( $olderRow->mbf_id );
188 - $olderURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $olderOffset, false ) ) );
189 - }
190 - if ( $newerRow ) {
191 - $newerOffset = wfTimestamp( TS_MW, $newerRow->mbf_timestamp ) . '|' . intval( $newerRow->mbf_id );
192 - $newerURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $newerOffset, true ) ) );
193 - }
194 - $olderText = wfMessage( 'moodbar-feedback-older' )->escaped();
195 - $newerText = wfMessage( 'moodbar-feedback-newer' )->escaped();
196 - $html .= '<div id="fbd-list-newer-older"><div id="fbd-list-newer">';
197 - if ( $newerURL ) {
198 - $html .= "<a href=\"$newerURL\">$newerText</a>";
199 - } else {
200 - $html .= "<span class=\"fbd-page-disabled\">$newerText</span>";
201 - }
202 - $html .= '</div><div id="fbd-list-older">';
203 - if ( $olderURL ) {
204 - $html .= "<a href=\"$olderURL\">$olderText</a>";
205 - } else {
206 - $html .= "<span class=\"fbd-page-disabled\">$olderText</span>";
207 - }
208 - $html .= '</div></div><div style="clear: both;"></div>';
209 - return $html;
210 - }
211 - }
212 -
213 - /**
214 - * Get a set of comments from the database.
215 - *
216 - * The way paging is handled by this function is a bit weird. $offset is taken from
217 - * the last row that was displayed, as opposed to the first row that was not displayed.
218 - * This means that if $offset is set, the first row in the result (the one matching $offset)
219 - * is dropped, as well as the last row. The dropped rows are only used to detect the presence
220 - * or absence of more rows in each direction, the offset values for paging are taken from the
221 - * first and last row that are actually shown.
222 - *
223 - * $retval['olderRow'] is the row whose offset should be used to display older rows, or null if
224 - * there are no older rows. This means that, if there are older rows, $retval['olderRow'] is set
225 - * to the oldest row in $retval['rows']. $retval['newerRows'] is set similarly.
226 - *
227 - * @param $filters array Array of filters to apply. Recognized keys are 'type' (array), 'username' (string) and 'id' (int)
228 - * @param $limit int Number of comments to fetch
229 - * @param $offset string Query offset. Timestamp and ID of the last shown result, formatted as 'timestamp|id'
230 - * @param $backwards bool If true, page in ascending order rather than descending order, i.e. get $limit rows after $offset rather than before $offset. The result will still be sorted in descending order
231 - * @return array( 'rows' => array( row, row, ... ), 'olderRow' => row|null, 'newerRow' => row|null )
232 - */
233 - public function doQuery( $filters, $limit, $offset, $backwards ) {
234 - $dbr = wfGetDB( DB_SLAVE );
235 -
236 - // Set $conds based on $filters
237 - $conds = array();
238 - if ( isset( $filters['type'] ) ) {
239 - $conds['mbf_type'] = $filters['type'];
240 - }
241 - if ( isset( $filters['username'] ) ) {
242 - $user = User::newFromName( $filters['username'] ); // Returns false for IPs
243 - if ( !$user || $user->isAnon() ) {
244 - $conds['mbf_user_id'] = 0;
245 - $conds['mbf_user_ip'] = $filters['username'];
246 - } else {
247 - $conds['mbf_user_id'] = $user->getID();
248 - $conds[] = 'mbf_user_ip IS NULL';
249 - }
250 - }
251 - if ( isset( $filters['id'] ) ) {
252 - $conds['mbf_id'] = $filters['id'];
253 - }
254 -
255 - // Process $offset
256 - if ( $offset !== false ) {
257 - $arr = explode( '|', $offset, 2 );
258 - $ts = $dbr->addQuotes( $dbr->timestamp( $arr[0] ) );
259 - $id = isset( $arr[1] ) ? intval( $arr[1] ) : 0;
260 - $op = $backwards ? '>' : '<';
261 - $conds[] = "mbf_timestamp $op $ts OR (mbf_timestamp = $ts AND mbf_id $op= $id)";
262 - }
263 -
264 - // Do the actual query
265 - $desc = $backwards ? '' : ' DESC';
266 - $res = $dbr->select( array( 'moodbar_feedback', 'user' ), array(
267 - 'user_name', 'mbf_id', 'mbf_type',
268 - 'mbf_timestamp', 'mbf_user_id', 'mbf_user_ip', 'mbf_comment'
269 - ),
270 - $conds,
271 - __METHOD__,
272 - array( 'LIMIT' => $limit + 2, 'ORDER BY' => "mbf_timestamp$desc, mbf_id$desc" ),
273 - array( 'user' => array( 'LEFT JOIN', 'user_id=mbf_user_id' ) )
274 - );
275 - $rows = iterator_to_array( $res, /*$use_keys=*/false );
276 -
277 - // Figure out whether there are newer and older rows
278 - $olderRow = $newerRow = null;
279 - $count = count( $rows );
280 - if ( $offset && $count > 0 ) {
281 - // If there is an offset, drop the first row
282 - if ( $count > 1 ) {
283 - array_shift( $rows );
284 - $count--;
285 - }
286 - // We now know there is a previous row
287 - $newerRow = $rows[0];
288 - }
289 - if ( $count > $limit ) {
290 - // If there are rows past the limit, drop them
291 - array_splice( $rows, $limit );
292 - // We now know there is a next row
293 - $olderRow = $rows[$limit - 1];
294 - }
295 -
296 - // If we got things backwards, reverse them
297 - if ( $backwards ) {
298 - $rows = array_reverse( $rows );
299 - list( $olderRow, $newerRow ) = array( $newerRow, $olderRow );
300 - }
301 - return array( 'rows' => $rows, 'olderRow' => $olderRow, 'newerRow' => $newerRow );
302 - }
303 -
304 - /**
305 - * Get a query string array for a given offset, using filter parameters obtained from $wgRequest.
306 - * @param $offset string Value for &offset=
307 - * @param $backwards bool If true, set &dir=prev
308 - * @return array
309 - */
310 - protected function getQuery( $offset, $backwards ) {
311 - global $wgRequest;
312 - $query = array(
313 - 'type' => $wgRequest->getArray( 'type', array() ),
314 - 'username' => $wgRequest->getVal( 'username' ),
315 - 'offset' => $offset,
316 - );
317 - if ( $backwards ) {
318 - $query['dir'] = 'prev';
319 - }
320 - return $query;
321 - }
322 -}
Index: trunk/extensions/MoodBar/SpecialFeedbackDashboard.php
@@ -0,0 +1,321 @@
 2+<?php
 3+/**
 4+ * Special:MoodBarFeedback. Special page for viewing moodbar comments.
 5+ */
 6+class SpecialMoodBarFeedback extends SpecialPage {
 7+ public function __construct() {
 8+ parent::__construct( 'MoodBarFeedback' );
 9+ }
 10+
 11+ public function getDescription() {
 12+ return wfMessage( 'moodbar-feedback-title' )->plain();
 13+ }
 14+
 15+ public function execute( $par ) {
 16+ global $wgOut, $wgRequest;
 17+
 18+ $limit = 20;
 19+ $offset = false;
 20+ $filterType = '';
 21+ $id = intval( $par );
 22+ if ( $id > 0 ) {
 23+ // Special:MoodBarFeedback/123 is an ID/permalink view
 24+ $filters = array( 'id' => $id );
 25+ $filterType = 'id';
 26+ } else {
 27+ // Determine filters and offset from the query string
 28+ $filters = array();
 29+ $type = $wgRequest->getArray( 'type' );
 30+ if ( $type ) {
 31+ $filters['type'] = $type;
 32+ }
 33+ $username = strval( $wgRequest->getVal( 'username' ) );
 34+ if ( $username !== '' ) {
 35+ $filters['username'] = $username;
 36+ }
 37+ $offset = $wgRequest->getVal( 'offset', $offset );
 38+ if ( count( $filters ) ) {
 39+ $filterType = 'filtered';
 40+ }
 41+ }
 42+ // Do the query
 43+ $backwards = $wgRequest->getVal( 'dir' ) === 'prev';
 44+ $res = $this->doQuery( $filters, $limit, $offset, $backwards );
 45+
 46+ // Output HTML
 47+ $wgOut->setPageTitle( wfMsg( 'moodbar-feedback-title' ) );
 48+ $wgOut->addHTML( $this->buildForm( $filterType ) );
 49+ $wgOut->addHTML( $this->buildList( $res ) );
 50+ $wgOut->addModuleStyles( 'ext.moodBar.dashboard.styles' );
 51+ $wgOut->addModules( 'ext.moodBar.dashboard' );
 52+ }
 53+
 54+ /**
 55+ * Build the filter form. The state of each form element is preserved
 56+ * using data in $wgRequest.
 57+ * @param $filterType string Value to pass in the <form>'s data-filtertype attribute
 58+ * @return string HTML
 59+ */
 60+ public function buildForm( $filterType ) {
 61+ global $wgRequest, $wgMoodBarConfig;
 62+ $filtersMsg = wfMessage( 'moodbar-feedback-filters' )->escaped();
 63+ $typeMsg = wfMessage( 'moodbar-feedback-filters-type' )->escaped();
 64+ $praiseMsg = wfMessage( 'moodbar-feedback-filters-type-happy' )->escaped();
 65+ $confusionMsg = wfMessage( 'moodbar-feedback-filters-type-confused' )->escaped();
 66+ $issuesMsg = wfMessage( 'moodbar-feedback-filters-type-sad' )->escaped();
 67+ $usernameMsg = wfMessage( 'moodbar-feedback-filters-username' )->escaped();
 68+ $setFiltersMsg = wfMessage( 'moodbar-feedback-filters-button' )->escaped();
 69+ $whatIsMsg = wfMessage( 'moodbar-feedback-whatis' )->escaped();
 70+ $whatIsURL = htmlspecialchars( $wgMoodBarConfig['infoUrl'] );
 71+ $actionURL = htmlspecialchars( $this->getTitle()->getLinkURL() );
 72+
 73+ $types = $wgRequest->getArray( 'type', array() );
 74+ $happyCheckbox = Xml::check( 'type[]', in_array( 'happy', $types ),
 75+ array( 'id' => 'fbd-filters-type-praise', 'value' => 'happy' ) );
 76+ $confusedCheckbox = Xml::check( 'type[]', in_array( 'confused', $types ),
 77+ array( 'id' => 'fbd-filters-type-confusion', 'value' => 'confused' ) );
 78+ $sadCheckbox = Xml::check( 'type[]', in_array( 'sad', $types ),
 79+ array( 'id' => 'fbd-filters-type-issues', 'value' => 'sad' ) );
 80+ $usernameTextbox = Html::input( 'username', $wgRequest->getText( 'username' ), 'text',
 81+ array( 'id' => 'fbd-filters-username', 'class' => 'fbd-filters-input' ) );
 82+ $filterType = htmlspecialchars( $filterType );
 83+
 84+ return <<<HTML
 85+ <div id="fbd-filters">
 86+ <form action="$actionURL" data-filtertype="$filterType">
 87+ <h3 id="fbd-filters-title">$filtersMsg</h3>
 88+ <fieldset id="fbd-filters-types">
 89+ <legend class="fbd-filters-label">$typeMsg</legend>
 90+ <ul>
 91+ <li>
 92+ $happyCheckbox
 93+ <label for="fbd-filters-type-praise" id="fbd-filters-type-praise-label">$praiseMsg</label>
 94+ </li>
 95+ <li>
 96+ $confusedCheckbox
 97+ <label for="fbd-filters-type-confusion" id="fbd-filters-type-confusion-label">$confusionMsg</label>
 98+ </li>
 99+ <li>
 100+ $sadCheckbox
 101+ <label for="fbd-filters-type-issues" id="fbd-filters-type-issues-label">$issuesMsg</label>
 102+ </li>
 103+ </ul>
 104+ </fieldset>
 105+ <label for="fbd-filters-username" class="fbd-filters-label">$usernameMsg</label>
 106+ $usernameTextbox
 107+ <button type="submit" id="fbd-filters-set">$setFiltersMsg</button>
 108+ </form>
 109+ <a href="$whatIsURL" id="fbd-about">$whatIsMsg</a>
 110+ </div>
 111+HTML;
 112+ }
 113+
 114+ /**
 115+ * Format a single list item from a database row.
 116+ * @param $row Database row object
 117+ * @return string HTML
 118+ */
 119+ public static function formatListItem( $row ) {
 120+ global $wgLang;
 121+ $type = $row->mbf_type;
 122+ $typeMsg = wfMessage( "moodbar-type-$type" )->escaped();
 123+ $time = $wgLang->formatTimePeriod( wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $row->mbf_timestamp ),
 124+ array( 'avoid' => 'avoidminutes', 'noabbrevs' => true )
 125+ );
 126+ $timeMsg = wfMessage( 'ago' )->params( $time )->escaped();
 127+ $username = htmlspecialchars( $row->user_name === null ? $row->mbf_user_ip : $row->user_name );
 128+ //$links = Linker::userToolLinks( $row->mbf_user_id, $username );
 129+ $links = $GLOBALS['wgUser']->getSkin()->userToolLinks( $row->mbf_user_id, $username ); // 1.17wmf1 compat
 130+ $comment = htmlspecialchars( $row->mbf_comment );
 131+ $permalinkURL = htmlspecialchars( SpecialPage::getTitleFor( 'MoodBarFeedback', $row->mbf_id )->getLinkURL() );
 132+ $permalinkText = wfMessage( 'moodbar-feedback-permalink' )->escaped();
 133+ $continueData = wfTimestamp( TS_MW, $row->mbf_timestamp ) . '|' . intval( $row->mbf_id );
 134+
 135+ return <<<HTML
 136+ <li class="fbd-item" data-mbccontinue="$continueData">
 137+ <div class="fbd-item-emoticon fbd-item-emoticon-$type">
 138+ <span class="fbd-item-emoticon-label">$typeMsg</span>
 139+ </div>
 140+ <div class="fbd-item-time">$timeMsg</div>
 141+ <h3 class="fbd-item-userName">
 142+ <a href="#">$username</a>
 143+ <sup class="fbd-item-userLinks">
 144+ $links
 145+ </sup>
 146+ </h3>
 147+ <div class="fbd-item-message">$comment</div>
 148+ <div class="fbd-item-permalink">(<a href="$permalinkURL">$permalinkText</a>)</div>
 149+ <div style="clear:both"></div>
 150+ </li>
 151+HTML;
 152+ }
 153+
 154+ /**
 155+ * Build a comment list from a query result
 156+ * @param $res array Return value of doQuery()
 157+ * @return string HTML
 158+ */
 159+ public function buildList( $res ) {
 160+ global $wgRequest;
 161+ $list = '';
 162+ foreach ( $res['rows'] as $row ) {
 163+ $list .= self::formatListItem( $row );
 164+ }
 165+
 166+ if ( $list === '' ) {
 167+ return '<div id="fbd-list">' . wfMessage( 'moodbar-feedback-noresults' )->escaped() . '</div>';
 168+ } else {
 169+ // FIXME: We also need to show the More link (hidden) if there were no results
 170+ $olderRow = $res['olderRow'];
 171+ $newerRow = $res['newerRow'];
 172+ $html = "<ul id=\"fbd-list\">$list</ul>";
 173+
 174+ // Output the "More" link
 175+ $moreText = wfMessage( 'moodbar-feedback-more' )->escaped();
 176+ $attribs = array( 'id' => 'fbd-list-more' );
 177+ if ( !$olderRow ) {
 178+ // There are no more rows. Hide the More link
 179+ // We still need to output it because the JS may need it later
 180+ $attribs['style'] = 'display: none;';
 181+ }
 182+ $html .= Html::rawElement( 'div', $attribs, '<a href="#">' . $moreText . '</a>' );
 183+
 184+ // Paging links for no-JS clients
 185+ $olderURL = $newerURL = false;
 186+ if ( $olderRow ) {
 187+ $olderOffset = wfTimestamp( TS_MW, $olderRow->mbf_timestamp ) . '|' . intval( $olderRow->mbf_id );
 188+ $olderURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $olderOffset, false ) ) );
 189+ }
 190+ if ( $newerRow ) {
 191+ $newerOffset = wfTimestamp( TS_MW, $newerRow->mbf_timestamp ) . '|' . intval( $newerRow->mbf_id );
 192+ $newerURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $newerOffset, true ) ) );
 193+ }
 194+ $olderText = wfMessage( 'moodbar-feedback-older' )->escaped();
 195+ $newerText = wfMessage( 'moodbar-feedback-newer' )->escaped();
 196+ $html .= '<div id="fbd-list-newer-older"><div id="fbd-list-newer">';
 197+ if ( $newerURL ) {
 198+ $html .= "<a href=\"$newerURL\">$newerText</a>";
 199+ } else {
 200+ $html .= "<span class=\"fbd-page-disabled\">$newerText</span>";
 201+ }
 202+ $html .= '</div><div id="fbd-list-older">';
 203+ if ( $olderURL ) {
 204+ $html .= "<a href=\"$olderURL\">$olderText</a>";
 205+ } else {
 206+ $html .= "<span class=\"fbd-page-disabled\">$olderText</span>";
 207+ }
 208+ $html .= '</div></div><div style="clear: both;"></div>';
 209+ return $html;
 210+ }
 211+ }
 212+
 213+ /**
 214+ * Get a set of comments from the database.
 215+ *
 216+ * The way paging is handled by this function is a bit weird. $offset is taken from
 217+ * the last row that was displayed, as opposed to the first row that was not displayed.
 218+ * This means that if $offset is set, the first row in the result (the one matching $offset)
 219+ * is dropped, as well as the last row. The dropped rows are only used to detect the presence
 220+ * or absence of more rows in each direction, the offset values for paging are taken from the
 221+ * first and last row that are actually shown.
 222+ *
 223+ * $retval['olderRow'] is the row whose offset should be used to display older rows, or null if
 224+ * there are no older rows. This means that, if there are older rows, $retval['olderRow'] is set
 225+ * to the oldest row in $retval['rows']. $retval['newerRows'] is set similarly.
 226+ *
 227+ * @param $filters array Array of filters to apply. Recognized keys are 'type' (array), 'username' (string) and 'id' (int)
 228+ * @param $limit int Number of comments to fetch
 229+ * @param $offset string Query offset. Timestamp and ID of the last shown result, formatted as 'timestamp|id'
 230+ * @param $backwards bool If true, page in ascending order rather than descending order, i.e. get $limit rows after $offset rather than before $offset. The result will still be sorted in descending order
 231+ * @return array( 'rows' => array( row, row, ... ), 'olderRow' => row|null, 'newerRow' => row|null )
 232+ */
 233+ public function doQuery( $filters, $limit, $offset, $backwards ) {
 234+ $dbr = wfGetDB( DB_SLAVE );
 235+
 236+ // Set $conds based on $filters
 237+ $conds = array();
 238+ if ( isset( $filters['type'] ) ) {
 239+ $conds['mbf_type'] = $filters['type'];
 240+ }
 241+ if ( isset( $filters['username'] ) ) {
 242+ $user = User::newFromName( $filters['username'] ); // Returns false for IPs
 243+ if ( !$user || $user->isAnon() ) {
 244+ $conds['mbf_user_id'] = 0;
 245+ $conds['mbf_user_ip'] = $filters['username'];
 246+ } else {
 247+ $conds['mbf_user_id'] = $user->getID();
 248+ $conds[] = 'mbf_user_ip IS NULL';
 249+ }
 250+ }
 251+ if ( isset( $filters['id'] ) ) {
 252+ $conds['mbf_id'] = $filters['id'];
 253+ }
 254+
 255+ // Process $offset
 256+ if ( $offset !== false ) {
 257+ $arr = explode( '|', $offset, 2 );
 258+ $ts = $dbr->addQuotes( $dbr->timestamp( $arr[0] ) );
 259+ $id = isset( $arr[1] ) ? intval( $arr[1] ) : 0;
 260+ $op = $backwards ? '>' : '<';
 261+ $conds[] = "mbf_timestamp $op $ts OR (mbf_timestamp = $ts AND mbf_id $op= $id)";
 262+ }
 263+
 264+ // Do the actual query
 265+ $desc = $backwards ? '' : ' DESC';
 266+ $res = $dbr->select( array( 'moodbar_feedback', 'user' ), array(
 267+ 'user_name', 'mbf_id', 'mbf_type',
 268+ 'mbf_timestamp', 'mbf_user_id', 'mbf_user_ip', 'mbf_comment'
 269+ ),
 270+ $conds,
 271+ __METHOD__,
 272+ array( 'LIMIT' => $limit + 2, 'ORDER BY' => "mbf_timestamp$desc, mbf_id$desc" ),
 273+ array( 'user' => array( 'LEFT JOIN', 'user_id=mbf_user_id' ) )
 274+ );
 275+ $rows = iterator_to_array( $res, /*$use_keys=*/false );
 276+
 277+ // Figure out whether there are newer and older rows
 278+ $olderRow = $newerRow = null;
 279+ $count = count( $rows );
 280+ if ( $offset && $count > 0 ) {
 281+ // If there is an offset, drop the first row
 282+ if ( $count > 1 ) {
 283+ array_shift( $rows );
 284+ $count--;
 285+ }
 286+ // We now know there is a previous row
 287+ $newerRow = $rows[0];
 288+ }
 289+ if ( $count > $limit ) {
 290+ // If there are rows past the limit, drop them
 291+ array_splice( $rows, $limit );
 292+ // We now know there is a next row
 293+ $olderRow = $rows[$limit - 1];
 294+ }
 295+
 296+ // If we got things backwards, reverse them
 297+ if ( $backwards ) {
 298+ $rows = array_reverse( $rows );
 299+ list( $olderRow, $newerRow ) = array( $newerRow, $olderRow );
 300+ }
 301+ return array( 'rows' => $rows, 'olderRow' => $olderRow, 'newerRow' => $newerRow );
 302+ }
 303+
 304+ /**
 305+ * Get a query string array for a given offset, using filter parameters obtained from $wgRequest.
 306+ * @param $offset string Value for &offset=
 307+ * @param $backwards bool If true, set &dir=prev
 308+ * @return array
 309+ */
 310+ protected function getQuery( $offset, $backwards ) {
 311+ global $wgRequest;
 312+ $query = array(
 313+ 'type' => $wgRequest->getArray( 'type', array() ),
 314+ 'username' => $wgRequest->getVal( 'username' ),
 315+ 'offset' => $offset,
 316+ );
 317+ if ( $backwards ) {
 318+ $query['dir'] = 'prev';
 319+ }
 320+ return $query;
 321+ }
 322+}
Property changes on: trunk/extensions/MoodBar/SpecialFeedbackDashboard.php
___________________________________________________________________
Added: svn:eol-style
1323 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r98230MoodBar: Rename Special:MoodBarFeedback to Special:FeedbackDashboard, part de...catrope16:17, 27 September 2011

Status & tagging log