28 * @see WP_List_Table::__construct() for more information on default arguments. |
28 * @see WP_List_Table::__construct() for more information on default arguments. |
29 * |
29 * |
30 * @param array $args An associative array of arguments. |
30 * @param array $args An associative array of arguments. |
31 */ |
31 */ |
32 public function __construct( $args = array() ) { |
32 public function __construct( $args = array() ) { |
33 parent::__construct( array( |
33 parent::__construct( |
34 'ajax' => true, |
34 array( |
35 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
35 'ajax' => true, |
36 ) ); |
36 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
37 } |
37 ) |
38 |
38 ); |
39 /** |
39 } |
40 * |
40 |
|
41 /** |
41 * @return bool |
42 * @return bool |
42 */ |
43 */ |
43 public function ajax_user_can() { |
44 public function ajax_user_can() { |
44 // Do not check edit_theme_options here. Ajax calls for available themes require switch_themes. |
45 // Do not check edit_theme_options here. Ajax calls for available themes require switch_themes. |
45 return current_user_can( 'switch_themes' ); |
46 return current_user_can( 'switch_themes' ); |
48 /** |
49 /** |
49 */ |
50 */ |
50 public function prepare_items() { |
51 public function prepare_items() { |
51 $themes = wp_get_themes( array( 'allowed' => true ) ); |
52 $themes = wp_get_themes( array( 'allowed' => true ) ); |
52 |
53 |
53 if ( ! empty( $_REQUEST['s'] ) ) |
54 if ( ! empty( $_REQUEST['s'] ) ) { |
54 $this->search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', strtolower( wp_unslash( $_REQUEST['s'] ) ) ) ) ) ); |
55 $this->search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', strtolower( wp_unslash( $_REQUEST['s'] ) ) ) ) ) ); |
55 |
56 } |
56 if ( ! empty( $_REQUEST['features'] ) ) |
57 |
|
58 if ( ! empty( $_REQUEST['features'] ) ) { |
57 $this->features = $_REQUEST['features']; |
59 $this->features = $_REQUEST['features']; |
|
60 } |
58 |
61 |
59 if ( $this->search_terms || $this->features ) { |
62 if ( $this->search_terms || $this->features ) { |
60 foreach ( $themes as $key => $theme ) { |
63 foreach ( $themes as $key => $theme ) { |
61 if ( ! $this->search_theme( $theme ) ) |
64 if ( ! $this->search_theme( $theme ) ) { |
62 unset( $themes[ $key ] ); |
65 unset( $themes[ $key ] ); |
|
66 } |
63 } |
67 } |
64 } |
68 } |
65 |
69 |
66 unset( $themes[ get_option( 'stylesheet' ) ] ); |
70 unset( $themes[ get_option( 'stylesheet' ) ] ); |
67 WP_Theme::sort_by_name( $themes ); |
71 WP_Theme::sort_by_name( $themes ); |
68 |
72 |
69 $per_page = 36; |
73 $per_page = 36; |
70 $page = $this->get_pagenum(); |
74 $page = $this->get_pagenum(); |
71 |
75 |
72 $start = ( $page - 1 ) * $per_page; |
76 $start = ( $page - 1 ) * $per_page; |
73 |
77 |
74 $this->items = array_slice( $themes, $start, $per_page, true ); |
78 $this->items = array_slice( $themes, $start, $per_page, true ); |
75 |
79 |
76 $this->set_pagination_args( array( |
80 $this->set_pagination_args( |
77 'total_items' => count( $themes ), |
81 array( |
78 'per_page' => $per_page, |
82 'total_items' => count( $themes ), |
79 'infinite_scroll' => true, |
83 'per_page' => $per_page, |
80 ) ); |
84 'infinite_scroll' => true, |
|
85 ) |
|
86 ); |
81 } |
87 } |
82 |
88 |
83 /** |
89 /** |
84 */ |
90 */ |
85 public function no_items() { |
91 public function no_items() { |
127 } |
134 } |
128 |
135 |
129 /** |
136 /** |
130 */ |
137 */ |
131 public function display() { |
138 public function display() { |
132 wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); |
139 wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' ); |
133 ?> |
140 ?> |
134 <?php $this->tablenav( 'top' ); ?> |
141 <?php $this->tablenav( 'top' ); ?> |
135 |
142 |
136 <div id="availablethemes"> |
143 <div id="availablethemes"> |
137 <?php $this->display_rows_or_placeholder(); ?> |
144 <?php $this->display_rows_or_placeholder(); ?> |
138 </div> |
145 </div> |
139 |
146 |
140 <?php $this->tablenav( 'bottom' ); ?> |
147 <?php $this->tablenav( 'bottom' ); ?> |
141 <?php |
148 <?php |
142 } |
149 } |
143 |
150 |
144 /** |
151 /** |
145 * |
|
146 * @return array |
152 * @return array |
147 */ |
153 */ |
148 public function get_columns() { |
154 public function get_columns() { |
149 return array(); |
155 return array(); |
150 } |
156 } |
164 /** |
170 /** |
165 */ |
171 */ |
166 public function display_rows() { |
172 public function display_rows() { |
167 $themes = $this->items; |
173 $themes = $this->items; |
168 |
174 |
169 foreach ( $themes as $theme ): |
175 foreach ( $themes as $theme ) : |
170 ?><div class="available-theme"><?php |
176 ?> |
|
177 <div class="available-theme"> |
|
178 <?php |
171 |
179 |
172 $template = $theme->get_template(); |
180 $template = $theme->get_template(); |
173 $stylesheet = $theme->get_stylesheet(); |
181 $stylesheet = $theme->get_stylesheet(); |
174 $title = $theme->display('Name'); |
182 $title = $theme->display( 'Name' ); |
175 $version = $theme->display('Version'); |
183 $version = $theme->display( 'Version' ); |
176 $author = $theme->display('Author'); |
184 $author = $theme->display( 'Author' ); |
177 |
185 |
178 $activate_link = wp_nonce_url( "themes.php?action=activate&template=" . urlencode( $template ) . "&stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $stylesheet ); |
186 $activate_link = wp_nonce_url( 'themes.php?action=activate&template=' . urlencode( $template ) . '&stylesheet=' . urlencode( $stylesheet ), 'switch-theme_' . $stylesheet ); |
179 |
187 |
180 $actions = array(); |
188 $actions = array(); |
181 $actions['activate'] = '<a href="' . $activate_link . '" class="activatelink" title="' |
189 $actions['activate'] = '<a href="' . $activate_link . '" class="activatelink" title="' |
182 . esc_attr( sprintf( __( 'Activate “%s”' ), $title ) ) . '">' . __( 'Activate' ) . '</a>'; |
190 . esc_attr( sprintf( __( 'Activate “%s”' ), $title ) ) . '">' . __( 'Activate' ) . '</a>'; |
183 |
191 |
184 if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { |
192 if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { |
185 $actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="load-customize hide-if-no-customize">' |
193 $actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="load-customize hide-if-no-customize">' |
186 . __( 'Live Preview' ) . '</a>'; |
194 . __( 'Live Preview' ) . '</a>'; |
187 } |
195 } |
188 |
196 |
189 if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) |
197 if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) { |
190 $actions['delete'] = '<a class="submitdelete deletion" href="' . wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet ) |
198 $actions['delete'] = '<a class="submitdelete deletion" href="' . wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet ) |
191 . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n 'Cancel' to stop, 'OK' to delete." ), $title ) ) |
199 . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n 'Cancel' to stop, 'OK' to delete." ), $title ) ) |
192 . "' );" . '">' . __( 'Delete' ) . '</a>'; |
200 . "' );" . '">' . __( 'Delete' ) . '</a>'; |
|
201 } |
193 |
202 |
194 /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ |
203 /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ |
195 $actions = apply_filters( 'theme_action_links', $actions, $theme, 'all' ); |
204 $actions = apply_filters( 'theme_action_links', $actions, $theme, 'all' ); |
196 |
205 |
197 /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ |
206 /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ |
198 $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme, 'all' ); |
207 $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme, 'all' ); |
199 $delete_action = isset( $actions['delete'] ) ? '<div class="delete-theme">' . $actions['delete'] . '</div>' : ''; |
208 $delete_action = isset( $actions['delete'] ) ? '<div class="delete-theme">' . $actions['delete'] . '</div>' : ''; |
200 unset( $actions['delete'] ); |
209 unset( $actions['delete'] ); |
214 |
223 |
215 <h3><?php echo $title; ?></h3> |
224 <h3><?php echo $title; ?></h3> |
216 <div class="theme-author"><?php printf( __( 'By %s' ), $author ); ?></div> |
225 <div class="theme-author"><?php printf( __( 'By %s' ), $author ); ?></div> |
217 <div class="action-links"> |
226 <div class="action-links"> |
218 <ul> |
227 <ul> |
219 <?php foreach ( $actions as $action ): ?> |
228 <?php foreach ( $actions as $action ) : ?> |
220 <li><?php echo $action; ?></li> |
229 <li><?php echo $action; ?></li> |
221 <?php endforeach; ?> |
230 <?php endforeach; ?> |
222 <li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e('Details') ?></a></li> |
231 <li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e( 'Details' ); ?></a></li> |
223 </ul> |
232 </ul> |
224 <?php echo $delete_action; ?> |
233 <?php echo $delete_action; ?> |
225 |
234 |
226 <?php theme_update_available( $theme ); ?> |
235 <?php theme_update_available( $theme ); ?> |
227 </div> |
236 </div> |
228 |
237 |
229 <div class="themedetaildiv hide-if-js"> |
238 <div class="themedetaildiv hide-if-js"> |
230 <p><strong><?php _e('Version:'); ?></strong> <?php echo $version; ?></p> |
239 <p><strong><?php _e( 'Version:' ); ?></strong> <?php echo $version; ?></p> |
231 <p><?php echo $theme->display('Description'); ?></p> |
240 <p><?php echo $theme->display( 'Description' ); ?></p> |
232 <?php if ( $theme->parent() ) { |
241 <?php |
233 printf( ' <p class="howto">' . __( 'This <a href="%1$s">child theme</a> requires its parent theme, %2$s.' ) . '</p>', |
242 if ( $theme->parent() ) { |
234 __( 'https://codex.wordpress.org/Child_Themes' ), |
243 printf( |
235 $theme->parent()->display( 'Name' ) ); |
244 /* translators: %s: link to documentation on child themes */ |
236 } ?> |
245 ' <p class="howto">' . __( 'This <a href="%1$s">child theme</a> requires its parent theme, %2$s.' ) . '</p>', |
|
246 __( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), |
|
247 $theme->parent()->display( 'Name' ) |
|
248 ); |
|
249 } |
|
250 ?> |
237 </div> |
251 </div> |
238 |
252 |
239 </div> |
253 </div> |
240 <?php |
254 <?php |
241 endforeach; |
255 endforeach; |
242 } |
256 } |
243 |
257 |
244 /** |
258 /** |
245 * @param WP_Theme $theme |
259 * @param WP_Theme $theme |
246 * @return bool |
260 * @return bool |
247 */ |
261 */ |
248 public function search_theme( $theme ) { |
262 public function search_theme( $theme ) { |
249 // Search the features |
263 // Search the features |
250 foreach ( $this->features as $word ) { |
264 foreach ( $this->features as $word ) { |
251 if ( ! in_array( $word, $theme->get('Tags') ) ) |
265 if ( ! in_array( $word, $theme->get( 'Tags' ) ) ) { |
252 return false; |
266 return false; |
|
267 } |
253 } |
268 } |
254 |
269 |
255 // Match all phrases |
270 // Match all phrases |
256 foreach ( $this->search_terms as $word ) { |
271 foreach ( $this->search_terms as $word ) { |
257 if ( in_array( $word, $theme->get('Tags') ) ) |
272 if ( in_array( $word, $theme->get( 'Tags' ) ) ) { |
258 continue; |
273 continue; |
|
274 } |
259 |
275 |
260 foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) { |
276 foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) { |
261 // Don't mark up; Do translate. |
277 // Don't mark up; Do translate. |
262 if ( false !== stripos( strip_tags( $theme->display( $header, false, true ) ), $word ) ) { |
278 if ( false !== stripos( strip_tags( $theme->display( $header, false, true ) ), $word ) ) { |
263 continue 2; |
279 continue 2; |
264 } |
280 } |
265 } |
281 } |
266 |
282 |
267 if ( false !== stripos( $theme->get_stylesheet(), $word ) ) |
283 if ( false !== stripos( $theme->get_stylesheet(), $word ) ) { |
268 continue; |
284 continue; |
269 |
285 } |
270 if ( false !== stripos( $theme->get_template(), $word ) ) |
286 |
|
287 if ( false !== stripos( $theme->get_template(), $word ) ) { |
271 continue; |
288 continue; |
|
289 } |
272 |
290 |
273 return false; |
291 return false; |
274 } |
292 } |
275 |
293 |
276 return true; |
294 return true; |
285 */ |
303 */ |
286 public function _js_vars( $extra_args = array() ) { |
304 public function _js_vars( $extra_args = array() ) { |
287 $search_string = isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; |
305 $search_string = isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; |
288 |
306 |
289 $args = array( |
307 $args = array( |
290 'search' => $search_string, |
308 'search' => $search_string, |
291 'features' => $this->features, |
309 'features' => $this->features, |
292 'paged' => $this->get_pagenum(), |
310 'paged' => $this->get_pagenum(), |
293 'total_pages' => ! empty( $this->_pagination_args['total_pages'] ) ? $this->_pagination_args['total_pages'] : 1, |
311 'total_pages' => ! empty( $this->_pagination_args['total_pages'] ) ? $this->_pagination_args['total_pages'] : 1, |
294 ); |
312 ); |
295 |
313 |
296 if ( is_array( $extra_args ) ) |
314 if ( is_array( $extra_args ) ) { |
297 $args = array_merge( $args, $extra_args ); |
315 $args = array_merge( $args, $extra_args ); |
|
316 } |
298 |
317 |
299 printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", wp_json_encode( $args ) ); |
318 printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", wp_json_encode( $args ) ); |
300 parent::_js_vars(); |
319 parent::_js_vars(); |
301 } |
320 } |
302 } |
321 } |