43 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
52 'screen' => isset( $args['screen'] ) ? $args['screen'] : null, |
44 ) |
53 ) |
45 ); |
54 ); |
46 |
55 |
47 $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all'; |
56 $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all'; |
48 if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ) ) ) { |
57 if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) { |
49 $status = 'all'; |
58 $status = 'all'; |
50 } |
59 } |
51 |
60 |
52 $page = $this->get_pagenum(); |
61 $page = $this->get_pagenum(); |
53 |
62 |
54 $this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false; |
63 $this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false; |
55 |
64 |
56 if ( $this->is_site_themes ) { |
65 if ( $this->is_site_themes ) { |
57 $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; |
66 $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; |
58 } |
67 } |
|
68 |
|
69 $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) && |
|
70 ! $this->is_site_themes && current_user_can( 'update_themes' ); |
59 } |
71 } |
60 |
72 |
61 /** |
73 /** |
62 * @return array |
74 * @return array |
63 */ |
75 */ |
64 protected function get_table_classes() { |
76 protected function get_table_classes() { |
65 // todo: remove and add CSS for .themes |
77 // @todo Remove and add CSS for .themes. |
66 return array( 'widefat', 'plugins' ); |
78 return array( 'widefat', 'plugins' ); |
67 } |
79 } |
68 |
80 |
69 /** |
81 /** |
70 * @return bool |
82 * @return bool |
105 'disabled' => array(), |
117 'disabled' => array(), |
106 'upgrade' => array(), |
118 'upgrade' => array(), |
107 'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ), |
119 'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ), |
108 ); |
120 ); |
109 |
121 |
|
122 if ( $this->show_autoupdates ) { |
|
123 $auto_updates = (array) get_site_option( 'auto_update_themes', array() ); |
|
124 |
|
125 $themes['auto-update-enabled'] = array(); |
|
126 $themes['auto-update-disabled'] = array(); |
|
127 } |
|
128 |
110 if ( $this->is_site_themes ) { |
129 if ( $this->is_site_themes ) { |
111 $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' ); |
130 $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' ); |
112 $allowed_where = 'site'; |
131 $allowed_where = 'site'; |
113 } else { |
132 } else { |
114 $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' ); |
133 $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' ); |
115 $allowed_where = 'network'; |
134 $allowed_where = 'network'; |
116 } |
135 } |
117 |
136 |
118 $maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current = get_site_transient( 'update_themes' ); |
137 $current = get_site_transient( 'update_themes' ); |
|
138 $maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current; |
119 |
139 |
120 foreach ( (array) $themes['all'] as $key => $theme ) { |
140 foreach ( (array) $themes['all'] as $key => $theme ) { |
121 if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) { |
141 if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) { |
122 unset( $themes['all'][ $key ] ); |
142 unset( $themes['all'][ $key ] ); |
123 continue; |
143 continue; |
128 $themes['upgrade'][ $key ] = $themes['all'][ $key ]; |
148 $themes['upgrade'][ $key ] = $themes['all'][ $key ]; |
129 } |
149 } |
130 |
150 |
131 $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled'; |
151 $filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled'; |
132 $themes[ $filter ][ $key ] = $themes['all'][ $key ]; |
152 $themes[ $filter ][ $key ] = $themes['all'][ $key ]; |
|
153 |
|
154 $theme_data = array( |
|
155 'update_supported' => isset( $theme->update_supported ) ? $theme->update_supported : true, |
|
156 ); |
|
157 |
|
158 // Extra info if known. array_merge() ensures $theme_data has precedence if keys collide. |
|
159 if ( isset( $current->response[ $key ] ) ) { |
|
160 $theme_data = array_merge( (array) $current->response[ $key ], $theme_data ); |
|
161 } elseif ( isset( $current->no_update[ $key ] ) ) { |
|
162 $theme_data = array_merge( (array) $current->no_update[ $key ], $theme_data ); |
|
163 } else { |
|
164 $theme_data['update_supported'] = false; |
|
165 } |
|
166 |
|
167 $theme->update_supported = $theme_data['update_supported']; |
|
168 |
|
169 /* |
|
170 * Create the expected payload for the auto_update_theme filter, this is the same data |
|
171 * as contained within $updates or $no_updates but used when the Theme is not known. |
|
172 */ |
|
173 $filter_payload = array( |
|
174 'theme' => $key, |
|
175 'new_version' => '', |
|
176 'url' => '', |
|
177 'package' => '', |
|
178 'requires' => '', |
|
179 'requires_php' => '', |
|
180 ); |
|
181 |
|
182 $filter_payload = array_merge( $filter_payload, array_intersect_key( $theme_data, $filter_payload ) ); |
|
183 |
|
184 $type = 'theme'; |
|
185 /** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */ |
|
186 $auto_update_forced = apply_filters( "auto_update_{$type}", null, (object) $filter_payload ); |
|
187 |
|
188 if ( ! is_null( $auto_update_forced ) ) { |
|
189 $theme->auto_update_forced = $auto_update_forced; |
|
190 } |
|
191 |
|
192 if ( $this->show_autoupdates ) { |
|
193 $enabled = in_array( $key, $auto_updates, true ) && $theme->update_supported; |
|
194 if ( isset( $theme->auto_update_forced ) ) { |
|
195 $enabled = (bool) $theme->auto_update_forced; |
|
196 } |
|
197 |
|
198 if ( $enabled ) { |
|
199 $themes['auto-update-enabled'][ $key ] = $theme; |
|
200 } else { |
|
201 $themes['auto-update-disabled'][ $key ] = $theme; |
|
202 } |
|
203 } |
133 } |
204 } |
134 |
205 |
135 if ( $s ) { |
206 if ( $s ) { |
136 $status = 'search'; |
207 $status = 'search'; |
137 $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) ); |
208 $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) ); |
297 continue; |
373 continue; |
298 } |
374 } |
299 |
375 |
300 switch ( $type ) { |
376 switch ( $type ) { |
301 case 'all': |
377 case 'all': |
302 $text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'themes' ); |
378 /* translators: %s: Number of themes. */ |
|
379 $text = _nx( |
|
380 'All <span class="count">(%s)</span>', |
|
381 'All <span class="count">(%s)</span>', |
|
382 $count, |
|
383 'themes' |
|
384 ); |
303 break; |
385 break; |
304 case 'enabled': |
386 case 'enabled': |
305 $text = _n( 'Enabled <span class="count">(%s)</span>', 'Enabled <span class="count">(%s)</span>', $count ); |
387 /* translators: %s: Number of themes. */ |
|
388 $text = _nx( |
|
389 'Enabled <span class="count">(%s)</span>', |
|
390 'Enabled <span class="count">(%s)</span>', |
|
391 $count, |
|
392 'themes' |
|
393 ); |
306 break; |
394 break; |
307 case 'disabled': |
395 case 'disabled': |
308 $text = _n( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', $count ); |
396 /* translators: %s: Number of themes. */ |
|
397 $text = _nx( |
|
398 'Disabled <span class="count">(%s)</span>', |
|
399 'Disabled <span class="count">(%s)</span>', |
|
400 $count, |
|
401 'themes' |
|
402 ); |
309 break; |
403 break; |
310 case 'upgrade': |
404 case 'upgrade': |
311 $text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count ); |
405 /* translators: %s: Number of themes. */ |
|
406 $text = _nx( |
|
407 'Update Available <span class="count">(%s)</span>', |
|
408 'Update Available <span class="count">(%s)</span>', |
|
409 $count, |
|
410 'themes' |
|
411 ); |
312 break; |
412 break; |
313 case 'broken': |
413 case 'broken': |
314 $text = _n( 'Broken <span class="count">(%s)</span>', 'Broken <span class="count">(%s)</span>', $count ); |
414 /* translators: %s: Number of themes. */ |
|
415 $text = _nx( |
|
416 'Broken <span class="count">(%s)</span>', |
|
417 'Broken <span class="count">(%s)</span>', |
|
418 $count, |
|
419 'themes' |
|
420 ); |
|
421 break; |
|
422 case 'auto-update-enabled': |
|
423 /* translators: %s: Number of themes. */ |
|
424 $text = _n( |
|
425 'Auto-updates Enabled <span class="count">(%s)</span>', |
|
426 'Auto-updates Enabled <span class="count">(%s)</span>', |
|
427 $count |
|
428 ); |
|
429 break; |
|
430 case 'auto-update-disabled': |
|
431 /* translators: %s: Number of themes. */ |
|
432 $text = _n( |
|
433 'Auto-updates Disabled <span class="count">(%s)</span>', |
|
434 'Auto-updates Disabled <span class="count">(%s)</span>', |
|
435 $count |
|
436 ); |
315 break; |
437 break; |
316 } |
438 } |
317 |
439 |
318 if ( $this->is_site_themes ) { |
440 if ( $this->is_site_themes ) { |
319 $url = 'site-themes.php?id=' . $this->site_id; |
441 $url = 'site-themes.php?id=' . $this->site_id; |
320 } else { |
442 } else { |
321 $url = 'themes.php'; |
443 $url = 'themes.php'; |
322 } |
444 } |
323 |
445 |
324 if ( 'search' != $type ) { |
446 if ( 'search' !== $type ) { |
325 $status_links[ $type ] = sprintf( |
447 $status_links[ $type ] = sprintf( |
326 "<a href='%s'%s>%s</a>", |
448 "<a href='%s'%s>%s</a>", |
327 esc_url( add_query_arg( 'theme_status', $type, $url ) ), |
449 esc_url( add_query_arg( 'theme_status', $type, $url ) ), |
328 ( $type === $status ) ? ' class="current" aria-current="page"' : '', |
450 ( $type === $status ) ? ' class="current" aria-current="page"' : '', |
329 sprintf( $text, number_format_i18n( $count ) ) |
451 sprintf( $text, number_format_i18n( $count ) ) |
341 */ |
463 */ |
342 protected function get_bulk_actions() { |
464 protected function get_bulk_actions() { |
343 global $status; |
465 global $status; |
344 |
466 |
345 $actions = array(); |
467 $actions = array(); |
346 if ( 'enabled' != $status ) { |
468 if ( 'enabled' !== $status ) { |
347 $actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ); |
469 $actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ); |
348 } |
470 } |
349 if ( 'disabled' != $status ) { |
471 if ( 'disabled' !== $status ) { |
350 $actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ); |
472 $actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ); |
351 } |
473 } |
352 if ( ! $this->is_site_themes ) { |
474 if ( ! $this->is_site_themes ) { |
353 if ( current_user_can( 'update_themes' ) ) { |
475 if ( current_user_can( 'update_themes' ) ) { |
354 $actions['update-selected'] = __( 'Update' ); |
476 $actions['update-selected'] = __( 'Update' ); |
355 } |
477 } |
356 if ( current_user_can( 'delete_themes' ) ) { |
478 if ( current_user_can( 'delete_themes' ) ) { |
357 $actions['delete-selected'] = __( 'Delete' ); |
479 $actions['delete-selected'] = __( 'Delete' ); |
358 } |
480 } |
359 } |
481 } |
|
482 |
|
483 if ( $this->show_autoupdates ) { |
|
484 if ( 'auto-update-enabled' !== $status ) { |
|
485 $actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' ); |
|
486 } |
|
487 |
|
488 if ( 'auto-update-disabled' !== $status ) { |
|
489 $actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' ); |
|
490 } |
|
491 } |
|
492 |
360 return $actions; |
493 return $actions; |
361 } |
494 } |
362 |
495 |
363 /** |
496 /** |
364 */ |
497 */ |
569 |
707 |
570 $stylesheet = $theme->get_stylesheet(); |
708 $stylesheet = $theme->get_stylesheet(); |
571 $theme_meta = array(); |
709 $theme_meta = array(); |
572 |
710 |
573 if ( $theme->get( 'Version' ) ) { |
711 if ( $theme->get( 'Version' ) ) { |
|
712 /* translators: %s: Theme version. */ |
574 $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display( 'Version' ) ); |
713 $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display( 'Version' ) ); |
575 } |
714 } |
|
715 |
|
716 /* translators: %s: Theme author. */ |
576 $theme_meta[] = sprintf( __( 'By %s' ), $theme->display( 'Author' ) ); |
717 $theme_meta[] = sprintf( __( 'By %s' ), $theme->display( 'Author' ) ); |
577 |
718 |
578 if ( $theme->get( 'ThemeURI' ) ) { |
719 if ( $theme->get( 'ThemeURI' ) ) { |
579 /* translators: %s: theme name */ |
720 /* translators: %s: Theme name. */ |
580 $aria_label = sprintf( __( 'Visit %s homepage' ), $theme->display( 'Name' ) ); |
721 $aria_label = sprintf( __( 'Visit %s homepage' ), $theme->display( 'Name' ) ); |
581 |
722 |
582 $theme_meta[] = sprintf( |
723 $theme_meta[] = sprintf( |
583 '<a href="%s" aria-label="%s">%s</a>', |
724 '<a href="%s" aria-label="%s">%s</a>', |
584 $theme->display( 'ThemeURI' ), |
725 $theme->display( 'ThemeURI' ), |
585 esc_attr( $aria_label ), |
726 esc_attr( $aria_label ), |
586 __( 'Visit Theme Site' ) |
727 __( 'Visit Theme Site' ) |
587 ); |
728 ); |
588 } |
729 } |
|
730 |
589 /** |
731 /** |
590 * Filters the array of row meta for each theme in the Multisite themes |
732 * Filters the array of row meta for each theme in the Multisite themes |
591 * list table. |
733 * list table. |
592 * |
734 * |
593 * @since 3.1.0 |
735 * @since 3.1.0 |
594 * |
736 * |
595 * @param string[] $theme_meta An array of the theme's metadata, |
737 * @param string[] $theme_meta An array of the theme's metadata, including |
596 * including the version, author, and |
738 * the version, author, and theme URI. |
597 * theme URI. |
|
598 * @param string $stylesheet Directory name of the theme. |
739 * @param string $stylesheet Directory name of the theme. |
599 * @param WP_Theme $theme WP_Theme object. |
740 * @param WP_Theme $theme WP_Theme object. |
600 * @param string $status Status of the theme. |
741 * @param string $status Status of the theme. |
601 */ |
742 */ |
602 $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status ); |
743 $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status ); |
|
744 |
603 echo implode( ' | ', $theme_meta ); |
745 echo implode( ' | ', $theme_meta ); |
604 |
746 |
605 echo '</div>'; |
747 echo '</div>'; |
|
748 } |
|
749 |
|
750 /** |
|
751 * Handles the auto-updates column output. |
|
752 * |
|
753 * @since 5.5.0 |
|
754 * |
|
755 * @global string $status |
|
756 * @global int $page |
|
757 * |
|
758 * @param WP_Theme $theme The current WP_Theme object. |
|
759 */ |
|
760 public function column_autoupdates( $theme ) { |
|
761 global $status, $page; |
|
762 |
|
763 static $auto_updates, $available_updates; |
|
764 |
|
765 if ( ! $auto_updates ) { |
|
766 $auto_updates = (array) get_site_option( 'auto_update_themes', array() ); |
|
767 } |
|
768 if ( ! $available_updates ) { |
|
769 $available_updates = get_site_transient( 'update_themes' ); |
|
770 } |
|
771 |
|
772 $stylesheet = $theme->get_stylesheet(); |
|
773 |
|
774 if ( isset( $theme->auto_update_forced ) ) { |
|
775 if ( $theme->auto_update_forced ) { |
|
776 // Forced on. |
|
777 $text = __( 'Auto-updates enabled' ); |
|
778 } else { |
|
779 $text = __( 'Auto-updates disabled' ); |
|
780 } |
|
781 $action = 'unavailable'; |
|
782 $time_class = ' hidden'; |
|
783 } elseif ( empty( $theme->update_supported ) ) { |
|
784 $text = ''; |
|
785 $action = 'unavailable'; |
|
786 $time_class = ' hidden'; |
|
787 } elseif ( in_array( $stylesheet, $auto_updates, true ) ) { |
|
788 $text = __( 'Disable auto-updates' ); |
|
789 $action = 'disable'; |
|
790 $time_class = ''; |
|
791 } else { |
|
792 $text = __( 'Enable auto-updates' ); |
|
793 $action = 'enable'; |
|
794 $time_class = ' hidden'; |
|
795 } |
|
796 |
|
797 $query_args = array( |
|
798 'action' => "{$action}-auto-update", |
|
799 'theme' => $stylesheet, |
|
800 'paged' => $page, |
|
801 'theme_status' => $status, |
|
802 ); |
|
803 |
|
804 $url = add_query_arg( $query_args, 'themes.php' ); |
|
805 |
|
806 if ( 'unavailable' === $action ) { |
|
807 $html[] = '<span class="label">' . $text . '</span>'; |
|
808 } else { |
|
809 $html[] = sprintf( |
|
810 '<a href="%s" class="toggle-auto-update aria-button-if-js" data-wp-action="%s">', |
|
811 wp_nonce_url( $url, 'updates' ), |
|
812 $action |
|
813 ); |
|
814 |
|
815 $html[] = '<span class="dashicons dashicons-update spin hidden" aria-hidden="true"></span>'; |
|
816 $html[] = '<span class="label">' . $text . '</span>'; |
|
817 $html[] = '</a>'; |
|
818 |
|
819 } |
|
820 |
|
821 if ( isset( $available_updates->response[ $stylesheet ] ) ) { |
|
822 $html[] = sprintf( |
|
823 '<div class="auto-update-time%s">%s</div>', |
|
824 $time_class, |
|
825 wp_get_auto_update_message() |
|
826 ); |
|
827 } |
|
828 |
|
829 $html = implode( '', $html ); |
|
830 |
|
831 /** |
|
832 * Filters the HTML of the auto-updates setting for each theme in the Themes list table. |
|
833 * |
|
834 * @since 5.5.0 |
|
835 * |
|
836 * @param string $html The HTML for theme's auto-update setting, including |
|
837 * toggle auto-update action link and time to next update. |
|
838 * @param string $stylesheet Directory name of the theme. |
|
839 * @param WP_Theme $theme WP_Theme object. |
|
840 */ |
|
841 echo apply_filters( 'theme_auto_update_setting_html', $html, $stylesheet, $theme ); |
|
842 |
|
843 echo '<div class="notice notice-error notice-alt inline hidden"><p></p></div>'; |
606 } |
844 } |
607 |
845 |
608 /** |
846 /** |
609 * Handles default column output. |
847 * Handles default column output. |
610 * |
848 * |