r98004 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98003‎ | r98004 | r98005 >
Date:15:19, 24 September 2011
Author:catrope
Status:ok (Comments)
Tags:
Comment:
SpecialMoodBarFeedback: Implement backwards paging
* Move query result post-processing logic into doQuery()
* Run the query backwards if &dir=prev is set, and set this on "Newer" links
* Request 2 extra rows and drop the first and last ones in certain circumstances. This involves some voodoo to figure out whether there are previous/next rows. The values of those rows are NOT used: we always set the offset to the value of the first/last displayed row, so the next request will grab that row then drop it.
* Use iterator_to_array( $rows, false ) because of a very weird issue I got where iterator_to_array() sometimes returns array( 1 => rowObj ). Passing false for the second parameter forces re-indexation
* Return an array structure from doQuery() with the rows to display, the row with the data for the newer link, and the row with the data for the older link
Modified paths:
  • /trunk/extensions/MoodBar/SpecialMoodBarFeedback.php (modified) (history)

Diff [purge]

Index: trunk/extensions/MoodBar/SpecialMoodBarFeedback.php
@@ -31,17 +31,13 @@
3232 $offset = $wgRequest->getVal( 'offset', $offset );
3333 }
3434 // Do the query
35 - $res = $this->doQuery( $filters, $limit + 1, $offset );
36 - $rows = iterator_to_array( $res );
37 - $lastRow = null;
38 - if ( count( $rows ) == $limit + 1 ) {
39 - $lastRow = array_pop( $rows );
40 - }
41 -
 35+ $backwards = $wgRequest->getVal( 'dir' ) === 'prev';
 36+ $res = $this->doQuery( $filters, $limit, $offset, $backwards );
 37+
4238 // Output HTML
4339 $wgOut->setPageTitle( wfMsg( 'moodbar-feedback-title' ) );
4440 $wgOut->addHTML( $this->buildForm() );
45 - $wgOut->addHTML( $this->buildList( $rows, $lastRow ) );
 41+ $wgOut->addHTML( $this->buildList( $res ) );
