run:R W Run
7.85 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
148.33 KB
2026-03-11 16:18:51
R W Run
11.45 KB
2026-03-11 16:18:51
R W Run
3.58 KB
2026-03-11 16:18:51
R W Run
2.53 KB
2026-03-11 16:18:51
R W Run
2.6 KB
2026-03-11 16:18:51
R W Run
6.59 KB
2026-03-11 16:18:51
R W Run
14.83 KB
2026-03-11 16:18:51
R W Run
21.18 KB
2026-03-11 16:18:51
R W Run
48.13 KB
2026-03-11 16:18:51
R W Run
4.07 KB
2026-03-11 16:18:51
R W Run
5.3 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
26.73 KB
2026-03-11 16:18:51
R W Run
2.8 KB
2026-03-11 16:18:51
R W Run
15.2 KB
2026-03-11 16:18:51
R W Run
192.08 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
22.89 KB
2026-03-11 16:18:51
R W Run
12.77 KB
2026-03-11 16:18:51
R W Run
4.08 KB
2026-03-11 16:18:51
R W Run
26.27 KB
2026-03-11 16:18:51
R W Run
4.97 KB
2026-03-11 16:18:51
R W Run
5.57 KB
2026-03-11 16:18:51
R W Run
13.93 KB
2026-03-11 16:18:51
R W Run
4.09 KB
2026-03-11 16:18:51
R W Run
6.79 KB
2026-03-11 16:18:51
R W Run
60.45 KB
2026-03-11 16:18:51
R W Run
32.4 KB
2026-03-11 16:18:51
R W Run
18.24 KB
2026-03-11 16:18:51
R W Run
66.01 KB
2026-03-11 16:18:51
R W Run
23.84 KB
2026-03-11 16:18:51
R W Run
17.72 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
18.05 KB
2026-03-11 16:18:51
R W Run
22.76 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
4.51 KB
2026-03-11 16:18:51
R W Run
9.02 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
51.76 KB
2026-03-11 16:18:51
R W Run
25.29 KB
2026-03-11 16:18:51
R W Run
21.61 KB
2026-03-11 16:18:51
R W Run
27.77 KB
2026-03-11 16:18:51
R W Run
15.35 KB
2026-03-11 16:18:51
R W Run
24.54 KB
2026-03-11 16:18:51
R W Run
56.44 KB
2026-03-11 16:18:51
R W Run
1.42 KB
2026-03-11 16:18:51
R W Run
63.66 KB
2026-03-11 16:18:51
R W Run
31.9 KB
2026-03-11 16:18:51
R W Run
14.44 KB
2026-03-11 16:18:51
R W Run
36.47 KB
2026-03-11 16:18:51
R W Run
14 KB
2026-03-11 16:18:51
R W Run
121.89 KB
2026-03-11 16:18:51
R W Run
6.26 KB
2026-03-11 16:18:51
R W Run
20.73 KB
2026-03-11 16:18:51
R W Run
15.23 KB
2026-03-11 16:18:51
R W Run
10.14 KB
2026-03-11 16:18:51
R W Run
6.94 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
46.85 KB
2026-03-11 16:18:51
R W Run
18.61 KB
2026-03-11 16:18:51
R W Run
6.08 KB
2026-03-11 16:18:51
R W Run
20.06 KB
2026-03-11 16:18:51
R W Run
5.73 KB
2026-03-11 16:18:51
R W Run
68.18 KB
2026-03-11 16:18:51
R W Run
40.8 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
25.26 KB
2026-03-11 16:18:51
R W Run
95.94 KB
2026-03-11 16:18:51
R W Run
43.12 KB
2026-03-11 16:18:51
R W Run
41.73 KB
2026-03-11 16:18:51
R W Run
6.46 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
116.31 KB
2026-03-11 16:18:51
R W Run
9.39 KB
2026-03-11 16:18:51
R W Run
64.34 KB
2026-03-11 16:18:51
R W Run
44.73 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
3.68 KB
2026-03-11 16:18:51
R W Run
33.53 KB
2026-03-11 16:18:51
R W Run
48.84 KB
2026-03-11 16:18:51
R W Run
26.35 KB
2026-03-11 16:18:51
R W Run
1.12 KB
2026-03-11 16:18:51
R W Run
4.19 KB
2026-03-11 16:18:51
R W Run
38.19 KB
2026-03-11 16:18:51
R W Run
91.33 KB
2026-03-11 16:18:51
R W Run
80.39 KB
2026-03-11 16:18:51
R W Run
32.67 KB
2026-03-11 16:18:51
R W Run
16.18 KB
2026-03-11 16:18:51
R W Run
44.46 KB
2026-03-11 16:18:51
R W Run
6.23 KB
2026-03-11 16:18:51
R W Run
8.23 KB
2026-03-11 16:18:51
R W Run
96.96 KB
2026-03-11 16:18:51
R W Run
6.83 KB
2026-03-11 16:18:51
R W Run
46.62 KB
2026-03-11 16:18:51
R W Run
10.82 KB
2026-03-11 16:18:51
R W Run
68.86 KB
2026-03-11 16:18:51
R W Run
33.63 KB
2026-03-11 16:18:51
R W Run
113.3 KB
2026-03-11 16:18:51
R W Run
22.98 KB
2026-03-11 16:18:51
R W Run
10.66 KB
2026-03-11 16:18:51
R W Run
error_log
📄class-wp-theme-install-list-table.php
1<?php
2/**
3 * List Table API: WP_Theme_Install_List_Table class
4 *
5 * @package WordPress
6 * @subpackage Administration
7 * @since 3.1.0
8 */
9
10/**
11 * Core class used to implement displaying themes to install in a list table.
12 *
13 * @since 3.1.0
14 *
15 * @see WP_Themes_List_Table
16 */
17class WP_Theme_Install_List_Table extends WP_Themes_List_Table {
18
19 public $features = array();
20
21 /**
22 * @return bool
23 */
24 public function ajax_user_can() {
25 return current_user_can( 'install_themes' );
26 }
27
28 /**
29 * @global array $tabs
30 * @global string $tab
31 * @global int $paged
32 * @global string $type
33 * @global array $theme_field_defaults
34 */
35 public function prepare_items() {
36 require ABSPATH . 'wp-admin/includes/theme-install.php';
37
38 global $tabs, $tab, $paged, $type, $theme_field_defaults;
39
40 $tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : '';
41
42 $search_terms = array();
43 $search_string = '';
44 if ( ! empty( $_REQUEST['s'] ) ) {
45 $search_string = strtolower( wp_unslash( $_REQUEST['s'] ) );
46 $search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', $search_string ) ) ) );
47 }
48
49 if ( ! empty( $_REQUEST['features'] ) ) {
50 $this->features = $_REQUEST['features'];
51 }
52
53 $paged = $this->get_pagenum();
54
55 $per_page = 36;
56
57 // These are the tabs which are shown on the page,
58 $tabs = array();
59 $tabs['dashboard'] = __( 'Search' );
60 if ( 'search' === $tab ) {
61 $tabs['search'] = __( 'Search Results' );
62 }
63 $tabs['upload'] = _x( 'Upload', 'noun' );
64 $tabs['featured'] = _x( 'Featured', 'themes' );
65 //$tabs['popular'] = _x( 'Popular', 'themes' );
66 $tabs['new'] = _x( 'Latest', 'themes' );
67 $tabs['updated'] = _x( 'Recently Updated', 'themes' );
68
69 $nonmenu_tabs = array( 'theme-information' ); // Valid actions to perform which do not have a Menu item.
70
71 /** This filter is documented in wp-admin/theme-install.php */
72 $tabs = apply_filters( 'install_themes_tabs', $tabs );
73
74 /**
75 * Filters tabs not associated with a menu item on the Install Themes screen.
76 *
77 * @since 2.8.0
78 *
79 * @param string[] $nonmenu_tabs The tabs that don't have a menu item on
80 * the Install Themes screen.
81 */
82 $nonmenu_tabs = apply_filters( 'install_themes_nonmenu_tabs', $nonmenu_tabs );
83
84 // If a non-valid menu tab has been selected, And it's not a non-menu action.
85 if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
86 $tab = key( $tabs );
87 }
88
89 $args = array(
90 'page' => $paged,
91 'per_page' => $per_page,
92 'fields' => $theme_field_defaults,
93 );
94
95 switch ( $tab ) {
96 case 'search':
97 $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
98 switch ( $type ) {
99 case 'tag':
100 $args['tag'] = array_map( 'sanitize_key', $search_terms );
101 break;
102 case 'term':
103 $args['search'] = $search_string;
104 break;
105 case 'author':
106 $args['author'] = $search_string;
107 break;
108 }
109
110 if ( ! empty( $this->features ) ) {
111 $args['tag'] = $this->features;
112 $_REQUEST['s'] = implode( ',', $this->features );
113 $_REQUEST['type'] = 'tag';
114 }
115
116 add_action( 'install_themes_table_header', 'install_theme_search_form', 10, 0 );
117 break;
118
119 case 'featured':
120 // case 'popular':
121 case 'new':
122 case 'updated':
123 $args['browse'] = $tab;
124 break;
125
126 default:
127 $args = false;
128 break;
129 }
130
131 /**
132 * Filters API request arguments for each Install Themes screen tab.
133 *
134 * The dynamic portion of the hook name, `$tab`, refers to the theme install
135 * tab.
136 *
137 * Possible hook names include:
138 *
139 * - `install_themes_table_api_args_dashboard`
140 * - `install_themes_table_api_args_featured`
141 * - `install_themes_table_api_args_new`
142 * - `install_themes_table_api_args_search`
143 * - `install_themes_table_api_args_updated`
144 * - `install_themes_table_api_args_upload`
145 *
146 * @since 3.7.0
147 *
148 * @param array|false $args Theme install API arguments.
149 */
150 $args = apply_filters( "install_themes_table_api_args_{$tab}", $args );
151
152 if ( ! $args ) {
153 return;
154 }
155
156 $api = themes_api( 'query_themes', $args );
157
158 if ( is_wp_error( $api ) ) {
159 wp_die( '<p>' . $api->get_error_message() . '</p> <p><a href="#" onclick="document.location.reload(); return false;">' . __( 'Try Again' ) . '</a></p>' );
160 }
161
162 $this->items = $api->themes;
163
164 $this->set_pagination_args(
165 array(
166 'total_items' => $api->info['results'],
167 'per_page' => $args['per_page'],
168 'infinite_scroll' => true,
169 )
170 );
171 }
172
173 /**
174 */
175 public function no_items() {
176 _e( 'No themes match your request.' );
177 }
178
179 /**
180 * @global array $tabs
181 * @global string $tab
182 * @return array
183 */
184 protected function get_views() {
185 global $tabs, $tab;
186
187 $display_tabs = array();
188 foreach ( (array) $tabs as $action => $text ) {
189 $display_tabs[ 'theme-install-' . $action ] = array(
190 'url' => self_admin_url( 'theme-install.php?tab=' . $action ),
191 'label' => $text,
192 'current' => $action === $tab,
193 );
194 }
195
196 return $this->get_views_links( $display_tabs );
197 }
198
199 /**
200 * Displays the theme install table.
201 *
202 * Overrides the parent display() method to provide a different container.
203 *
204 * @since 3.1.0
205 */
206 public function display() {
207 wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
208 ?>
209 <div class="tablenav top themes">
210 <div class="alignleft actions">
211 <?php
212 /**
213 * Fires in the Install Themes list table header.
214 *
215 * @since 2.8.0
216 */
217 do_action( 'install_themes_table_header' );
218 ?>
219 </div>
220 <?php $this->pagination( 'top' ); ?>
221 <br class="clear" />
222 </div>
223
224 <div id="availablethemes">
225 <?php $this->display_rows_or_placeholder(); ?>
226 </div>
227
228 <?php
229 $this->tablenav( 'bottom' );
230 }
231
232 /**
233 * Generates the list table rows.
234 *
235 * @since 3.1.0
236 */
237 public function display_rows() {
238 $themes = $this->items;
239 foreach ( $themes as $theme ) {
240 ?>
241 <div class="available-theme installable-theme">
242 <?php
243 $this->single_row( $theme );
244 ?>
245 </div>
246 <?php
247 } // End foreach $theme_names.
248
249 $this->theme_installer();
250 }
251
252 /**
253 * Prints a theme from the WordPress.org API.
254 *
255 * @since 3.1.0
256 *
257 * @global array $themes_allowedtags
258 *
259 * @param stdClass $theme {
260 * An object that contains theme data returned by the WordPress.org API.
261 *
262 * @type string $name Theme name, e.g. 'Twenty Twenty-One'.
263 * @type string $slug Theme slug, e.g. 'twentytwentyone'.
264 * @type string $version Theme version, e.g. '1.1'.
265 * @type string $author Theme author username, e.g. 'melchoyce'.
266 * @type string $preview_url Preview URL, e.g. 'https://2021.wordpress.net/'.
267 * @type string $screenshot_url Screenshot URL, e.g. 'https://wordpress.org/themes/twentytwentyone/'.
268 * @type float $rating Rating score.
269 * @type int $num_ratings The number of ratings.
270 * @type string $homepage Theme homepage, e.g. 'https://wordpress.org/themes/twentytwentyone/'.
271 * @type string $description Theme description.
272 * @type string $download_link Theme ZIP download URL.
273 * }
274 */
275 public function single_row( $theme ) {
276 global $themes_allowedtags;
277
278 if ( empty( $theme ) ) {
279 return;
280 }
281
282 $name = wp_kses( $theme->name, $themes_allowedtags );
283 $author = wp_kses( $theme->author, $themes_allowedtags );
284
285 /* translators: %s: Theme name. */
286 $preview_title = sprintf( __( 'Preview &#8220;%s&#8221;' ), $name );
287 $preview_url = add_query_arg(
288 array(
289 'tab' => 'theme-information',
290 'theme' => $theme->slug,
291 ),
292 self_admin_url( 'theme-install.php' )
293 );
294
295 $actions = array();
296
297 $install_url = add_query_arg(
298 array(
299 'action' => 'install-theme',
300 'theme' => $theme->slug,
301 ),
302 self_admin_url( 'update.php' )
303 );
304
305 $update_url = add_query_arg(
306 array(
307 'action' => 'upgrade-theme',
308 'theme' => $theme->slug,
309 ),
310 self_admin_url( 'update.php' )
311 );
312
313 $status = $this->_get_theme_status( $theme );
314
315 switch ( $status ) {
316 case 'update_available':
317 $actions[] = sprintf(
318 '<a class="install-now" href="%s" aria-label="%s">%s</a>',
319 esc_url( wp_nonce_url( $update_url, 'upgrade-theme_' . $theme->slug ) ),
320 /* translators: %s: Theme version. */
321 esc_attr( sprintf( __( 'Update to version %s' ), $theme->version ) ),
322 __( 'Update' )
323 );
324 break;
325 case 'newer_installed':
326 case 'latest_installed':
327 $actions[] = sprintf(
328 '<span class="install-now">%s</span>',
329 _x( 'Installed', 'theme' )
330 );
331 break;
332 case 'install':
333 default:
334 $actions[] = sprintf(
335 '<a class="install-now" href="%s" aria-label="%s">%s</a>',
336 esc_url( wp_nonce_url( $install_url, 'install-theme_' . $theme->slug ) ),
337 /* translators: %s: Theme name. */
338 esc_attr( sprintf( _x( 'Install %s', 'theme' ), $name ) ),
339 _x( 'Install Now', 'theme' )
340 );
341 break;
342 }
343
344 $actions[] = sprintf(
345 '<a class="install-theme-preview" href="%s" aria-label="%s">%s</a>',
346 esc_url( $preview_url ),
347 esc_attr( $preview_title ),
348 __( 'Preview' )
349 );
350
351 /**
352 * Filters the install action links for a theme in the Install Themes list table.
353 *
354 * @since 3.4.0
355 *
356 * @param string[] $actions An array of theme action links. Defaults are
357 * links to Install Now, Preview, and Details.
358 * @param stdClass $theme An object that contains theme data returned by the
359 * WordPress.org API.
360 */
361 $actions = apply_filters( 'theme_install_actions', $actions, $theme );
362
363 ?>
364 <a class="screenshot install-theme-preview" href="<?php echo esc_url( $preview_url ); ?>" aria-label="<?php echo esc_attr( $preview_title ); ?>">
365 <img src="<?php echo esc_url( $theme->screenshot_url . '?ver=' . $theme->version ); ?>" width="150" alt="" />
366 </a>
367
368 <h3><?php echo $name; ?></h3>
369 <div class="theme-author">
370 <?php
371 /* translators: %s: Theme author. */
372 printf( __( 'By %s' ), $author );
373 ?>
374 </div>
375
376 <div class="action-links">
377 <ul>
378 <?php foreach ( $actions as $action ) : ?>
379 <li><?php echo $action; ?></li>
380 <?php endforeach; ?>
381 <li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e( 'Details' ); ?></a></li>
382 </ul>
383 </div>
384
385 <?php
386 $this->install_theme_info( $theme );
387 }
388
389 /**
390 * Prints the wrapper for the theme installer.
391 */
392 public function theme_installer() {
393 ?>
394 <div id="theme-installer" class="wp-full-overlay expanded">
395 <div class="wp-full-overlay-sidebar">
396 <div class="wp-full-overlay-header">
397 <a href="#" class="close-full-overlay button"><?php _e( 'Close' ); ?></a>
398 <span class="theme-install"></span>
399 </div>
400 <div class="wp-full-overlay-sidebar-content">
401 <div class="install-theme-info"></div>
402 </div>
403 <div class="wp-full-overlay-footer">
404 <button type="button" class="collapse-sidebar button" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
405 <span class="collapse-sidebar-arrow"></span>
406 <span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
407 </button>
408 </div>
409 </div>
410 <div class="wp-full-overlay-main"></div>
411 </div>
412 <?php
413 }
414
415 /**
416 * Prints the wrapper for the theme installer with a provided theme's data.
417 * Used to make the theme installer work for no-js.
418 *
419 * @param stdClass $theme A WordPress.org Theme API object.
420 */
421 public function theme_installer_single( $theme ) {
422 ?>
423 <div id="theme-installer" class="wp-full-overlay single-theme">
424 <div class="wp-full-overlay-sidebar">
425 <?php $this->install_theme_info( $theme ); ?>
426 </div>
427 <div class="wp-full-overlay-main">
428 <iframe src="<?php echo esc_url( $theme->preview_url ); ?>"></iframe>
429 </div>
430 </div>
431 <?php
432 }
433
434 /**
435 * Prints the info for a theme (to be used in the theme installer modal).
436 *
437 * @global array $themes_allowedtags
438 *
439 * @param stdClass $theme A WordPress.org Theme API object.
440 */
441 public function install_theme_info( $theme ) {
442 global $themes_allowedtags;
443
444 if ( empty( $theme ) ) {
445 return;
446 }
447
448 $name = wp_kses( $theme->name, $themes_allowedtags );
449 $author = wp_kses( $theme->author, $themes_allowedtags );
450
451 $install_url = add_query_arg(
452 array(
453 'action' => 'install-theme',
454 'theme' => $theme->slug,
455 ),
456 self_admin_url( 'update.php' )
457 );
458
459 $update_url = add_query_arg(
460 array(
461 'action' => 'upgrade-theme',
462 'theme' => $theme->slug,
463 ),
464 self_admin_url( 'update.php' )
465 );
466
467 $status = $this->_get_theme_status( $theme );
468
469 ?>
470 <div class="install-theme-info">
471 <?php
472 switch ( $status ) {
473 case 'update_available':
474 printf(
475 '<a class="theme-install button button-primary" href="%s" aria-label="%s">%s</a>',
476 esc_url( wp_nonce_url( $update_url, 'upgrade-theme_' . $theme->slug ) ),
477 /* translators: %s: Theme version. */
478 esc_attr( sprintf( __( 'Update to version %s' ), $theme->version ) ),
479 __( 'Update' )
480 );
481 break;
482 case 'newer_installed':
483 case 'latest_installed':
484 printf(
485 '<span class="theme-install">%s</span>',
486 _x( 'Installed', 'theme' )
487 );
488 break;
489 case 'install':
490 default:
491 printf(
492 '<a class="theme-install button button-primary" href="%s">%s</a>',
493 esc_url( wp_nonce_url( $install_url, 'install-theme_' . $theme->slug ) ),
494 __( 'Install' )
495 );
496 break;
497 }
498 ?>
499 <h3 class="theme-name"><?php echo $name; ?></h3>
500 <span class="theme-by">
501 <?php
502 /* translators: %s: Theme author. */
503 printf( __( 'By %s' ), $author );
504 ?>
505 </span>
506 <?php if ( isset( $theme->screenshot_url ) ) : ?>
507 <img class="theme-screenshot" src="<?php echo esc_url( $theme->screenshot_url . '?ver=' . $theme->version ); ?>" alt="" />
508 <?php endif; ?>
509 <div class="theme-details">
510 <?php
511 wp_star_rating(
512 array(
513 'rating' => $theme->rating,
514 'type' => 'percent',
515 'number' => $theme->num_ratings,
516 )
517 );
518 ?>
519 <div class="theme-version">
520 <strong><?php _e( 'Version:' ); ?> </strong>
521 <?php echo wp_kses( $theme->version, $themes_allowedtags ); ?>
522 </div>
523 <div class="theme-description">
524 <?php echo wp_kses( $theme->description, $themes_allowedtags ); ?>
525 </div>
526 </div>
527 <input class="theme-preview-url" type="hidden" value="<?php echo esc_url( $theme->preview_url ); ?>" />
528 </div>
529 <?php
530 }
531
532 /**
533 * Send required variables to JavaScript land
534 *
535 * @since 3.4.0
536 *
537 * @global string $tab Current tab within Themes->Install screen
538 * @global string $type Type of search.
539 *
540 * @param array $extra_args Unused.
541 */
542 public function _js_vars( $extra_args = array() ) {
543 global $tab, $type;
544 parent::_js_vars( compact( 'tab', 'type' ) );
545 }
546
547 /**
548 * Checks to see if the theme is already installed.
549 *
550 * @since 3.4.0
551 *
552 * @param stdClass $theme A WordPress.org Theme API object.
553 * @return string Theme status.
554 */
555 private function _get_theme_status( $theme ) {
556 $status = 'install';
557
558 $installed_theme = wp_get_theme( $theme->slug );
559 if ( $installed_theme->exists() ) {
560 if ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '=' ) ) {
561 $status = 'latest_installed';
562 } elseif ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '>' ) ) {
563 $status = 'newer_installed';
564 } else {
565 $status = 'update_available';
566 }
567 }
568
569 return $status;
570 }
571}
572