WP_Media_List_Table

Core class used to implement displaying media items in a list table.

Defined (1)

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

/wp-admin/includes/class-wp-media-list-table.php  
  1. class WP_Media_List_Table extends WP_List_Table { 
  2. /** 
  3. * Holds the number of pending comments for each post. 
  4. * @since 4.4.0 
  5. * @var array 
  6. * @access protected 
  7. */ 
  8. protected $comment_pending_count = array(); 
  9.  
  10. private $detached; 
  11.  
  12. private $is_trash; 
  13.  
  14. /** 
  15. * Constructor. 
  16. * @since 3.1.0 
  17. * @access public 
  18. * @see WP_List_Table::__construct() for more information on default arguments. 
  19. * @param array $args An associative array of arguments. 
  20. */ 
  21. public function __construct( $args = array() ) { 
  22. $this->detached = ( isset( $_REQUEST['attachment-filter'] ) && 'detached' === $_REQUEST['attachment-filter'] ); 
  23.  
  24. $this->modes = array( 
  25. 'list' => __( 'List View' ),  
  26. 'grid' => __( 'Grid View' ) 
  27. ); 
  28.  
  29. parent::__construct( array( 
  30. 'plural' => 'media',  
  31. 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,  
  32. ) ); 
  33.  
  34. /** 
  35. * @return bool 
  36. */ 
  37. public function ajax_user_can() { 
  38. return current_user_can('upload_files'); 
  39.  
  40. /** 
  41. * @global WP_Query $wp_query 
  42. * @global array $post_mime_types 
  43. * @global array $avail_post_mime_types 
  44. * @global string $mode 
  45. */ 
  46. public function prepare_items() { 
  47. global $wp_query, $post_mime_types, $avail_post_mime_types, $mode; 
  48.  
  49. list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $_REQUEST ); 
  50.  
  51. $this->is_trash = isset( $_REQUEST['attachment-filter'] ) && 'trash' === $_REQUEST['attachment-filter']; 
  52.  
  53. $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode']; 
  54.  
  55. $this->set_pagination_args( array( 
  56. 'total_items' => $wp_query->found_posts,  
  57. 'total_pages' => $wp_query->max_num_pages,  
  58. 'per_page' => $wp_query->query_vars['posts_per_page'],  
  59. ) ); 
  60.  
  61. /** 
  62. * @global array $post_mime_types 
  63. * @global array $avail_post_mime_types 
  64. * @return array 
  65. */ 
  66. protected function get_views() { 
  67. global $post_mime_types, $avail_post_mime_types; 
  68.  
  69. $type_links = array(); 
  70.  
  71. $filter = empty( $_GET['attachment-filter'] ) ? '' : $_GET['attachment-filter']; 
  72.  
  73. $type_links['all'] = sprintf( 
  74. '<option value=""%s>%s</option>',  
  75. selected( $filter, true, false ),  
  76. __( 'All media items' ) 
  77. ); 
  78.  
  79. foreach ( $post_mime_types as $mime_type => $label ) { 
  80. if ( ! wp_match_mime_types( $mime_type, $avail_post_mime_types ) ) { 
  81. continue; 
  82.  
  83. $selected = selected( 
  84. $filter && 0 === strpos( $filter, 'post_mime_type:' ) && 
  85. wp_match_mime_types( $mime_type, str_replace( 'post_mime_type:', '', $filter ) ),  
  86. true,  
  87. false 
  88. ); 
  89.  
  90. $type_links[$mime_type] = sprintf( 
  91. '<option value="post_mime_type:%s"%s>%s</option>',  
  92. esc_attr( $mime_type ),  
  93. $selected,  
  94. $label[0] 
  95. ); 
  96. $type_links['detached'] = '<option value="detached"' . ( $this->detached ? ' selected="selected"' : '' ) . '>' . __( 'Unattached' ) . '</option>'; 
  97.  
  98. if ( $this->is_trash || ( defined( 'MEDIA_TRASH') && MEDIA_TRASH ) ) { 
  99. $type_links['trash'] = sprintf( 
  100. '<option value="trash"%s>%s</option>',  
  101. selected( 'trash' === $filter, true, false ),  
  102. _x( 'Trash', 'attachment filter' ) 
  103. ); 
  104. return $type_links; 
  105.  
  106. /** 
  107. * @return array 
  108. */ 
  109. protected function get_bulk_actions() { 
  110. $actions = array(); 
  111. if ( MEDIA_TRASH ) { 
  112. if ( $this->is_trash ) { 
  113. $actions['untrash'] = __( 'Restore' ); 
  114. $actions['delete'] = __( 'Delete Permanently' ); 
  115. } else { 
  116. $actions['trash'] = _x( 'Trash', 'verb' ); 
  117. } else { 
  118. $actions['delete'] = __( 'Delete Permanently' ); 
  119.  
  120. if ( $this->detached ) 
  121. $actions['attach'] = __( 'Attach' ); 
  122.  
  123. return $actions; 
  124.  
  125. /** 
  126. * @param string $which 
  127. */ 
  128. protected function extra_tablenav( $which ) { 
  129. if ( 'bar' !== $which ) { 
  130. return; 
  131. ?> 
  132. <div class="actions"> 
  133. <?php 
  134. if ( ! is_singular() ) { 
  135. if ( ! $this->is_trash ) { 
  136. $this->months_dropdown( 'attachment' ); 
  137.  
  138. /** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */ 
  139. do_action( 'restrict_manage_posts', $this->screen->post_type ); 
  140.  
  141. submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) ); 
  142.  
  143. if ( $this->is_trash && current_user_can( 'edit_others_posts' ) ) { 
  144. submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); 
  145. } ?> 
  146. </div> 
  147. <?php 
  148.  
  149. /** 
  150. * @return string 
  151. */ 
  152. public function current_action() { 
  153. if ( isset( $_REQUEST['found_post_id'] ) && isset( $_REQUEST['media'] ) ) 
  154. return 'attach'; 
  155.  
  156. if ( isset( $_REQUEST['parent_post_id'] ) && isset( $_REQUEST['media'] ) ) 
  157. return 'detach'; 
  158.  
  159. if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) 
  160. return 'delete_all'; 
  161.  
  162. return parent::current_action(); 
  163.  
  164. /** 
  165. * @return bool 
  166. */ 
  167. public function has_items() { 
  168. return have_posts(); 
  169.  
  170. /** 
  171. * @access public 
  172. */ 
  173. public function no_items() { 
  174. _e( 'No media files found.' ); 
  175.  
  176. /** 
  177. * Override parent views so we can use the filter bar display. 
  178. * @global string $mode 
  179. */ 
  180. public function views() { 
  181. global $mode; 
  182.  
  183. $views = $this->get_views(); 
  184.  
  185. $this->screen->render_screen_reader_content( 'heading_views' ); 
  186. ?> 
  187. <div class="wp-filter"> 
  188. <div class="filter-items"> 
  189. <?php $this->view_switcher( $mode ); ?> 
  190.  
  191. <label for="attachment-filter" class="screen-reader-text"><?php _e( 'Filter by type' ); ?></label> 
  192. <select class="attachment-filters" name="attachment-filter" id="attachment-filter"> 
  193. <?php 
  194. if ( ! empty( $views ) ) { 
  195. foreach ( $views as $class => $view ) { 
  196. echo "\t$view\n"; 
  197. ?> 
  198. </select> 
  199.  
  200. <?php 
  201. $this->extra_tablenav( 'bar' ); 
  202.  
  203. /** This filter is documented in wp-admin/inclues/class-wp-list-table.php */ 
  204. $views = apply_filters( "views_{$this->screen->id}", array() ); 
  205.  
  206. // Back compat for pre-4.0 view links. 
  207. if ( ! empty( $views ) ) { 
  208. echo '<ul class="filter-links">'; 
  209. foreach ( $views as $class => $view ) { 
  210. echo "<li class='$class'>$view</li>"; 
  211. echo '</ul>'; 
  212. ?> 
  213. </div> 
  214.  
  215. <div class="search-form"> 
  216. <label for="media-search-input" class="screen-reader-text"><?php esc_html_e( 'Search Media' ); ?></label> 
  217. <input type="search" placeholder="<?php esc_attr_e( 'Search' ) ?>" id="media-search-input" class="search" name="s" value="<?php _admin_search_query(); ?>"></div> 
  218. </div> 
  219. <?php 
  220.  
  221. /** 
  222. * @return array 
  223. */ 
  224. public function get_columns() { 
  225. $posts_columns = array(); 
  226. $posts_columns['cb'] = '<input type="checkbox" />'; 
  227. /** translators: column name */ 
  228. $posts_columns['title'] = _x( 'File', 'column name' ); 
  229. $posts_columns['author'] = __( 'Author' ); 
  230.  
  231. $taxonomies = get_taxonomies_for_attachments( 'objects' ); 
  232. $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); 
  233.  
  234. /** 
  235. * Filters the taxonomy columns for attachments in the Media list table. 
  236. * @since 3.5.0 
  237. * @param array $taxonomies An array of registered taxonomies to show for attachments. 
  238. * @param string $post_type The post type. Default 'attachment'. 
  239. */ 
  240. $taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' ); 
  241. $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); 
  242.  
  243. foreach ( $taxonomies as $taxonomy ) { 
  244. if ( 'category' === $taxonomy ) { 
  245. $column_key = 'categories'; 
  246. } elseif ( 'post_tag' === $taxonomy ) { 
  247. $column_key = 'tags'; 
  248. } else { 
  249. $column_key = 'taxonomy-' . $taxonomy; 
  250. $posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name; 
  251.  
  252. /** translators: column name */ 
  253. if ( !$this->detached ) { 
  254. $posts_columns['parent'] = _x( 'Uploaded to', 'column name' ); 
  255. if ( post_type_supports( 'attachment', 'comments' ) ) 
  256. $posts_columns['comments'] = '<span class="vers comment-grey-bubble" title="' . esc_attr__( 'Comments' ) . '"><span class="screen-reader-text">' . __( 'Comments' ) . '</span></span>'; 
  257. /** translators: column name */ 
  258. $posts_columns['date'] = _x( 'Date', 'column name' ); 
  259. /** 
  260. * Filters the Media list table columns. 
  261. * @since 2.5.0 
  262. * @param array $posts_columns An array of columns displayed in the Media list table. 
  263. * @param bool $detached Whether the list table contains media not attached 
  264. * to any posts. Default true. 
  265. */ 
  266. return apply_filters( 'manage_media_columns', $posts_columns, $this->detached ); 
  267.  
  268. /** 
  269. * @return array 
  270. */ 
  271. protected function get_sortable_columns() { 
  272. return array( 
  273. 'title' => 'title',  
  274. 'author' => 'author',  
  275. 'parent' => 'parent',  
  276. 'comments' => 'comment_count',  
  277. 'date' => array( 'date', true ),  
  278. ); 
  279.  
  280. /** 
  281. * Handles the checkbox column output. 
  282. * @since 4.3.0 
  283. * @access public 
  284. * @param WP_Post $post The current WP_Post object. 
  285. */ 
  286. public function column_cb( $post ) { 
  287. if ( current_user_can( 'edit_post', $post->ID ) ) { ?> 
  288. <label class="screen-reader-text" for="cb-select-<?php echo $post->ID; ?>"><?php 
  289. echo sprintf( __( 'Select %s' ), _draft_or_post_title() ); 
  290. ?></label> 
  291. <input type="checkbox" name="media[]" id="cb-select-<?php echo $post->ID; ?>" value="<?php echo $post->ID; ?>" /> 
  292. <?php } 
  293.  
  294. /** 
  295. * Handles the title column output. 
  296. * @since 4.3.0 
  297. * @access public 
  298. * @param WP_Post $post The current WP_Post object. 
  299. */ 
  300. public function column_title( $post ) { 
  301. list( $mime ) = explode( '/', $post->post_mime_type ); 
  302.  
  303. $title = _draft_or_post_title(); 
  304. $thumb = wp_get_attachment_image( $post->ID, array( 60, 60 ), true, array( 'alt' => '' ) ); 
  305. $link_start = $link_end = ''; 
  306.  
  307. if ( current_user_can( 'edit_post', $post->ID ) && ! $this->is_trash ) { 
  308. $link_start = sprintf( 
  309. '<a href="%s" aria-label="%s">',  
  310. get_edit_post_link( $post->ID ),  
  311. /** translators: %s: attachment title */ 
  312. esc_attr( sprintf( __( '“%s” (Edit)' ), $title ) ) 
  313. ); 
  314. $link_end = '</a>'; 
  315.  
  316. $class = $thumb ? ' class="has-media-icon"' : ''; 
  317. ?> 
  318. <strong<?php echo $class; ?>> 
  319. <?php 
  320. echo $link_start; 
  321. if ( $thumb ) : ?> 
  322. <span class="media-icon <?php echo sanitize_html_class( $mime . '-icon' ); ?>"><?php echo $thumb; ?></span> 
  323. <?php endif; 
  324. echo $title . $link_end; 
  325. _media_states( $post ); 
  326. ?> 
  327. </strong> 
  328. <p class="filename"> 
  329. <span class="screen-reader-text"><?php _e( 'File name:' ); ?> </span> 
  330. <?php 
  331. $file = get_attached_file( $post->ID ); 
  332. echo esc_html( wp_basename( $file ) ); 
  333. ?> 
  334. </p> 
  335. <?php 
  336.  
  337. /** 
  338. * Handles the author column output. 
  339. * @since 4.3.0 
  340. * @access public 
  341. * @param WP_Post $post The current WP_Post object. 
  342. */ 
  343. public function column_author( $post ) { 
  344. printf( '<a href="%s">%s</a>',  
  345. esc_url( add_query_arg( array( 'author' => get_the_author_meta('ID') ), 'upload.php' ) ),  
  346. get_the_author() 
  347. ); 
  348.  
  349. /** 
  350. * Handles the description column output. 
  351. * @since 4.3.0 
  352. * @access public 
  353. * @param WP_Post $post The current WP_Post object. 
  354. */ 
  355. public function column_desc( $post ) { 
  356. echo has_excerpt() ? $post->post_excerpt : ''; 
  357.  
  358. /** 
  359. * Handles the date column output. 
  360. * @since 4.3.0 
  361. * @access public 
  362. * @param WP_Post $post The current WP_Post object. 
  363. */ 
  364. public function column_date( $post ) { 
  365. if ( '0000-00-00 00:00:00' === $post->post_date ) { 
  366. $h_time = __( 'Unpublished' ); 
  367. } else { 
  368. $m_time = $post->post_date; 
  369. $time = get_post_time( 'G', true, $post, false ); 
  370. if ( ( abs( $t_diff = time() - $time ) ) < DAY_IN_SECONDS ) { 
  371. if ( $t_diff < 0 ) { 
  372. $h_time = sprintf( __( '%s from now' ), human_time_diff( $time ) ); 
  373. } else { 
  374. $h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) ); 
  375. } else { 
  376. $h_time = mysql2date( __( 'Y/m/d' ), $m_time ); 
  377.  
  378. echo $h_time; 
  379.  
  380. /** 
  381. * Handles the parent column output. 
  382. * @since 4.3.0 
  383. * @access public 
  384. * @param WP_Post $post The current WP_Post object. 
  385. */ 
  386. public function column_parent( $post ) { 
  387. $user_can_edit = current_user_can( 'edit_post', $post->ID ); 
  388.  
  389. if ( $post->post_parent > 0 ) { 
  390. $parent = get_post( $post->post_parent ); 
  391. } else { 
  392. $parent = false; 
  393.  
  394. if ( $parent ) { 
  395. $title = _draft_or_post_title( $post->post_parent ); 
  396. $parent_type = get_post_type_object( $parent->post_type ); 
  397.  
  398. if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $post->post_parent ) ) { 
  399. ?> 
  400. <strong><a href="<?php echo get_edit_post_link( $post->post_parent ); ?>"> 
  401. <?php echo $title ?></a></strong><?php 
  402. } elseif ( $parent_type && current_user_can( 'read_post', $post->post_parent ) ) { 
  403. ?> 
  404. <strong><?php echo $title ?></strong><?php 
  405. } else { 
  406. _e( '(Private post)' ); 
  407.  
  408. if ( $user_can_edit ): 
  409. $detach_url = add_query_arg( array( 
  410. 'parent_post_id' => $post->post_parent,  
  411. 'media[]' => $post->ID,  
  412. '_wpnonce' => wp_create_nonce( 'bulk-' . $this->_args['plural'] ) 
  413. ), 'upload.php' ); 
  414. printf( 
  415. '<br /><a href="%s" class="hide-if-no-js detach-from-parent" aria-label="%s">%s</a>',  
  416. $detach_url,  
  417. /** translators: %s: title of the post the attachment is attached to */ 
  418. esc_attr( sprintf( __( 'Detach from “%s”' ), $title ) ),  
  419. __( 'Detach' ) 
  420. ); 
  421. endif; 
  422. } else { 
  423. _e( '(Unattached)' ); ?> 
  424. <?php if ( $user_can_edit ) { 
  425. $title = _draft_or_post_title( $post->post_parent ); 
  426. printf( 
  427. '<br /><a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>',  
  428. $post->ID,  
  429. /** translators: %s: attachment title */ 
  430. esc_attr( sprintf( __( 'Attach “%s” to existing content' ), $title ) ),  
  431. __( 'Attach' ) 
  432. ); 
  433.  
  434. /** 
  435. * Handles the comments column output. 
  436. * @since 4.3.0 
  437. * @access public 
  438. * @param WP_Post $post The current WP_Post object. 
  439. */ 
  440. public function column_comments( $post ) { 
  441. echo '<div class="post-com-count-wrapper">'; 
  442.  
  443. if ( isset( $this->comment_pending_count[ $post->ID ] ) ) { 
  444. $pending_comments = $this->comment_pending_count[ $post->ID ]; 
  445. } else { 
  446. $pending_comments = get_pending_comments_num( $post->ID ); 
  447.  
  448. $this->comments_bubble( $post->ID, $pending_comments ); 
  449.  
  450. echo '</div>'; 
  451.  
  452. /** 
  453. * Handles output for the default column. 
  454. * @since 4.3.0 
  455. * @access public 
  456. * @param WP_Post $post The current WP_Post object. 
  457. * @param string $column_name Current column name. 
  458. */ 
  459. public function column_default( $post, $column_name ) { 
  460. if ( 'categories' === $column_name ) { 
  461. $taxonomy = 'category'; 
  462. } elseif ( 'tags' === $column_name ) { 
  463. $taxonomy = 'post_tag'; 
  464. } elseif ( 0 === strpos( $column_name, 'taxonomy-' ) ) { 
  465. $taxonomy = substr( $column_name, 9 ); 
  466. } else { 
  467. $taxonomy = false; 
  468.  
  469. if ( $taxonomy ) { 
  470. $terms = get_the_terms( $post->ID, $taxonomy ); 
  471. if ( is_array( $terms ) ) { 
  472. $out = array(); 
  473. foreach ( $terms as $t ) { 
  474. $posts_in_term_qv = array(); 
  475. $posts_in_term_qv['taxonomy'] = $taxonomy; 
  476. $posts_in_term_qv['term'] = $t->slug; 
  477.  
  478. $out[] = sprintf( '<a href="%s">%s</a>',  
  479. esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ),  
  480. esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) ) 
  481. ); 
  482. /** translators: used between list items, there is a space after the comma */ 
  483. echo join( __( ', ' ), $out ); 
  484. } else { 
  485. echo '<span aria-hidden="true">—</span><span class="screen-reader-text">' . get_taxonomy( $taxonomy )->labels->no_terms . '</span>'; 
  486.  
  487. return; 
  488.  
  489. /** 
  490. * Fires for each custom column in the Media list table. 
  491. * Custom columns are registered using the {@see 'manage_media_columns'} filter. 
  492. * @since 2.5.0 
  493. * @param string $column_name Name of the custom column. 
  494. * @param int $post_id Attachment ID. 
  495. */ 
  496. do_action( 'manage_media_custom_column', $column_name, $post->ID ); 
  497.  
  498. /** 
  499. * @global WP_Post $post 
  500. */ 
  501. public function display_rows() { 
  502. global $post, $wp_query; 
  503.  
  504. $post_ids = wp_list_pluck( $wp_query->posts, 'ID' ); 
  505. reset( $wp_query->posts ); 
  506.  
  507. $this->comment_pending_count = get_pending_comments_num( $post_ids ); 
  508.  
  509. add_filter( 'the_title', 'esc_html' ); 
  510.  
  511. while ( have_posts() ) : the_post(); 
  512. if ( 
  513. ( $this->is_trash && $post->post_status != 'trash' ) 
  514. || ( ! $this->is_trash && $post->post_status === 'trash' ) 
  515. ) { 
  516. continue; 
  517. $post_owner = ( get_current_user_id() == $post->post_author ) ? 'self' : 'other'; 
  518. ?> 
  519. <tr id="post-<?php echo $post->ID; ?>" class="<?php echo trim( ' author-' . $post_owner . ' status-' . $post->post_status ); ?>"> 
  520. <?php $this->single_row_columns( $post ); ?> 
  521. </tr> 
  522. <?php 
  523. endwhile; 
  524.  
  525. /** 
  526. * Gets the name of the default primary column. 
  527. * @since 4.3.0 
  528. * @access protected 
  529. * @return string Name of the default primary column, in this case, 'title'. 
  530. */ 
  531. protected function get_default_primary_column_name() { 
  532. return 'title'; 
  533.  
  534. /** 
  535. * @param WP_Post $post 
  536. * @param string $att_title 
  537. * @return array 
  538. */ 
  539. private function _get_row_actions( $post, $att_title ) { 
  540. $actions = array(); 
  541.  
  542. if ( $this->detached ) { 
  543. if ( current_user_can( 'edit_post', $post->ID ) ) { 
  544. $actions['edit'] = sprintf( 
  545. '<a href="%s" aria-label="%s">%s</a>',  
  546. get_edit_post_link( $post->ID ),  
  547. /** translators: %s: attachment title */ 
  548. esc_attr( sprintf( __( 'Edit “%s”' ), $att_title ) ),  
  549. __( 'Edit' ) 
  550. ); 
  551. if ( current_user_can( 'delete_post', $post->ID ) ) { 
  552. if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { 
  553. $actions['trash'] = sprintf( 
  554. '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',  
  555. wp_nonce_url( "post.php?action=trash&post=$post->ID", 'trash-post_' . $post->ID ),  
  556. /** translators: %s: attachment title */ 
  557. esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $att_title ) ),  
  558. _x( 'Trash', 'verb' ) 
  559. ); 
  560. } else { 
  561. $delete_ays = ! MEDIA_TRASH ? " onclick='return showNotice.warn();'" : ''; 
  562. $actions['delete'] = sprintf( 
  563. '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>',  
  564. wp_nonce_url( "post.php?action=delete&post=$post->ID", 'delete-post_' . $post->ID ),  
  565. $delete_ays,  
  566. /** translators: %s: attachment title */ 
  567. esc_attr( sprintf( __( 'Delete “%s” permanently' ), $att_title ) ),  
  568. __( 'Delete Permanently' ) 
  569. ); 
  570. $actions['view'] = sprintf( 
  571. '<a href="%s" aria-label="%s" rel="permalink">%s</a>',  
  572. get_permalink( $post->ID ),  
  573. /** translators: %s: attachment title */ 
  574. esc_attr( sprintf( __( 'View “%s”' ), $att_title ) ),  
  575. __( 'View' ) 
  576. ); 
  577.  
  578. if ( current_user_can( 'edit_post', $post->ID ) ) { 
  579. $actions['attach'] = sprintf( 
  580. '<a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>',  
  581. $post->ID,  
  582. /** translators: %s: attachment title */ 
  583. esc_attr( sprintf( __( 'Attach “%s” to existing content' ), $att_title ) ),  
  584. __( 'Attach' ) 
  585. ); 
  586. else { 
  587. if ( current_user_can( 'edit_post', $post->ID ) && !$this->is_trash ) { 
  588. $actions['edit'] = sprintf( 
  589. '<a href="%s" aria-label="%s">%s</a>',  
  590. get_edit_post_link( $post->ID ),  
  591. /** translators: %s: attachment title */ 
  592. esc_attr( sprintf( __( 'Edit “%s”' ), $att_title ) ),  
  593. __( 'Edit' ) 
  594. ); 
  595. if ( current_user_can( 'delete_post', $post->ID ) ) { 
  596. if ( $this->is_trash ) { 
  597. $actions['untrash'] = sprintf( 
  598. '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',  
  599. wp_nonce_url( "post.php?action=untrash&post=$post->ID", 'untrash-post_' . $post->ID ),  
  600. /** translators: %s: attachment title */ 
  601. esc_attr( sprintf( __( 'Restore “%s” from the Trash' ), $att_title ) ),  
  602. __( 'Restore' ) 
  603. ); 
  604. } elseif ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) { 
  605. $actions['trash'] = sprintf( 
  606. '<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',  
  607. wp_nonce_url( "post.php?action=trash&post=$post->ID", 'trash-post_' . $post->ID ),  
  608. /** translators: %s: attachment title */ 
  609. esc_attr( sprintf( __( 'Move “%s” to the Trash' ), $att_title ) ),  
  610. _x( 'Trash', 'verb' ) 
  611. ); 
  612. if ( $this->is_trash || ! EMPTY_TRASH_DAYS || ! MEDIA_TRASH ) { 
  613. $delete_ays = ( !$this->is_trash && !MEDIA_TRASH ) ? " onclick='return showNotice.warn();'" : ''; 
  614. $actions['delete'] = sprintf( 
  615. '<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>',  
  616. wp_nonce_url( "post.php?action=delete&post=$post->ID", 'delete-post_' . $post->ID ),  
  617. $delete_ays,  
  618. /** translators: %s: attachment title */ 
  619. esc_attr( sprintf( __( 'Delete “%s” permanently' ), $att_title ) ),  
  620. __( 'Delete Permanently' ) 
  621. ); 
  622. if ( ! $this->is_trash ) { 
  623. $actions['view'] = sprintf( 
  624. '<a href="%s" aria-label="%s" rel="permalink">%s</a>',  
  625. get_permalink( $post->ID ),  
  626. /** translators: %s: attachment title */ 
  627. esc_attr( sprintf( __( 'View “%s”' ), $att_title ) ),  
  628. __( 'View' ) 
  629. ); 
  630.  
  631. /** 
  632. * Filters the action links for each attachment in the Media list table. 
  633. * @since 2.8.0 
  634. * @param array $actions An array of action links for each attachment. 
  635. * Default 'Edit', 'Delete Permanently', 'View'. 
  636. * @param WP_Post $post WP_Post object for the current attachment. 
  637. * @param bool $detached Whether the list table contains media not attached 
  638. * to any posts. Default true. 
  639. */ 
  640. return apply_filters( 'media_row_actions', $actions, $post, $this->detached ); 
  641.  
  642. /** 
  643. * Generates and displays row action links. 
  644. * @since 4.3.0 
  645. * @access protected 
  646. * @param object $post Attachment being acted upon. 
  647. * @param string $column_name Current column name. 
  648. * @param string $primary Primary column name. 
  649. * @return string Row actions output for media attachments. 
  650. */ 
  651. protected function handle_row_actions( $post, $column_name, $primary ) { 
  652. if ( $primary !== $column_name ) { 
  653. return ''; 
  654.  
  655. $att_title = _draft_or_post_title(); 
  656. return $this->row_actions( $this->_get_row_actions( $post, $att_title ) );