4642 $wgOut->addModuleStyles( 'ext.moodBar.dashboard.styles' );
4743 }
4844
@@ -98,12 +94,11 @@
9995 HTML;
10096 }
10197
102 - public function buildList( $rows, $lastRow ) {
 98+ public function buildList( $res ) {
10399 global $wgLang, $wgRequest;
104100 $now = wfTimestamp( TS_UNIX );
105101 $list = '';
106 - $firstRow = false; // TODO support the "Newer" link with this
107 - foreach ( $rows as $row ) {
 102+ foreach ( $res['rows'] as $row ) {
108103 $type = $row->mbf_type;
109104 $typeMsg = wfMessage( "moodbar-type-$type" )->escaped();
110105 $time = $wgLang->formatTimePeriod( $now - wfTimestamp( TS_UNIX, $row->mbf_timestamp ),
@@ -134,23 +129,28 @@
135130 </li>
136131 HTML;
137132 }
 133+
138134 if ( $list === '' ) {
139135 return '<div id="fbd-list">' . wfMessage( 'moodbar-feedback-noresults' )->escaped() . '</div>';
140136 } else {
141137 // Only show paging stuff if the result is not empty and there are more results
 138+ $olderRow = $res['olderRow'];
 139+ $newerRow = $res['newerRow'];
142140 $html = "<ul id=\"fbd-list\">$list</ul>";
143 - if ( $lastRow ) {
 141+ if ( $olderRow ) {
144142 $moreText = wfMessage( 'moodbar-feedback-more' )->escaped();
145143 $html .= '<div id="fbd-list-more"><a href="#">' . $moreText . '</a></div>';
146144 }
147145
148146 $olderURL = $newerURL = false;
149 - if ( $lastRow ) {
150 - $offset = wfTimestamp( TS_MW, $lastRow->mbf_timestamp ) . '|' . intval( $lastRow->mbf_id );
151 - $olderURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $offset ) ) );
 147+ if ( $olderRow ) {
 148+ $olderOffset = wfTimestamp( TS_MW, $olderRow->mbf_timestamp ) . '|' . intval( $olderRow->mbf_id );
 149+ $olderURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $olderOffset, false ) ) );
152150 }
153 - if ( $firstRow ) {
154 - $newerURL = htmlspecialchars( '#' ); // TODO
 151+ if ( $newerRow ) {
 152+ // TODO: Figure out when there are no newer rows
 153+ $newerOffset = wfTimestamp( TS_MW, $newerRow->mbf_timestamp ) . '|' . intval( $newerRow->mbf_id );
 154+ $newerURL = htmlspecialchars( $this->getTitle()->getLinkURL( $this->getQuery( $newerOffset, true ) ) );
155155 }
156156 $olderText = wfMessage( 'moodbar-feedback-older' )->escaped();
157157 $newerText = wfMessage( 'moodbar-feedback-newer' )->escaped();
@@ -171,7 +171,7 @@
172172 }
173173 }
174174
175 - public function doQuery( $filters, $limit, $offset ) {
 175+ public function doQuery( $filters, $limit, $offset, $backwards ) {
176176 $dbr = wfGetDB( DB_SLAVE );
177177 $conds = array();
178178 if ( isset( $filters['type'] ) ) {
@@ -194,26 +194,59 @@
195195 $arr = explode( '|', $offset, 2 );
196196 $ts = $dbr->addQuotes( $dbr->timestamp( $arr[0] ) );
197197 $id = isset( $arr[1] ) ? intval( $arr[1] ) : 0;
198 - $conds[] = "mbf_timestamp < $ts OR (mbf_timestamp = $ts AND mbf_id <= $id)";
 198+ $op = $backwards ? '>' : '<';
 199+ $conds[] = "mbf_timestamp $op $ts OR (mbf_timestamp = $ts AND mbf_id $op= $id)";
199200 }
200201
201 - return $dbr->select( array( 'moodbar_feedback', 'user' ), array(
 202+ $desc = $backwards ? '' : ' DESC';
 203+ $res = $dbr->select( array( 'moodbar_feedback', 'user' ), array(
202204 'user_name', 'mbf_id', 'mbf_type',
203205 'mbf_timestamp', 'mbf_user_id', 'mbf_user_ip', 'mbf_comment'
204206 ),
205207 $conds,
206208 __METHOD__,
207 - array( 'LIMIT' => $limit, 'ORDER BY' => 'mbf_timestamp DESC, mbf_id DESC' ),
 209+ array( 'LIMIT' => $limit + 2, 'ORDER BY' => "mbf_timestamp$desc, mbf_id$desc" ),
208210 array( 'user' => array( 'LEFT JOIN', 'user_id=mbf_user_id' ) )
209211 );
 212+ $rows = iterator_to_array( $res, /*$use_keys=*/false );
 213+
 214+ // Figure out whether there are newer and older rows
 215+ $olderRow = $newerRow = null;
 216+ $count = count( $rows );
 217+ if ( $offset && $count > 0 ) {
 218+ // If there is an offset, drop the first row
 219+ if ( $count > 1 ) {
 220+ array_shift( $rows );
 221+ $count--;
 222+ }
 223+ // We now know there is a previous row
 224+ $newerRow = $rows[0];
 225+ }
 226+ if ( $count > $limit ) {
 227+ // If there are rows past the limit, drop them
 228+ array_splice( $rows, $limit );
 229+ // We now know there is a next row
 230+ $olderRow = $rows[$limit - 1];
 231+ }
 232+
 233+ // If we got everything backwards, reverse it
 234+ if ( $backwards ) {
 235+ $rows = array_reverse( $rows );
 236+ list( $olderRow, $newerRow ) = array( $newerRow, $olderRow );
 237+ }
 238+ return array( 'rows' => $rows, 'olderRow' => $olderRow, 'newerRow' => $newerRow );
210239 }
211240
212 - protected function getQuery( $offset ) {
 241+ protected function getQuery( $offset, $backwards ) {
213242 global $wgRequest;
214 - return array(
 243+ $query = array(
215244 'type' => $wgRequest->getArray( 'type', array() ),
216245 'username' => $wgRequest->getVal( 'username' ),
217246 'offset' => $offset,
218247 );
 248+ if ( $backwards ) {
 249+ $query['dir'] = 'prev';
 250+ }
 251+ return $query;
219252 }
220253 }

Comments

#Comment by Tim Starling (talk | contribs)   05:49, 30 December 2011

Backwards paging is tricky isn't it? I just wanted to plug IndexPager again ;) This really is the problem it was invented for.

Status & tagging log