7 * @since 3.1.0 |
7 * @since 3.1.0 |
8 * @access private |
8 * @access private |
9 */ |
9 */ |
10 class WP_Media_List_Table extends WP_List_Table { |
10 class WP_Media_List_Table extends WP_List_Table { |
11 |
11 |
12 function __construct( $args = array() ) { |
12 private $detached; |
13 $this->detached = isset( $_REQUEST['detached'] ) || isset( $_REQUEST['find_detached'] ); |
13 |
|
14 private $is_trash; |
|
15 |
|
16 /** |
|
17 * Constructor. |
|
18 * |
|
19 * @since 3.1.0 |
|
20 * @access public |
|
21 * |
|
22 * @see WP_List_Table::__construct() for more information on default arguments. |
|
23 * |
|
24 * @param array $args An associative array of arguments. |
|
25 */ |
|
26 public function __construct( $args = array() ) { |
|
27 $this->detached = ( isset( $_REQUEST['attachment-filter'] ) && 'detached' === $_REQUEST['attachment-filter'] ); |
|
28 |
|
29 $this->modes = array( |
|
30 'list' => __( 'List View' ), |
|
31 'grid' => __( 'Grid View' ) |
|
32 ); |
14 |
33 |
15 parent::__construct( array( |
34 parent::__construct( array( |
16 'plural' => 'media', |
35 'plural' => 'media', |
17 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
36 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
18 ) ); |
37 ) ); |
19 } |
38 } |
20 |
39 |
21 function ajax_user_can() { |
40 public function ajax_user_can() { |
22 return current_user_can('upload_files'); |
41 return current_user_can('upload_files'); |
23 } |
42 } |
24 |
43 |
25 function prepare_items() { |
44 public function prepare_items() { |
26 global $lost, $wpdb, $wp_query, $post_mime_types, $avail_post_mime_types; |
45 global $wp_query, $post_mime_types, $avail_post_mime_types, $mode; |
27 |
46 |
28 $q = $_REQUEST; |
47 list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $_REQUEST ); |
29 |
48 |
30 if ( !empty( $lost ) ) |
49 $this->is_trash = isset( $_REQUEST['attachment-filter'] ) && 'trash' == $_REQUEST['attachment-filter']; |
31 $q['post__in'] = implode( ',', $lost ); |
50 |
32 |
51 $mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode']; |
33 list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $q ); |
|
34 |
|
35 $this->is_trash = isset( $_REQUEST['status'] ) && 'trash' == $_REQUEST['status']; |
|
36 |
52 |
37 $this->set_pagination_args( array( |
53 $this->set_pagination_args( array( |
38 'total_items' => $wp_query->found_posts, |
54 'total_items' => $wp_query->found_posts, |
39 'total_pages' => $wp_query->max_num_pages, |
55 'total_pages' => $wp_query->max_num_pages, |
40 'per_page' => $wp_query->query_vars['posts_per_page'], |
56 'per_page' => $wp_query->query_vars['posts_per_page'], |
41 ) ); |
57 ) ); |
42 } |
58 } |
43 |
59 |
44 function get_views() { |
60 protected function get_views() { |
45 global $wpdb, $post_mime_types, $avail_post_mime_types; |
61 global $wpdb, $post_mime_types, $avail_post_mime_types; |
46 |
62 |
47 $type_links = array(); |
63 $type_links = array(); |
48 $_num_posts = (array) wp_count_attachments(); |
64 $_num_posts = (array) wp_count_attachments(); |
49 $_total_posts = array_sum($_num_posts) - $_num_posts['trash']; |
65 $_total_posts = array_sum($_num_posts) - $_num_posts['trash']; |
51 $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts)); |
67 $matches = wp_match_mime_types(array_keys($post_mime_types), array_keys($_num_posts)); |
52 foreach ( $matches as $type => $reals ) |
68 foreach ( $matches as $type => $reals ) |
53 foreach ( $reals as $real ) |
69 foreach ( $reals as $real ) |
54 $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real]; |
70 $num_posts[$type] = ( isset( $num_posts[$type] ) ) ? $num_posts[$type] + $_num_posts[$real] : $_num_posts[$real]; |
55 |
71 |
56 $class = ( empty($_GET['post_mime_type']) && !$this->detached && !isset($_GET['status']) ) ? ' class="current"' : ''; |
72 $selected = empty( $_GET['attachment-filter'] ) ? ' selected="selected"' : ''; |
57 $type_links['all'] = "<a href='upload.php'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $_total_posts, 'uploaded files' ), number_format_i18n( $_total_posts ) ) . '</a>'; |
73 $type_links['all'] = "<option value=''$selected>" . sprintf( _nx( 'All (%s)', 'All (%s)', $_total_posts, 'uploaded files' ), number_format_i18n( $_total_posts ) ) . '</option>'; |
58 foreach ( $post_mime_types as $mime_type => $label ) { |
74 foreach ( $post_mime_types as $mime_type => $label ) { |
59 $class = ''; |
|
60 |
|
61 if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) ) |
75 if ( !wp_match_mime_types($mime_type, $avail_post_mime_types) ) |
62 continue; |
76 continue; |
63 |
77 |
64 if ( !empty($_GET['post_mime_type']) && wp_match_mime_types($mime_type, $_GET['post_mime_type']) ) |
78 $selected = ''; |
65 $class = ' class="current"'; |
79 if ( !empty( $_GET['attachment-filter'] ) && strpos( $_GET['attachment-filter'], 'post_mime_type:' ) === 0 && wp_match_mime_types( $mime_type, str_replace( 'post_mime_type:', '', $_GET['attachment-filter'] ) ) ) |
|
80 $selected = ' selected="selected"'; |
66 if ( !empty( $num_posts[$mime_type] ) ) |
81 if ( !empty( $num_posts[$mime_type] ) ) |
67 $type_links[$mime_type] = "<a href='upload.php?post_mime_type=$mime_type'$class>" . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), number_format_i18n( $num_posts[$mime_type] )) . '</a>'; |
82 $type_links[$mime_type] = '<option value="post_mime_type:' . esc_attr( $mime_type ) . '"' . $selected . '>' . sprintf( translate_nooped_plural( $label[2], $num_posts[$mime_type] ), number_format_i18n( $num_posts[$mime_type] )) . '</option>'; |
68 } |
83 } |
69 $type_links['detached'] = '<a href="upload.php?detached=1"' . ( $this->detached ? ' class="current"' : '' ) . '>' . sprintf( _nx( 'Unattached <span class="count">(%s)</span>', 'Unattached <span class="count">(%s)</span>', $total_orphans, 'detached files' ), number_format_i18n( $total_orphans ) ) . '</a>'; |
84 $type_links['detached'] = '<option value="detached"' . ( $this->detached ? ' selected="selected"' : '' ) . '>' . sprintf( _nx( 'Unattached (%s)', 'Unattached (%s)', $total_orphans, 'detached files' ), number_format_i18n( $total_orphans ) ) . '</option>'; |
70 |
85 |
71 if ( !empty($_num_posts['trash']) ) |
86 if ( !empty($_num_posts['trash']) ) |
72 $type_links['trash'] = '<a href="upload.php?status=trash"' . ( (isset($_GET['status']) && $_GET['status'] == 'trash' ) ? ' class="current"' : '') . '>' . sprintf( _nx( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>', $_num_posts['trash'], 'uploaded files' ), number_format_i18n( $_num_posts['trash'] ) ) . '</a>'; |
87 $type_links['trash'] = '<option value="trash"' . ( (isset($_GET['attachment-filter']) && $_GET['attachment-filter'] == 'trash' ) ? ' selected="selected"' : '') . '>' . sprintf( _nx( 'Trash (%s)', 'Trash (%s)', $_num_posts['trash'], 'uploaded files' ), number_format_i18n( $_num_posts['trash'] ) ) . '</option>'; |
73 |
88 |
74 return $type_links; |
89 return $type_links; |
75 } |
90 } |
76 |
91 |
77 function get_bulk_actions() { |
92 protected function get_bulk_actions() { |
78 $actions = array(); |
93 $actions = array(); |
79 $actions['delete'] = __( 'Delete Permanently' ); |
94 if ( MEDIA_TRASH ) { |
|
95 if ( $this->is_trash ) { |
|
96 $actions['untrash'] = __( 'Restore' ); |
|
97 $actions['delete'] = __( 'Delete Permanently' ); |
|
98 } else { |
|
99 $actions['trash'] = __( 'Trash' ); |
|
100 } |
|
101 } else { |
|
102 $actions['delete'] = __( 'Delete Permanently' ); |
|
103 } |
|
104 |
80 if ( $this->detached ) |
105 if ( $this->detached ) |
81 $actions['attach'] = __( 'Attach to a post' ); |
106 $actions['attach'] = __( 'Attach to a post' ); |
82 |
107 |
83 return $actions; |
108 return $actions; |
84 } |
109 } |
85 |
110 |
86 function extra_tablenav( $which ) { |
111 /** |
87 ?> |
112 * @param string $which |
88 <div class="alignleft actions"> |
113 */ |
89 <?php |
114 protected function extra_tablenav( $which ) { |
90 if ( 'top' == $which && !is_singular() && !$this->detached && !$this->is_trash ) { |
115 if ( 'bar' !== $which ) { |
91 $this->months_dropdown( 'attachment' ); |
116 return; |
92 |
117 } |
|
118 ?> |
|
119 <div class="actions"> |
|
120 <?php |
|
121 if ( ! is_singular() ) { |
|
122 if ( ! $this->is_trash ) { |
|
123 $this->months_dropdown( 'attachment' ); |
|
124 } |
|
125 |
|
126 /** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */ |
93 do_action( 'restrict_manage_posts' ); |
127 do_action( 'restrict_manage_posts' ); |
94 submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) ); |
128 submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) ); |
95 } |
129 } |
96 |
130 |
97 if ( $this->detached ) { |
131 if ( $this->is_trash && current_user_can( 'edit_others_posts' ) ) { |
98 submit_button( __( 'Scan for lost attachments' ), 'secondary', 'find_detached', false ); |
|
99 } elseif ( $this->is_trash && current_user_can( 'edit_others_posts' ) ) { |
|
100 submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); |
132 submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false ); |
101 } ?> |
133 } ?> |
102 </div> |
134 </div> |
103 <?php |
135 <?php |
104 } |
136 } |
105 |
137 |
106 function current_action() { |
138 public function current_action() { |
107 if ( isset( $_REQUEST['find_detached'] ) ) |
|
108 return 'find_detached'; |
|
109 |
|
110 if ( isset( $_REQUEST['found_post_id'] ) && isset( $_REQUEST['media'] ) ) |
139 if ( isset( $_REQUEST['found_post_id'] ) && isset( $_REQUEST['media'] ) ) |
111 return 'attach'; |
140 return 'attach'; |
112 |
141 |
|
142 if ( isset( $_REQUEST['parent_post_id'] ) && isset( $_REQUEST['media'] ) ) |
|
143 return 'detach'; |
|
144 |
113 if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) |
145 if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) |
114 return 'delete_all'; |
146 return 'delete_all'; |
115 |
147 |
116 return parent::current_action(); |
148 return parent::current_action(); |
117 } |
149 } |
118 |
150 |
119 function has_items() { |
151 public function has_items() { |
120 return have_posts(); |
152 return have_posts(); |
121 } |
153 } |
122 |
154 |
123 function no_items() { |
155 public function no_items() { |
124 _e( 'No media attachments found.' ); |
156 _e( 'No media attachments found.' ); |
125 } |
157 } |
126 |
158 |
127 function get_columns() { |
159 /** |
|
160 * Override parent views so we can use the filter bar display. |
|
161 */ |
|
162 public function views() { |
|
163 global $mode; |
|
164 |
|
165 $views = $this->get_views(); |
|
166 ?> |
|
167 <div class="wp-filter"> |
|
168 <div class="filter-items"> |
|
169 <?php $this->view_switcher( $mode ); ?> |
|
170 |
|
171 <label for="attachment-filter" class="screen-reader-text"><?php _e( 'Filter by type' ); ?></label> |
|
172 <select class="attachment-filters" name="attachment-filter" id="attachment-filter"> |
|
173 <?php |
|
174 if ( ! empty( $views ) ) { |
|
175 foreach ( $views as $class => $view ) { |
|
176 echo "\t$view\n"; |
|
177 } |
|
178 } |
|
179 ?> |
|
180 </select> |
|
181 |
|
182 <?php |
|
183 $this->extra_tablenav( 'bar' ); |
|
184 |
|
185 /** This filter is documented in wp-admin/inclues/class-wp-list-table.php */ |
|
186 $views = apply_filters( "views_{$this->screen->id}", array() ); |
|
187 |
|
188 // Back compat for pre-4.0 view links. |
|
189 if ( ! empty( $views ) ) { |
|
190 echo '<ul class="filter-links">'; |
|
191 foreach ( $views as $class => $view ) { |
|
192 echo "<li class='$class'>$view</li>"; |
|
193 } |
|
194 echo '</ul>'; |
|
195 } |
|
196 ?> |
|
197 </div> |
|
198 |
|
199 <div class="search-form"> |
|
200 <label for="media-search-input" class="screen-reader-text"><?php esc_html_e( 'Search Media' ); ?></label> |
|
201 <input type="search" placeholder="<?php esc_attr_e( 'Search' ) ?>" id="media-search-input" class="search" name="s" value="<?php _admin_search_query(); ?>"></div> |
|
202 </div> |
|
203 <?php |
|
204 } |
|
205 |
|
206 public function get_columns() { |
128 $posts_columns = array(); |
207 $posts_columns = array(); |
129 $posts_columns['cb'] = '<input type="checkbox" />'; |
208 $posts_columns['cb'] = '<input type="checkbox" />'; |
130 $posts_columns['icon'] = ''; |
209 $posts_columns['icon'] = ''; |
131 /* translators: column name */ |
210 /* translators: column name */ |
132 $posts_columns['title'] = _x( 'File', 'column name' ); |
211 $posts_columns['title'] = _x( 'File', 'column name' ); |
133 $posts_columns['author'] = __( 'Author' ); |
212 $posts_columns['author'] = __( 'Author' ); |
134 |
213 |
135 $taxonomies = array(); |
|
136 |
|
137 $taxonomies = get_taxonomies_for_attachments( 'objects' ); |
214 $taxonomies = get_taxonomies_for_attachments( 'objects' ); |
138 $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); |
215 $taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' ); |
139 |
216 |
|
217 /** |
|
218 * Filter the taxonomy columns for attachments in the Media list table. |
|
219 * |
|
220 * @since 3.5.0 |
|
221 * |
|
222 * @param array $taxonomies An array of registered taxonomies to show for attachments. |
|
223 * @param string $post_type The post type. Default 'attachment'. |
|
224 */ |
140 $taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' ); |
225 $taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' ); |
141 $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); |
226 $taxonomies = array_filter( $taxonomies, 'taxonomy_exists' ); |
142 |
227 |
143 foreach ( $taxonomies as $taxonomy ) { |
228 foreach ( $taxonomies as $taxonomy ) { |
144 if ( 'category' == $taxonomy ) |
229 if ( 'category' == $taxonomy ) |
153 |
238 |
154 /* translators: column name */ |
239 /* translators: column name */ |
155 if ( !$this->detached ) { |
240 if ( !$this->detached ) { |
156 $posts_columns['parent'] = _x( 'Uploaded to', 'column name' ); |
241 $posts_columns['parent'] = _x( 'Uploaded to', 'column name' ); |
157 if ( post_type_supports( 'attachment', 'comments' ) ) |
242 if ( post_type_supports( 'attachment', 'comments' ) ) |
158 $posts_columns['comments'] = '<span class="vers"><div title="' . esc_attr__( 'Comments' ) . '" class="comment-grey-bubble"></div></span>'; |
243 $posts_columns['comments'] = '<span class="vers"><span title="' . esc_attr__( 'Comments' ) . '" class="comment-grey-bubble"></span></span>'; |
159 } |
244 } |
160 /* translators: column name */ |
245 /* translators: column name */ |
161 $posts_columns['date'] = _x( 'Date', 'column name' ); |
246 $posts_columns['date'] = _x( 'Date', 'column name' ); |
|
247 /** |
|
248 * Filter the Media list table columns. |
|
249 * |
|
250 * @since 2.5.0 |
|
251 * |
|
252 * @param array $posts_columns An array of columns displayed in the Media list table. |
|
253 * @param bool $detached Whether the list table contains media not attached |
|
254 * to any posts. Default true. |
|
255 */ |
162 $posts_columns = apply_filters( 'manage_media_columns', $posts_columns, $this->detached ); |
256 $posts_columns = apply_filters( 'manage_media_columns', $posts_columns, $this->detached ); |
163 |
257 |
164 return $posts_columns; |
258 return $posts_columns; |
165 } |
259 } |
166 |
260 |
167 function get_sortable_columns() { |
261 protected function get_sortable_columns() { |
168 return array( |
262 return array( |
169 'title' => 'title', |
263 'title' => 'title', |
170 'author' => 'author', |
264 'author' => 'author', |
171 'parent' => 'parent', |
265 'parent' => 'parent', |
172 'comments' => 'comment_count', |
266 'comments' => 'comment_count', |
173 'date' => array( 'date', true ), |
267 'date' => array( 'date', true ), |
174 ); |
268 ); |
175 } |
269 } |
176 |
270 |
177 function display_rows() { |
271 public function display_rows() { |
178 global $post; |
272 global $post; |
179 |
273 |
180 add_filter( 'the_title','esc_html' ); |
274 add_filter( 'the_title','esc_html' ); |
181 $alt = ''; |
|
182 |
275 |
183 while ( have_posts() ) : the_post(); |
276 while ( have_posts() ) : the_post(); |
184 $user_can_edit = current_user_can( 'edit_post', $post->ID ); |
277 $user_can_edit = current_user_can( 'edit_post', $post->ID ); |
185 |
278 |
186 if ( $this->is_trash && $post->post_status != 'trash' |
279 if ( $this->is_trash && $post->post_status != 'trash' |
187 || !$this->is_trash && $post->post_status == 'trash' ) |
280 || !$this->is_trash && $post->post_status == 'trash' ) |
188 continue; |
281 continue; |
189 |
282 |
190 $alt = ( 'alternate' == $alt ) ? '' : 'alternate'; |
|
191 $post_owner = ( get_current_user_id() == $post->post_author ) ? 'self' : 'other'; |
283 $post_owner = ( get_current_user_id() == $post->post_author ) ? 'self' : 'other'; |
192 $att_title = _draft_or_post_title(); |
284 $att_title = _draft_or_post_title(); |
193 ?> |
285 ?> |
194 <tr id='post-<?php echo $post->ID; ?>' class='<?php echo trim( $alt . ' author-' . $post_owner . ' status-' . $post->post_status ); ?>' valign="top"> |
286 <tr id="post-<?php echo $post->ID; ?>" class="<?php echo trim( ' author-' . $post_owner . ' status-' . $post->post_status ); ?>"> |
195 <?php |
287 <?php |
196 |
288 |
197 list( $columns, $hidden ) = $this->get_column_info(); |
289 list( $columns, $hidden ) = $this->get_column_info(); |
198 foreach ( $columns as $column_name => $column_display_name ) { |
290 foreach ( $columns as $column_name => $column_display_name ) { |
199 $class = "class='$column_name column-$column_name'"; |
291 $class = "class='$column_name column-$column_name'"; |