[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/includes/ -> class-wp-ms-themes-list-table.php (source)

   1  <?php
   2  /**
   3   * List Table API: WP_MS_Themes_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 in a list table for the network admin.
  12   *
  13   * @since 3.1.0
  14   * @access private
  15   *
  16   * @see WP_List_Table
  17   */
  18  class WP_MS_Themes_List_Table extends WP_List_Table {
  19  
  20      public $site_id;
  21      public $is_site_themes;
  22  
  23      private $has_items;
  24  
  25      /**
  26       * Whether to show the auto-updates UI.
  27       *
  28       * @since 5.5.0
  29       *
  30       * @var bool True if auto-updates UI is to be shown, false otherwise.
  31       */
  32      protected $show_autoupdates = true;
  33  
  34      /**
  35       * Constructor.
  36       *
  37       * @since 3.1.0
  38       *
  39       * @see WP_List_Table::__construct() for more information on default arguments.
  40       *
  41       * @global string $status
  42       * @global int    $page
  43       *
  44       * @param array $args An associative array of arguments.
  45       */
  46  	public function __construct( $args = array() ) {
  47          global $status, $page;
  48  
  49          parent::__construct(
  50              array(
  51                  'plural' => 'themes',
  52                  'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
  53              )
  54          );
  55  
  56          $status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
  57          if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) {
  58              $status = 'all';
  59          }
  60  
  61          $page = $this->get_pagenum();
  62  
  63          $this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false;
  64  
  65          if ( $this->is_site_themes ) {
  66              $this->site_id = isset( $_REQUEST['id'] ) ? (int) $_REQUEST['id'] : 0;
  67          }
  68  
  69          $this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) &&
  70              ! $this->is_site_themes && current_user_can( 'update_themes' );
  71      }
  72  
  73      /**
  74       * @return array
  75       */
  76  	protected function get_table_classes() {
  77          // @todo Remove and add CSS for .themes.
  78          return array( 'widefat', 'plugins' );
  79      }
  80  
  81      /**
  82       * @return bool
  83       */
  84  	public function ajax_user_can() {
  85          if ( $this->is_site_themes ) {
  86              return current_user_can( 'manage_sites' );
  87          } else {
  88              return current_user_can( 'manage_network_themes' );
  89          }
  90      }
  91  
  92      /**
  93       * @global string $status
  94       * @global array $totals
  95       * @global int $page
  96       * @global string $orderby
  97       * @global string $order
  98       * @global string $s
  99       */
 100  	public function prepare_items() {
 101          global $status, $totals, $page, $orderby, $order, $s;
 102  
 103          wp_reset_vars( array( 'orderby', 'order', 's' ) );
 104  
 105          $themes = array(
 106              /**
 107               * Filters the full array of WP_Theme objects to list in the Multisite
 108               * themes list table.
 109               *
 110               * @since 3.1.0
 111               *
 112               * @param WP_Theme[] $all Array of WP_Theme objects to display in the list table.
 113               */
 114              'all'      => apply_filters( 'all_themes', wp_get_themes() ),
 115              'search'   => array(),
 116              'enabled'  => array(),
 117              'disabled' => array(),
 118              'upgrade'  => array(),
 119              'broken'   => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
 120          );
 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  
 129          if ( $this->is_site_themes ) {
 130              $themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
 131              $allowed_where   = 'site';
 132          } else {
 133              $themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
 134              $allowed_where   = 'network';
 135          }
 136  
 137          $current      = get_site_transient( 'update_themes' );
 138          $maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current;
 139  
 140          foreach ( (array) $themes['all'] as $key => $theme ) {
 141              if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) {
 142                  unset( $themes['all'][ $key ] );
 143                  continue;
 144              }
 145  
 146              if ( $maybe_update && isset( $current->response[ $key ] ) ) {
 147                  $themes['all'][ $key ]->update = true;
 148                  $themes['upgrade'][ $key ]     = $themes['all'][ $key ];
 149              }
 150  
 151              $filter                    = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
 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 = (object) array_merge( $filter_payload, array_intersect_key( $theme_data, $filter_payload ) );
 183  
 184              $auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, $filter_payload );
 185  
 186              if ( ! is_null( $auto_update_forced ) ) {
 187                  $theme->auto_update_forced = $auto_update_forced;
 188              }
 189  
 190              if ( $this->show_autoupdates ) {
 191                  $enabled = in_array( $key, $auto_updates, true ) && $theme->update_supported;
 192                  if ( isset( $theme->auto_update_forced ) ) {
 193                      $enabled = (bool) $theme->auto_update_forced;
 194                  }
 195  
 196                  if ( $enabled ) {
 197                      $themes['auto-update-enabled'][ $key ] = $theme;
 198                  } else {
 199                      $themes['auto-update-disabled'][ $key ] = $theme;
 200                  }
 201              }
 202          }
 203  
 204          if ( $s ) {
 205              $status           = 'search';
 206              $themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) );
 207          }
 208  
 209          $totals    = array();
 210          $js_themes = array();
 211          foreach ( $themes as $type => $list ) {
 212              $totals[ $type ]    = count( $list );
 213              $js_themes[ $type ] = array_keys( $list );
 214          }
 215  
 216          if ( empty( $themes[ $status ] ) && ! in_array( $status, array( 'all', 'search' ), true ) ) {
 217              $status = 'all';
 218          }
 219  
 220          $this->items = $themes[ $status ];
 221          WP_Theme::sort_by_name( $this->items );
 222  
 223          $this->has_items = ! empty( $themes['all'] );
 224          $total_this_page = $totals[ $status ];
 225  
 226          wp_localize_script(
 227              'updates',
 228              '_wpUpdatesItemCounts',
 229              array(
 230                  'themes' => $js_themes,
 231                  'totals' => wp_get_update_data(),
 232              )
 233          );
 234  
 235          if ( $orderby ) {
 236              $orderby = ucfirst( $orderby );
 237              $order   = strtoupper( $order );
 238  
 239              if ( 'Name' === $orderby ) {
 240                  if ( 'ASC' === $order ) {
 241                      $this->items = array_reverse( $this->items );
 242                  }
 243              } else {
 244                  uasort( $this->items, array( $this, '_order_callback' ) );
 245              }
 246          }
 247  
 248          $start = ( $page - 1 ) * $themes_per_page;
 249  
 250          if ( $total_this_page > $themes_per_page ) {
 251              $this->items = array_slice( $this->items, $start, $themes_per_page, true );
 252          }
 253  
 254          $this->set_pagination_args(
 255              array(
 256                  'total_items' => $total_this_page,
 257                  'per_page'    => $themes_per_page,
 258              )
 259          );
 260      }
 261  
 262      /**
 263       * @param WP_Theme $theme
 264       * @return bool
 265       */
 266  	public function _search_callback( $theme ) {
 267          static $term = null;
 268          if ( is_null( $term ) ) {
 269              $term = wp_unslash( $_REQUEST['s'] );
 270          }
 271  
 272          foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
 273              // Don't mark up; Do translate.
 274              if ( false !== stripos( $theme->display( $field, false, true ), $term ) ) {
 275                  return true;
 276              }
 277          }
 278  
 279          if ( false !== stripos( $theme->get_stylesheet(), $term ) ) {
 280              return true;
 281          }
 282  
 283          if ( false !== stripos( $theme->get_template(), $term ) ) {
 284              return true;
 285          }
 286  
 287          return false;
 288      }
 289  
 290      // Not used by any core columns.
 291      /**
 292       * @global string $orderby
 293       * @global string $order
 294       * @param array $theme_a
 295       * @param array $theme_b
 296       * @return int
 297       */
 298  	public function _order_callback( $theme_a, $theme_b ) {
 299          global $orderby, $order;
 300  
 301          $a = $theme_a[ $orderby ];
 302          $b = $theme_b[ $orderby ];
 303  
 304          if ( $a === $b ) {
 305              return 0;
 306          }
 307  
 308          if ( 'DESC' === $order ) {
 309              return ( $a < $b ) ? 1 : -1;
 310          } else {
 311              return ( $a < $b ) ? -1 : 1;
 312          }
 313      }
 314  
 315      /**
 316       */
 317  	public function no_items() {
 318          if ( $this->has_items ) {
 319              _e( 'No themes found.' );
 320          } else {
 321              _e( 'No themes are currently available.' );
 322          }
 323      }
 324  
 325      /**
 326       * @return array
 327       */
 328  	public function get_columns() {
 329          $columns = array(
 330              'cb'          => '<input type="checkbox" />',
 331              'name'        => __( 'Theme' ),
 332              'description' => __( 'Description' ),
 333          );
 334  
 335          if ( $this->show_autoupdates ) {
 336              $columns['auto-updates'] = __( 'Automatic Updates' );
 337          }
 338  
 339          return $columns;
 340      }
 341  
 342      /**
 343       * @return array
 344       */
 345  	protected function get_sortable_columns() {
 346          return array(
 347              'name' => 'name',
 348          );
 349      }
 350  
 351      /**
 352       * Gets the name of the primary column.
 353       *
 354       * @since 4.3.0
 355       *
 356       * @return string Unalterable name of the primary column name, in this case, 'name'.
 357       */
 358  	protected function get_primary_column_name() {
 359          return 'name';
 360      }
 361  
 362      /**
 363       * @global array $totals
 364       * @global string $status
 365       * @return array
 366       */
 367  	protected function get_views() {
 368          global $totals, $status;
 369  
 370          $status_links = array();
 371          foreach ( $totals as $type => $count ) {
 372              if ( ! $count ) {
 373                  continue;
 374              }
 375  
 376              switch ( $type ) {
 377                  case 'all':
 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                      );
 385                      break;
 386                  case 'enabled':
 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                      );
 394                      break;
 395                  case 'disabled':
 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                      );
 403                      break;
 404                  case 'upgrade':
 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                      );
 412                      break;
 413                  case 'broken':
 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                      );
 437                      break;
 438              }
 439  
 440              if ( $this->is_site_themes ) {
 441                  $url = 'site-themes.php?id=' . $this->site_id;
 442              } else {
 443                  $url = 'themes.php';
 444              }
 445  
 446              if ( 'search' !== $type ) {
 447                  $status_links[ $type ] = sprintf(
 448                      "<a href='%s'%s>%s</a>",
 449                      esc_url( add_query_arg( 'theme_status', $type, $url ) ),
 450                      ( $type === $status ) ? ' class="current" aria-current="page"' : '',
 451                      sprintf( $text, number_format_i18n( $count ) )
 452                  );
 453              }
 454          }
 455  
 456          return $status_links;
 457      }
 458  
 459      /**
 460       * @global string $status
 461       *
 462       * @return array
 463       */
 464  	protected function get_bulk_actions() {
 465          global $status;
 466  
 467          $actions = array();
 468          if ( 'enabled' !== $status ) {
 469              $actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' );
 470          }
 471          if ( 'disabled' !== $status ) {
 472              $actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' );
 473          }
 474          if ( ! $this->is_site_themes ) {
 475              if ( current_user_can( 'update_themes' ) ) {
 476                  $actions['update-selected'] = __( 'Update' );
 477              }
 478              if ( current_user_can( 'delete_themes' ) ) {
 479                  $actions['delete-selected'] = __( 'Delete' );
 480              }
 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  
 493          return $actions;
 494      }
 495  
 496      /**
 497       */
 498  	public function display_rows() {
 499          foreach ( $this->items as $theme ) {
 500              $this->single_row( $theme );
 501          }
 502      }
 503  
 504      /**
 505       * Handles the checkbox column output.
 506       *
 507       * @since 4.3.0
 508       * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support.
 509       *
 510       * @param WP_Theme $item The current WP_Theme object.
 511       */
 512  	public function column_cb( $item ) {
 513          // Restores the more descriptive, specific name for use within this method.
 514          $theme       = $item;
 515          $checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
 516          ?>
 517          <input type="checkbox" name="checked[]" value="<?php echo esc_attr( $theme->get_stylesheet() ); ?>" id="<?php echo $checkbox_id; ?>" />
 518          <label class="screen-reader-text" for="<?php echo $checkbox_id; ?>" ><?php _e( 'Select' ); ?>  <?php echo $theme->display( 'Name' ); ?></label>
 519          <?php
 520      }
 521  
 522      /**
 523       * Handles the name column output.
 524       *
 525       * @since 4.3.0
 526       *
 527       * @global string $status
 528       * @global int    $page
 529       * @global string $s
 530       *
 531       * @param WP_Theme $theme The current WP_Theme object.
 532       */
 533  	public function column_name( $theme ) {
 534          global $status, $page, $s;
 535  
 536          $context = $status;
 537  
 538          if ( $this->is_site_themes ) {
 539              $url     = "site-themes.php?id={$this->site_id}&amp;";
 540              $allowed = $theme->is_allowed( 'site', $this->site_id );
 541          } else {
 542              $url     = 'themes.php?';
 543              $allowed = $theme->is_allowed( 'network' );
 544          }
 545  
 546          // Pre-order.
 547          $actions = array(
 548              'enable'  => '',
 549              'disable' => '',
 550              'delete'  => '',
 551          );
 552  
 553          $stylesheet = $theme->get_stylesheet();
 554          $theme_key  = urlencode( $stylesheet );
 555  
 556          if ( ! $allowed ) {
 557              if ( ! $theme->errors() ) {
 558                  $url = add_query_arg(
 559                      array(
 560                          'action' => 'enable',
 561                          'theme'  => $theme_key,
 562                          'paged'  => $page,
 563                          's'      => $s,
 564                      ),
 565                      $url
 566                  );
 567  
 568                  if ( $this->is_site_themes ) {
 569                      /* translators: %s: Theme name. */
 570                      $aria_label = sprintf( __( 'Enable %s' ), $theme->display( 'Name' ) );
 571                  } else {
 572                      /* translators: %s: Theme name. */
 573                      $aria_label = sprintf( __( 'Network Enable %s' ), $theme->display( 'Name' ) );
 574                  }
 575  
 576                  $actions['enable'] = sprintf(
 577                      '<a href="%s" class="edit" aria-label="%s">%s</a>',
 578                      esc_url( wp_nonce_url( $url, 'enable-theme_' . $stylesheet ) ),
 579                      esc_attr( $aria_label ),
 580                      ( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) )
 581                  );
 582              }
 583          } else {
 584              $url = add_query_arg(
 585                  array(
 586                      'action' => 'disable',
 587                      'theme'  => $theme_key,
 588                      'paged'  => $page,
 589                      's'      => $s,
 590                  ),
 591                  $url
 592              );
 593  
 594              if ( $this->is_site_themes ) {
 595                  /* translators: %s: Theme name. */
 596                  $aria_label = sprintf( __( 'Disable %s' ), $theme->display( 'Name' ) );
 597              } else {
 598                  /* translators: %s: Theme name. */
 599                  $aria_label = sprintf( __( 'Network Disable %s' ), $theme->display( 'Name' ) );
 600              }
 601  
 602              $actions['disable'] = sprintf(
 603                  '<a href="%s" aria-label="%s">%s</a>',
 604                  esc_url( wp_nonce_url( $url, 'disable-theme_' . $stylesheet ) ),
 605                  esc_attr( $aria_label ),
 606                  ( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) )
 607              );
 608          }
 609  
 610          if ( ! $allowed && ! $this->is_site_themes
 611              && current_user_can( 'delete_themes' )
 612              && get_option( 'stylesheet' ) !== $stylesheet
 613              && get_option( 'template' ) !== $stylesheet
 614          ) {
 615              $url = add_query_arg(
 616                  array(
 617                      'action'       => 'delete-selected',
 618                      'checked[]'    => $theme_key,
 619                      'theme_status' => $context,
 620                      'paged'        => $page,
 621                      's'            => $s,
 622                  ),
 623                  'themes.php'
 624              );
 625  
 626              /* translators: %s: Theme name. */
 627              $aria_label = sprintf( _x( 'Delete %s', 'theme' ), $theme->display( 'Name' ) );
 628  
 629              $actions['delete'] = sprintf(
 630                  '<a href="%s" class="delete" aria-label="%s">%s</a>',
 631                  esc_url( wp_nonce_url( $url, 'bulk-themes' ) ),
 632                  esc_attr( $aria_label ),
 633                  __( 'Delete' )
 634              );
 635          }
 636          /**
 637           * Filters the action links displayed for each theme in the Multisite
 638           * themes list table.
 639           *
 640           * The action links displayed are determined by the theme's status, and
 641           * which Multisite themes list table is being displayed - the Network
 642           * themes list table (themes.php), which displays all installed themes,
 643           * or the Site themes list table (site-themes.php), which displays the
 644           * non-network enabled themes when editing a site in the Network admin.
 645           *
 646           * The default action links for the Network themes list table include
 647           * 'Network Enable', 'Network Disable', and 'Delete'.
 648           *
 649           * The default action links for the Site themes list table include
 650           * 'Enable', and 'Disable'.
 651           *
 652           * @since 2.8.0
 653           *
 654           * @param string[] $actions An array of action links.
 655           * @param WP_Theme $theme   The current WP_Theme object.
 656           * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
 657           */
 658          $actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context );
 659  
 660          /**
 661           * Filters the action links of a specific theme in the Multisite themes
 662           * list table.
 663           *
 664           * The dynamic portion of the hook name, `$stylesheet`, refers to the
 665           * directory name of the theme, which in most cases is synonymous
 666           * with the template name.
 667           *
 668           * @since 3.1.0
 669           *
 670           * @param string[] $actions An array of action links.
 671           * @param WP_Theme $theme   The current WP_Theme object.
 672           * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
 673           */
 674          $actions = apply_filters( "theme_action_links_{$stylesheet}", $actions, $theme, $context );
 675  
 676          echo $this->row_actions( $actions, true );
 677      }
 678  
 679      /**
 680       * Handles the description column output.
 681       *
 682       * @since 4.3.0
 683       *
 684       * @global string $status
 685       * @global array  $totals
 686       *
 687       * @param WP_Theme $theme The current WP_Theme object.
 688       */
 689  	public function column_description( $theme ) {
 690          global $status, $totals;
 691  
 692          if ( $theme->errors() ) {
 693              $pre = 'broken' === $status ? __( 'Broken Theme:' ) . ' ' : '';
 694              echo '<p><strong class="error-message">' . $pre . $theme->errors()->get_error_message() . '</strong></p>';
 695          }
 696  
 697          if ( $this->is_site_themes ) {
 698              $allowed = $theme->is_allowed( 'site', $this->site_id );
 699          } else {
 700              $allowed = $theme->is_allowed( 'network' );
 701          }
 702  
 703          $class = ! $allowed ? 'inactive' : 'active';
 704          if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
 705              $class .= ' update';
 706          }
 707  
 708          echo "<div class='theme-description'><p>" . $theme->display( 'Description' ) . "</p></div>
 709              <div class='$class second theme-version-author-uri'>";
 710  
 711          $stylesheet = $theme->get_stylesheet();
 712          $theme_meta = array();
 713  
 714          if ( $theme->get( 'Version' ) ) {
 715              /* translators: %s: Theme version. */
 716              $theme_meta[] = sprintf( __( 'Version %s' ), $theme->display( 'Version' ) );
 717          }
 718  
 719          /* translators: %s: Theme author. */
 720          $theme_meta[] = sprintf( __( 'By %s' ), $theme->display( 'Author' ) );
 721  
 722          if ( $theme->get( 'ThemeURI' ) ) {
 723              /* translators: %s: Theme name. */
 724              $aria_label = sprintf( __( 'Visit theme site for %s' ), $theme->display( 'Name' ) );
 725  
 726              $theme_meta[] = sprintf(
 727                  '<a href="%s" aria-label="%s">%s</a>',
 728                  $theme->display( 'ThemeURI' ),
 729                  esc_attr( $aria_label ),
 730                  __( 'Visit Theme Site' )
 731              );
 732          }
 733  
 734          if ( $theme->parent() ) {
 735              $theme_meta[] = sprintf(
 736                  /* translators: %s: Theme name. */
 737                  __( 'Child theme of %s' ),
 738                  '<strong>' . $theme->parent()->display( 'Name' ) . '</strong>'
 739              );
 740          }
 741  
 742          /**
 743           * Filters the array of row meta for each theme in the Multisite themes
 744           * list table.
 745           *
 746           * @since 3.1.0
 747           *
 748           * @param string[] $theme_meta An array of the theme's metadata, including
 749           *                             the version, author, and theme URI.
 750           * @param string   $stylesheet Directory name of the theme.
 751           * @param WP_Theme $theme      WP_Theme object.
 752           * @param string   $status     Status of the theme.
 753           */
 754          $theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status );
 755  
 756          echo implode( ' | ', $theme_meta );
 757  
 758          echo '</div>';
 759      }
 760  
 761      /**
 762       * Handles the auto-updates column output.
 763       *
 764       * @since 5.5.0
 765       *
 766       * @global string $status
 767       * @global int  $page
 768       *
 769       * @param WP_Theme $theme The current WP_Theme object.
 770       */
 771  	public function column_autoupdates( $theme ) {
 772          global $status, $page;
 773  
 774          static $auto_updates, $available_updates;
 775  
 776          if ( ! $auto_updates ) {
 777              $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
 778          }
 779          if ( ! $available_updates ) {
 780              $available_updates = get_site_transient( 'update_themes' );
 781          }
 782  
 783          $stylesheet = $theme->get_stylesheet();
 784  
 785          if ( isset( $theme->auto_update_forced ) ) {
 786              if ( $theme->auto_update_forced ) {
 787                  // Forced on.
 788                  $text = __( 'Auto-updates enabled' );
 789              } else {
 790                  $text = __( 'Auto-updates disabled' );
 791              }
 792              $action     = 'unavailable';
 793              $time_class = ' hidden';
 794          } elseif ( empty( $theme->update_supported ) ) {
 795              $text       = '';
 796              $action     = 'unavailable';
 797              $time_class = ' hidden';
 798          } elseif ( in_array( $stylesheet, $auto_updates, true ) ) {
 799              $text       = __( 'Disable auto-updates' );
 800              $action     = 'disable';
 801              $time_class = '';
 802          } else {
 803              $text       = __( 'Enable auto-updates' );
 804              $action     = 'enable';
 805              $time_class = ' hidden';
 806          }
 807  
 808          $query_args = array(
 809              'action'       => "{$action}-auto-update",
 810              'theme'        => $stylesheet,
 811              'paged'        => $page,
 812              'theme_status' => $status,
 813          );
 814  
 815          $url = add_query_arg( $query_args, 'themes.php' );
 816  
 817          if ( 'unavailable' === $action ) {
 818              $html[] = '<span class="label">' . $text . '</span>';
 819          } else {
 820              $html[] = sprintf(
 821                  '<a href="%s" class="toggle-auto-update aria-button-if-js" data-wp-action="%s">',
 822                  wp_nonce_url( $url, 'updates' ),
 823                  $action
 824              );
 825  
 826              $html[] = '<span class="dashicons dashicons-update spin hidden" aria-hidden="true"></span>';
 827              $html[] = '<span class="label">' . $text . '</span>';
 828              $html[] = '</a>';
 829  
 830          }
 831  
 832          if ( isset( $available_updates->response[ $stylesheet ] ) ) {
 833              $html[] = sprintf(
 834                  '<div class="auto-update-time%s">%s</div>',
 835                  $time_class,
 836                  wp_get_auto_update_message()
 837              );
 838          }
 839  
 840          $html = implode( '', $html );
 841  
 842          /**
 843           * Filters the HTML of the auto-updates setting for each theme in the Themes list table.
 844           *
 845           * @since 5.5.0
 846           *
 847           * @param string   $html       The HTML for theme's auto-update setting, including
 848           *                             toggle auto-update action link and time to next update.
 849           * @param string   $stylesheet Directory name of the theme.
 850           * @param WP_Theme $theme      WP_Theme object.
 851           */
 852          echo apply_filters( 'theme_auto_update_setting_html', $html, $stylesheet, $theme );
 853  
 854          echo '<div class="notice notice-error notice-alt inline hidden"><p></p></div>';
 855      }
 856  
 857      /**
 858       * Handles default column output.
 859       *
 860       * @since 4.3.0
 861       * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support.
 862       *
 863       * @param WP_Theme $item        The current WP_Theme object.
 864       * @param string   $column_name The current column name.
 865       */
 866  	public function column_default( $item, $column_name ) {
 867          /**
 868           * Fires inside each custom column of the Multisite themes list table.
 869           *
 870           * @since 3.1.0
 871           *
 872           * @param string   $column_name Name of the column.
 873           * @param string   $stylesheet  Directory name of the theme.
 874           * @param WP_Theme $theme       Current WP_Theme object.
 875           */
 876          do_action(
 877              'manage_themes_custom_column',
 878              $column_name,
 879              $item->get_stylesheet(), // Directory name of the theme.
 880              $item // Theme object.
 881          );
 882      }
 883  
 884      /**
 885       * Handles the output for a single table row.
 886       *
 887       * @since 4.3.0
 888       *
 889       * @param WP_Theme $item The current WP_Theme object.
 890       */
 891  	public function single_row_columns( $item ) {
 892          list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
 893  
 894          foreach ( $columns as $column_name => $column_display_name ) {
 895              $extra_classes = '';
 896              if ( in_array( $column_name, $hidden, true ) ) {
 897                  $extra_classes .= ' hidden';
 898              }
 899  
 900              switch ( $column_name ) {
 901                  case 'cb':
 902                      echo '<th scope="row" class="check-column">';
 903  
 904                      $this->column_cb( $item );
 905  
 906                      echo '</th>';
 907                      break;
 908  
 909                  case 'name':
 910                      $active_theme_label = '';
 911  
 912                      /* The presence of the site_id property means that this is a subsite view and a label for the active theme needs to be added */
 913                      if ( ! empty( $this->site_id ) ) {
 914                          $stylesheet = get_blog_option( $this->site_id, 'stylesheet' );
 915                          $template   = get_blog_option( $this->site_id, 'template' );
 916  
 917                          /* Add a label for the active template */
 918                          if ( $item->get_template() === $template ) {
 919                              $active_theme_label = ' &mdash; ' . __( 'Active Theme' );
 920                          }
 921  
 922                          /* In case this is a child theme, label it properly */
 923                          if ( $stylesheet !== $template && $item->get_stylesheet() === $stylesheet ) {
 924                              $active_theme_label = ' &mdash; ' . __( 'Active Child Theme' );
 925                          }
 926                      }
 927  
 928                      echo "<td class='theme-title column-primary{$extra_classes}'><strong>" . $item->display( 'Name' ) . $active_theme_label . '</strong>';
 929  
 930                      $this->column_name( $item );
 931  
 932                      echo '</td>';
 933                      break;
 934  
 935                  case 'description':
 936                      echo "<td class='column-description desc{$extra_classes}'>";
 937  
 938                      $this->column_description( $item );
 939  
 940                      echo '</td>';
 941                      break;
 942  
 943                  case 'auto-updates':
 944                      echo "<td class='column-auto-updates{$extra_classes}'>";
 945  
 946                      $this->column_autoupdates( $item );
 947  
 948                      echo '</td>';
 949                      break;
 950                  default:
 951                      echo "<td class='$column_name column-$column_name{$extra_classes}'>";
 952  
 953                      $this->column_default( $item, $column_name );
 954  
 955                      echo '</td>';
 956                      break;
 957              }
 958          }
 959      }
 960  
 961      /**
 962       * @global string $status
 963       * @global array  $totals
 964       *
 965       * @param WP_Theme $theme
 966       */
 967  	public function single_row( $theme ) {
 968          global $status, $totals;
 969  
 970          if ( $this->is_site_themes ) {
 971              $allowed = $theme->is_allowed( 'site', $this->site_id );
 972          } else {
 973              $allowed = $theme->is_allowed( 'network' );
 974          }
 975  
 976          $stylesheet = $theme->get_stylesheet();
 977  
 978          $class = ! $allowed ? 'inactive' : 'active';
 979          if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
 980              $class .= ' update';
 981          }
 982  
 983          printf(
 984              '<tr class="%s" data-slug="%s">',
 985              esc_attr( $class ),
 986              esc_attr( $stylesheet )
 987          );
 988  
 989          $this->single_row_columns( $theme );
 990  
 991          echo '</tr>';
 992  
 993          if ( $this->is_site_themes ) {
 994              remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' );
 995          }
 996  
 997          /**
 998           * Fires after each row in the Multisite themes list table.
 999           *
1000           * @since 3.1.0
1001           *
1002           * @param string   $stylesheet Directory name of the theme.
1003           * @param WP_Theme $theme      Current WP_Theme object.
1004           * @param string   $status     Status of the theme.
1005           */
1006          do_action( 'after_theme_row', $stylesheet, $theme, $status );
1007  
1008          /**
1009           * Fires after each specific row in the Multisite themes list table.
1010           *
1011           * The dynamic portion of the hook name, `$stylesheet`, refers to the
1012           * directory name of the theme, most often synonymous with the template
1013           * name of the theme.
1014           *
1015           * @since 3.5.0
1016           *
1017           * @param string   $stylesheet Directory name of the theme.
1018           * @param WP_Theme $theme      Current WP_Theme object.
1019           * @param string   $status     Status of the theme.
1020           */
1021          do_action( "after_theme_row_{$stylesheet}", $stylesheet, $theme, $status );
1022      }
1023  }


Generated: Thu Nov 21 01:00:03 2024 Cross-referenced by PHPXref 0.7.1