MediaWiki
REL1_24
|
00001 <?php 00028 abstract class TablePager extends IndexPager { 00029 protected $mSort; 00030 00031 protected $mCurrentRow; 00032 00033 public function __construct( IContextSource $context = null ) { 00034 if ( $context ) { 00035 $this->setContext( $context ); 00036 } 00037 00038 $this->mSort = $this->getRequest()->getText( 'sort' ); 00039 if ( !array_key_exists( $this->mSort, $this->getFieldNames() ) 00040 || !$this->isFieldSortable( $this->mSort ) 00041 ) { 00042 $this->mSort = $this->getDefaultSort(); 00043 } 00044 if ( $this->getRequest()->getBool( 'asc' ) ) { 00045 $this->mDefaultDirection = IndexPager::DIR_ASCENDING; 00046 } elseif ( $this->getRequest()->getBool( 'desc' ) ) { 00047 $this->mDefaultDirection = IndexPager::DIR_DESCENDING; 00048 } /* Else leave it at whatever the class default is */ 00049 00050 parent::__construct(); 00051 } 00052 00067 final public function getBody() { 00068 $this->getOutput()->addModuleStyles( $this->getModuleStyles() ); 00069 return parent::getBody(); 00070 } 00071 00081 public function getBodyOutput() { 00082 $body = parent::getBody(); 00083 00084 $pout = new ParserOutput; 00085 $pout->setText( $body ); 00086 $pout->addModuleStyles( $this->getModuleStyles() ); 00087 return $pout; 00088 } 00089 00099 public function getFullOutput() { 00100 $navigation = $this->getNavigationBar(); 00101 $body = parent::getBody(); 00102 00103 $pout = new ParserOutput; 00104 $pout->setText( $navigation . $body . $navigation ); 00105 $pout->addModuleStyles( $this->getModuleStyles() ); 00106 return $pout; 00107 } 00108 00113 function getStartBody() { 00114 $sortClass = $this->getSortHeaderClass(); 00115 00116 $s = ''; 00117 $fields = $this->getFieldNames(); 00118 00119 // Make table header 00120 foreach ( $fields as $field => $name ) { 00121 if ( strval( $name ) == '' ) { 00122 $s .= Html::rawElement( 'th', array(), ' ' ) . "\n"; 00123 } elseif ( $this->isFieldSortable( $field ) ) { 00124 $query = array( 'sort' => $field, 'limit' => $this->mLimit ); 00125 $linkType = null; 00126 $class = null; 00127 00128 if ( $this->mSort == $field ) { 00129 // The table is sorted by this field already, make a link to sort in the other direction 00130 // We don't actually know in which direction other fields will be sorted by default… 00131 if ( $this->mDefaultDirection == IndexPager::DIR_DESCENDING ) { 00132 $linkType = 'asc'; 00133 $class = "$sortClass TablePager_sort-descending"; 00134 $query['asc'] = '1'; 00135 $query['desc'] = ''; 00136 } else { 00137 $linkType = 'desc'; 00138 $class = "$sortClass TablePager_sort-ascending"; 00139 $query['asc'] = ''; 00140 $query['desc'] = '1'; 00141 } 00142 } 00143 00144 $link = $this->makeLink( htmlspecialchars( $name ), $query, $linkType ); 00145 $s .= Html::rawElement( 'th', array( 'class' => $class ), $link ) . "\n"; 00146 } else { 00147 $s .= Html::element( 'th', array(), $name ) . "\n"; 00148 } 00149 } 00150 00151 $tableClass = $this->getTableClass(); 00152 $ret = Html::openElement( 'table', array( 00153 'class' => "mw-datatable $tableClass" ) 00154 ); 00155 $ret .= Html::rawElement( 'thead', array(), Html::rawElement( 'tr', array(), "\n" . $s . "\n" ) ); 00156 $ret .= Html::openElement( 'tbody' ) . "\n"; 00157 00158 return $ret; 00159 } 00160 00165 function getEndBody() { 00166 return "</tbody></table>\n"; 00167 } 00168 00173 function getEmptyBody() { 00174 $colspan = count( $this->getFieldNames() ); 00175 $msgEmpty = $this->msg( 'table_pager_empty' )->text(); 00176 return Html::rawElement( 'tr', array(), 00177 Html::element( 'td', array( 'colspan' => $colspan ), $msgEmpty ) ); 00178 } 00179 00185 function formatRow( $row ) { 00186 $this->mCurrentRow = $row; // In case formatValue etc need to know 00187 $s = Html::openElement( 'tr', $this->getRowAttrs( $row ) ) . "\n"; 00188 $fieldNames = $this->getFieldNames(); 00189 00190 foreach ( $fieldNames as $field => $name ) { 00191 $value = isset( $row->$field ) ? $row->$field : null; 00192 $formatted = strval( $this->formatValue( $field, $value ) ); 00193 00194 if ( $formatted == '' ) { 00195 $formatted = ' '; 00196 } 00197 00198 $s .= Html::rawElement( 'td', $this->getCellAttrs( $field, $value ), $formatted ) . "\n"; 00199 } 00200 00201 $s .= Html::closeElement( 'tr' ) . "\n"; 00202 00203 return $s; 00204 } 00205 00214 function getRowClass( $row ) { 00215 return ''; 00216 } 00217 00226 function getRowAttrs( $row ) { 00227 $class = $this->getRowClass( $row ); 00228 if ( $class === '' ) { 00229 // Return an empty array to avoid clutter in HTML like class="" 00230 return array(); 00231 } else { 00232 return array( 'class' => $this->getRowClass( $row ) ); 00233 } 00234 } 00235 00247 function getCellAttrs( $field, $value ) { 00248 return array( 'class' => 'TablePager_col_' . $field ); 00249 } 00250 00255 function getIndexField() { 00256 return $this->mSort; 00257 } 00258 00263 function getTableClass() { 00264 return 'TablePager'; 00265 } 00266 00271 function getNavClass() { 00272 return 'TablePager_nav'; 00273 } 00274 00279 function getSortHeaderClass() { 00280 return 'TablePager_sort'; 00281 } 00282 00287 public function getNavigationBar() { 00288 if ( !$this->isNavigationBarShown() ) { 00289 return ''; 00290 } 00291 00292 $labels = array( 00293 'first' => 'table_pager_first', 00294 'prev' => 'table_pager_prev', 00295 'next' => 'table_pager_next', 00296 'last' => 'table_pager_last', 00297 ); 00298 00299 $linkTexts = array(); 00300 $disabledTexts = array(); 00301 foreach ( $labels as $type => $label ) { 00302 $msgLabel = $this->msg( $label )->escaped(); 00303 $linkTexts[$type] = "<div class='TablePager_nav-enabled'>$msgLabel</div>"; 00304 $disabledTexts[$type] = "<div class='TablePager_nav-disabled'>$msgLabel</div>"; 00305 } 00306 $links = $this->getPagingLinks( $linkTexts, $disabledTexts ); 00307 00308 $s = Html::openElement( 'table', array( 'class' => $this->getNavClass() ) ); 00309 $s .= Html::openElement( 'tr' ) . "\n"; 00310 $width = 100 / count( $links ) . '%'; 00311 foreach ( $labels as $type => $label ) { 00312 // We want every cell to have the same width. We could use table-layout: fixed; in CSS, 00313 // but it only works if we specify the width of a cell or the table and we don't want to. 00314 // There is no better way. <http://www.w3.org/TR/CSS2/tables.html#fixed-table-layout> 00315 $s .= Html::rawElement( 'td', 00316 array( 'style' => "width: $width;", 'class' => "TablePager_nav-$type" ), 00317 $links[$type] ) . "\n"; 00318 } 00319 $s .= Html::closeElement( 'tr' ) . Html::closeElement( 'table' ) . "\n"; 00320 return $s; 00321 } 00322 00328 public function getModuleStyles() { 00329 return array( 'mediawiki.pager.tablePager' ); 00330 } 00331 00338 public function getLimitSelect( $attribs = array() ) { 00339 $select = new XmlSelect( 'limit', false, $this->mLimit ); 00340 $select->addOptions( $this->getLimitSelectList() ); 00341 foreach ( $attribs as $name => $value ) { 00342 $select->setAttribute( $name, $value ); 00343 } 00344 return $select->getHTML(); 00345 } 00346 00354 public function getLimitSelectList() { 00355 # Add the current limit from the query string 00356 # to avoid that the limit is lost after clicking Go next time 00357 if ( !in_array( $this->mLimit, $this->mLimitsShown ) ) { 00358 $this->mLimitsShown[] = $this->mLimit; 00359 sort( $this->mLimitsShown ); 00360 } 00361 $ret = array(); 00362 foreach ( $this->mLimitsShown as $key => $value ) { 00363 # The pair is either $index => $limit, in which case the $value 00364 # will be numeric, or $limit => $text, in which case the $value 00365 # will be a string. 00366 if ( is_int( $value ) ) { 00367 $limit = $value; 00368 $text = $this->getLanguage()->formatNum( $limit ); 00369 } else { 00370 $limit = $key; 00371 $text = $value; 00372 } 00373 $ret[$text] = $limit; 00374 } 00375 return $ret; 00376 } 00377 00386 function getHiddenFields( $blacklist = array() ) { 00387 $blacklist = (array)$blacklist; 00388 $query = $this->getRequest()->getQueryValues(); 00389 foreach ( $blacklist as $name ) { 00390 unset( $query[$name] ); 00391 } 00392 $s = ''; 00393 foreach ( $query as $name => $value ) { 00394 $s .= Html::hidden( $name, $value ) . "\n"; 00395 } 00396 return $s; 00397 } 00398 00404 function getLimitForm() { 00405 return Html::rawElement( 00406 'form', 00407 array( 00408 'method' => 'get', 00409 'action' => wfScript(), 00410 ), 00411 "\n" . $this->getLimitDropdown() 00412 ) . "\n"; 00413 } 00414 00420 function getLimitDropdown() { 00421 # Make the select with some explanatory text 00422 $msgSubmit = $this->msg( 'table_pager_limit_submit' )->escaped(); 00423 00424 return $this->msg( 'table_pager_limit' ) 00425 ->rawParams( $this->getLimitSelect() )->escaped() . 00426 "\n<input type=\"submit\" value=\"$msgSubmit\"/>\n" . 00427 $this->getHiddenFields( array( 'limit' ) ); 00428 } 00429 00436 abstract function isFieldSortable( $field ); 00437 00450 abstract function formatValue( $name, $value ); 00451 00459 abstract function getDefaultSort(); 00460 00468 abstract function getFieldNames(); 00469 }