/wp-admin/includes/class-wp-themes-list-table.php

  1. <?php 
  2. /** 
  3. * List Table API: WP_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 installed themes in a list table. 
  12. * 
  13. * @since 3.1.0 
  14. * @access private 
  15. * 
  16. * @see WP_List_Table 
  17. */ 
  18. class WP_Themes_List_Table extends WP_List_Table { 
  19.  
  20. protected $search_terms = array(); 
  21. public $features = array(); 
  22.  
  23. /** 
  24. * Constructor. 
  25. * 
  26. * @since 3.1.0 
  27. * @access public 
  28. * 
  29. * @see WP_List_Table::__construct() for more information on default arguments. 
  30. * 
  31. * @param array $args An associative array of arguments. 
  32. */ 
  33. public function __construct( $args = array() ) { 
  34. parent::__construct( array( 
  35. 'ajax' => true,  
  36. 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,  
  37. ) ); 
  38.  
  39. /** 
  40. * 
  41. * @return bool 
  42. */ 
  43. public function ajax_user_can() { 
  44. // Do not check edit_theme_options here. Ajax calls for available themes require switch_themes. 
  45. return current_user_can( 'switch_themes' ); 
  46.  
  47. /** 
  48. * @access public 
  49. */ 
  50. public function prepare_items() { 
  51. $themes = wp_get_themes( array( 'allowed' => true ) ); 
  52.  
  53. if ( ! empty( $_REQUEST['s'] ) ) 
  54. $this->search_terms = array_unique( array_filter( array_map( 'trim', explode( ', ', strtolower( wp_unslash( $_REQUEST['s'] ) ) ) ) ) ); 
  55.  
  56. if ( ! empty( $_REQUEST['features'] ) ) 
  57. $this->features = $_REQUEST['features']; 
  58.  
  59. if ( $this->search_terms || $this->features ) { 
  60. foreach ( $themes as $key => $theme ) { 
  61. if ( ! $this->search_theme( $theme ) ) 
  62. unset( $themes[ $key ] ); 
  63.  
  64. unset( $themes[ get_option( 'stylesheet' ) ] ); 
  65. WP_Theme::sort_by_name( $themes ); 
  66.  
  67. $per_page = 36; 
  68. $page = $this->get_pagenum(); 
  69.  
  70. $start = ( $page - 1 ) * $per_page; 
  71.  
  72. $this->items = array_slice( $themes, $start, $per_page, true ); 
  73.  
  74. $this->set_pagination_args( array( 
  75. 'total_items' => count( $themes ),  
  76. 'per_page' => $per_page,  
  77. 'infinite_scroll' => true,  
  78. ) ); 
  79.  
  80. /** 
  81. * @access public 
  82. */ 
  83. public function no_items() { 
  84. if ( $this->search_terms || $this->features ) { 
  85. _e( 'No items found.' ); 
  86. return; 
  87.  
  88. $blog_id = get_current_blog_id(); 
  89. if ( is_multisite() ) { 
  90. if ( current_user_can( 'install_themes' ) && current_user_can( 'manage_network_themes' ) ) { 
  91. printf( __( 'You only have one theme enabled for this site right now. Visit the Network Admin to <a href="%1$s">enable</a> or <a href="%2$s">install</a> more themes.' ), network_admin_url( 'site-themes.php?id=' . $blog_id ), network_admin_url( 'theme-install.php' ) ); 
  92.  
  93. return; 
  94. } elseif ( current_user_can( 'manage_network_themes' ) ) { 
  95. printf( __( 'You only have one theme enabled for this site right now. Visit the Network Admin to <a href="%1$s">enable</a> more themes.' ), network_admin_url( 'site-themes.php?id=' . $blog_id ) ); 
  96.  
  97. return; 
  98. // Else, fallthrough. install_themes doesn't help if you can't enable it. 
  99. } else { 
  100. if ( current_user_can( 'install_themes' ) ) { 
  101. printf( __( 'You only have one theme installed right now. Live a little! You can choose from over 1, 000 free themes in the WordPress Theme Directory at any time: just click on the <a href="%s">Install Themes</a> tab above.' ), admin_url( 'theme-install.php' ) ); 
  102.  
  103. return; 
  104. // Fallthrough. 
  105. printf( __( 'Only the current theme is available to you. Contact the %s administrator for information about accessing additional themes.' ), get_site_option( 'site_name' ) ); 
  106.  
  107. /** 
  108. * @param string $which 
  109. */ 
  110. public function tablenav( $which = 'top' ) { 
  111. if ( $this->get_pagination_arg( 'total_pages' ) <= 1 ) 
  112. return; 
  113. ?> 
  114. <div class="tablenav themes <?php echo $which; ?>"> 
  115. <?php $this->pagination( $which ); ?> 
  116. <span class="spinner"></span> 
  117. <br class="clear" /> 
  118. </div> 
  119. <?php 
  120.  
  121. /** 
  122. * @access public 
  123. */ 
  124. public function display() { 
  125. wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); 
  126. ?> 
  127. <?php $this->tablenav( 'top' ); ?> 
  128.  
  129. <div id="availablethemes"> 
  130. <?php $this->display_rows_or_placeholder(); ?> 
  131. </div> 
  132.  
  133. <?php $this->tablenav( 'bottom' ); ?> 
  134. <?php 
  135.  
  136. /** 
  137. * 
  138. * @return array 
  139. */ 
  140. public function get_columns() { 
  141. return array(); 
  142.  
  143. /** 
  144. * @access public 
  145. */ 
  146. public function display_rows_or_placeholder() { 
  147. if ( $this->has_items() ) { 
  148. $this->display_rows(); 
  149. } else { 
  150. echo '<div class="no-items">'; 
  151. $this->no_items(); 
  152. echo '</div>'; 
  153.  
  154. /** 
  155. * @access public 
  156. */ 
  157. public function display_rows() { 
  158. $themes = $this->items; 
  159.  
  160. foreach ( $themes as $theme ): 
  161. ?><div class="available-theme"><?php 
  162.  
  163. $template = $theme->get_template(); 
  164. $stylesheet = $theme->get_stylesheet(); 
  165. $title = $theme->display('Name'); 
  166. $version = $theme->display('Version'); 
  167. $author = $theme->display('Author'); 
  168.  
  169. $activate_link = wp_nonce_url( "themes.php?action=activate&template=" . urlencode( $template ) . "&stylesheet=" . urlencode( $stylesheet ), 'switch-theme_' . $stylesheet ); 
  170.  
  171. $actions = array(); 
  172. $actions['activate'] = '<a href="' . $activate_link . '" class="activatelink" title="' 
  173. . esc_attr( sprintf( __( 'Activate “%s”' ), $title ) ) . '">' . __( 'Activate' ) . '</a>'; 
  174.  
  175. if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { 
  176. $actions['preview'] .= '<a href="' . wp_customize_url( $stylesheet ) . '" class="load-customize hide-if-no-customize">' 
  177. . __( 'Live Preview' ) . '</a>'; 
  178.  
  179. if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) 
  180. $actions['delete'] = '<a class="submitdelete deletion" href="' . wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet ) 
  181. . '" onclick="' . "return confirm( '" . esc_js( sprintf( __( "You are about to delete this theme '%s'\n 'Cancel' to stop, 'OK' to delete." ), $title ) ) 
  182. . "' );" . '">' . __( 'Delete' ) . '</a>'; 
  183.  
  184. /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ 
  185. $actions = apply_filters( 'theme_action_links', $actions, $theme ); 
  186.  
  187. /** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */ 
  188. $actions = apply_filters( "theme_action_links_$stylesheet", $actions, $theme ); 
  189. $delete_action = isset( $actions['delete'] ) ? '<div class="delete-theme">' . $actions['delete'] . '</div>' : ''; 
  190. unset( $actions['delete'] ); 
  191.  
  192. ?> 
  193.  
  194. <span class="screenshot hide-if-customize"> 
  195. <?php if ( $screenshot = $theme->get_screenshot() ) : ?> 
  196. <img src="<?php echo esc_url( $screenshot ); ?>" alt="" /> 
  197. <?php endif; ?> 
  198. </span> 
  199. <a href="<?php echo wp_customize_url( $stylesheet ); ?>" class="screenshot load-customize hide-if-no-customize"> 
  200. <?php if ( $screenshot = $theme->get_screenshot() ) : ?> 
  201. <img src="<?php echo esc_url( $screenshot ); ?>" alt="" /> 
  202. <?php endif; ?> 
  203. </a> 
  204.  
  205. <h3><?php echo $title; ?></h3> 
  206. <div class="theme-author"><?php printf( __( 'By %s' ), $author ); ?></div> 
  207. <div class="action-links"> 
  208. <ul> 
  209. <?php foreach ( $actions as $action ): ?> 
  210. <li><?php echo $action; ?></li> 
  211. <?php endforeach; ?> 
  212. <li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e('Details') ?></a></li> 
  213. </ul> 
  214. <?php echo $delete_action; ?> 
  215.  
  216. <?php theme_update_available( $theme ); ?> 
  217. </div> 
  218.  
  219. <div class="themedetaildiv hide-if-js"> 
  220. <p><strong><?php _e('Version:'); ?></strong> <?php echo $version; ?></p> 
  221. <p><?php echo $theme->display('Description'); ?></p> 
  222. <?php if ( $theme->parent() ) { 
  223. printf( ' <p class="howto">' . __( 'This <a href="%1$s">child theme</a> requires its parent theme, %2$s.' ) . '</p>',  
  224. __( 'https://codex.wordpress.org/Child_Themes' ),  
  225. $theme->parent()->display( 'Name' ) ); 
  226. } ?> 
  227. </div> 
  228.  
  229. </div> 
  230. <?php 
  231. endforeach; 
  232.  
  233. /** 
  234. * @param WP_Theme $theme 
  235. * @return bool 
  236. */ 
  237. public function search_theme( $theme ) { 
  238. // Search the features 
  239. foreach ( $this->features as $word ) { 
  240. if ( ! in_array( $word, $theme->get('Tags') ) ) 
  241. return false; 
  242.  
  243. // Match all phrases 
  244. foreach ( $this->search_terms as $word ) { 
  245. if ( in_array( $word, $theme->get('Tags') ) ) 
  246. continue; 
  247.  
  248. foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) { 
  249. // Don't mark up; Do translate. 
  250. if ( false !== stripos( strip_tags( $theme->display( $header, false, true ) ), $word ) ) { 
  251. continue 2; 
  252.  
  253. if ( false !== stripos( $theme->get_stylesheet(), $word ) ) 
  254. continue; 
  255.  
  256. if ( false !== stripos( $theme->get_template(), $word ) ) 
  257. continue; 
  258.  
  259. return false; 
  260.  
  261. return true; 
  262.  
  263. /** 
  264. * Send required variables to JavaScript land 
  265. * 
  266. * @since 3.4.0 
  267. * @access public 
  268. * 
  269. * @param array $extra_args 
  270. */ 
  271. public function _js_vars( $extra_args = array() ) { 
  272. $search_string = isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : ''; 
  273.  
  274. $args = array( 
  275. 'search' => $search_string,  
  276. 'features' => $this->features,  
  277. 'paged' => $this->get_pagenum(),  
  278. 'total_pages' => ! empty( $this->_pagination_args['total_pages'] ) ? $this->_pagination_args['total_pages'] : 1,  
  279. ); 
  280.  
  281. if ( is_array( $extra_args ) ) 
  282. $args = array_merge( $args, $extra_args ); 
  283.  
  284. printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", wp_json_encode( $args ) ); 
  285. parent::_js_vars(); 
.