WPDK  1.5.0
WordPress Development Kit
 All Data Structures Files Functions Variables Pages
wpdk-listtable-viewcontroller.php
Go to the documentation of this file.
1 <?php
2 if ( !class_exists( 'WP_List_Table' ) ) {
3  require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
4 }
5 
21 class WPDKListTableViewController extends WP_List_Table {
22 
26  const GET_STATUS = 'status';
27 
35  public $id;
36 
44  public $title;
45 
54 
62  public $getStatusID;
63 
71  protected $args;
72 
81  public $model;
82 
90  public $column_headers = array();
91 
106  public function __construct( $id, $title, $args )
107  {
108  // Create an instance of WP_List_Table class
109  parent::__construct( $args );
110 
111  // Set static properties.
112  $this->id = sanitize_key( $id );
113  $this->title = $title;
114  $this->args = $args;
115  $this->getStatusID = self::GET_STATUS;
116 
117  // Init the internal view controller.
118  $this->viewController = new WPDKViewController( $this->id, $this->title );
119  $this->viewController->view->class[] = 'wpdk-list-table-box';
120 
121  }
122 
123  // -------------------------------------------------------------------------------------------------------------------
124  // Ask information to override to custom
125  // -------------------------------------------------------------------------------------------------------------------
126 
136  public function get_columns()
137  {
138  return array();
139  }
140 
150  public function get_statuses()
151  {
152  return array();
153  }
154 
165  public function get_status( $status )
166  {
167  return;
168  }
169 
181  public function get_actions_with_status( $item, $status )
182  {
183  return array();
184  }
185 
196  public function get_bulk_actions_with_status( $status )
197  {
198  return array();
199  }
200 
208  public static function action()
209  {
210  if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] ) {
211  return $_REQUEST['action'];
212  }
213 
214  if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] ) {
215  return $_REQUEST['action2'];
216  }
217 
218  return false;
219  }
220 
221  // -------------------------------------------------------------------------------------------------------------------
222  // Private Utility
223  // -------------------------------------------------------------------------------------------------------------------
224 
248  private function _defaultStatus()
249  {
250  $default_status = '';
251  $statuses = $this->get_statuses();
252  foreach ( $statuses as $status ) {
253  if ( is_array( $status ) && true === $status[1] ) {
254  $default_status = $status[0];
255  break;
256  }
257  elseif ( empty( $default_status ) ) {
258  $default_status = $status;
259  break;
260  }
261  }
262  return $default_status;
263  }
264 
272  private function _defaultSortableColumn()
273  {
274  $sortable_columns = $this->get_sortable_columns();
275  if ( !empty( $sortable_columns ) ) {
276  foreach ( $sortable_columns as $column_name => $value ) {
277  if ( true === $value[1] ) {
278  return $column_name;
279  }
280  }
281  }
282  return false;
283  }
284 
292  private function _currentViewStatus()
293  {
294  $current_status = isset( $_REQUEST[$this->getStatusID] ) ? $_REQUEST[$this->getStatusID] : $this->_defaultStatus();
295  return $current_status;
296  }
297 
298  // -------------------------------------------------------------------------------------------------------------------
299  // Utility for select
300  // -------------------------------------------------------------------------------------------------------------------
301 
311  private function _SQLDefaultOrder( $default_order = 'ASC' )
312  {
313  $column_name = $this->_defaultSortableColumn();
314  $order_by = isset( $_GET['order_by'] ) ? $_GET['order_by'] : $column_name;
315  $order = isset( $_GET['order'] ) ? $_GET['order'] : $default_order;
316  return sprintf( '%s %s', $order_by, $order );
317  }
318 
326  private function _SQLStatus()
327  {
328  $status_field = $this->getStatusID;
329  $current_status = $this->_currentViewStatus();
330 
331  return sprintf( ' AND %s = "%s"', $status_field, $current_status );
332  }
333 
334 
335  // -------------------------------------------------------------------------------------------------------------------
336  // WPDKViewController Interface
337  // -------------------------------------------------------------------------------------------------------------------
338 
343  public function load()
344  {
345  }
346 
351  public function admin_head()
352  {
353  }
354 
359  public function _admin_head()
360  {
361  }
362 
366  public static function willLoad()
367  {
368  }
369 
373  public static function didHeadLoad()
374  {
375  }
376 
377  // -------------------------------------------------------------------------------------------------------------------
378  // Display
379  // -------------------------------------------------------------------------------------------------------------------
380 
386  public function display()
387  {
388  echo $this->html();
389  }
390 
401  public function html()
402  {
403  /* Buffering... */
404  ob_start();
405 
406  /* Fetch, prepare, sort, and filter our data... */
407  if ( !$this->prepare_items() ) :
408  $this->views(); ?>
409 
410  <form id="<?php echo $this->id ?>" class="wpdk-list-table-form" method="get" action="">
411 
412  <?php if ( isset( $_REQUEST['page'] ) ) : ?>
413  <input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>" />
414  <?php endif; ?>
415 
416  <?php if ( isset( $_REQUEST['post_type'] ) ) : ?>
417  <input type="hidden" name="post_type" value="<?php echo $_REQUEST['post_type'] ?>" />
418  <?php endif; ?>
419 
420  <?php if ( isset( $_REQUEST['orderby'] ) ) : ?>
421  <input type="hidden" name="orderby" value="<?php echo $_REQUEST['orderby'] ?>" />
422  <?php endif; ?>
423 
424  <?php if ( isset( $_REQUEST['order'] ) ) : ?>
425  <input type="hidden" name="order" value="<?php echo $_REQUEST['order'] ?>" />
426  <?php endif; ?>
427 
428  <?php do_action( 'wpdk_list_table_form', $this ); ?>
429  <?php unset( $_REQUEST['action'] ); ?>
430  <?php $_SERVER['REQUEST_URI'] = remove_query_arg( array( 'action', '_wp_http_referer', '_wp_nonce' ), $_SERVER['REQUEST_URI']); ?>
431 
432  <?php parent::display() ?>
433 
434  </form>
435  <?php endif; ?>
436  <?php
437  $content = ob_get_contents();
438  ob_end_clean();
439 
440  $this->viewController->viewHead->content = $content;
441 
442  add_action( 'wpdk_header_view_title_did_appear', array( $this, 'wpdk_header_view_title_did_appear' ) );
443 
444  return $this->viewController->html();
445  }
446 
454  public function wpdk_header_view_title_did_appear( $view )
455  {
456  if ( 'new' != $this->current_action() ) {
457  $add_new = sprintf( '<a class="wpdk-add-new button button-primary" href="%s">%s</a>', $this->urlAddNew(), __( 'Add New', WPDK_TEXTDOMAIN ) );
458  $add_new = apply_filters( 'wpdk_listtable_viewcontroller_add_new', $add_new, $this );
459  if ( !empty( $add_new ) ) {
460  echo $add_new;
461  }
462  }
463  }
464 
465  // -------------------------------------------------------------------------------------------------------------------
466  // Override standard WP_List_Table
467  // -------------------------------------------------------------------------------------------------------------------
468 
476  public function no_items()
477  {
478  /* Default message. */
479  printf( __( 'No %s found.', WPDK_TEXTDOMAIN ), $this->title );
480 
481  /* If in search mode. */
482  /* @todo Find a way to determine if we are in 'search' mode or not */
483  echo '<br/>';
484  _e( 'Please, check again your search parameters.', WPDK_TEXTDOMAIN );
485  }
486 
507  public function get_views()
508  {
509  // Prepare return
510  $views = array();
511 
512  // Status
513  $get_status_id = $this->getStatusID;
514  $filter_status = isset( $_GET[$get_status_id] ) ? $_GET[$get_status_id] : $this->_defaultStatus();
515 
516  // URI
517  $uri = ( isset( $_SERVER['HTTP_REFERER'] ) && wpdk_is_ajax() ) ? $_SERVER['HTTP_REFERER'] : false;
518 
519  foreach ( $this->get_statuses() as $key => $status ) {
520 
521  // See _defaultStatus() for detail for this array.
522  $status = is_array( $status ) ? $status[0] : $status;
523 
524  // Recompute!
525  $count = $this->get_status( $key );
526  if ( !empty( $count ) ) {
527 
528  $current = ( $filter_status == $key ) ? 'class="current"' : '';
529  $args = array(
530  'status' => $key,
531  'paged' => false,
532  'action' => false,
533  $this->_args['singular'] => false
534  );
535  $href = add_query_arg( $args, $uri );
536 
537  $views[$key] = sprintf( '<a %s href="%s">%s <span class="count">(%s)</span></a>', $current, $href, $status, $count );
538  }
539  }
540  return $views;
541  }
542 
550  public function statuses( $statuses )
551  {
552  return $statuses;
553  }
554 
563  public function prepare_items()
564  {
569  if ( $this->process_bulk_action() ) {
570  return true;
571  }
572 
573  // First, lets decide how many records per page to show.
574  $id_user = get_current_user_id();
575 
579  $screen = get_current_screen();
580 
581  $option = $screen->get_option( 'per_page', 'option' );
582  if( !empty( $option ) ) {
583  $per_page = get_user_meta( $id_user, $option, true );
584  }
585 
586  if ( empty ( $per_page ) || $per_page < 1 ) {
587  $per_page = $screen->get_option( 'per_page', 'default' );
588  if( empty( $per_page ) ) {
589  $per_page = 10;
590  }
591  }
592 
593  // Columns Header
594  $this->column_headers = $this->get_column_info();
595 
596  // This is required because some GET params keep in the url
597  $remove = array( 'action' );
598  $_SERVER['REQUEST_URI'] = remove_query_arg( $remove, stripslashes( $_SERVER['REQUEST_URI'] ) );
599 
600  // Get data.
601  $data = $this->data();
602 
608  $current_page = $this->get_pagenum();
609 
616  $total_items = apply_filters( 'wpdk_listtable_total_items_' . $this->id, count( $data ) );
617 
623  $slice_data = array_slice( $data, ( ( $current_page - 1 ) * $per_page ), $per_page );
624 
629  $this->items = apply_filters( 'wpdk_listtable_items_' . $this->id, $slice_data, $data );
630 
634  $args = array(
635  'total_items' => $total_items,
636  'per_page' => $per_page,
637  'total_pages' => ceil( $total_items / $per_page )
638  );
639  $this->set_pagination_args( $args );
640  return false;
641  }
642 
643  // -------------------------------------------------------------------------------------------------------------------
644  // To override
645  // -------------------------------------------------------------------------------------------------------------------
646 
654  public function data()
655  {
656  if( !empty( $this->model ) && method_exists( $this->model, 'select' ) ) {
657  return $this->model->select( $_REQUEST );
658  }
659  return array();
660  }
661 
674  public function column_default( $item, $column_name )
675  {
676  switch ( $column_name ) {
677  default:
678  return print_r( $item, true );
679  }
680  }
681 
698  public function actions_column( $item, $column_name = 'description', $item_status = '', $custom_content = '' )
699  {
700  /* Get the current view status. */
701  $status = $this->_currentViewStatus();
702 
703  if ( !empty( $item_status ) ) {
704  $status = $item_status;
705  }
706 
707  $stack = array();
708  foreach ( $this->get_actions_with_status( $item, $status ) as $action => $label ) {
709  if ( !empty( $action ) ) {
710  $args = array(
711  'action' => $action,
712  $this->args['singular'] => $item[$this->args['singular']]
713  );
714  $href = apply_filters( 'wpdk_listtable_action_' . $action, add_query_arg( $args ), $args );
715  $stack[$action] = sprintf( '<a href="%s">%s</a>', $href, $label );
716  }
717  }
718 
719  $description = empty( $custom_content ) ? sprintf( '<strong>%s</strong>', $item[$column_name] ) : $custom_content;
720  return sprintf( '%s %s', $description, $this->row_actions( $stack ) );
721  }
722 
734  public function column_cb( $item )
735  {
736  $name = $this->args['singular'];
737  $value = $item[$name];
738  return sprintf( '<input type="checkbox" name="%s[]" value="%s" />', $name, $value );
739  }
740 
748  public function get_bulk_actions()
749  {
750  /* Get the current status, could be empty. */
751  $current_status = isset( $_REQUEST[$this->getStatusID] ) ? $_REQUEST[$this->getStatusID] : $this->_defaultStatus();
752  return $this->get_bulk_actions_with_status( $current_status );
753  }
754 
755  // -------------------------------------------------------------------------------------------------------------------
756  // Bulk and single actions
757  // -------------------------------------------------------------------------------------------------------------------
758 
768  public function process_bulk_action()
769  {
770  die( __METHOD__ . ' must be over-ridden in a sub-class.' );
771  }
772 
773  // -------------------------------------------------------------------------------------------------------------------
774  // Utility for Bulk actions
775  // -------------------------------------------------------------------------------------------------------------------
776 
789  public static function actions( $args, $status )
790  {
791 
792  $id = key( $args );
793  $id_value = $args[$id];
794  $actions = array();
795 
796  foreach ( $args['actions'] as $key => $label ) {
797  $args = array(
798  'action' => $key,
799  $id => $id_value
800  );
801  $href = add_query_arg( $args );
802  $actions[$key] = sprintf( '<a href="%s">%s</a>', $href, $label );
803  }
804 
805  if ( empty( $status ) || $status != 'trash' ) {
806  unset( $actions['untrash'] );
807  unset( $actions['delete'] );
808  }
809  else if ( $status == 'trash' ) {
810  unset( $actions['edit'] );
811  unset( $actions['trash'] );
812  }
813 
814  return $actions;
815  }
816 
817  // -------------------------------------------------------------------------------------------------------------------
818  // Utility for build url
819  // -------------------------------------------------------------------------------------------------------------------
820 
828  public function urlRemveAction()
829  {
830  $remove = array(
831  'action',
832  $this->_args['singular']
833  );
834  $url = remove_query_arg( $remove, stripslashes( $_SERVER['REQUEST_URI'] ) );
835  return $url;
836  }
837 
845  public function urlRemoveNonce()
846  {
847  $remove = array(
848  '_wp_http_referer',
849  '_wpnonce',
850  $this->_args['singular']
851  );
852  $url = remove_query_arg( $remove, stripslashes( $_SERVER['REQUEST_URI'] ) );
853  return $url;
854  }
855 
863  public function urlAddNew()
864  {
865  $add = array(
866  'action' => 'new',
867  'page' => $_REQUEST['page']
868  );
869  $url = add_query_arg( $add, $this->urlRemoveNonce() );
870  return $url;
871  }
872 
878  public function redirect()
879  {
880  $url = $this->urlRemveAction();
881  wp_redirect( $url );
882  exit;
883  }
884 
885 }
886 
899 
907  public function __construct()
908  {
909  }
910 
916  public function select()
917  {
918  die( __METHOD__ . ' must be override in your subclass' );
919  }
920 
927  public function process_action()
928  {
929  // Override when you need to process actions before wp is loaded
930  }
931 
932 }