MediaWiki  REL1_24
TablePager.php
Go to the documentation of this file.
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(), '&#160;' ) . "\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 = '&#160;';
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 }