wp/wp-admin/includes/class-wp-ms-themes-list-table.php
changeset 9 177826044cd9
parent 7 cf61fcea0001
child 16 a86126ab1dd4
equal deleted inserted replaced
8:c7c34916027a 9:177826044cd9
    35 	 * @param array $args An associative array of arguments.
    35 	 * @param array $args An associative array of arguments.
    36 	 */
    36 	 */
    37 	public function __construct( $args = array() ) {
    37 	public function __construct( $args = array() ) {
    38 		global $status, $page;
    38 		global $status, $page;
    39 
    39 
    40 		parent::__construct( array(
    40 		parent::__construct(
    41 			'plural' => 'themes',
    41 			array(
    42 			'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
    42 				'plural' => 'themes',
    43 		) );
    43 				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
       
    44 			)
       
    45 		);
    44 
    46 
    45 		$status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
    47 		$status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
    46 		if ( !in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ) ) )
    48 		if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken' ) ) ) {
    47 			$status = 'all';
    49 			$status = 'all';
       
    50 		}
    48 
    51 
    49 		$page = $this->get_pagenum();
    52 		$page = $this->get_pagenum();
    50 
    53 
    51 		$this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false;
    54 		$this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false;
    52 
    55 
    53 		if ( $this->is_site_themes )
    56 		if ( $this->is_site_themes ) {
    54 			$this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
    57 			$this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0;
    55 	}
    58 		}
    56 
    59 	}
    57 	/**
    60 
    58 	 *
    61 	/**
    59 	 * @return array
    62 	 * @return array
    60 	 */
    63 	 */
    61 	protected function get_table_classes() {
    64 	protected function get_table_classes() {
    62 		// todo: remove and add CSS for .themes
    65 		// todo: remove and add CSS for .themes
    63 		return array( 'widefat', 'plugins' );
    66 		return array( 'widefat', 'plugins' );
    64 	}
    67 	}
    65 
    68 
    66 	/**
    69 	/**
    67 	 *
       
    68 	 * @return bool
    70 	 * @return bool
    69 	 */
    71 	 */
    70 	public function ajax_user_can() {
    72 	public function ajax_user_can() {
    71 		if ( $this->is_site_themes )
    73 		if ( $this->is_site_themes ) {
    72 			return current_user_can( 'manage_sites' );
    74 			return current_user_can( 'manage_sites' );
    73 		else
    75 		} else {
    74 			return current_user_can( 'manage_network_themes' );
    76 			return current_user_can( 'manage_network_themes' );
    75 	}
    77 		}
    76 
    78 	}
    77 	/**
    79 
    78 	 *
    80 	/**
    79 	 * @global string $status
    81 	 * @global string $status
    80 	 * @global array $totals
    82 	 * @global array $totals
    81 	 * @global int $page
    83 	 * @global int $page
    82 	 * @global string $orderby
    84 	 * @global string $orderby
    83 	 * @global string $order
    85 	 * @global string $order
    93 			 * Filters the full array of WP_Theme objects to list in the Multisite
    95 			 * Filters the full array of WP_Theme objects to list in the Multisite
    94 			 * themes list table.
    96 			 * themes list table.
    95 			 *
    97 			 *
    96 			 * @since 3.1.0
    98 			 * @since 3.1.0
    97 			 *
    99 			 *
    98 			 * @param array $all An array of WP_Theme objects to display in the list table.
   100 			 * @param WP_Theme[] $all Array of WP_Theme objects to display in the list table.
    99 			 */
   101 			 */
   100 			'all' => apply_filters( 'all_themes', wp_get_themes() ),
   102 			'all'      => apply_filters( 'all_themes', wp_get_themes() ),
   101 			'search' => array(),
   103 			'search'   => array(),
   102 			'enabled' => array(),
   104 			'enabled'  => array(),
   103 			'disabled' => array(),
   105 			'disabled' => array(),
   104 			'upgrade' => array(),
   106 			'upgrade'  => array(),
   105 			'broken' => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
   107 			'broken'   => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
   106 		);
   108 		);
   107 
   109 
   108 		if ( $this->is_site_themes ) {
   110 		if ( $this->is_site_themes ) {
   109 			$themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
   111 			$themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
   110 			$allowed_where = 'site';
   112 			$allowed_where   = 'site';
   111 		} else {
   113 		} else {
   112 			$themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
   114 			$themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
   113 			$allowed_where = 'network';
   115 			$allowed_where   = 'network';
   114 		}
   116 		}
   115 
   117 
   116 		$maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current = get_site_transient( 'update_themes' );
   118 		$maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current = get_site_transient( 'update_themes' );
   117 
   119 
   118 		foreach ( (array) $themes['all'] as $key => $theme ) {
   120 		foreach ( (array) $themes['all'] as $key => $theme ) {
   121 				continue;
   123 				continue;
   122 			}
   124 			}
   123 
   125 
   124 			if ( $maybe_update && isset( $current->response[ $key ] ) ) {
   126 			if ( $maybe_update && isset( $current->response[ $key ] ) ) {
   125 				$themes['all'][ $key ]->update = true;
   127 				$themes['all'][ $key ]->update = true;
   126 				$themes['upgrade'][ $key ] = $themes['all'][ $key ];
   128 				$themes['upgrade'][ $key ]     = $themes['all'][ $key ];
   127 			}
   129 			}
   128 
   130 
   129 			$filter = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
   131 			$filter                    = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
   130 			$themes[ $filter ][ $key ] = $themes['all'][ $key ];
   132 			$themes[ $filter ][ $key ] = $themes['all'][ $key ];
   131 		}
   133 		}
   132 
   134 
   133 		if ( $s ) {
   135 		if ( $s ) {
   134 			$status = 'search';
   136 			$status           = 'search';
   135 			$themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) );
   137 			$themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) );
   136 		}
   138 		}
   137 
   139 
   138 		$totals = array();
   140 		$totals = array();
   139 		foreach ( $themes as $type => $list )
   141 		foreach ( $themes as $type => $list ) {
   140 			$totals[ $type ] = count( $list );
   142 			$totals[ $type ] = count( $list );
   141 
   143 		}
   142 		if ( empty( $themes[ $status ] ) && !in_array( $status, array( 'all', 'search' ) ) )
   144 
       
   145 		if ( empty( $themes[ $status ] ) && ! in_array( $status, array( 'all', 'search' ) ) ) {
   143 			$status = 'all';
   146 			$status = 'all';
       
   147 		}
   144 
   148 
   145 		$this->items = $themes[ $status ];
   149 		$this->items = $themes[ $status ];
   146 		WP_Theme::sort_by_name( $this->items );
   150 		WP_Theme::sort_by_name( $this->items );
   147 
   151 
   148 		$this->has_items = ! empty( $themes['all'] );
   152 		$this->has_items = ! empty( $themes['all'] );
   149 		$total_this_page = $totals[ $status ];
   153 		$total_this_page = $totals[ $status ];
   150 
   154 
   151 		wp_localize_script( 'updates', '_wpUpdatesItemCounts', array(
   155 		wp_localize_script(
   152 			'themes' => $totals,
   156 			'updates',
   153 			'totals' => wp_get_update_data(),
   157 			'_wpUpdatesItemCounts',
   154 		) );
   158 			array(
       
   159 				'themes' => $totals,
       
   160 				'totals' => wp_get_update_data(),
       
   161 			)
       
   162 		);
   155 
   163 
   156 		if ( $orderby ) {
   164 		if ( $orderby ) {
   157 			$orderby = ucfirst( $orderby );
   165 			$orderby = ucfirst( $orderby );
   158 			$order = strtoupper( $order );
   166 			$order   = strtoupper( $order );
   159 
   167 
   160 			if ( $orderby === 'Name' ) {
   168 			if ( $orderby === 'Name' ) {
   161 				if ( 'ASC' === $order ) {
   169 				if ( 'ASC' === $order ) {
   162 					$this->items = array_reverse( $this->items );
   170 					$this->items = array_reverse( $this->items );
   163 				}
   171 				}
   166 			}
   174 			}
   167 		}
   175 		}
   168 
   176 
   169 		$start = ( $page - 1 ) * $themes_per_page;
   177 		$start = ( $page - 1 ) * $themes_per_page;
   170 
   178 
   171 		if ( $total_this_page > $themes_per_page )
   179 		if ( $total_this_page > $themes_per_page ) {
   172 			$this->items = array_slice( $this->items, $start, $themes_per_page, true );
   180 			$this->items = array_slice( $this->items, $start, $themes_per_page, true );
   173 
   181 		}
   174 		$this->set_pagination_args( array(
   182 
   175 			'total_items' => $total_this_page,
   183 		$this->set_pagination_args(
   176 			'per_page' => $themes_per_page,
   184 			array(
   177 		) );
   185 				'total_items' => $total_this_page,
       
   186 				'per_page'    => $themes_per_page,
       
   187 			)
       
   188 		);
   178 	}
   189 	}
   179 
   190 
   180 	/**
   191 	/**
   181 	 * @staticvar string $term
   192 	 * @staticvar string $term
   182 	 * @param WP_Theme $theme
   193 	 * @param WP_Theme $theme
   183 	 * @return bool
   194 	 * @return bool
   184 	 */
   195 	 */
   185 	public function _search_callback( $theme ) {
   196 	public function _search_callback( $theme ) {
   186 		static $term = null;
   197 		static $term = null;
   187 		if ( is_null( $term ) )
   198 		if ( is_null( $term ) ) {
   188 			$term = wp_unslash( $_REQUEST['s'] );
   199 			$term = wp_unslash( $_REQUEST['s'] );
       
   200 		}
   189 
   201 
   190 		foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
   202 		foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
   191 			// Don't mark up; Do translate.
   203 			// Don't mark up; Do translate.
   192 			if ( false !== stripos( $theme->display( $field, false, true ), $term ) )
   204 			if ( false !== stripos( $theme->display( $field, false, true ), $term ) ) {
   193 				return true;
   205 				return true;
   194 		}
   206 			}
   195 
   207 		}
   196 		if ( false !== stripos( $theme->get_stylesheet(), $term ) )
   208 
       
   209 		if ( false !== stripos( $theme->get_stylesheet(), $term ) ) {
   197 			return true;
   210 			return true;
   198 
   211 		}
   199 		if ( false !== stripos( $theme->get_template(), $term ) )
   212 
       
   213 		if ( false !== stripos( $theme->get_template(), $term ) ) {
   200 			return true;
   214 			return true;
       
   215 		}
   201 
   216 
   202 		return false;
   217 		return false;
   203 	}
   218 	}
   204 
   219 
   205 	// Not used by any core columns.
   220 	// Not used by any core columns.
   214 		global $orderby, $order;
   229 		global $orderby, $order;
   215 
   230 
   216 		$a = $theme_a[ $orderby ];
   231 		$a = $theme_a[ $orderby ];
   217 		$b = $theme_b[ $orderby ];
   232 		$b = $theme_b[ $orderby ];
   218 
   233 
   219 		if ( $a == $b )
   234 		if ( $a == $b ) {
   220 			return 0;
   235 			return 0;
   221 
   236 		}
   222 		if ( 'DESC' === $order )
   237 
       
   238 		if ( 'DESC' === $order ) {
   223 			return ( $a < $b ) ? 1 : -1;
   239 			return ( $a < $b ) ? 1 : -1;
   224 		else
   240 		} else {
   225 			return ( $a < $b ) ? -1 : 1;
   241 			return ( $a < $b ) ? -1 : 1;
       
   242 		}
   226 	}
   243 	}
   227 
   244 
   228 	/**
   245 	/**
   229 	 */
   246 	 */
   230 	public function no_items() {
   247 	public function no_items() {
   234 			_e( 'You do not appear to have any themes available at this time.' );
   251 			_e( 'You do not appear to have any themes available at this time.' );
   235 		}
   252 		}
   236 	}
   253 	}
   237 
   254 
   238 	/**
   255 	/**
   239 	 *
       
   240 	 * @return array
   256 	 * @return array
   241 	 */
   257 	 */
   242 	public function get_columns() {
   258 	public function get_columns() {
   243 		return array(
   259 		return array(
   244 			'cb'          => '<input type="checkbox" />',
   260 			'cb'          => '<input type="checkbox" />',
   246 			'description' => __( 'Description' ),
   262 			'description' => __( 'Description' ),
   247 		);
   263 		);
   248 	}
   264 	}
   249 
   265 
   250 	/**
   266 	/**
   251 	 *
       
   252 	 * @return array
   267 	 * @return array
   253 	 */
   268 	 */
   254 	protected function get_sortable_columns() {
   269 	protected function get_sortable_columns() {
   255 		return array(
   270 		return array(
   256 			'name'         => 'name',
   271 			'name' => 'name',
   257 		);
   272 		);
   258 	}
   273 	}
   259 
   274 
   260 	/**
   275 	/**
   261 	 * Gets the name of the primary column.
   276 	 * Gets the name of the primary column.
   267 	protected function get_primary_column_name() {
   282 	protected function get_primary_column_name() {
   268 		return 'name';
   283 		return 'name';
   269 	}
   284 	}
   270 
   285 
   271 	/**
   286 	/**
   272 	 *
       
   273 	 * @global array $totals
   287 	 * @global array $totals
   274 	 * @global string $status
   288 	 * @global string $status
   275 	 * @return array
   289 	 * @return array
   276 	 */
   290 	 */
   277 	protected function get_views() {
   291 	protected function get_views() {
   278 		global $totals, $status;
   292 		global $totals, $status;
   279 
   293 
   280 		$status_links = array();
   294 		$status_links = array();
   281 		foreach ( $totals as $type => $count ) {
   295 		foreach ( $totals as $type => $count ) {
   282 			if ( !$count )
   296 			if ( ! $count ) {
   283 				continue;
   297 				continue;
       
   298 			}
   284 
   299 
   285 			switch ( $type ) {
   300 			switch ( $type ) {
   286 				case 'all':
   301 				case 'all':
   287 					$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'themes' );
   302 					$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'themes' );
   288 					break;
   303 					break;
   293 					$text = _n( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', $count );
   308 					$text = _n( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', $count );
   294 					break;
   309 					break;
   295 				case 'upgrade':
   310 				case 'upgrade':
   296 					$text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count );
   311 					$text = _n( 'Update Available <span class="count">(%s)</span>', 'Update Available <span class="count">(%s)</span>', $count );
   297 					break;
   312 					break;
   298 				case 'broken' :
   313 				case 'broken':
   299 					$text = _n( 'Broken <span class="count">(%s)</span>', 'Broken <span class="count">(%s)</span>', $count );
   314 					$text = _n( 'Broken <span class="count">(%s)</span>', 'Broken <span class="count">(%s)</span>', $count );
   300 					break;
   315 					break;
   301 			}
   316 			}
   302 
   317 
   303 			if ( $this->is_site_themes )
   318 			if ( $this->is_site_themes ) {
   304 				$url = 'site-themes.php?id=' . $this->site_id;
   319 				$url = 'site-themes.php?id=' . $this->site_id;
   305 			else
   320 			} else {
   306 				$url = 'themes.php';
   321 				$url = 'themes.php';
       
   322 			}
   307 
   323 
   308 			if ( 'search' != $type ) {
   324 			if ( 'search' != $type ) {
   309 				$status_links[$type] = sprintf( "<a href='%s'%s>%s</a>",
   325 				$status_links[ $type ] = sprintf(
   310 					esc_url( add_query_arg('theme_status', $type, $url) ),
   326 					"<a href='%s'%s>%s</a>",
       
   327 					esc_url( add_query_arg( 'theme_status', $type, $url ) ),
   311 					( $type === $status ) ? ' class="current" aria-current="page"' : '',
   328 					( $type === $status ) ? ' class="current" aria-current="page"' : '',
   312 					sprintf( $text, number_format_i18n( $count ) )
   329 					sprintf( $text, number_format_i18n( $count ) )
   313 				);
   330 				);
   314 			}
   331 			}
   315 		}
   332 		}
   324 	 */
   341 	 */
   325 	protected function get_bulk_actions() {
   342 	protected function get_bulk_actions() {
   326 		global $status;
   343 		global $status;
   327 
   344 
   328 		$actions = array();
   345 		$actions = array();
   329 		if ( 'enabled' != $status )
   346 		if ( 'enabled' != $status ) {
   330 			$actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' );
   347 			$actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' );
   331 		if ( 'disabled' != $status )
   348 		}
       
   349 		if ( 'disabled' != $status ) {
   332 			$actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' );
   350 			$actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' );
       
   351 		}
   333 		if ( ! $this->is_site_themes ) {
   352 		if ( ! $this->is_site_themes ) {
   334 			if ( current_user_can( 'update_themes' ) )
   353 			if ( current_user_can( 'update_themes' ) ) {
   335 				$actions['update-selected'] = __( 'Update' );
   354 				$actions['update-selected'] = __( 'Update' );
   336 			if ( current_user_can( 'delete_themes' ) )
   355 			}
       
   356 			if ( current_user_can( 'delete_themes' ) ) {
   337 				$actions['delete-selected'] = __( 'Delete' );
   357 				$actions['delete-selected'] = __( 'Delete' );
       
   358 			}
   338 		}
   359 		}
   339 		return $actions;
   360 		return $actions;
   340 	}
   361 	}
   341 
   362 
   342 	/**
   363 	/**
   343 	 */
   364 	 */
   344 	public function display_rows() {
   365 	public function display_rows() {
   345 		foreach ( $this->items as $theme )
   366 		foreach ( $this->items as $theme ) {
   346 			$this->single_row( $theme );
   367 			$this->single_row( $theme );
       
   368 		}
   347 	}
   369 	}
   348 
   370 
   349 	/**
   371 	/**
   350 	 * Handles the checkbox column output.
   372 	 * Handles the checkbox column output.
   351 	 *
   373 	 *
   352 	 * @since 4.3.0
   374 	 * @since 4.3.0
   353 	 *
   375 	 *
   354 	 * @param WP_Theme $theme The current WP_Theme object.
   376 	 * @param WP_Theme $theme The current WP_Theme object.
   355 	 */
   377 	 */
   356 	public function column_cb( $theme ) {
   378 	public function column_cb( $theme ) {
   357 		$checkbox_id = 'checkbox_' . md5( $theme->get('Name') );
   379 		$checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
   358 		?>
   380 		?>
   359 		<input type="checkbox" name="checked[]" value="<?php echo esc_attr( $theme->get_stylesheet() ) ?>" id="<?php echo $checkbox_id ?>" />
   381 		<input type="checkbox" name="checked[]" value="<?php echo esc_attr( $theme->get_stylesheet() ); ?>" id="<?php echo $checkbox_id; ?>" />
   360 		<label class="screen-reader-text" for="<?php echo $checkbox_id ?>" ><?php _e( 'Select' ) ?>  <?php echo $theme->display( 'Name' ) ?></label>
   382 		<label class="screen-reader-text" for="<?php echo $checkbox_id; ?>" ><?php _e( 'Select' ); ?>  <?php echo $theme->display( 'Name' ); ?></label>
   361 		<?php
   383 		<?php
   362 	}
   384 	}
   363 
   385 
   364 	/**
   386 	/**
   365 	 * Handles the name column output.
   387 	 * Handles the name column output.
   376 		global $status, $page, $s;
   398 		global $status, $page, $s;
   377 
   399 
   378 		$context = $status;
   400 		$context = $status;
   379 
   401 
   380 		if ( $this->is_site_themes ) {
   402 		if ( $this->is_site_themes ) {
   381 			$url = "site-themes.php?id={$this->site_id}&amp;";
   403 			$url     = "site-themes.php?id={$this->site_id}&amp;";
   382 			$allowed = $theme->is_allowed( 'site', $this->site_id );
   404 			$allowed = $theme->is_allowed( 'site', $this->site_id );
   383 		} else {
   405 		} else {
   384 			$url = 'themes.php?';
   406 			$url     = 'themes.php?';
   385 			$allowed = $theme->is_allowed( 'network' );
   407 			$allowed = $theme->is_allowed( 'network' );
   386 		}
   408 		}
   387 
   409 
   388 		// Pre-order.
   410 		// Pre-order.
   389 		$actions = array(
   411 		$actions = array(
   390 			'enable' => '',
   412 			'enable'  => '',
   391 			'disable' => '',
   413 			'disable' => '',
   392 			'delete' => ''
   414 			'delete'  => '',
   393 		);
   415 		);
   394 
   416 
   395 		$stylesheet = $theme->get_stylesheet();
   417 		$stylesheet = $theme->get_stylesheet();
   396 		$theme_key = urlencode( $stylesheet );
   418 		$theme_key  = urlencode( $stylesheet );
   397 
   419 
   398 		if ( ! $allowed ) {
   420 		if ( ! $allowed ) {
   399 			if ( ! $theme->errors() ) {
   421 			if ( ! $theme->errors() ) {
   400 				$url = add_query_arg( array(
   422 				$url = add_query_arg(
   401 					'action' => 'enable',
   423 					array(
   402 					'theme'  => $theme_key,
   424 						'action' => 'enable',
   403 					'paged'  => $page,
   425 						'theme'  => $theme_key,
   404 					's'      => $s,
   426 						'paged'  => $page,
   405 				), $url );
   427 						's'      => $s,
       
   428 					),
       
   429 					$url
       
   430 				);
   406 
   431 
   407 				if ( $this->is_site_themes ) {
   432 				if ( $this->is_site_themes ) {
   408 					/* translators: %s: theme name */
   433 					/* translators: %s: theme name */
   409 					$aria_label = sprintf( __( 'Enable %s' ), $theme->display( 'Name' ) );
   434 					$aria_label = sprintf( __( 'Enable %s' ), $theme->display( 'Name' ) );
   410 				} else {
   435 				} else {
   411 					/* translators: %s: theme name */
   436 					/* translators: %s: theme name */
   412 					$aria_label = sprintf( __( 'Network Enable %s' ), $theme->display( 'Name' ) );
   437 					$aria_label = sprintf( __( 'Network Enable %s' ), $theme->display( 'Name' ) );
   413 				}
   438 				}
   414 
   439 
   415 				$actions['enable'] = sprintf( '<a href="%s" class="edit" aria-label="%s">%s</a>',
   440 				$actions['enable'] = sprintf(
       
   441 					'<a href="%s" class="edit" aria-label="%s">%s</a>',
   416 					esc_url( wp_nonce_url( $url, 'enable-theme_' . $stylesheet ) ),
   442 					esc_url( wp_nonce_url( $url, 'enable-theme_' . $stylesheet ) ),
   417 					esc_attr( $aria_label ),
   443 					esc_attr( $aria_label ),
   418 					( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) )
   444 					( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) )
   419 				);
   445 				);
   420 			}
   446 			}
   421 		} else {
   447 		} else {
   422 			$url = add_query_arg( array(
   448 			$url = add_query_arg(
   423 				'action' => 'disable',
   449 				array(
   424 				'theme'  => $theme_key,
   450 					'action' => 'disable',
   425 				'paged'  => $page,
   451 					'theme'  => $theme_key,
   426 				's'      => $s,
   452 					'paged'  => $page,
   427 			), $url );
   453 					's'      => $s,
       
   454 				),
       
   455 				$url
       
   456 			);
   428 
   457 
   429 			if ( $this->is_site_themes ) {
   458 			if ( $this->is_site_themes ) {
   430 				/* translators: %s: theme name */
   459 				/* translators: %s: theme name */
   431 				$aria_label = sprintf( __( 'Disable %s' ), $theme->display( 'Name' ) );
   460 				$aria_label = sprintf( __( 'Disable %s' ), $theme->display( 'Name' ) );
   432 			} else {
   461 			} else {
   433 				/* translators: %s: theme name */
   462 				/* translators: %s: theme name */
   434 				$aria_label = sprintf( __( 'Network Disable %s' ), $theme->display( 'Name' ) );
   463 				$aria_label = sprintf( __( 'Network Disable %s' ), $theme->display( 'Name' ) );
   435 			}
   464 			}
   436 
   465 
   437 			$actions['disable'] = sprintf( '<a href="%s" aria-label="%s">%s</a>',
   466 			$actions['disable'] = sprintf(
       
   467 				'<a href="%s" aria-label="%s">%s</a>',
   438 				esc_url( wp_nonce_url( $url, 'disable-theme_' . $stylesheet ) ),
   468 				esc_url( wp_nonce_url( $url, 'disable-theme_' . $stylesheet ) ),
   439 				esc_attr( $aria_label ),
   469 				esc_attr( $aria_label ),
   440 				( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) )
   470 				( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) )
   441 			);
   471 			);
   442 		}
   472 		}
   443 
   473 
   444 		if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $stylesheet != get_option( 'stylesheet' ) && $stylesheet != get_option( 'template' ) ) {
   474 		if ( ! $allowed && current_user_can( 'delete_themes' ) && ! $this->is_site_themes && $stylesheet != get_option( 'stylesheet' ) && $stylesheet != get_option( 'template' ) ) {
   445 			$url = add_query_arg( array(
   475 			$url = add_query_arg(
   446 				'action'       => 'delete-selected',
   476 				array(
   447 				'checked[]'    => $theme_key,
   477 					'action'       => 'delete-selected',
   448 				'theme_status' => $context,
   478 					'checked[]'    => $theme_key,
   449 				'paged'        => $page,
   479 					'theme_status' => $context,
   450 				's'            => $s,
   480 					'paged'        => $page,
   451 			), 'themes.php' );
   481 					's'            => $s,
       
   482 				),
       
   483 				'themes.php'
       
   484 			);
   452 
   485 
   453 			/* translators: %s: theme name */
   486 			/* translators: %s: theme name */
   454 			$aria_label = sprintf( _x( 'Delete %s', 'theme' ), $theme->display( 'Name' ) );
   487 			$aria_label = sprintf( _x( 'Delete %s', 'theme' ), $theme->display( 'Name' ) );
   455 
   488 
   456 			$actions['delete'] = sprintf( '<a href="%s" class="delete" aria-label="%s">%s</a>',
   489 			$actions['delete'] = sprintf(
       
   490 				'<a href="%s" class="delete" aria-label="%s">%s</a>',
   457 				esc_url( wp_nonce_url( $url, 'bulk-themes' ) ),
   491 				esc_url( wp_nonce_url( $url, 'bulk-themes' ) ),
   458 				esc_attr( $aria_label ),
   492 				esc_attr( $aria_label ),
   459 				__( 'Delete' )
   493 				__( 'Delete' )
   460 			);
   494 			);
   461 		}
   495 		}
   475 		 * The default action links for the Site themes list table include
   509 		 * The default action links for the Site themes list table include
   476 		 * 'Enable', and 'Disable'.
   510 		 * 'Enable', and 'Disable'.
   477 		 *
   511 		 *
   478 		 * @since 2.8.0
   512 		 * @since 2.8.0
   479 		 *
   513 		 *
   480 		 * @param array    $actions An array of action links.
   514 		 * @param string[] $actions An array of action links.
   481 		 * @param WP_Theme $theme   The current WP_Theme object.
   515 		 * @param WP_Theme $theme   The current WP_Theme object.
   482 		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
   516 		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
   483 		 */
   517 		 */
   484 		$actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context );
   518 		$actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context );
   485 
   519 
   491 		 * directory name of the theme, which in most cases is synonymous
   525 		 * directory name of the theme, which in most cases is synonymous
   492 		 * with the template name.
   526 		 * with the template name.
   493 		 *
   527 		 *
   494 		 * @since 3.1.0
   528 		 * @since 3.1.0
   495 		 *
   529 		 *
   496 		 * @param array    $actions An array of action links.
   530 		 * @param string[] $actions An array of action links.
   497 		 * @param WP_Theme $theme   The current WP_Theme object.
   531 		 * @param WP_Theme $theme   The current WP_Theme object.
   498 		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
   532 		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
   499 		 */
   533 		 */
   500 		$actions = apply_filters( "theme_action_links_{$stylesheet}", $actions, $theme, $context );
   534 		$actions = apply_filters( "theme_action_links_{$stylesheet}", $actions, $theme, $context );
   501 
   535 
   524 		} else {
   558 		} else {
   525 			$allowed = $theme->is_allowed( 'network' );
   559 			$allowed = $theme->is_allowed( 'network' );
   526 		}
   560 		}
   527 
   561 
   528 		$class = ! $allowed ? 'inactive' : 'active';
   562 		$class = ! $allowed ? 'inactive' : 'active';
   529 		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) )
   563 		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
   530 			$class .= ' update';
   564 			$class .= ' update';
       
   565 		}
   531 
   566 
   532 		echo "<div class='theme-description'><p>" . $theme->display( 'Description' ) . "</p></div>
   567 		echo "<div class='theme-description'><p>" . $theme->display( 'Description' ) . "</p></div>
   533 			<div class='$class second theme-version-author-uri'>";
   568 			<div class='$class second theme-version-author-uri'>";
   534 
   569 
   535 		$stylesheet = $theme->get_stylesheet();
   570 		$stylesheet = $theme->get_stylesheet();
   536 		$theme_meta = array();
   571 		$theme_meta = array();
   537 
   572 
   538 		if ( $theme->get('Version') ) {
   573 		if ( $theme->get( 'Version' ) ) {
   539 			$theme_meta[] = sprintf( __( 'Version %s' ), $theme->display('Version') );
   574 			$theme_meta[] = sprintf( __( 'Version %s' ), $theme->display( 'Version' ) );
   540 		}
   575 		}
   541 		$theme_meta[] = sprintf( __( 'By %s' ), $theme->display('Author') );
   576 		$theme_meta[] = sprintf( __( 'By %s' ), $theme->display( 'Author' ) );
   542 
   577 
   543 		if ( $theme->get('ThemeURI') ) {
   578 		if ( $theme->get( 'ThemeURI' ) ) {
   544 			/* translators: %s: theme name */
   579 			/* translators: %s: theme name */
   545 			$aria_label = sprintf( __( 'Visit %s homepage' ), $theme->display( 'Name' ) );
   580 			$aria_label = sprintf( __( 'Visit %s homepage' ), $theme->display( 'Name' ) );
   546 
   581 
   547 			$theme_meta[] = sprintf( '<a href="%s" aria-label="%s">%s</a>',
   582 			$theme_meta[] = sprintf(
       
   583 				'<a href="%s" aria-label="%s">%s</a>',
   548 				$theme->display( 'ThemeURI' ),
   584 				$theme->display( 'ThemeURI' ),
   549 				esc_attr( $aria_label ),
   585 				esc_attr( $aria_label ),
   550 				__( 'Visit Theme Site' )
   586 				__( 'Visit Theme Site' )
   551 			);
   587 			);
   552 		}
   588 		}
   554 		 * Filters the array of row meta for each theme in the Multisite themes
   590 		 * Filters the array of row meta for each theme in the Multisite themes
   555 		 * list table.
   591 		 * list table.
   556 		 *
   592 		 *
   557 		 * @since 3.1.0
   593 		 * @since 3.1.0
   558 		 *
   594 		 *
   559 		 * @param array    $theme_meta An array of the theme's metadata,
   595 		 * @param string[] $theme_meta An array of the theme's metadata,
   560 		 *                             including the version, author, and
   596 		 *                             including the version, author, and
   561 		 *                             theme URI.
   597 		 *                             theme URI.
   562 		 * @param string   $stylesheet Directory name of the theme.
   598 		 * @param string   $stylesheet Directory name of the theme.
   563 		 * @param WP_Theme $theme      WP_Theme object.
   599 		 * @param WP_Theme $theme      WP_Theme object.
   564 		 * @param string   $status     Status of the theme.
   600 		 * @param string   $status     Status of the theme.
   616 
   652 
   617 					echo '</th>';
   653 					echo '</th>';
   618 					break;
   654 					break;
   619 
   655 
   620 				case 'name':
   656 				case 'name':
   621 
       
   622 					$active_theme_label = '';
   657 					$active_theme_label = '';
   623 
   658 
   624 					/* 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 */
   659 					/* 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 */
   625 					if ( ! empty( $this->site_id ) ) {
   660 					if ( ! empty( $this->site_id ) ) {
   626 						$stylesheet = get_blog_option( $this->site_id, 'stylesheet' );
   661 						$stylesheet = get_blog_option( $this->site_id, 'stylesheet' );
   630 						if ( $item->get_template() === $template ) {
   665 						if ( $item->get_template() === $template ) {
   631 							$active_theme_label = ' &mdash; ' . __( 'Active Theme' );
   666 							$active_theme_label = ' &mdash; ' . __( 'Active Theme' );
   632 						}
   667 						}
   633 
   668 
   634 						/* In case this is a child theme, label it properly */
   669 						/* In case this is a child theme, label it properly */
   635 						if ( $stylesheet !== $template && $item->get_stylesheet() === $stylesheet) {
   670 						if ( $stylesheet !== $template && $item->get_stylesheet() === $stylesheet ) {
   636 							$active_theme_label = ' &mdash; ' . __( 'Active Child Theme' );
   671 							$active_theme_label = ' &mdash; ' . __( 'Active Child Theme' );
   637 						}
   672 						}
   638 					}
   673 					}
   639 
   674 
   640 					echo "<td class='theme-title column-primary{$extra_classes}'><strong>" . $item->display( 'Name' ) . $active_theme_label . '</strong>';
   675 					echo "<td class='theme-title column-primary{$extra_classes}'><strong>" . $item->display( 'Name' ) . $active_theme_label . '</strong>';
   641 
   676 
   642 					$this->column_name( $item );
   677 					$this->column_name( $item );
   643 
   678 
   644 					echo "</td>";
   679 					echo '</td>';
   645 					break;
   680 					break;
   646 
   681 
   647 				case 'description':
   682 				case 'description':
   648 					echo "<td class='column-description desc{$extra_classes}'>";
   683 					echo "<td class='column-description desc{$extra_classes}'>";
   649 
   684 
   655 				default:
   690 				default:
   656 					echo "<td class='$column_name column-$column_name{$extra_classes}'>";
   691 					echo "<td class='$column_name column-$column_name{$extra_classes}'>";
   657 
   692 
   658 					$this->column_default( $item, $column_name );
   693 					$this->column_default( $item, $column_name );
   659 
   694 
   660 					echo "</td>";
   695 					echo '</td>';
   661 					break;
   696 					break;
   662 			}
   697 			}
   663 		}
   698 		}
   664 	}
   699 	}
   665 
   700 
   683 		$class = ! $allowed ? 'inactive' : 'active';
   718 		$class = ! $allowed ? 'inactive' : 'active';
   684 		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
   719 		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
   685 			$class .= ' update';
   720 			$class .= ' update';
   686 		}
   721 		}
   687 
   722 
   688 		printf( '<tr class="%s" data-slug="%s">',
   723 		printf(
       
   724 			'<tr class="%s" data-slug="%s">',
   689 			esc_attr( $class ),
   725 			esc_attr( $class ),
   690 			esc_attr( $stylesheet )
   726 			esc_attr( $stylesheet )
   691 		);
   727 		);
   692 
   728 
   693 		$this->single_row_columns( $theme );
   729 		$this->single_row_columns( $theme );
   694 
   730 
   695 		echo "</tr>";
   731 		echo '</tr>';
   696 
   732 
   697 		if ( $this->is_site_themes )
   733 		if ( $this->is_site_themes ) {
   698 			remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' );
   734 			remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' );
       
   735 		}
   699 
   736 
   700 		/**
   737 		/**
   701 		 * Fires after each row in the Multisite themes list table.
   738 		 * Fires after each row in the Multisite themes list table.
   702 		 *
   739 		 *
   703 		 * @since 3.1.0
   740 		 * @since 3.1.0