9 /** |
9 /** |
10 * Remove a theme |
10 * Remove a theme |
11 * |
11 * |
12 * @since 2.8.0 |
12 * @since 2.8.0 |
13 * |
13 * |
|
14 * @global WP_Filesystem_Base $wp_filesystem Subclass |
|
15 * |
14 * @param string $stylesheet Stylesheet of the theme to delete |
16 * @param string $stylesheet Stylesheet of the theme to delete |
15 * @param string $redirect Redirect to page when complete. |
17 * @param string $redirect Redirect to page when complete. |
16 * @return mixed |
18 * @return void|bool|WP_Error When void, echoes content. |
17 */ |
19 */ |
18 function delete_theme($stylesheet, $redirect = '') { |
20 function delete_theme($stylesheet, $redirect = '') { |
19 global $wp_filesystem; |
21 global $wp_filesystem; |
20 |
22 |
21 if ( empty($stylesheet) ) |
23 if ( empty($stylesheet) ) |
22 return false; |
24 return false; |
23 |
25 |
|
26 if ( empty( $redirect ) ) { |
|
27 $redirect = wp_nonce_url('themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet); |
|
28 } |
|
29 |
24 ob_start(); |
30 ob_start(); |
25 if ( empty( $redirect ) ) |
31 $credentials = request_filesystem_credentials( $redirect ); |
26 $redirect = wp_nonce_url('themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet); |
32 $data = ob_get_clean(); |
27 if ( false === ($credentials = request_filesystem_credentials($redirect)) ) { |
33 |
28 $data = ob_get_contents(); |
34 if ( false === $credentials ) { |
29 ob_end_clean(); |
35 if ( ! empty( $data ) ){ |
30 if ( ! empty($data) ){ |
|
31 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
36 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
32 echo $data; |
37 echo $data; |
33 include( ABSPATH . 'wp-admin/admin-footer.php'); |
38 include( ABSPATH . 'wp-admin/admin-footer.php'); |
34 exit; |
39 exit; |
35 } |
40 } |
36 return; |
41 return; |
37 } |
42 } |
38 |
43 |
39 if ( ! WP_Filesystem($credentials) ) { |
44 if ( ! WP_Filesystem( $credentials ) ) { |
40 request_filesystem_credentials($redirect, '', true); // Failed to connect, Error and request again |
45 ob_start(); |
41 $data = ob_get_contents(); |
46 request_filesystem_credentials( $redirect, '', true ); // Failed to connect, Error and request again. |
42 ob_end_clean(); |
47 $data = ob_get_clean(); |
|
48 |
43 if ( ! empty($data) ) { |
49 if ( ! empty($data) ) { |
44 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
50 include_once( ABSPATH . 'wp-admin/admin-header.php'); |
45 echo $data; |
51 echo $data; |
46 include( ABSPATH . 'wp-admin/admin-footer.php'); |
52 include( ABSPATH . 'wp-admin/admin-footer.php'); |
47 exit; |
53 exit; |
79 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.po' ); |
85 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.po' ); |
80 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.mo' ); |
86 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.mo' ); |
81 } |
87 } |
82 } |
88 } |
83 |
89 |
|
90 // Remove the theme from allowed themes on the network. |
|
91 if ( is_multisite() ) { |
|
92 WP_Theme::network_disable_theme( $stylesheet ); |
|
93 } |
|
94 |
84 // Force refresh of theme update information. |
95 // Force refresh of theme update information. |
85 delete_site_transient( 'update_themes' ); |
96 delete_site_transient( 'update_themes' ); |
86 |
97 |
87 return true; |
98 return true; |
88 } |
99 } |
89 |
100 |
90 /** |
101 /** |
91 * Get the Page Templates available in this theme |
102 * Get the Page Templates available in this theme |
92 * |
103 * |
93 * @since 1.5.0 |
104 * @since 1.5.0 |
94 * |
105 * @since 4.7.0 Added the `$post_type` parameter. |
95 * @param WP_Post|null $post Optional. The post being edited, provided for context. |
106 * |
|
107 * @param WP_Post|null $post Optional. The post being edited, provided for context. |
|
108 * @param string $post_type Optional. Post type to get the templates for. Default 'page'. |
96 * @return array Key is the template name, value is the filename of the template |
109 * @return array Key is the template name, value is the filename of the template |
97 */ |
110 */ |
98 function get_page_templates( $post = null ) { |
111 function get_page_templates( $post = null, $post_type = 'page' ) { |
99 return array_flip( wp_get_theme()->get_page_templates( $post ) ); |
112 return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) ); |
100 } |
113 } |
101 |
114 |
102 /** |
115 /** |
103 * Tidies a filename for url display by the theme editor. |
116 * Tidies a filename for url display by the theme editor. |
104 * |
117 * |
157 if ( isset($themes_update->response[ $stylesheet ]) ) { |
172 if ( isset($themes_update->response[ $stylesheet ]) ) { |
158 $update = $themes_update->response[ $stylesheet ]; |
173 $update = $themes_update->response[ $stylesheet ]; |
159 $theme_name = $theme->display('Name'); |
174 $theme_name = $theme->display('Name'); |
160 $details_url = add_query_arg(array('TB_iframe' => 'true', 'width' => 1024, 'height' => 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list. |
175 $details_url = add_query_arg(array('TB_iframe' => 'true', 'width' => 1024, 'height' => 800), $update['url']); //Theme browser inside WP? replace this, Also, theme preview JS will override this on the available list. |
161 $update_url = wp_nonce_url( admin_url( 'update.php?action=upgrade-theme&theme=' . urlencode( $stylesheet ) ), 'upgrade-theme_' . $stylesheet ); |
176 $update_url = wp_nonce_url( admin_url( 'update.php?action=upgrade-theme&theme=' . urlencode( $stylesheet ) ), 'upgrade-theme_' . $stylesheet ); |
162 $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __("Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.") ) . '\') ) {return true;}return false;"'; |
|
163 |
177 |
164 if ( !is_multisite() ) { |
178 if ( !is_multisite() ) { |
165 if ( ! current_user_can('update_themes') ) { |
179 if ( ! current_user_can('update_themes') ) { |
166 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a>.' ) . '</strong></p>', |
180 /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number */ |
167 $theme_name, esc_url( $details_url ), esc_attr( $theme['Name'] ), $update['new_version'] ); |
181 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ) . '</strong></p>', |
|
182 $theme_name, |
|
183 esc_url( $details_url ), |
|
184 sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', |
|
185 /* translators: 1: theme name, 2: version number */ |
|
186 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) |
|
187 ), |
|
188 $update['new_version'] |
|
189 ); |
168 } elseif ( empty( $update['package'] ) ) { |
190 } elseif ( empty( $update['package'] ) ) { |
169 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>', |
191 /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number */ |
170 $theme_name, esc_url( $details_url ), esc_attr( $theme['Name'] ), $update['new_version'] ); |
192 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>', |
|
193 $theme_name, |
|
194 esc_url( $details_url ), |
|
195 sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', |
|
196 /* translators: 1: theme name, 2: version number */ |
|
197 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) |
|
198 ), |
|
199 $update['new_version'] |
|
200 ); |
171 } else { |
201 } else { |
172 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" class="thickbox" title="%3$s">View version %4$s details</a> or <a href="%5$s">update now</a>.' ) . '</strong></p>', |
202 /* translators: 1: theme name, 2: theme details URL, 3: additional link attributes, 4: version number, 5: update URL, 6: additional link attributes */ |
173 $theme_name, esc_url( $details_url ), esc_attr( $theme['Name'] ), $update['new_version'], $update_url, $update_onclick ); |
203 $html = sprintf( '<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ) . '</strong></p>', |
|
204 $theme_name, |
|
205 esc_url( $details_url ), |
|
206 sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', |
|
207 /* translators: 1: theme name, 2: version number */ |
|
208 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) ) |
|
209 ), |
|
210 $update['new_version'], |
|
211 $update_url, |
|
212 sprintf( 'aria-label="%s" id="update-theme" data-slug="%s"', |
|
213 /* translators: %s: theme name */ |
|
214 esc_attr( sprintf( __( 'Update %s now' ), $theme_name ) ), |
|
215 $stylesheet |
|
216 ) |
|
217 ); |
174 } |
218 } |
175 } |
219 } |
176 } |
220 } |
177 |
221 |
178 return $html; |
222 return $html; |
181 /** |
225 /** |
182 * Retrieve list of WordPress theme features (aka theme tags) |
226 * Retrieve list of WordPress theme features (aka theme tags) |
183 * |
227 * |
184 * @since 3.1.0 |
228 * @since 3.1.0 |
185 * |
229 * |
186 * @param bool $api Optional. Whether try to fetch tags from the WP.org API. Defaults to true. |
230 * @param bool $api Optional. Whether try to fetch tags from the WordPress.org API. Defaults to true. |
187 * @return array Array of features keyed by category with translations keyed by slug. |
231 * @return array Array of features keyed by category with translations keyed by slug. |
188 */ |
232 */ |
189 function get_theme_feature_list( $api = true ) { |
233 function get_theme_feature_list( $api = true ) { |
190 // Hard-coded list is used if api not accessible. |
234 // Hard-coded list is used if api not accessible. |
191 $features = array( |
235 $features = array( |
192 __( 'Colors' ) => array( |
236 |
193 'black' => __( 'Black' ), |
237 __( 'Subject' ) => array( |
194 'blue' => __( 'Blue' ), |
238 'blog' => __( 'Blog' ), |
195 'brown' => __( 'Brown' ), |
239 'e-commerce' => __( 'E-Commerce' ), |
196 'gray' => __( 'Gray' ), |
240 'education' => __( 'Education' ), |
197 'green' => __( 'Green' ), |
241 'entertainment' => __( 'Entertainment' ), |
198 'orange' => __( 'Orange' ), |
242 'food-and-drink' => __( 'Food & Drink' ), |
199 'pink' => __( 'Pink' ), |
243 'holiday' => __( 'Holiday' ), |
200 'purple' => __( 'Purple' ), |
244 'news' => __( 'News' ), |
201 'red' => __( 'Red' ), |
245 'photography' => __( 'Photography' ), |
202 'silver' => __( 'Silver' ), |
246 'portfolio' => __( 'Portfolio' ), |
203 'tan' => __( 'Tan' ), |
247 ), |
204 'white' => __( 'White' ), |
248 |
205 'yellow' => __( 'Yellow' ), |
249 __( 'Features' ) => array( |
206 'dark' => __( 'Dark' ), |
250 'accessibility-ready' => __( 'Accessibility Ready' ), |
207 'light' => __( 'Light' ), |
251 'custom-background' => __( 'Custom Background' ), |
208 ), |
252 'custom-colors' => __( 'Custom Colors' ), |
|
253 'custom-header' => __( 'Custom Header' ), |
|
254 'custom-logo' => __( 'Custom Logo' ), |
|
255 'editor-style' => __( 'Editor Style' ), |
|
256 'featured-image-header' => __( 'Featured Image Header' ), |
|
257 'featured-images' => __( 'Featured Images' ), |
|
258 'footer-widgets' => __( 'Footer Widgets' ), |
|
259 'full-width-template' => __( 'Full Width Template' ), |
|
260 'post-formats' => __( 'Post Formats' ), |
|
261 'sticky-post' => __( 'Sticky Post' ), |
|
262 'theme-options' => __( 'Theme Options' ), |
|
263 ), |
209 |
264 |
210 __( 'Layout' ) => array( |
265 __( 'Layout' ) => array( |
211 'fixed-layout' => __( 'Fixed Layout' ), |
266 'grid-layout' => __( 'Grid Layout' ), |
212 'fluid-layout' => __( 'Fluid Layout' ), |
|
213 'responsive-layout' => __( 'Responsive Layout' ), |
|
214 'one-column' => __( 'One Column' ), |
267 'one-column' => __( 'One Column' ), |
215 'two-columns' => __( 'Two Columns' ), |
268 'two-columns' => __( 'Two Columns' ), |
216 'three-columns' => __( 'Three Columns' ), |
269 'three-columns' => __( 'Three Columns' ), |
217 'four-columns' => __( 'Four Columns' ), |
270 'four-columns' => __( 'Four Columns' ), |
218 'left-sidebar' => __( 'Left Sidebar' ), |
271 'left-sidebar' => __( 'Left Sidebar' ), |
219 'right-sidebar' => __( 'Right Sidebar' ), |
272 'right-sidebar' => __( 'Right Sidebar' ), |
220 ), |
|
221 |
|
222 __( 'Features' ) => array( |
|
223 'accessibility-ready' => __( 'Accessibility Ready' ), |
|
224 'blavatar' => __( 'Blavatar' ), |
|
225 'buddypress' => __( 'BuddyPress' ), |
|
226 'custom-background' => __( 'Custom Background' ), |
|
227 'custom-colors' => __( 'Custom Colors' ), |
|
228 'custom-header' => __( 'Custom Header' ), |
|
229 'custom-menu' => __( 'Custom Menu' ), |
|
230 'editor-style' => __( 'Editor Style' ), |
|
231 'featured-image-header' => __( 'Featured Image Header' ), |
|
232 'featured-images' => __( 'Featured Images' ), |
|
233 'flexible-header' => __( 'Flexible Header' ), |
|
234 'front-page-post-form' => __( 'Front Page Posting' ), |
|
235 'full-width-template' => __( 'Full Width Template' ), |
|
236 'microformats' => __( 'Microformats' ), |
|
237 'post-formats' => __( 'Post Formats' ), |
|
238 'rtl-language-support' => __( 'RTL Language Support' ), |
|
239 'sticky-post' => __( 'Sticky Post' ), |
|
240 'theme-options' => __( 'Theme Options' ), |
|
241 'threaded-comments' => __( 'Threaded Comments' ), |
|
242 'translation-ready' => __( 'Translation Ready' ), |
|
243 ), |
|
244 |
|
245 __( 'Subject' ) => array( |
|
246 'holiday' => __( 'Holiday' ), |
|
247 'photoblogging' => __( 'Photoblogging' ), |
|
248 'seasonal' => __( 'Seasonal' ), |
|
249 ) |
273 ) |
|
274 |
250 ); |
275 ); |
251 |
276 |
252 if ( ! $api || ! current_user_can( 'install_themes' ) ) |
277 if ( ! $api || ! current_user_can( 'install_themes' ) ) |
253 return $features; |
278 return $features; |
254 |
279 |
290 |
314 |
291 return $wporg_features; |
315 return $wporg_features; |
292 } |
316 } |
293 |
317 |
294 /** |
318 /** |
295 * Retrieve theme installer pages from WordPress Themes API. |
319 * Retrieves theme installer pages from the WordPress.org Themes API. |
296 * |
320 * |
297 * It is possible for a theme to override the Themes API result with three |
321 * It is possible for a theme to override the Themes API result with three |
298 * filters. Assume this is for themes, which can extend on the Theme Info to |
322 * filters. Assume this is for themes, which can extend on the Theme Info to |
299 * offer more choices. This is very powerful and must be used with care, when |
323 * offer more choices. This is very powerful and must be used with care, when |
300 * overriding the filters. |
324 * overriding the filters. |
301 * |
325 * |
302 * The first filter, 'themes_api_args', is for the args and gives the action as |
326 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action |
303 * the second parameter. The hook for 'themes_api_args' must ensure that an |
327 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that |
304 * object is returned. |
328 * an object is returned. |
305 * |
329 * |
306 * The second filter, 'themes_api', is the result that would be returned. |
330 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org |
|
331 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list', |
|
332 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed. |
|
333 * |
|
334 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the |
|
335 * response object or array, depending on the `$action` type. |
|
336 * |
|
337 * Supported arguments per action: |
|
338 * |
|
339 * | Argument Name | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list' | |
|
340 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: | |
|
341 * | `$slug` | No | Yes | No | No | |
|
342 * | `$per_page` | Yes | No | No | No | |
|
343 * | `$page` | Yes | No | No | No | |
|
344 * | `$number` | No | No | Yes | No | |
|
345 * | `$search` | Yes | No | No | No | |
|
346 * | `$tag` | Yes | No | No | No | |
|
347 * | `$author` | Yes | No | No | No | |
|
348 * | `$user` | Yes | No | No | No | |
|
349 * | `$browse` | Yes | No | No | No | |
|
350 * | `$locale` | Yes | Yes | No | No | |
|
351 * | `$fields` | Yes | Yes | No | No | |
307 * |
352 * |
308 * @since 2.8.0 |
353 * @since 2.8.0 |
309 * |
354 * |
310 * @param string $action The requested action. Likely values are 'theme_information', |
355 * @param string $action API action to perform: 'query_themes', 'theme_information', |
311 * 'feature_list', or 'query_themes'. |
356 * 'hot_tags' or 'feature_list'. |
312 * @param array|object $args Optional. Arguments to serialize for the Theme Info API. |
357 * @param array|object $args { |
313 * @return mixed |
358 * Optional. Array or object of arguments to serialize for the Themes API. |
314 */ |
359 * |
315 function themes_api( $action, $args = null ) { |
360 * @type string $slug The theme slug. Default empty. |
|
361 * @type int $per_page Number of themes per page. Default 24. |
|
362 * @type int $page Number of current page. Default 1. |
|
363 * @type int $number Number of tags to be queried. |
|
364 * @type string $search A search term. Default empty. |
|
365 * @type string $tag Tag to filter themes. Default empty. |
|
366 * @type string $author Username of an author to filter themes. Default empty. |
|
367 * @type string $user Username to query for their favorites. Default empty. |
|
368 * @type string $browse Browse view: 'featured', 'popular', 'updated', 'favorites'. |
|
369 * @type string $locale Locale to provide context-sensitive results. Default is the value of get_locale(). |
|
370 * @type array $fields { |
|
371 * Array of fields which should or should not be returned. |
|
372 * |
|
373 * @type bool $description Whether to return the theme full description. Default false. |
|
374 * @type bool $sections Whether to return the theme readme sections: description, installation, |
|
375 * FAQ, screenshots, other notes, and changelog. Default false. |
|
376 * @type bool $rating Whether to return the rating in percent and total number of ratings. |
|
377 * Default false. |
|
378 * @type bool $ratings Whether to return the number of rating for each star (1-5). Default false. |
|
379 * @type bool $downloaded Whether to return the download count. Default false. |
|
380 * @type bool $downloadlink Whether to return the download link for the package. Default false. |
|
381 * @type bool $last_updated Whether to return the date of the last update. Default false. |
|
382 * @type bool $tags Whether to return the assigned tags. Default false. |
|
383 * @type bool $homepage Whether to return the theme homepage link. Default false. |
|
384 * @type bool $screenshots Whether to return the screenshots. Default false. |
|
385 * @type int $screenshot_count Number of screenshots to return. Default 1. |
|
386 * @type bool $screenshot_url Whether to return the URL of the first screenshot. Default false. |
|
387 * @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false. |
|
388 * @type bool $template Whether to return the slug of the parent theme. Default false. |
|
389 * @type bool $parent Whether to return the slug, name and homepage of the parent theme. Default false. |
|
390 * @type bool $versions Whether to return the list of all available versions. Default false. |
|
391 * @type bool $theme_url Whether to return theme's URL. Default false. |
|
392 * @type bool $extended_author Whether to return nicename or nicename and display name. Default false. |
|
393 * } |
|
394 * } |
|
395 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the |
|
396 * {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article} |
|
397 * for more information on the make-up of possible return objects depending on the value of `$action`. |
|
398 */ |
|
399 function themes_api( $action, $args = array() ) { |
316 |
400 |
317 if ( is_array( $args ) ) { |
401 if ( is_array( $args ) ) { |
318 $args = (object) $args; |
402 $args = (object) $args; |
319 } |
403 } |
320 |
404 |
321 if ( ! isset( $args->per_page ) ) { |
405 if ( ! isset( $args->per_page ) ) { |
322 $args->per_page = 24; |
406 $args->per_page = 24; |
323 } |
407 } |
324 |
408 |
325 if ( ! isset( $args->locale ) ) { |
409 if ( ! isset( $args->locale ) ) { |
326 $args->locale = get_locale(); |
410 $args->locale = get_user_locale(); |
327 } |
411 } |
328 |
412 |
329 /** |
413 /** |
330 * Filter arguments used to query for installer pages from the WordPress.org Themes API. |
414 * Filters arguments used to query for installer pages from the WordPress.org Themes API. |
331 * |
415 * |
332 * Important: An object MUST be returned to this filter. |
416 * Important: An object MUST be returned to this filter. |
333 * |
417 * |
334 * @since 2.8.0 |
418 * @since 2.8.0 |
335 * |
419 * |
338 * 'feature_list', or 'query_themes'. |
422 * 'feature_list', or 'query_themes'. |
339 */ |
423 */ |
340 $args = apply_filters( 'themes_api_args', $args, $action ); |
424 $args = apply_filters( 'themes_api_args', $args, $action ); |
341 |
425 |
342 /** |
426 /** |
343 * Filter whether to override the WordPress.org Themes API. |
427 * Filters whether to override the WordPress.org Themes API. |
344 * |
428 * |
345 * Returning a value of true to this filter allows a theme to completely |
429 * Passing a non-false value will effectively short-circuit the WordPress.org API request. |
346 * override the built-in WordPress.org API. |
430 * |
|
431 * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST |
|
432 * be passed. If `$action` is 'hot_tags', an array should be passed. |
347 * |
433 * |
348 * @since 2.8.0 |
434 * @since 2.8.0 |
349 * |
435 * |
350 * @param bool $bool Whether to override the WordPress.org Themes API. Default false. |
436 * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false. |
351 * @param string $action Requested action. Likely values are 'theme_information', |
437 * @param string $action Requested action. Likely values are 'theme_information', |
352 * 'feature_list', or 'query_themes'. |
438 * 'feature_list', or 'query_themes'. |
353 * @param object $args Arguments used to query for installer pages from the Themes API. |
439 * @param object $args Arguments used to query for installer pages from the Themes API. |
354 */ |
440 */ |
355 $res = apply_filters( 'themes_api', false, $action, $args ); |
441 $res = apply_filters( 'themes_api', false, $action, $args ); |
356 |
442 |
357 if ( ! $res ) { |
443 if ( ! $res ) { |
|
444 // include an unmodified $wp_version |
|
445 include( ABSPATH . WPINC . '/version.php' ); |
|
446 |
358 $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/'; |
447 $url = $http_url = 'http://api.wordpress.org/themes/info/1.0/'; |
359 if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) |
448 if ( $ssl = wp_http_supports( array( 'ssl' ) ) ) |
360 $url = set_url_scheme( $url, 'https' ); |
449 $url = set_url_scheme( $url, 'https' ); |
361 |
450 |
362 $http_args = array( |
451 $http_args = array( |
|
452 'user-agent' => 'WordPress/' . $wp_version . '; ' . home_url( '/' ), |
363 'body' => array( |
453 'body' => array( |
364 'action' => $action, |
454 'action' => $action, |
365 'request' => serialize( $args ) |
455 'request' => serialize( $args ) |
366 ) |
456 ) |
367 ); |
457 ); |
368 $request = wp_remote_post( $url, $http_args ); |
458 $request = wp_remote_post( $url, $http_args ); |
369 |
459 |
370 if ( $ssl && is_wp_error( $request ) ) { |
460 if ( $ssl && is_wp_error( $request ) ) { |
371 if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { |
461 if ( ! wp_doing_ajax() ) { |
372 trigger_error( __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE ); |
462 trigger_error( |
|
463 sprintf( |
|
464 /* translators: %s: support forums URL */ |
|
465 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ), |
|
466 __( 'https://wordpress.org/support/' ) |
|
467 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ), |
|
468 headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE |
|
469 ); |
373 } |
470 } |
374 $request = wp_remote_post( $http_url, $http_args ); |
471 $request = wp_remote_post( $http_url, $http_args ); |
375 } |
472 } |
376 |
473 |
377 if ( is_wp_error($request) ) { |
474 if ( is_wp_error($request) ) { |
378 $res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ), $request->get_error_message() ); |
475 $res = new WP_Error( 'themes_api_failed', |
|
476 sprintf( |
|
477 /* translators: %s: support forums URL */ |
|
478 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ), |
|
479 __( 'https://wordpress.org/support/' ) |
|
480 ), |
|
481 $request->get_error_message() |
|
482 ); |
379 } else { |
483 } else { |
380 $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); |
484 $res = maybe_unserialize( wp_remote_retrieve_body( $request ) ); |
381 if ( ! is_object( $res ) && ! is_array( $res ) ) |
485 if ( ! is_object( $res ) && ! is_array( $res ) ) { |
382 $res = new WP_Error('themes_api_failed', __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="https://wordpress.org/support/">support forums</a>.' ), wp_remote_retrieve_body( $request ) ); |
486 $res = new WP_Error( 'themes_api_failed', |
|
487 sprintf( |
|
488 /* translators: %s: support forums URL */ |
|
489 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ), |
|
490 __( 'https://wordpress.org/support/' ) |
|
491 ), |
|
492 wp_remote_retrieve_body( $request ) |
|
493 ); |
|
494 } |
383 } |
495 } |
384 } |
496 } |
385 |
497 |
386 /** |
498 /** |
387 * Filter the returned WordPress.org Themes API response. |
499 * Filters the returned WordPress.org Themes API response. |
388 * |
500 * |
389 * @since 2.8.0 |
501 * @since 2.8.0 |
390 * |
502 * |
391 * @param array|object $res WordPress.org Themes API response. |
503 * @param array|object|WP_Error $res WordPress.org Themes API response. |
392 * @param string $action Requested action. Likely values are 'theme_information', |
504 * @param string $action Requested action. Likely values are 'theme_information', |
393 * 'feature_list', or 'query_themes'. |
505 * 'feature_list', or 'query_themes'. |
394 * @param object $args Arguments used to query for installer pages from the WordPress.org Themes API. |
506 * @param object $args Arguments used to query for installer pages from the WordPress.org Themes API. |
395 */ |
507 */ |
396 return apply_filters( 'themes_api_result', $res, $action, $args ); |
508 return apply_filters( 'themes_api_result', $res, $action, $args ); |
397 } |
509 } |
398 |
510 |
399 /** |
511 /** |
469 'version' => $theme->display( 'Version' ), |
592 'version' => $theme->display( 'Version' ), |
470 'tags' => $theme->display( 'Tags' ), |
593 'tags' => $theme->display( 'Tags' ), |
471 'parent' => $parent, |
594 'parent' => $parent, |
472 'active' => $slug === $current_theme, |
595 'active' => $slug === $current_theme, |
473 'hasUpdate' => isset( $updates[ $slug ] ), |
596 'hasUpdate' => isset( $updates[ $slug ] ), |
|
597 'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ][ 'package' ] ), |
474 'update' => get_theme_update_available( $theme ), |
598 'update' => get_theme_update_available( $theme ), |
475 'actions' => array( |
599 'actions' => array( |
476 'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null, |
600 'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null, |
477 'customize' => ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) ? wp_customize_url( $slug ) : null, |
601 'customize' => $customize_action, |
478 'preview' => add_query_arg( array( |
|
479 'preview' => 1, |
|
480 'template' => urlencode( $theme->get_template() ), |
|
481 'stylesheet' => urlencode( $slug ), |
|
482 'preview_iframe' => true, |
|
483 'TB_iframe' => true, |
|
484 ), home_url( '/' ) ), |
|
485 'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null, |
602 'delete' => current_user_can( 'delete_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null, |
486 ), |
603 ), |
487 ); |
604 ); |
488 } |
605 } |
489 |
606 |
510 * Print JS templates for the theme-browsing UI in the Customizer. |
627 * Print JS templates for the theme-browsing UI in the Customizer. |
511 * |
628 * |
512 * @since 4.2.0 |
629 * @since 4.2.0 |
513 */ |
630 */ |
514 function customize_themes_print_templates() { |
631 function customize_themes_print_templates() { |
515 $preview_url = esc_url( add_query_arg( 'theme', '__THEME__' ) ); // Token because esc_url() strips curly braces. |
|
516 $preview_url = str_replace( '__THEME__', '{{ data.id }}', $preview_url ); |
|
517 ?> |
632 ?> |
518 <script type="text/html" id="tmpl-customize-themes-details-view"> |
633 <script type="text/html" id="tmpl-customize-themes-details-view"> |
519 <div class="theme-backdrop"></div> |
634 <div class="theme-backdrop"></div> |
520 <div class="theme-wrap"> |
635 <div class="theme-wrap wp-clearfix" role="document"> |
521 <div class="theme-header"> |
636 <div class="theme-header"> |
522 <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button> |
637 <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show previous theme' ); ?></span></button> |
523 <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button> |
638 <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Show next theme' ); ?></span></button> |
524 <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button> |
639 <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text"><?php _e( 'Close details dialog' ); ?></span></button> |
525 </div> |
640 </div> |
526 <div class="theme-about"> |
641 <div class="theme-about wp-clearfix"> |
527 <div class="theme-screenshots"> |
642 <div class="theme-screenshots"> |
528 <# if ( data.screenshot[0] ) { #> |
643 <# if ( data.screenshot && data.screenshot[0] ) { #> |
529 <div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div> |
644 <div class="screenshot"><img src="{{ data.screenshot[0] }}" alt="" /></div> |
530 <# } else { #> |
645 <# } else { #> |
531 <div class="screenshot blank"></div> |
646 <div class="screenshot blank"></div> |
532 <# } #> |
647 <# } #> |
533 </div> |
648 </div> |
534 |
649 |
535 <div class="theme-info"> |
650 <div class="theme-info"> |
536 <# if ( data.active ) { #> |
651 <# if ( data.active ) { #> |
537 <span class="current-label"><?php _e( 'Current Theme' ); ?></span> |
652 <span class="current-label"><?php _e( 'Current Theme' ); ?></span> |
538 <# } #> |
653 <# } #> |
539 <h3 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h3> |
654 <h2 class="theme-name">{{{ data.name }}}<span class="theme-version"><?php printf( __( 'Version: %s' ), '{{ data.version }}' ); ?></span></h2> |
540 <h4 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h4> |
655 <h3 class="theme-author"><?php printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' ); ?></h3> |
541 <p class="theme-description">{{{ data.description }}}</p> |
656 |
|
657 <# if ( data.stars && 0 != data.num_ratings ) { #> |
|
658 <div class="theme-rating"> |
|
659 {{{ data.stars }}} |
|
660 <span class="num-ratings"> |
|
661 <?php |
|
662 /* translators: %s: number of ratings */ |
|
663 echo sprintf( __( '(%s ratings)' ), '{{ data.num_ratings }}' ); |
|
664 ?> |
|
665 </span> |
|
666 </div> |
|
667 <# } #> |
|
668 |
|
669 <# if ( data.hasUpdate ) { #> |
|
670 <div class="notice notice-warning notice-alt notice-large" data-slug="{{ data.id }}"> |
|
671 <h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3> |
|
672 {{{ data.update }}} |
|
673 </div> |
|
674 <# } #> |
542 |
675 |
543 <# if ( data.parent ) { #> |
676 <# if ( data.parent ) { #> |
544 <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p> |
677 <p class="parent-theme"><?php printf( __( 'This is a child theme of %s.' ), '<strong>{{{ data.parent }}}</strong>' ); ?></p> |
545 <# } #> |
678 <# } #> |
546 |
679 |
|
680 <p class="theme-description">{{{ data.description }}}</p> |
|
681 |
547 <# if ( data.tags ) { #> |
682 <# if ( data.tags ) { #> |
548 <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{ data.tags }}</p> |
683 <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{{ data.tags }}}</p> |
549 <# } #> |
684 <# } #> |
550 </div> |
685 </div> |
551 </div> |
686 </div> |
552 |
687 |
553 <# if ( ! data.active ) { #> |
688 <div class="theme-actions"> |
554 <div class="theme-actions"> |
689 <# if ( data.active ) { #> |
555 <div class="inactive-theme"> |
690 <button type="button" class="button button-primary customize-theme"><?php _e( 'Customize' ); ?></button> |
556 <a href="<?php echo $preview_url; ?>" target="_top" class="button button-primary"><?php _e( 'Live Preview' ); ?></a> |
691 <# } else if ( 'installed' === data.type ) { #> |
557 </div> |
692 <?php if ( current_user_can( 'delete_themes' ) ) { ?> |
558 </div> |
693 <# if ( data.actions && data.actions['delete'] ) { #> |
559 <# } #> |
694 <a href="{{{ data.actions['delete'] }}}" data-slug="{{ data.id }}" class="button button-secondary delete-theme"><?php _e( 'Delete' ); ?></a> |
|
695 <# } #> |
|
696 <?php } ?> |
|
697 <button type="button" class="button button-primary preview-theme" data-slug="{{ data.id }}"><?php _e( 'Live Preview' ); ?></button> |
|
698 <# } else { #> |
|
699 <button type="button" class="button theme-install" data-slug="{{ data.id }}"><?php _e( 'Install' ); ?></button> |
|
700 <button type="button" class="button button-primary theme-install preview" data-slug="{{ data.id }}"><?php _e( 'Install & Preview' ); ?></button> |
|
701 <# } #> |
|
702 </div> |
560 </div> |
703 </div> |
561 </script> |
704 </script> |
562 <?php |
705 <?php |
563 } |
706 } |
564 add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' ); |
|