WP_Posts_List_Table

Core class used to implement displaying posts in a list table.

Defined (1)

The class is defined in the following location(s).

/wp-admin/includes/class-wp-posts-list-table.php  
  1. class WP_Posts_List_Table extends WP_List_Table { 
  2.  
  3. /** 
  4. * Whether the items should be displayed hierarchically or linearly. 
  5. * @since 3.1.0 
  6. * @var bool 
  7. * @access protected 
  8. */ 
  9. protected $hierarchical_display; 
  10.  
  11. /** 
  12. * Holds the number of pending comments for each post. 
  13. * @since 3.1.0 
  14. * @var array 
  15. * @access protected 
  16. */ 
  17. protected $comment_pending_count; 
  18.  
  19. /** 
  20. * Holds the number of posts for this user. 
  21. * @since 3.1.0 
  22. * @var int 
  23. * @access private 
  24. */ 
  25. private $user_posts_count; 
  26.  
  27. /** 
  28. * Holds the number of posts which are sticky. 
  29. * @since 3.1.0 
  30. * @var int 
  31. * @access private 
  32. */ 
  33. private $sticky_posts_count = 0; 
  34.  
  35. private $is_trash; 
  36.  
  37. /** 
  38. * Current level for output. 
  39. * @since 4.3.0 
  40. * @access protected 
  41. * @var int 
  42. */ 
  43. protected $current_level = 0; 
  44.  
  45. /** 
  46. * Constructor. 
  47. * @since 3.1.0 
  48. * @access public 
  49. * @see WP_List_Table::__construct() for more information on default arguments. 
  50. * @global WP_Post_Type $post_type_object 
  51. * @global wpdb $wpdb 
  52. * @param array $args An associative array of arguments. 
  53. */ 
  54. public function __construct( $args = array() ) { 
  55. global $post_type_object, $wpdb; 
  56.  
  57. parent::__construct( array( 
  58. 'plural' => 'posts',  
  59. 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,  
  60. ) ); 
  61.  
  62. $post_type = $this->screen->post_type; 
  63. $post_type_object = get_post_type_object( $post_type ); 
  64.  
  65. $exclude_states = get_post_stati( array( 
  66. 'show_in_admin_all_list' => false,  
  67. ) ); 
  68. $this->user_posts_count = intval( $wpdb->get_var( $wpdb->prepare( " 
  69. SELECT COUNT( 1 ) 
  70. FROM $wpdb->posts 
  71. WHERE post_type = %s 
  72. AND post_status NOT IN ( '" . implode( "', '", $exclude_states ) . "' ) 
  73. AND post_author = %d 
  74. ", $post_type, get_current_user_id() ) ) ); 
  75.  
  76. if ( $this->user_posts_count && ! current_user_can( $post_type_object->cap->edit_others_posts ) && empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['all_posts'] ) && empty( $_REQUEST['author'] ) && empty( $_REQUEST['show_sticky'] ) ) { 
  77. $_GET['author'] = get_current_user_id(); 
  78.  
  79. if ( 'post' === $post_type && $sticky_posts = get_option( 'sticky_posts' ) ) { 
  80. $sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) ); 
  81. $this->sticky_posts_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( 1 ) FROM $wpdb->posts WHERE post_type = %s AND post_status NOT IN ('trash', 'auto-draft') AND ID IN ($sticky_posts)", $post_type ) ); 
  82.  
  83. /** 
  84. * Sets whether the table layout should be hierarchical or not. 
  85. * @since 4.2.0 
  86. * @param bool $display Whether the table layout should be hierarchical. 
  87. */ 
  88. public function set_hierarchical_display( $display ) { 
  89. $this->hierarchical_display = $display; 
  90.  
  91. /** 
  92. * @return bool 
  93. */ 
  94. public function ajax_user_can() { 
  95. return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts ); 
  96.  
  97. /** 
  98. * @global array $avail_post_stati 
  99. * @global WP_Query $wp_query 
  100. * @global int $per_page 
  101. * @global string $mode 
  102. */ 
  103. public function prepare_items() { 
  104. global $avail_post_stati, $wp_query, $per_page, $mode; 
  105.  
  106. // is going to call wp() 
  107. $avail_post_stati = wp_edit_posts_query(); 
  108.  
  109. $this->set_hierarchical_display( is_post_type_hierarchical( $this->screen->post_type ) && 'menu_order title' === $wp_query->query['orderby'] ); 
  110.  
  111. $post_type = $this->screen->post_type; 
  112. $per_page = $this->get_items_per_page( 'edit_' . $post_type . '_per_page' ); 
  113.  
  114. /** This filter is documented in wp-admin/includes/post.php */ 
  115. $per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type ); 
  116.  
  117. if ( $this->hierarchical_display ) { 
  118. $total_items = $wp_query->post_count; 
  119. } elseif ( $wp_query->found_posts || $this->get_pagenum() === 1 ) { 
  120. $total_items = $wp_query->found_posts; 
  121. } else { 
  122. $post_counts = (array) wp_count_posts( $post_type, 'readable' ); 
  123.  
  124. if ( isset( $_REQUEST['post_status'] ) && in_array( $_REQUEST['post_status'] , $avail_post_stati ) ) { 
  125. $total_items = $post_counts[ $_REQUEST['post_status'] ]; 
  126. } elseif ( isset( $_REQUEST['show_sticky'] ) && $_REQUEST['show_sticky'] ) { 
  127. $total_items = $this->sticky_posts_count; 
  128. } elseif ( isset( $_GET['author'] ) && $_GET['author'] == get_current_user_id() ) { 
  129. $total_items = $this->user_posts_count; 
  130. } else { 
  131. $total_items = array_sum( $post_counts ); 
  132.  
  133. // Subtract post types that are not included in the admin all list. 
  134. foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) { 
  135. $total_items -= $post_counts[ $state ]; 
  136.  
  137. if ( ! empty( $_REQUEST['mode'] ) ) { 
  138. $mode = $_REQUEST['mode'] === 'excerpt' ? 'excerpt' : 'list'; 
  139. set_user_setting( 'posts_list_mode', $mode ); 
  140. } else { 
  141. $mode = get_user_setting( 'posts_list_mode', 'list' ); 
  142.  
  143. $this->is_trash = isset( $_REQUEST['post_status'] ) && $_REQUEST['post_status'] === 'trash'; 
  144.  
  145. $this->set_pagination_args( array( 
  146. 'total_items' => $total_items,  
  147. 'per_page' => $per_page 
  148. ) ); 
  149.  
  150. /** 
  151. * @return bool 
  152. */ 
  153. public function has_items() { 
  154. return have_posts(); 
  155.  
  156. /** 
  157. * @access public 
  158. */ 
  159. public function no_items() { 
  160. if ( isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'] ) 
  161. echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash; 
  162. else 
  163. echo get_post_type_object( $this->screen->post_type )->labels->not_found; 
  164.  
  165. /** 
  166. * Determine if the current view is the "All" view. 
  167. * @since 4.2.0 
  168. * @return bool Whether the current view is the "All" view. 
  169. */ 
  170. protected function is_base_request() { 
  171. $vars = $_GET; 
  172. unset( $vars['paged'] ); 
  173.  
  174. if ( empty( $vars ) ) { 
  175. return true; 
  176. } elseif ( 1 === count( $vars ) && ! empty( $vars['post_type'] ) ) { 
  177. return $this->screen->post_type === $vars['post_type']; 
  178.  
  179. return 1 === count( $vars ) && ! empty( $vars['mode'] ); 
  180.  
  181. /** 
  182. * Helper to create links to edit.php with params. 
  183. * @since 4.4.0 
  184. * @access protected 
  185. * @param array $args URL parameters for the link. 
  186. * @param string $label Link text. 
  187. * @param string $class Optional. Class attribute. Default empty string. 
  188. * @return string The formatted link string. 
  189. */ 
  190. protected function get_edit_link( $args, $label, $class = '' ) { 
  191. $url = add_query_arg( $args, 'edit.php' ); 
  192.  
  193. $class_html = ''; 
  194. if ( ! empty( $class ) ) { 
  195. $class_html = sprintf( 
  196. ' class="%s"',  
  197. esc_attr( $class ) 
  198. ); 
  199.  
  200. return sprintf( 
  201. '<a href="%s"%s>%s</a>',  
  202. esc_url( $url ),  
  203. $class_html,  
  204. $label 
  205. ); 
  206.  
  207. /** 
  208. * @global array $locked_post_status This seems to be deprecated. 
  209. * @global array $avail_post_stati 
  210. * @return array 
  211. */ 
  212. protected function get_views() { 
  213. global $locked_post_status, $avail_post_stati; 
  214.  
  215. $post_type = $this->screen->post_type; 
  216.  
  217. if ( !empty($locked_post_status) ) 
  218. return array(); 
  219.  
  220. $status_links = array(); 
  221. $num_posts = wp_count_posts( $post_type, 'readable' ); 
  222. $total_posts = array_sum( (array) $num_posts ); 
  223. $class = ''; 
  224.  
  225. $current_user_id = get_current_user_id(); 
  226. $all_args = array( 'post_type' => $post_type ); 
  227. $mine = ''; 
  228.  
  229. // Subtract post types that are not included in the admin all list. 
  230. foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) { 
  231. $total_posts -= $num_posts->$state; 
  232.  
  233. if ( $this->user_posts_count && $this->user_posts_count !== $total_posts ) { 
  234. if ( isset( $_GET['author'] ) && ( $_GET['author'] == $current_user_id ) ) { 
  235. $class = 'current'; 
  236.  
  237. $mine_args = array( 
  238. 'post_type' => $post_type,  
  239. 'author' => $current_user_id 
  240. ); 
  241.  
  242. $mine_inner_html = sprintf( 
  243. _nx( 
  244. 'Mine <span class="count">(%s)</span>',  
  245. 'Mine <span class="count">(%s)</span>',  
  246. $this->user_posts_count,  
  247. 'posts' 
  248. ),  
  249. number_format_i18n( $this->user_posts_count ) 
  250. ); 
  251.  
  252. $mine = $this->get_edit_link( $mine_args, $mine_inner_html, $class ); 
  253.  
  254. $all_args['all_posts'] = 1; 
  255. $class = ''; 
  256.  
  257. if ( empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ) ) { 
  258. $class = 'current'; 
  259.  
  260. $all_inner_html = sprintf( 
  261. _nx( 
  262. 'All <span class="count">(%s)</span>',  
  263. 'All <span class="count">(%s)</span>',  
  264. $total_posts,  
  265. 'posts' 
  266. ),  
  267. number_format_i18n( $total_posts ) 
  268. ); 
  269.  
  270. $status_links['all'] = $this->get_edit_link( $all_args, $all_inner_html, $class ); 
  271. if ( $mine ) { 
  272. $status_links['mine'] = $mine; 
  273.  
  274. foreach ( get_post_stati(array('show_in_admin_status_list' => true), 'objects') as $status ) { 
  275. $class = ''; 
  276.  
  277. $status_name = $status->name; 
  278.  
  279. if ( ! in_array( $status_name, $avail_post_stati ) || empty( $num_posts->$status_name ) ) { 
  280. continue; 
  281.  
  282. if ( isset($_REQUEST['post_status']) && $status_name === $_REQUEST['post_status'] ) { 
  283. $class = 'current'; 
  284.  
  285. $status_args = array( 
  286. 'post_status' => $status_name,  
  287. 'post_type' => $post_type,  
  288. ); 
  289.  
  290. $status_label = sprintf( 
  291. translate_nooped_plural( $status->label_count, $num_posts->$status_name ),  
  292. number_format_i18n( $num_posts->$status_name ) 
  293. ); 
  294.  
  295. $status_links[ $status_name ] = $this->get_edit_link( $status_args, $status_label, $class ); 
  296.  
  297. if ( ! empty( $this->sticky_posts_count ) ) { 
  298. $class = ! empty( $_REQUEST['show_sticky'] ) ? 'current' : ''; 
  299.  
  300. $sticky_args = array( 
  301. 'post_type' => $post_type,  
  302. 'show_sticky' => 1 
  303. ); 
  304.  
  305. $sticky_inner_html = sprintf( 
  306. _nx( 
  307. 'Sticky <span class="count">(%s)</span>',  
  308. 'Sticky <span class="count">(%s)</span>',  
  309. $this->sticky_posts_count,  
  310. 'posts' 
  311. ),  
  312. number_format_i18n( $this->sticky_posts_count ) 
  313. ); 
  314.  
  315. $sticky_link = array( 
  316. 'sticky' => $this->get_edit_link( $sticky_args, $sticky_inner_html, $class ) 
  317. ); 
  318.  
  319. // Sticky comes after Publish, or if not listed, after All. 
  320. $split = 1 + array_search( ( isset( $status_links['publish'] ) ? 'publish' : 'all' ), array_keys( $status_links ) ); 
  321. $status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) ); 
  322.  
  323. return $status_links; 
  324.  
  325. /** 
  326. * @return array 
  327. */ 
  328. protected function get_bulk_actions() { 
  329. $actions = array(); 
  330. $post_type_obj = get_post_type_object( $this->screen->post_type ); 
  331.  
  332. if ( current_user_can( $post_type_obj->cap->edit_posts ) ) { 
  333. if ( $this->is_trash ) { 
  334. $actions['untrash'] = __( 'Restore' ); 
  335. } else { 
  336. $actions['edit'] = __( 'Edit' ); 
  337.  
  338. if ( current_user_can( $post_type_obj->cap->delete_posts ) ) { 
  339. if ( $this->is_trash || ! EMPTY_TRASH_DAYS ) { 
  340. $actions['delete'] = __( 'Delete Permanently' ); 
  341. } else { 
  342. $actions['trash'] = __( 'Move to Trash' ); 
  343.  
  344. return $actions; 
  345.  
  346. /** 
  347. * Displays a categories drop-down for filtering on the Posts list table. 
  348. * @since 4.6.0 
  349. * @access protected 
  350. * @global int $cat Currently selected category. 
  351. * @param string $post_type Post type slug. 
  352. */ 
  353. protected function categories_dropdown( $post_type ) { 
  354. global $cat; 
  355.  
  356. /** 
  357. * Filters whether to remove the 'Categories' drop-down from the post list table. 
  358. * @since 4.6.0 
  359. * @param bool $disable Whether to disable the categories drop-down. Default false. 
  360. * @param string $post_type Post type slug. 
  361. */ 
  362. if ( false !== apply_filters( 'disable_categories_dropdown', false, $post_type ) ) { 
  363. return; 
  364.  
  365. if ( is_object_in_taxonomy( $post_type, 'category' ) ) { 
  366. $dropdown_options = array( 
  367. 'show_option_all' => get_taxonomy( 'category' )->labels->all_items,  
  368. 'hide_empty' => 0,  
  369. 'hierarchical' => 1,  
  370. 'show_count' => 0,  
  371. 'orderby' => 'name',  
  372. 'selected' => $cat 
  373. ); 
  374.  
  375. echo '<label class="screen-reader-text" for="cat">' . __( 'Filter by category' ) . '</label>'; 
  376. wp_dropdown_categories( $dropdown_options ); 
  377.  
  378. /** 
  379. * @param string $which 
  380. */ 
  381. protected function extra_tablenav( $which ) { 
  382. ?> 
  383. <div class="alignleft actions"> 
  384. <?php 
  385. if ( 'top' === $which && !is_singular() ) { 
  386.  
  387. $this->months_dropdown( $this->screen->post_type ); 
  388. $this->categories_dropdown( $this->screen->post_type ); 
  389.  
  390. /** 
  391. * Fires before the Filter button on the Posts and Pages list tables. 
  392. * The Filter button allows sorting by date and/or category on the 
  393. * Posts list table, and sorting by date on the Pages list table. 
  394. * @since 2.1.0 
  395. * @since 4.4.0 The `$post_type` parameter was added. 
  396. * @since 4.6.0 The `$which` parameter was added. 
  397. * @param string $post_type The post type slug. 
  398. * @param string $which The location of the extra table nav markup: 
  399. * 'top' or 'bottom'. 
  400. */ 
  401. do_action( 'restrict_manage_posts', $this->screen->post_type, $which ); 
  402.  
  403. submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) ); 
  404.  
  405. if ( $this->is_trash && current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts ) ) { 
  406. submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); 
  407. ?> 
  408. </div> 
  409. <?php 
  410. /** 
  411. * Fires immediately following the closing "actions" div in the tablenav for the posts 
  412. * list table. 
  413. * @since 4.4.0 
  414. * @param string $which The location of the extra table nav markup: 'top' or 'bottom'. 
  415. */ 
  416. do_action( 'manage_posts_extra_tablenav', $which ); 
  417.  
  418. /** 
  419. * @return string 
  420. */ 
  421. public function current_action() { 
  422. if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) 
  423. return 'delete_all'; 
  424.  
  425. return parent::current_action(); 
  426.  
  427. /** 
  428. * @return array 
  429. */ 
  430. protected function get_table_classes() { 
  431. return array( 'widefat', 'fixed', 'striped', is_post_type_hierarchical( $this->screen->post_type ) ? 'pages' : 'posts' ); 
  432.  
  433. /** 
  434. * @return array 
  435. */ 
  436. public function get_columns() { 
  437. $post_type = $this->screen->post_type; 
  438.  
  439. $posts_columns = array(); 
  440.  
  441. $posts_columns['cb'] = '<input type="checkbox" />'; 
  442.  
  443. /** translators: manage posts column name */ 
  444. $posts_columns['title'] = _x( 'Title', 'column name' ); 
  445.  
  446. if ( post_type_supports( $post_type, 'author' ) ) { 
  447. $posts_columns['author'] = __( 'Author' ); 
  448.  
  449. $taxonomies = get_object_taxonomies( $post_type, 'objects' ); 
  450. $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); 
  451.  
  452. /** 
  453. * Filters the taxonomy columns in the Posts list table. 
  454. * The dynamic portion of the hook name, `$post_type`, refers to the post 
  455. * type slug. 
  456. * @since 3.5.0 
  457. * @param array $taxonomies Array of taxonomies to show columns for. 
  458. * @param string $post_type The post type. 
  459. */ 
  460. $taxonomies = apply_filters( "manage_taxonomies_for_{$post_type}_columns", $taxonomies, $post_type ); 
  461. $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); 
  462.  
  463. foreach ( $taxonomies as $taxonomy ) { 
  464. if ( 'category' === $taxonomy ) 
  465. $column_key = 'categories'; 
  466. elseif ( 'post_tag' === $taxonomy ) 
  467. $column_key = 'tags'; 
  468. else 
  469. $column_key = 'taxonomy-' . $taxonomy; 
  470.  
  471. $posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name; 
  472.  
  473. $post_status = !empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all'; 
  474. if ( post_type_supports( $post_type, 'comments' ) && !in_array( $post_status, array( 'pending', 'draft', 'future' ) ) ) 
  475. $posts_columns['comments'] = '<span class="vers comment-grey-bubble" title="' . esc_attr__( 'Comments' ) . '"><span class="screen-reader-text">' . __( 'Comments' ) . '</span></span>'; 
  476.  
  477. $posts_columns['date'] = __( 'Date' ); 
  478.  
  479. if ( 'page' === $post_type ) { 
  480.  
  481. /** 
  482. * Filters the columns displayed in the Pages list table. 
  483. * @since 2.5.0 
  484. * @param array $post_columns An array of column names. 
  485. */ 
  486. $posts_columns = apply_filters( 'manage_pages_columns', $posts_columns ); 
  487. } else { 
  488.  
  489. /** 
  490. * Filters the columns displayed in the Posts list table. 
  491. * @since 1.5.0 
  492. * @param array $posts_columns An array of column names. 
  493. * @param string $post_type The post type slug. 
  494. */ 
  495. $posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type ); 
  496.  
  497. /** 
  498. * Filters the columns displayed in the Posts list table for a specific post type. 
  499. * The dynamic portion of the hook name, `$post_type`, refers to the post type slug. 
  500. * @since 3.0.0 
  501. * @param array $post_columns An array of column names. 
  502. */ 
  503. return apply_filters( "manage_{$post_type}_posts_columns", $posts_columns ); 
  504.  
  505. /** 
  506. * @return array 
  507. */ 
  508. protected function get_sortable_columns() { 
  509. return array( 
  510. 'title' => 'title',  
  511. 'parent' => 'parent',  
  512. 'comments' => 'comment_count',  
  513. 'date' => array( 'date', true ) 
  514. ); 
  515.  
  516. /** 
  517. * @global WP_Query $wp_query 
  518. * @global int $per_page 
  519. * @param array $posts 
  520. * @param int $level 
  521. */ 
  522. public function display_rows( $posts = array(), $level = 0 ) { 
  523. global $wp_query, $per_page; 
  524.  
  525. if ( empty( $posts ) ) 
  526. $posts = $wp_query->posts; 
  527.  
  528. add_filter( 'the_title', 'esc_html' ); 
  529.  
  530. if ( $this->hierarchical_display ) { 
  531. $this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page ); 
  532. } else { 
  533. $this->_display_rows( $posts, $level ); 
  534.  
  535. /** 
  536. * @param array $posts 
  537. * @param int $level 
  538. */ 
  539. private function _display_rows( $posts, $level = 0 ) { 
  540. // Create array of post IDs. 
  541. $post_ids = array(); 
  542.  
  543. foreach ( $posts as $a_post ) 
  544. $post_ids[] = $a_post->ID; 
  545.  
  546. $this->comment_pending_count = get_pending_comments_num( $post_ids ); 
  547.  
  548. foreach ( $posts as $post ) 
  549. $this->single_row( $post, $level ); 
  550.  
  551. /** 
  552. * @global wpdb $wpdb 
  553. * @global WP_Post $post 
  554. * @param array $pages 
  555. * @param int $pagenum 
  556. * @param int $per_page 
  557. */ 
  558. private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) { 
  559. global $wpdb; 
  560.  
  561. $level = 0; 
  562.  
  563. if ( ! $pages ) { 
  564. $pages = get_pages( array( 'sort_column' => 'menu_order' ) ); 
  565.  
  566. if ( ! $pages ) 
  567. return; 
  568.  
  569. /** 
  570. * Arrange pages into two parts: top level pages and children_pages 
  571. * children_pages is two dimensional array, eg. 
  572. * children_pages[10][] contains all sub-pages whose parent is 10. 
  573. * It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations 
  574. * If searching, ignore hierarchy and treat everything as top level 
  575. */ 
  576. if ( empty( $_REQUEST['s'] ) ) { 
  577.  
  578. $top_level_pages = array(); 
  579. $children_pages = array(); 
  580.  
  581. foreach ( $pages as $page ) { 
  582.  
  583. // Catch and repair bad pages. 
  584. if ( $page->post_parent == $page->ID ) { 
  585. $page->post_parent = 0; 
  586. $wpdb->update( $wpdb->posts, array( 'post_parent' => 0 ), array( 'ID' => $page->ID ) ); 
  587. clean_post_cache( $page ); 
  588.  
  589. if ( 0 == $page->post_parent ) 
  590. $top_level_pages[] = $page; 
  591. else 
  592. $children_pages[ $page->post_parent ][] = $page; 
  593.  
  594. $pages = &$top_level_pages; 
  595.  
  596. $count = 0; 
  597. $start = ( $pagenum - 1 ) * $per_page; 
  598. $end = $start + $per_page; 
  599. $to_display = array(); 
  600.  
  601. foreach ( $pages as $page ) { 
  602. if ( $count >= $end ) 
  603. break; 
  604.  
  605. if ( $count >= $start ) { 
  606. $to_display[$page->ID] = $level; 
  607.  
  608. $count++; 
  609.  
  610. if ( isset( $children_pages ) ) 
  611. $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display ); 
  612.  
  613. // If it is the last pagenum and there are orphaned pages, display them with paging as well. 
  614. if ( isset( $children_pages ) && $count < $end ) { 
  615. foreach ( $children_pages as $orphans ) { 
  616. foreach ( $orphans as $op ) { 
  617. if ( $count >= $end ) 
  618. break; 
  619.  
  620. if ( $count >= $start ) { 
  621. $to_display[$op->ID] = 0; 
  622.  
  623. $count++; 
  624.  
  625. $ids = array_keys( $to_display ); 
  626. _prime_post_caches( $ids ); 
  627.  
  628. if ( ! isset( $GLOBALS['post'] ) ) { 
  629. $GLOBALS['post'] = reset( $ids ); 
  630.  
  631. foreach ( $to_display as $page_id => $level ) { 
  632. echo "\t"; 
  633. $this->single_row( $page_id, $level ); 
  634.  
  635. /** 
  636. * Given a top level page ID, display the nested hierarchy of sub-pages 
  637. * together with paging support 
  638. * @since 3.1.0 (Standalone function exists since 2.6.0) 
  639. * @since 4.2.0 Added the `$to_display` parameter. 
  640. * @param array $children_pages 
  641. * @param int $count 
  642. * @param int $parent 
  643. * @param int $level 
  644. * @param int $pagenum 
  645. * @param int $per_page 
  646. * @param array $to_display List of pages to be displayed. Passed by reference. 
  647. */ 
  648. private function _page_rows( &$children_pages, &$count, $parent, $level, $pagenum, $per_page, &$to_display ) { 
  649. if ( ! isset( $children_pages[$parent] ) ) 
  650. return; 
  651.  
  652. $start = ( $pagenum - 1 ) * $per_page; 
  653. $end = $start + $per_page; 
  654.  
  655. foreach ( $children_pages[$parent] as $page ) { 
  656. if ( $count >= $end ) 
  657. break; 
  658.  
  659. // If the page starts in a subtree, print the parents. 
  660. if ( $count == $start && $page->post_parent > 0 ) { 
  661. $my_parents = array(); 
  662. $my_parent = $page->post_parent; 
  663. while ( $my_parent ) { 
  664. // Get the ID from the list or the attribute if my_parent is an object 
  665. $parent_id = $my_parent; 
  666. if ( is_object( $my_parent ) ) { 
  667. $parent_id = $my_parent->ID; 
  668.  
  669. $my_parent = get_post( $parent_id ); 
  670. $my_parents[] = $my_parent; 
  671. if ( !$my_parent->post_parent ) 
  672. break; 
  673. $my_parent = $my_parent->post_parent; 
  674. $num_parents = count( $my_parents ); 
  675. while ( $my_parent = array_pop( $my_parents ) ) { 
  676. $to_display[$my_parent->ID] = $level - $num_parents; 
  677. $num_parents--; 
  678.  
  679. if ( $count >= $start ) { 
  680. $to_display[$page->ID] = $level; 
  681.  
  682. $count++; 
  683.  
  684. $this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display ); 
  685.  
  686. unset( $children_pages[$parent] ); //required in order to keep track of orphans 
  687.  
  688. /** 
  689. * Handles the checkbox column output. 
  690. * @since 4.3.0 
  691. * @access public 
  692. * @param WP_Post $post The current WP_Post object. 
  693. */ 
  694. public function column_cb( $post ) { 
  695. if ( current_user_can( 'edit_post', $post->ID ) ): ?> 
  696. <label class="screen-reader-text" for="cb-select-<?php the_ID(); ?>"><?php 
  697. printf( __( 'Select %s' ), _draft_or_post_title() ); 
  698. ?></label> 
  699. <input id="cb-select-<?php the_ID(); ?>" type="checkbox" name="post[]" value="<?php the_ID(); ?>" /> 
  700. <div class="locked-indicator"></div> 
  701. <?php endif; 
  702.  
  703. /** 
  704. * @since 4.3.0 
  705. * @access protected 
  706. * @param WP_Post $post 
  707. * @param string $classes 
  708. * @param string $data 
  709. * @param string $primary 
  710. */ 
  711. protected function _column_title( $post, $classes, $data, $primary ) { 
  712. echo '<td class="' . $classes . ' page-title" ', $data, '>'; 
  713. echo $this->column_title( $post ); 
  714. echo $this->handle_row_actions( $post, 'title', $primary ); 
  715. echo '</td>'; 
  716.  
  717. /** 
  718. * Handles the title column output. 
  719. * @since 4.3.0 
  720. * @access public 
  721. * @global string $mode 
  722. * @param WP_Post $post The current WP_Post object. 
  723. */ 
  724. public function column_title( $post ) { 
  725. global $mode; 
  726.  
  727. if ( $this->hierarchical_display ) { 
  728. if ( 0 === $this->current_level && (int) $post->post_parent > 0 ) { 
  729. // Sent level 0 by accident, by default, or because we don't know the actual level. 
  730. $find_main_page = (int) $post->post_parent; 
  731. while ( $find_main_page > 0 ) { 
  732. $parent = get_post( $find_main_page ); 
  733.  
  734. if ( is_null( $parent ) ) { 
  735. break; 
  736.  
  737. $this->current_level++; 
  738. $find_main_page = (int) $parent->post_parent; 
  739.  
  740. if ( ! isset( $parent_name ) ) { 
  741. /** This filter is documented in wp-includes/post-template.php */ 
  742. $parent_name = apply_filters( 'the_title', $parent->post_title, $parent->ID ); 
  743.  
  744. $pad = str_repeat( '— ', $this->current_level ); 
  745. echo "<strong>"; 
  746.  
  747. $format = get_post_format( $post->ID ); 
  748. if ( $format ) { 
  749. $label = get_post_format_string( $format ); 
  750.  
  751. $format_class = 'post-state-format post-format-icon post-format-' . $format; 
  752.  
  753. $format_args = array( 
  754. 'post_format' => $format,  
  755. 'post_type' => $post->post_type 
  756. ); 
  757.  
  758. echo $this->get_edit_link( $format_args, $label . ':', $format_class ); 
  759.  
  760. $can_edit_post = current_user_can( 'edit_post', $post->ID ); 
  761. $title = _draft_or_post_title(); 
  762.  
  763. if ( $can_edit_post && $post->post_status != 'trash' ) { 
  764. printf( 
  765. '<a class="row-title" href="%s" aria-label="%s">%s%s</a>',  
  766. get_edit_post_link( $post->ID ),  
  767. /** translators: %s: post title */ 
  768. esc_attr( sprintf( __( '“%s” (Edit)' ), $title ) ),  
  769. $pad,  
  770. $title 
  771. ); 
  772. } else { 
  773. echo $pad . $title; 
  774. _post_states( $post ); 
  775.  
  776. if ( isset( $parent_name ) ) { 
  777. $post_type_object = get_post_type_object( $post->post_type ); 
  778. echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name ); 
  779. echo "</strong>\n"; 
  780.  
  781. if ( $can_edit_post && $post->post_status != 'trash' ) { 
  782. $lock_holder = wp_check_post_lock( $post->ID ); 
  783.  
  784. if ( $lock_holder ) { 
  785. $lock_holder = get_userdata( $lock_holder ); 
  786. $locked_avatar = get_avatar( $lock_holder->ID, 18 ); 
  787. $locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) ); 
  788. } else { 
  789. $locked_avatar = $locked_text = ''; 
  790.  
  791. echo '<div class="locked-info"><span class="locked-avatar">' . $locked_avatar . '</span> <span class="locked-text">' . $locked_text . "</span></div>\n"; 
  792.  
  793. if ( ! is_post_type_hierarchical( $this->screen->post_type ) && 'excerpt' === $mode && current_user_can( 'read_post', $post->ID ) ) { 
  794. the_excerpt(); 
  795.  
  796. get_inline_data( $post ); 
  797.  
  798. /** 
  799. * Handles the post date column output. 
  800. * @since 4.3.0 
  801. * @access public 
  802. * @global string $mode 
  803. * @param WP_Post $post The current WP_Post object. 
  804. */ 
  805. public function column_date( $post ) { 
  806. global $mode; 
  807.  
  808. if ( '0000-00-00 00:00:00' === $post->post_date ) { 
  809. $t_time = $h_time = __( 'Unpublished' ); 
  810. $time_diff = 0; 
  811. } else { 
  812. $t_time = get_the_time( __( 'Y/m/d g:i:s a' ) ); 
  813. $m_time = $post->post_date; 
  814. $time = get_post_time( 'G', true, $post ); 
  815.  
  816. $time_diff = time() - $time; 
  817.  
  818. if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) { 
  819. $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); 
  820. } else { 
  821. $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); 
  822.  
  823. if ( 'publish' === $post->post_status ) { 
  824. _e( 'Published' ); 
  825. } elseif ( 'future' === $post->post_status ) { 
  826. if ( $time_diff > 0 ) { 
  827. echo '<strong class="error-message">' . __( 'Missed schedule' ) . '</strong>'; 
  828. } else { 
  829. _e( 'Scheduled' ); 
  830. } else { 
  831. _e( 'Last Modified' ); 
  832. echo '<br />'; 
  833. if ( 'excerpt' === $mode ) { 
  834. /** 
  835. * Filters the published time of the post. 
  836. * If `$mode` equals 'excerpt', the published time and date are both displayed. 
  837. * If `$mode` equals 'list' (default), the publish date is displayed, with the 
  838. * time and date together available as an abbreviation definition. 
  839. * @since 2.5.1 
  840. * @param string $t_time The published time. 
  841. * @param WP_Post $post Post object. 
  842. * @param string $column_name The column name. 
  843. * @param string $mode The list display mode ('excerpt' or 'list'). 
  844. */ 
  845. echo apply_filters( 'post_date_column_time', $t_time, $post, 'date', $mode ); 
  846. } else { 
  847.  
  848. /** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */ 
  849. echo '<abbr title="' . $t_time . '">' . apply_filters( 'post_date_column_time', $h_time, $post, 'date', $mode ) . '</abbr>'; 
  850.  
  851. /** 
  852. * Handles the comments column output. 
  853. * @since 4.3.0 
  854. * @access public 
  855. * @param WP_Post $post The current WP_Post object. 
  856. */ 
  857. public function column_comments( $post ) { 
  858. ?> 
  859. <div class="post-com-count-wrapper"> 
  860. <?php 
  861. $pending_comments = isset( $this->comment_pending_count[$post->ID] ) ? $this->comment_pending_count[$post->ID] : 0; 
  862.  
  863. $this->comments_bubble( $post->ID, $pending_comments ); 
  864. ?> 
  865. </div> 
  866. <?php 
  867.  
  868. /** 
  869. * Handles the post author column output. 
  870. * @since 4.3.0 
  871. * @access public 
  872. * @param WP_Post $post The current WP_Post object. 
  873. */ 
  874. public function column_author( $post ) { 
  875. $args = array( 
  876. 'post_type' => $post->post_type,  
  877. 'author' => get_the_author_meta( 'ID' ) 
  878. ); 
  879. echo $this->get_edit_link( $args, get_the_author() ); 
  880.  
  881. /** 
  882. * Handles the default column output. 
  883. * @since 4.3.0 
  884. * @access public 
  885. * @param WP_Post $post The current WP_Post object. 
  886. * @param string $column_name The current column name. 
  887. */ 
  888. public function column_default( $post, $column_name ) { 
  889. if ( 'categories' === $column_name ) { 
  890. $taxonomy = 'category'; 
  891. } elseif ( 'tags' === $column_name ) { 
  892. $taxonomy = 'post_tag'; 
  893. } elseif ( 0 === strpos( $column_name, 'taxonomy-' ) ) { 
  894. $taxonomy = substr( $column_name, 9 ); 
  895. } else { 
  896. $taxonomy = false; 
  897. if ( $taxonomy ) { 
  898. $taxonomy_object = get_taxonomy( $taxonomy ); 
  899. $terms = get_the_terms( $post->ID, $taxonomy ); 
  900. if ( is_array( $terms ) ) { 
  901. $out = array(); 
  902. foreach ( $terms as $t ) { 
  903. $posts_in_term_qv = array(); 
  904. if ( 'post' != $post->post_type ) { 
  905. $posts_in_term_qv['post_type'] = $post->post_type; 
  906. if ( $taxonomy_object->query_var ) { 
  907. $posts_in_term_qv[ $taxonomy_object->query_var ] = $t->slug; 
  908. } else { 
  909. $posts_in_term_qv['taxonomy'] = $taxonomy; 
  910. $posts_in_term_qv['term'] = $t->slug; 
  911.  
  912. $label = esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ); 
  913. $out[] = $this->get_edit_link( $posts_in_term_qv, $label ); 
  914. /** translators: used between list items, there is a space after the comma */ 
  915. echo join( __( ', ' ), $out ); 
  916. } else { 
  917. echo '<span aria-hidden="true">—</span><span class="screen-reader-text">' . $taxonomy_object->labels->no_terms . '</span>'; 
  918. return; 
  919.  
  920. if ( is_post_type_hierarchical( $post->post_type ) ) { 
  921.  
  922. /** 
  923. * Fires in each custom column on the Posts list table. 
  924. * This hook only fires if the current post type is hierarchical,  
  925. * such as pages. 
  926. * @since 2.5.0 
  927. * @param string $column_name The name of the column to display. 
  928. * @param int $post_id The current post ID. 
  929. */ 
  930. do_action( 'manage_pages_custom_column', $column_name, $post->ID ); 
  931. } else { 
  932.  
  933. /** 
  934. * Fires in each custom column in the Posts list table. 
  935. * This hook only fires if the current post type is non-hierarchical,  
  936. * such as posts. 
  937. * @since 1.5.0 
  938. * @param string $column_name The name of the column to display. 
  939. * @param int $post_id The current post ID. 
  940. */ 
  941. do_action( 'manage_posts_custom_column', $column_name, $post->ID ); 
  942.  
  943. /** 
  944. * Fires for each custom column of a specific post type in the Posts list table. 
  945. * The dynamic portion of the hook name, `$post->post_type`, refers to the post type. 
  946. * @since 3.1.0 
  947. * @param string $column_name The name of the column to display. 
  948. * @param int $post_id The current post ID. 
  949. */ 
  950. do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID ); 
  951.  
  952. /** 
  953. * @global WP_Post $post 
  954. * @param int|WP_Post $post 
  955. * @param int $level 
  956. */ 
  957. public function single_row( $post, $level = 0 ) { 
  958. $global_post = get_post(); 
  959.  
  960. $post = get_post( $post ); 
  961. $this->current_level = $level; 
  962.  
  963. $GLOBALS['post'] = $post; 
  964. setup_postdata( $post ); 
  965.  
  966. $classes = 'iedit author-' . ( get_current_user_id() == $post->post_author ? 'self' : 'other' ); 
  967.  
  968. $lock_holder = wp_check_post_lock( $post->ID ); 
  969. if ( $lock_holder ) { 
  970. $classes .= ' wp-locked'; 
  971.  
  972. if ( $post->post_parent ) { 
  973. $count = count( get_post_ancestors( $post->ID ) ); 
  974. $classes .= ' level-'. $count; 
  975. } else { 
  976. $classes .= ' level-0'; 
  977. ?> 
  978. <tr id="post-<?php echo $post->ID; ?>" class="<?php echo implode( ' ', get_post_class( $classes, $post->ID ) ); ?>"> 
  979. <?php $this->single_row_columns( $post ); ?> 
  980. </tr> 
  981. <?php 
  982. $GLOBALS['post'] = $global_post; 
  983.  
  984. /** 
  985. * Gets the name of the default primary column. 
  986. * @since 4.3.0 
  987. * @access protected 
  988. * @return string Name of the default primary column, in this case, 'title'. 
  989. */ 
  990. protected function get_default_primary_column_name() { 
  991. return 'title'; 
  992.  
  993. /** 
  994. * Generates and displays row action links. 
  995. * @since 4.3.0 
  996. * @access protected 
  997. * @param object $post Post being acted upon. 
  998. * @param string $column_name Current column name. 
  999. * @param string $primary Primary column name. 
  1000. * @return string Row actions output for posts. 
  1001. */ 
  1002. protected function handle_row_actions( $post, $column_name, $primary ) { 
  1003. if ( $primary !== $column_name ) { 
  1004. return ''; 
  1005.  
  1006. $post_type_object = get_post_type_object( $post->post_type ); 
  1007. $can_edit_post = current_user_can( 'edit_post', $post->ID ); 
  1008. $actions = array(); 
  1009. $title = _draft_or_post_title(); 
  1010.  
  1011. if ( $can_edit_post && 'trash' != $post->post_status ) { 
  1012. $actions['edit'] = sprintf( 
  1013. '<a href="%s" aria-label="%s">%s</a>',  
  1014. get_edit_post_link( $post->ID ),  
  1015. /** translators: %s: post title */ 
  1016. esc_attr( sprintf( __( 'Edit “%s”' ), $title ) ),  
  1017. __( 'Edit' ) 
  1018. ); 
  1019. $actions['inline hide-if-no-js'] = sprintf( 
  1020. '<a href="#" class="editinline" aria-label="%s">%s</a>',  
  1021. /** translators: %s: post title */ 
  1022. esc_attr( sprintf( __( 'Quick edit “%s” inline' ), $title ) ),  
  1023. __( 'Quick Edit' ) 
  1024. ); 
  1025.  
  1026. if ( current_user_can( 'delete_post', $post->ID ) ) { 
  1027. if ( 'trash' === $post->post_status ) { 
  1028. $actions['untrash'] = sprintf( 
  1029. '<a href="%s" aria-label="%s">%s</a>',  
  1030. wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ),  
  1031. /** translators: %s: post title */ 
  1032. esc_attr( sprintf( __( 'Restore “%s” from the Trash' ), $title ) ),  
  1033. __( 'Restore' ) 
  1034. ); 
  1035. } elseif ( EMPTY_TRASH_DAYS ) { 
  1036. $actions['trash'] = sprintf( 
  1037. '<a href="%s" class="submitdelete" aria-label="%s">%s</a>',  
  1038. get_delete_post_link( $post->ID ),  
  1039. /** translators: %s: post title */ 
  1040. esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $title ) ),  
  1041. _x( 'Trash', 'verb' ) 
  1042. ); 
  1043. if ( 'trash' === $post->post_status || ! EMPTY_TRASH_DAYS ) { 
  1044. $actions['delete'] = sprintf( 
  1045. '<a href="%s" class="submitdelete" aria-label="%s">%s</a>',  
  1046. get_delete_post_link( $post->ID, '', true ),  
  1047. /** translators: %s: post title */ 
  1048. esc_attr( sprintf( __( 'Delete “%s” permanently' ), $title ) ),  
  1049. __( 'Delete Permanently' ) 
  1050. ); 
  1051.  
  1052. if ( is_post_type_viewable( $post_type_object ) ) { 
  1053. if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { 
  1054. if ( $can_edit_post ) { 
  1055. $preview_link = get_preview_post_link( $post ); 
  1056. $actions['view'] = sprintf( 
  1057. '<a href="%s" rel="permalink" aria-label="%s">%s</a>',  
  1058. esc_url( $preview_link ),  
  1059. /** translators: %s: post title */ 
  1060. esc_attr( sprintf( __( 'Preview “%s”' ), $title ) ),  
  1061. __( 'Preview' ) 
  1062. ); 
  1063. } elseif ( 'trash' != $post->post_status ) { 
  1064. $actions['view'] = sprintf( 
  1065. '<a href="%s" rel="permalink" aria-label="%s">%s</a>',  
  1066. get_permalink( $post->ID ),  
  1067. /** translators: %s: post title */ 
  1068. esc_attr( sprintf( __( 'View “%s”' ), $title ) ),  
  1069. __( 'View' ) 
  1070. ); 
  1071.  
  1072. if ( is_post_type_hierarchical( $post->post_type ) ) { 
  1073.  
  1074. /** 
  1075. * Filters the array of row action links on the Pages list table. 
  1076. * The filter is evaluated only for hierarchical post types. 
  1077. * @since 2.8.0 
  1078. * @param array $actions An array of row action links. Defaults are 
  1079. * 'Edit', 'Quick Edit', 'Restore, 'Trash',  
  1080. * 'Delete Permanently', 'Preview', and 'View'. 
  1081. * @param WP_Post $post The post object. 
  1082. */ 
  1083. $actions = apply_filters( 'page_row_actions', $actions, $post ); 
  1084. } else { 
  1085.  
  1086. /** 
  1087. * Filters the array of row action links on the Posts list table. 
  1088. * The filter is evaluated only for non-hierarchical post types. 
  1089. * @since 2.8.0 
  1090. * @param array $actions An array of row action links. Defaults are 
  1091. * 'Edit', 'Quick Edit', 'Restore, 'Trash',  
  1092. * 'Delete Permanently', 'Preview', and 'View'. 
  1093. * @param WP_Post $post The post object. 
  1094. */ 
  1095. $actions = apply_filters( 'post_row_actions', $actions, $post ); 
  1096.  
  1097. return $this->row_actions( $actions ); 
  1098.  
  1099. /** 
  1100. * Outputs the hidden row displayed when inline editing 
  1101. * @since 3.1.0 
  1102. * @global string $mode 
  1103. */ 
  1104. public function inline_edit() { 
  1105. global $mode; 
  1106.  
  1107. $screen = $this->screen; 
  1108.  
  1109. $post = get_default_post_to_edit( $screen->post_type ); 
  1110. $post_type_object = get_post_type_object( $screen->post_type ); 
  1111.  
  1112. $taxonomy_names = get_object_taxonomies( $screen->post_type ); 
  1113. $hierarchical_taxonomies = array(); 
  1114. $flat_taxonomies = array(); 
  1115. foreach ( $taxonomy_names as $taxonomy_name ) { 
  1116.  
  1117. $taxonomy = get_taxonomy( $taxonomy_name ); 
  1118.  
  1119. $show_in_quick_edit = $taxonomy->show_in_quick_edit; 
  1120.  
  1121. /** 
  1122. * Filters whether the current taxonomy should be shown in the Quick Edit panel. 
  1123. * @since 4.2.0 
  1124. * @param bool $show_in_quick_edit Whether to show the current taxonomy in Quick Edit. 
  1125. * @param string $taxonomy_name Taxonomy name. 
  1126. * @param string $post_type Post type of current Quick Edit post. 
  1127. */ 
  1128. if ( ! apply_filters( 'quick_edit_show_taxonomy', $show_in_quick_edit, $taxonomy_name, $screen->post_type ) ) { 
  1129. continue; 
  1130.  
  1131. if ( $taxonomy->hierarchical ) 
  1132. $hierarchical_taxonomies[] = $taxonomy; 
  1133. else 
  1134. $flat_taxonomies[] = $taxonomy; 
  1135.  
  1136. $m = ( isset( $mode ) && 'excerpt' === $mode ) ? 'excerpt' : 'list'; 
  1137. $can_publish = current_user_can( $post_type_object->cap->publish_posts ); 
  1138. $core_columns = array( 'cb' => true, 'date' => true, 'title' => true, 'categories' => true, 'tags' => true, 'comments' => true, 'author' => true ); 
  1139.  
  1140. ?> 
  1141.  
  1142. <form method="get"><table style="display: none"><tbody id="inlineedit"> 
  1143. <?php 
  1144. $hclass = count( $hierarchical_taxonomies ) ? 'post' : 'page'; 
  1145. $bulk = 0; 
  1146. while ( $bulk < 2 ) { ?> 
  1147.  
  1148. <tr id="<?php echo $bulk ? 'bulk-edit' : 'inline-edit'; ?>" class="inline-edit-row inline-edit-row-<?php echo "$hclass inline-edit-" . $screen->post_type; 
  1149. echo $bulk ? " bulk-edit-row bulk-edit-row-$hclass bulk-edit-{$screen->post_type}" : " quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}"; 
  1150. ?>" style="display: none"><td colspan="<?php echo $this->get_column_count(); ?>" class="colspanchange"> 
  1151.  
  1152. <fieldset class="inline-edit-col-left"> 
  1153. <legend class="inline-edit-legend"><?php echo $bulk ? __( 'Bulk Edit' ) : __( 'Quick Edit' ); ?></legend> 
  1154. <div class="inline-edit-col"> 
  1155. <?php 
  1156.  
  1157. if ( post_type_supports( $screen->post_type, 'title' ) ) : 
  1158. if ( $bulk ) : ?> 
  1159. <div id="bulk-title-div"> 
  1160. <div id="bulk-titles"></div> 
  1161. </div> 
  1162.  
  1163. <?php else : // $bulk ?> 
  1164.  
  1165. <label> 
  1166. <span class="title"><?php _e( 'Title' ); ?></span> 
  1167. <span class="input-text-wrap"><input type="text" name="post_title" class="ptitle" value="" /></span> 
  1168. </label> 
  1169.  
  1170. <label> 
  1171. <span class="title"><?php _e( 'Slug' ); ?></span> 
  1172. <span class="input-text-wrap"><input type="text" name="post_name" value="" /></span> 
  1173. </label> 
  1174.  
  1175. <?php endif; // $bulk 
  1176. endif; // post_type_supports title ?> 
  1177.  
  1178. <?php if ( !$bulk ) : ?> 
  1179. <fieldset class="inline-edit-date"> 
  1180. <legend><span class="title"><?php _e( 'Date' ); ?></span></legend> 
  1181. <?php touch_time( 1, 1, 0, 1 ); ?> 
  1182. </fieldset> 
  1183. <br class="clear" /> 
  1184. <?php endif; // $bulk 
  1185.  
  1186. if ( post_type_supports( $screen->post_type, 'author' ) ) : 
  1187. $authors_dropdown = ''; 
  1188.  
  1189. if ( is_super_admin() || current_user_can( $post_type_object->cap->edit_others_posts ) ) : 
  1190. $users_opt = array( 
  1191. 'hide_if_only_one_author' => false,  
  1192. 'who' => 'authors',  
  1193. 'name' => 'post_author',  
  1194. 'class'=> 'authors',  
  1195. 'multi' => 1,  
  1196. 'echo' => 0,  
  1197. 'show' => 'display_name_with_login',  
  1198. ); 
  1199. if ( $bulk ) 
  1200. $users_opt['show_option_none'] = __( '— No Change —' ); 
  1201.  
  1202. if ( $authors = wp_dropdown_users( $users_opt ) ) : 
  1203. $authors_dropdown = '<label class="inline-edit-author">'; 
  1204. $authors_dropdown .= '<span class="title">' . __( 'Author' ) . '</span>'; 
  1205. $authors_dropdown .= $authors; 
  1206. $authors_dropdown .= '</label>'; 
  1207. endif; 
  1208. endif; // authors 
  1209. ?> 
  1210.  
  1211. <?php if ( !$bulk ) echo $authors_dropdown; 
  1212. endif; // post_type_supports author 
  1213.  
  1214. if ( !$bulk && $can_publish ) : 
  1215. ?> 
  1216.  
  1217. <div class="inline-edit-group wp-clearfix"> 
  1218. <label class="alignleft"> 
  1219. <span class="title"><?php _e( 'Password' ); ?></span> 
  1220. <span class="input-text-wrap"><input type="text" name="post_password" class="inline-edit-password-input" value="" /></span> 
  1221. </label> 
  1222.  
  1223. <em class="alignleft inline-edit-or"> 
  1224. <?php 
  1225. /** translators: Between password field and private checkbox on post quick edit interface */ 
  1226. _e( '–OR–' ); 
  1227. ?> 
  1228. </em> 
  1229. <label class="alignleft inline-edit-private"> 
  1230. <input type="checkbox" name="keep_private" value="private" /> 
  1231. <span class="checkbox-title"><?php _e( 'Private' ); ?></span> 
  1232. </label> 
  1233. </div> 
  1234.  
  1235. <?php endif; ?> 
  1236.  
  1237. </div></fieldset> 
  1238.  
  1239. <?php if ( count( $hierarchical_taxonomies ) && !$bulk ) : ?> 
  1240.  
  1241. <fieldset class="inline-edit-col-center inline-edit-categories"><div class="inline-edit-col"> 
  1242.  
  1243. <?php foreach ( $hierarchical_taxonomies as $taxonomy ) : ?> 
  1244.  
  1245. <span class="title inline-edit-categories-label"><?php echo esc_html( $taxonomy->labels->name ) ?></span> 
  1246. <input type="hidden" name="<?php echo ( $taxonomy->name === 'category' ) ? 'post_category[]' : 'tax_input[' . esc_attr( $taxonomy->name ) . '][]'; ?>" value="0" /> 
  1247. <ul class="cat-checklist <?php echo esc_attr( $taxonomy->name )?>-checklist"> 
  1248. <?php wp_terms_checklist( null, array( 'taxonomy' => $taxonomy->name ) ) ?> 
  1249. </ul> 
  1250.  
  1251. <?php endforeach; //$hierarchical_taxonomies as $taxonomy ?> 
  1252.  
  1253. </div></fieldset> 
  1254.  
  1255. <?php endif; // count( $hierarchical_taxonomies ) && !$bulk ?> 
  1256.  
  1257. <fieldset class="inline-edit-col-right"><div class="inline-edit-col"> 
  1258.  
  1259. <?php 
  1260. if ( post_type_supports( $screen->post_type, 'author' ) && $bulk ) 
  1261. echo $authors_dropdown; 
  1262.  
  1263. if ( post_type_supports( $screen->post_type, 'page-attributes' ) ) : 
  1264.  
  1265. if ( $post_type_object->hierarchical ) : 
  1266. ?> 
  1267. <label> 
  1268. <span class="title"><?php _e( 'Parent' ); ?></span> 
  1269. <?php 
  1270. $dropdown_args = array( 
  1271. 'post_type' => $post_type_object->name,  
  1272. 'selected' => $post->post_parent,  
  1273. 'name' => 'post_parent',  
  1274. 'show_option_none' => __( 'Main Page (no parent)' ),  
  1275. 'option_none_value' => 0,  
  1276. 'sort_column' => 'menu_order, post_title',  
  1277. ); 
  1278.  
  1279. if ( $bulk ) 
  1280. $dropdown_args['show_option_no_change'] = __( '— No Change —' ); 
  1281.  
  1282. /** 
  1283. * Filters the arguments used to generate the Quick Edit page-parent drop-down. 
  1284. * @since 2.7.0 
  1285. * @see wp_dropdown_pages() 
  1286. * @param array $dropdown_args An array of arguments. 
  1287. */ 
  1288. $dropdown_args = apply_filters( 'quick_edit_dropdown_pages_args', $dropdown_args ); 
  1289.  
  1290. wp_dropdown_pages( $dropdown_args ); 
  1291. ?> 
  1292. </label> 
  1293.  
  1294. <?php 
  1295. endif; // hierarchical 
  1296.  
  1297. if ( !$bulk ) : ?> 
  1298.  
  1299. <label> 
  1300. <span class="title"><?php _e( 'Order' ); ?></span> 
  1301. <span class="input-text-wrap"><input type="text" name="menu_order" class="inline-edit-menu-order-input" value="<?php echo $post->menu_order ?>" /></span> 
  1302. </label> 
  1303.  
  1304. <?php endif; // !$bulk 
  1305.  
  1306. if ( 'page' === $screen->post_type ) : 
  1307. ?> 
  1308.  
  1309. <label> 
  1310. <span class="title"><?php _e( 'Template' ); ?></span> 
  1311. <select name="page_template"> 
  1312. <?php if ( $bulk ) : ?> 
  1313. <option value="-1"><?php _e( '— No Change —' ); ?></option> 
  1314. <?php endif; // $bulk ?> 
  1315. <?php 
  1316. /** This filter is documented in wp-admin/includes/meta-boxes.php */ 
  1317. $default_title = apply_filters( 'default_page_template_title', __( 'Default Template' ), 'quick-edit' ); 
  1318. ?> 
  1319. <option value="default"><?php echo esc_html( $default_title ); ?></option> 
  1320. <?php page_template_dropdown() ?> 
  1321. </select> 
  1322. </label> 
  1323.  
  1324. <?php 
  1325. endif; // page post_type 
  1326. endif; // page-attributes 
  1327. ?> 
  1328.  
  1329. <?php if ( count( $flat_taxonomies ) && !$bulk ) : ?> 
  1330.  
  1331. <?php foreach ( $flat_taxonomies as $taxonomy ) : ?> 
  1332. <?php if ( current_user_can( $taxonomy->cap->assign_terms ) ) : ?> 
  1333. <label class="inline-edit-tags"> 
  1334. <span class="title"><?php echo esc_html( $taxonomy->labels->name ) ?></span> 
  1335. <textarea cols="22" rows="1" name="tax_input[<?php echo esc_attr( $taxonomy->name )?>]" class="tax_input_<?php echo esc_attr( $taxonomy->name )?>"></textarea> 
  1336. </label> 
  1337. <?php endif; ?> 
  1338.  
  1339. <?php endforeach; //$flat_taxonomies as $taxonomy ?> 
  1340.  
  1341. <?php endif; // count( $flat_taxonomies ) && !$bulk ?> 
  1342.  
  1343. <?php if ( post_type_supports( $screen->post_type, 'comments' ) || post_type_supports( $screen->post_type, 'trackbacks' ) ) : 
  1344. if ( $bulk ) : ?> 
  1345.  
  1346. <div class="inline-edit-group wp-clearfix"> 
  1347. <?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?> 
  1348. <label class="alignleft"> 
  1349. <span class="title"><?php _e( 'Comments' ); ?></span> 
  1350. <select name="comment_status"> 
  1351. <option value=""><?php _e( '— No Change —' ); ?></option> 
  1352. <option value="open"><?php _e( 'Allow' ); ?></option> 
  1353. <option value="closed"><?php _e( 'Do not allow' ); ?></option> 
  1354. </select> 
  1355. </label> 
  1356. <?php endif; if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?> 
  1357. <label class="alignright"> 
  1358. <span class="title"><?php _e( 'Pings' ); ?></span> 
  1359. <select name="ping_status"> 
  1360. <option value=""><?php _e( '— No Change —' ); ?></option> 
  1361. <option value="open"><?php _e( 'Allow' ); ?></option> 
  1362. <option value="closed"><?php _e( 'Do not allow' ); ?></option> 
  1363. </select> 
  1364. </label> 
  1365. <?php endif; ?> 
  1366. </div> 
  1367.  
  1368. <?php else : // $bulk ?> 
  1369.  
  1370. <div class="inline-edit-group wp-clearfix"> 
  1371. <?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?> 
  1372. <label class="alignleft"> 
  1373. <input type="checkbox" name="comment_status" value="open" /> 
  1374. <span class="checkbox-title"><?php _e( 'Allow Comments' ); ?></span> 
  1375. </label> 
  1376. <?php endif; if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?> 
  1377. <label class="alignleft"> 
  1378. <input type="checkbox" name="ping_status" value="open" /> 
  1379. <span class="checkbox-title"><?php _e( 'Allow Pings' ); ?></span> 
  1380. </label> 
  1381. <?php endif; ?> 
  1382. </div> 
  1383.  
  1384. <?php endif; // $bulk 
  1385. endif; // post_type_supports comments or pings ?> 
  1386.  
  1387. <div class="inline-edit-group wp-clearfix"> 
  1388. <label class="inline-edit-status alignleft"> 
  1389. <span class="title"><?php _e( 'Status' ); ?></span> 
  1390. <select name="_status"> 
  1391. <?php if ( $bulk ) : ?> 
  1392. <option value="-1"><?php _e( '— No Change —' ); ?></option> 
  1393. <?php endif; // $bulk ?> 
  1394. <?php if ( $can_publish ) : // Contributors only get "Unpublished" and "Pending Review" ?> 
  1395. <option value="publish"><?php _e( 'Published' ); ?></option> 
  1396. <option value="future"><?php _e( 'Scheduled' ); ?></option> 
  1397. <?php if ( $bulk ) : ?> 
  1398. <option value="private"><?php _e( 'Private' ) ?></option> 
  1399. <?php endif; // $bulk ?> 
  1400. <?php endif; ?> 
  1401. <option value="pending"><?php _e( 'Pending Review' ); ?></option> 
  1402. <option value="draft"><?php _e( 'Draft' ); ?></option> 
  1403. </select> 
  1404. </label> 
  1405.  
  1406. <?php if ( 'post' === $screen->post_type && $can_publish && current_user_can( $post_type_object->cap->edit_others_posts ) ) : ?> 
  1407.  
  1408. <?php if ( $bulk ) : ?> 
  1409.  
  1410. <label class="alignright"> 
  1411. <span class="title"><?php _e( 'Sticky' ); ?></span> 
  1412. <select name="sticky"> 
  1413. <option value="-1"><?php _e( '— No Change —' ); ?></option> 
  1414. <option value="sticky"><?php _e( 'Sticky' ); ?></option> 
  1415. <option value="unsticky"><?php _e( 'Not Sticky' ); ?></option> 
  1416. </select> 
  1417. </label> 
  1418.  
  1419. <?php else : // $bulk ?> 
  1420.  
  1421. <label class="alignleft"> 
  1422. <input type="checkbox" name="sticky" value="sticky" /> 
  1423. <span class="checkbox-title"><?php _e( 'Make this post sticky' ); ?></span> 
  1424. </label> 
  1425.  
  1426. <?php endif; // $bulk ?> 
  1427.  
  1428. <?php endif; // 'post' && $can_publish && current_user_can( 'edit_others_cap' ) ?> 
  1429.  
  1430. </div> 
  1431.  
  1432. <?php 
  1433.  
  1434. if ( $bulk && current_theme_supports( 'post-formats' ) && post_type_supports( $screen->post_type, 'post-formats' ) ) { 
  1435. $post_formats = get_theme_support( 'post-formats' ); 
  1436.  
  1437. ?> 
  1438. <label class="alignleft"> 
  1439. <span class="title"><?php _ex( 'Format', 'post format' ); ?></span> 
  1440. <select name="post_format"> 
  1441. <option value="-1"><?php _e( '— No Change —' ); ?></option> 
  1442. <option value="0"><?php echo get_post_format_string( 'standard' ); ?></option> 
  1443. <?php 
  1444. if ( is_array( $post_formats[0] ) ) { 
  1445. foreach ( $post_formats[0] as $format ) { 
  1446. ?> 
  1447. <option value="<?php echo esc_attr( $format ); ?>"><?php echo esc_html( get_post_format_string( $format ) ); ?></option> 
  1448. <?php 
  1449. ?> 
  1450. </select></label> 
  1451. <?php 
  1452.  
  1453.  
  1454. ?> 
  1455.  
  1456. </div></fieldset> 
  1457.  
  1458. <?php 
  1459. list( $columns ) = $this->get_column_info(); 
  1460.  
  1461. foreach ( $columns as $column_name => $column_display_name ) { 
  1462. if ( isset( $core_columns[$column_name] ) ) 
  1463. continue; 
  1464.  
  1465. if ( $bulk ) { 
  1466.  
  1467. /** 
  1468. * Fires once for each column in Bulk Edit mode. 
  1469. * @since 2.7.0 
  1470. * @param string $column_name Name of the column to edit. 
  1471. * @param WP_Post $post_type The post type slug. 
  1472. */ 
  1473. do_action( 'bulk_edit_custom_box', $column_name, $screen->post_type ); 
  1474. } else { 
  1475.  
  1476. /** 
  1477. * Fires once for each column in Quick Edit mode. 
  1478. * @since 2.7.0 
  1479. * @param string $column_name Name of the column to edit. 
  1480. * @param string $post_type The post type slug. 
  1481. */ 
  1482. do_action( 'quick_edit_custom_box', $column_name, $screen->post_type ); 
  1483.  
  1484. ?> 
  1485. <p class="submit inline-edit-save"> 
  1486. <button type="button" class="button-secondary cancel alignleft"><?php _e( 'Cancel' ); ?></button> 
  1487. <?php if ( ! $bulk ) { 
  1488. wp_nonce_field( 'inlineeditnonce', '_inline_edit', false ); 
  1489. ?> 
  1490. <button type="button" class="button-primary save alignright"><?php _e( 'Update' ); ?></button> 
  1491. <span class="spinner"></span> 
  1492. <?php } else { 
  1493. submit_button( __( 'Update' ), 'button-primary alignright', 'bulk_edit', false ); 
  1494. } ?> 
  1495. <input type="hidden" name="post_view" value="<?php echo esc_attr( $m ); ?>" /> 
  1496. <input type="hidden" name="screen" value="<?php echo esc_attr( $screen->id ); ?>" /> 
  1497. <?php if ( ! $bulk && ! post_type_supports( $screen->post_type, 'author' ) ) { ?> 
  1498. <input type="hidden" name="post_author" value="<?php echo esc_attr( $post->post_author ); ?>" /> 
  1499. <?php } ?> 
  1500. <span class="error" style="display:none"></span> 
  1501. <br class="clear" /> 
  1502. </p> 
  1503. </td></tr> 
  1504. <?php 
  1505. $bulk++; 
  1506. ?> 
  1507. </tbody></table></form> 
  1508. <?php