run:R W Run
7.85 KB
2026-03-11 16:18:51
R W Run
3.54 KB
2026-03-11 16:18:51
R W Run
148.33 KB
2026-03-11 16:18:51
R W Run
11.45 KB
2026-03-11 16:18:51
R W Run
3.58 KB
2026-03-11 16:18:51
R W Run
2.53 KB
2026-03-11 16:18:51
R W Run
2.6 KB
2026-03-11 16:18:51
R W Run
6.59 KB
2026-03-11 16:18:51
R W Run
14.83 KB
2026-03-11 16:18:51
R W Run
21.18 KB
2026-03-11 16:18:51
R W Run
48.13 KB
2026-03-11 16:18:51
R W Run
4.07 KB
2026-03-11 16:18:51
R W Run
5.3 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
26.73 KB
2026-03-11 16:18:51
R W Run
2.8 KB
2026-03-11 16:18:51
R W Run
15.2 KB
2026-03-11 16:18:51
R W Run
192.08 KB
2026-03-11 16:18:51
R W Run
11.77 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
22.89 KB
2026-03-11 16:18:51
R W Run
12.77 KB
2026-03-11 16:18:51
R W Run
4.08 KB
2026-03-11 16:18:51
R W Run
26.27 KB
2026-03-11 16:18:51
R W Run
4.97 KB
2026-03-11 16:18:51
R W Run
5.57 KB
2026-03-11 16:18:51
R W Run
13.93 KB
2026-03-11 16:18:51
R W Run
4.09 KB
2026-03-11 16:18:51
R W Run
6.79 KB
2026-03-11 16:18:51
R W Run
60.45 KB
2026-03-11 16:18:51
R W Run
32.4 KB
2026-03-11 16:18:51
R W Run
18.24 KB
2026-03-11 16:18:51
R W Run
66.01 KB
2026-03-11 16:18:51
R W Run
23.84 KB
2026-03-11 16:18:51
R W Run
17.72 KB
2026-03-11 16:18:51
R W Run
22.71 KB
2026-03-11 16:18:51
R W Run
18.05 KB
2026-03-11 16:18:51
R W Run
22.76 KB
2026-03-11 16:18:51
R W Run
7.34 KB
2026-03-11 16:18:51
R W Run
4.51 KB
2026-03-11 16:18:51
R W Run
9.02 KB
2026-03-11 16:18:51
R W Run
1.46 KB
2026-03-11 16:18:51
R W Run
51.76 KB
2026-03-11 16:18:51
R W Run
25.29 KB
2026-03-11 16:18:51
R W Run
21.61 KB
2026-03-11 16:18:51
R W Run
27.77 KB
2026-03-11 16:18:51
R W Run
15.35 KB
2026-03-11 16:18:51
R W Run
24.54 KB
2026-03-11 16:18:51
R W Run
56.44 KB
2026-03-11 16:18:51
R W Run
1.42 KB
2026-03-11 16:18:51
R W Run
63.66 KB
2026-03-11 16:18:51
R W Run
31.9 KB
2026-03-11 16:18:51
R W Run
14.44 KB
2026-03-11 16:18:51
R W Run
36.47 KB
2026-03-11 16:18:51
R W Run
14 KB
2026-03-11 16:18:51
R W Run
121.89 KB
2026-03-11 16:18:51
R W Run
6.26 KB
2026-03-11 16:18:51
R W Run
20.73 KB
2026-03-11 16:18:51
R W Run
15.23 KB
2026-03-11 16:18:51
R W Run
10.14 KB
2026-03-11 16:18:51
R W Run
6.94 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
46.85 KB
2026-03-11 16:18:51
R W Run
18.61 KB
2026-03-11 16:18:51
R W Run
6.08 KB
2026-03-11 16:18:51
R W Run
20.06 KB
2026-03-11 16:18:51
R W Run
5.73 KB
2026-03-11 16:18:51
R W Run
68.18 KB
2026-03-11 16:18:51
R W Run
40.8 KB
2026-03-11 16:18:51
R W Run
1.44 KB
2026-03-11 16:18:51
R W Run
25.26 KB
2026-03-11 16:18:51
R W Run
95.94 KB
2026-03-11 16:18:51
R W Run
43.12 KB
2026-03-11 16:18:51
R W Run
41.73 KB
2026-03-11 16:18:51
R W Run
6.46 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
116.31 KB
2026-03-11 16:18:51
R W Run
9.39 KB
2026-03-11 16:18:51
R W Run
64.34 KB
2026-03-11 16:18:51
R W Run
44.73 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
3.68 KB
2026-03-11 16:18:51
R W Run
33.53 KB
2026-03-11 16:18:51
R W Run
48.84 KB
2026-03-11 16:18:51
R W Run
26.35 KB
2026-03-11 16:18:51
R W Run
1.12 KB
2026-03-11 16:18:51
R W Run
4.19 KB
2026-03-11 16:18:51
R W Run
38.19 KB
2026-03-11 16:18:51
R W Run
91.33 KB
2026-03-11 16:18:51
R W Run
80.39 KB
2026-03-11 16:18:51
R W Run
32.67 KB
2026-03-11 16:18:51
R W Run
16.18 KB
2026-03-11 16:18:51
R W Run
44.46 KB
2026-03-11 16:18:51
R W Run
6.23 KB
2026-03-11 16:18:51
R W Run
8.23 KB
2026-03-11 16:18:51
R W Run
96.96 KB
2026-03-11 16:18:51
R W Run
6.83 KB
2026-03-11 16:18:51
R W Run
46.62 KB
2026-03-11 16:18:51
R W Run
10.82 KB
2026-03-11 16:18:51
R W Run
68.86 KB
2026-03-11 16:18:51
R W Run
33.63 KB
2026-03-11 16:18:51
R W Run
113.3 KB
2026-03-11 16:18:51
R W Run
22.98 KB
2026-03-11 16:18:51
R W Run
10.66 KB
2026-03-11 16:18:51
R W Run
error_log
📄theme.php
1<?php
2/**
3 * WordPress Theme Administration API
4 *
5 * @package WordPress
6 * @subpackage Administration
7 */
8
9/**
10 * Removes a theme.
11 *
12 * @since 2.8.0
13 *
14 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
15 *
16 * @param string $stylesheet Stylesheet of the theme to delete.
17 * @param string $redirect Redirect to page when complete.
18 * @return bool|null|WP_Error True on success, false if `$stylesheet` is empty, WP_Error on failure.
19 * Null if filesystem credentials are required to proceed.
20 */
21function delete_theme( $stylesheet, $redirect = '' ) {
22 global $wp_filesystem;
23
24 if ( empty( $stylesheet ) ) {
25 return false;
26 }
27
28 if ( empty( $redirect ) ) {
29 $redirect = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet );
30 }
31
32 ob_start();
33 $credentials = request_filesystem_credentials( $redirect );
34 $data = ob_get_clean();
35
36 if ( false === $credentials ) {
37 if ( ! empty( $data ) ) {
38 require_once ABSPATH . 'wp-admin/admin-header.php';
39 echo $data;
40 require_once ABSPATH . 'wp-admin/admin-footer.php';
41 exit;
42 }
43 return;
44 }
45
46 if ( ! WP_Filesystem( $credentials ) ) {
47 ob_start();
48 // Failed to connect. Error and request again.
49 request_filesystem_credentials( $redirect, '', true );
50 $data = ob_get_clean();
51
52 if ( ! empty( $data ) ) {
53 require_once ABSPATH . 'wp-admin/admin-header.php';
54 echo $data;
55 require_once ABSPATH . 'wp-admin/admin-footer.php';
56 exit;
57 }
58 return;
59 }
60
61 if ( ! is_object( $wp_filesystem ) ) {
62 return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
63 }
64
65 if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
66 return new WP_Error( 'fs_error', __( 'Filesystem error.' ), $wp_filesystem->errors );
67 }
68
69 // Get the base theme folder.
70 $themes_dir = $wp_filesystem->wp_themes_dir();
71 if ( empty( $themes_dir ) ) {
72 return new WP_Error( 'fs_no_themes_dir', __( 'Unable to locate WordPress theme directory.' ) );
73 }
74
75 /**
76 * Fires immediately before a theme deletion attempt.
77 *
78 * @since 5.8.0
79 *
80 * @param string $stylesheet Stylesheet of the theme to delete.
81 */
82 do_action( 'delete_theme', $stylesheet );
83
84 $theme = wp_get_theme( $stylesheet );
85
86 $themes_dir = trailingslashit( $themes_dir );
87 $theme_dir = trailingslashit( $themes_dir . $stylesheet );
88 $deleted = $wp_filesystem->delete( $theme_dir, true );
89
90 /**
91 * Fires immediately after a theme deletion attempt.
92 *
93 * @since 5.8.0
94 *
95 * @param string $stylesheet Stylesheet of the theme to delete.
96 * @param bool $deleted Whether the theme deletion was successful.
97 */
98 do_action( 'deleted_theme', $stylesheet, $deleted );
99
100 if ( ! $deleted ) {
101 return new WP_Error(
102 'could_not_remove_theme',
103 /* translators: %s: Theme name. */
104 sprintf( __( 'Could not fully remove the theme %s.' ), $stylesheet )
105 );
106 }
107
108 $theme_translations = wp_get_installed_translations( 'themes' );
109
110 // Remove language files, silently.
111 if ( ! empty( $theme_translations[ $stylesheet ] ) ) {
112 $translations = $theme_translations[ $stylesheet ];
113
114 foreach ( $translations as $translation => $data ) {
115 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.po' );
116 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.mo' );
117 $wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.l10n.php' );
118
119 $json_translation_files = glob( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '-*.json' );
120 if ( $json_translation_files ) {
121 array_map( array( $wp_filesystem, 'delete' ), $json_translation_files );
122 }
123 }
124 }
125
126 // Remove the theme from allowed themes on the network.
127 if ( is_multisite() ) {
128 WP_Theme::network_disable_theme( $stylesheet );
129 }
130
131 // Clear theme caches.
132 $theme->cache_delete();
133
134 // Force refresh of theme update information.
135 delete_site_transient( 'update_themes' );
136
137 return true;
138}
139
140/**
141 * Gets the page templates available in this theme.
142 *
143 * @since 1.5.0
144 * @since 4.7.0 Added the `$post_type` parameter.
145 *
146 * @param WP_Post|null $post Optional. The post being edited, provided for context.
147 * @param string $post_type Optional. Post type to get the templates for. Default 'page'.
148 * @return string[] Array of template file names keyed by the template header name.
149 */
150function get_page_templates( $post = null, $post_type = 'page' ) {
151 return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) );
152}
153
154/**
155 * Tidies a filename for url display by the theme file editor.
156 *
157 * @since 2.9.0
158 * @access private
159 *
160 * @param string $fullpath Full path to the theme file
161 * @param string $containingfolder Path of the theme parent folder
162 * @return string
163 */
164function _get_template_edit_filename( $fullpath, $containingfolder ) {
165 return str_replace( dirname( $containingfolder, 2 ), '', $fullpath );
166}
167
168/**
169 * Check if there is an update for a theme available.
170 *
171 * Will display link, if there is an update available.
172 *
173 * @since 2.7.0
174 *
175 * @see get_theme_update_available()
176 *
177 * @param WP_Theme $theme Theme data object.
178 */
179function theme_update_available( $theme ) {
180 echo get_theme_update_available( $theme );
181}
182
183/**
184 * Retrieves the update link if there is a theme update available.
185 *
186 * Will return a link if there is an update available.
187 *
188 * @since 3.8.0
189 *
190 * @param WP_Theme $theme WP_Theme object.
191 * @return string|false HTML for the update link, or false if invalid info was passed.
192 */
193function get_theme_update_available( $theme ) {
194 static $themes_update = null;
195
196 if ( ! current_user_can( 'update_themes' ) ) {
197 return false;
198 }
199
200 if ( ! isset( $themes_update ) ) {
201 $themes_update = get_site_transient( 'update_themes' );
202 }
203
204 if ( ! ( $theme instanceof WP_Theme ) ) {
205 return false;
206 }
207
208 $stylesheet = $theme->get_stylesheet();
209
210 $html = '';
211
212 if ( isset( $themes_update->response[ $stylesheet ] ) ) {
213 $update = $themes_update->response[ $stylesheet ];
214 $theme_name = $theme->display( 'Name' );
215 $details_url = add_query_arg(
216 array(
217 'TB_iframe' => 'true',
218 'width' => 1024,
219 'height' => 800,
220 ),
221 $update['url']
222 ); // Theme browser inside WP? Replace this. Also, theme preview JS will override this on the available list.
223 $update_url = wp_nonce_url( admin_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $stylesheet ) ), 'upgrade-theme_' . $stylesheet );
224
225 if ( ! is_multisite() ) {
226 if ( ! current_user_can( 'update_themes' ) ) {
227 $html = sprintf(
228 /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */
229 '<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>',
230 $theme_name,
231 esc_url( $details_url ),
232 sprintf(
233 'class="thickbox open-plugin-details-modal" aria-label="%s"',
234 /* translators: 1: Theme name, 2: Version number. */
235 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
236 ),
237 $update['new_version']
238 );
239 } elseif ( empty( $update['package'] ) ) {
240 $html = sprintf(
241 /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */
242 '<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>',
243 $theme_name,
244 esc_url( $details_url ),
245 sprintf(
246 'class="thickbox open-plugin-details-modal" aria-label="%s"',
247 /* translators: 1: Theme name, 2: Version number. */
248 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
249 ),
250 $update['new_version']
251 );
252 } else {
253 $html = sprintf(
254 /* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
255 '<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>',
256 $theme_name,
257 esc_url( $details_url ),
258 sprintf(
259 'class="thickbox open-plugin-details-modal" aria-label="%s"',
260 /* translators: 1: Theme name, 2: Version number. */
261 esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
262 ),
263 $update['new_version'],
264 $update_url,
265 sprintf(
266 'aria-label="%s" id="update-theme" data-slug="%s"',
267 /* translators: %s: Theme name. */
268 esc_attr( sprintf( _x( 'Update %s now', 'theme' ), $theme_name ) ),
269 $stylesheet
270 )
271 );
272 }
273 }
274 }
275
276 return $html;
277}
278
279/**
280 * Retrieves list of WordPress theme features (aka theme tags).
281 *
282 * @since 3.1.0
283 * @since 3.2.0 Added 'Gray' color and 'Featured Image Header', 'Featured Images',
284 * 'Full Width Template', and 'Post Formats' features.
285 * @since 3.5.0 Added 'Flexible Header' feature.
286 * @since 3.8.0 Renamed 'Width' filter to 'Layout'.
287 * @since 3.8.0 Renamed 'Fixed Width' and 'Flexible Width' options
288 * to 'Fixed Layout' and 'Fluid Layout'.
289 * @since 3.8.0 Added 'Accessibility Ready' feature and 'Responsive Layout' option.
290 * @since 3.9.0 Combined 'Layout' and 'Columns' filters.
291 * @since 4.6.0 Removed 'Colors' filter.
292 * @since 4.6.0 Added 'Grid Layout' option.
293 * Removed 'Fixed Layout', 'Fluid Layout', and 'Responsive Layout' options.
294 * @since 4.6.0 Added 'Custom Logo' and 'Footer Widgets' features.
295 * Removed 'Blavatar' feature.
296 * @since 4.6.0 Added 'Blog', 'E-Commerce', 'Education', 'Entertainment', 'Food & Drink',
297 * 'Holiday', 'News', 'Photography', and 'Portfolio' subjects.
298 * Removed 'Photoblogging' and 'Seasonal' subjects.
299 * @since 4.9.0 Reordered the filters from 'Layout', 'Features', 'Subject'
300 * to 'Subject', 'Features', 'Layout'.
301 * @since 4.9.0 Removed 'BuddyPress', 'Custom Menu', 'Flexible Header',
302 * 'Front Page Posting', 'Microformats', 'RTL Language Support',
303 * 'Threaded Comments', and 'Translation Ready' features.
304 * @since 5.5.0 Added 'Block Editor Patterns', 'Block Editor Styles',
305 * and 'Full Site Editing' features.
306 * @since 5.5.0 Added 'Wide Blocks' layout option.
307 * @since 5.8.1 Added 'Template Editing' feature.
308 * @since 6.1.1 Replaced 'Full Site Editing' feature name with 'Site Editor'.
309 * @since 6.2.0 Added 'Style Variations' feature.
310 *
311 * @param bool $api Optional. Whether try to fetch tags from the WordPress.org API. Defaults to true.
312 * @return array Array of features keyed by category with translations keyed by slug.
313 */
314function get_theme_feature_list( $api = true ) {
315 // Hard-coded list is used if API is not accessible.
316 $features = array(
317
318 __( 'Subject' ) => array(
319 'blog' => __( 'Blog' ),
320 'e-commerce' => __( 'E-Commerce' ),
321 'education' => __( 'Education' ),
322 'entertainment' => __( 'Entertainment' ),
323 'food-and-drink' => __( 'Food & Drink' ),
324 'holiday' => __( 'Holiday' ),
325 'news' => __( 'News' ),
326 'photography' => __( 'Photography' ),
327 'portfolio' => __( 'Portfolio' ),
328 ),
329
330 __( 'Features' ) => array(
331 'accessibility-ready' => __( 'Accessibility Ready' ),
332 'block-patterns' => __( 'Block Editor Patterns' ),
333 'block-styles' => __( 'Block Editor Styles' ),
334 'custom-background' => __( 'Custom Background' ),
335 'custom-colors' => __( 'Custom Colors' ),
336 'custom-header' => __( 'Custom Header' ),
337 'custom-logo' => __( 'Custom Logo' ),
338 'editor-style' => __( 'Editor Style' ),
339 'featured-image-header' => __( 'Featured Image Header' ),
340 'featured-images' => __( 'Featured Images' ),
341 'footer-widgets' => __( 'Footer Widgets' ),
342 'full-site-editing' => __( 'Site Editor' ),
343 'full-width-template' => __( 'Full Width Template' ),
344 'post-formats' => __( 'Post Formats' ),
345 'sticky-post' => __( 'Sticky Post' ),
346 'style-variations' => __( 'Style Variations' ),
347 'template-editing' => __( 'Template Editing' ),
348 'theme-options' => __( 'Theme Options' ),
349 ),
350
351 __( 'Layout' ) => array(
352 'grid-layout' => __( 'Grid Layout' ),
353 'one-column' => __( 'One Column' ),
354 'two-columns' => __( 'Two Columns' ),
355 'three-columns' => __( 'Three Columns' ),
356 'four-columns' => __( 'Four Columns' ),
357 'left-sidebar' => __( 'Left Sidebar' ),
358 'right-sidebar' => __( 'Right Sidebar' ),
359 'wide-blocks' => __( 'Wide Blocks' ),
360 ),
361
362 );
363
364 if ( ! $api || ! current_user_can( 'install_themes' ) ) {
365 return $features;
366 }
367
368 $feature_list = get_site_transient( 'wporg_theme_feature_list' );
369 if ( ! $feature_list ) {
370 set_site_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS );
371 }
372
373 if ( ! $feature_list ) {
374 $feature_list = themes_api( 'feature_list', array() );
375 if ( is_wp_error( $feature_list ) ) {
376 return $features;
377 }
378 }
379
380 if ( ! $feature_list ) {
381 return $features;
382 }
383
384 set_site_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS );
385
386 $category_translations = array(
387 'Layout' => __( 'Layout' ),
388 'Features' => __( 'Features' ),
389 'Subject' => __( 'Subject' ),
390 );
391
392 $wporg_features = array();
393
394 // Loop over the wp.org canonical list and apply translations.
395 foreach ( (array) $feature_list as $feature_category => $feature_items ) {
396 if ( isset( $category_translations[ $feature_category ] ) ) {
397 $feature_category = $category_translations[ $feature_category ];
398 }
399
400 $wporg_features[ $feature_category ] = array();
401
402 foreach ( $feature_items as $feature ) {
403 if ( isset( $features[ $feature_category ][ $feature ] ) ) {
404 $wporg_features[ $feature_category ][ $feature ] = $features[ $feature_category ][ $feature ];
405 } else {
406 $wporg_features[ $feature_category ][ $feature ] = $feature;
407 }
408 }
409 }
410
411 return $wporg_features;
412}
413
414/**
415 * Retrieves theme installer pages from the WordPress.org Themes API.
416 *
417 * It is possible for a theme to override the Themes API result with three
418 * filters. Assume this is for themes, which can extend on the Theme Info to
419 * offer more choices. This is very powerful and must be used with care, when
420 * overriding the filters.
421 *
422 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
423 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
424 * an object is returned.
425 *
426 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
427 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
428 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
429 *
430 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
431 * response object or array, depending on the `$action` type.
432 *
433 * Supported arguments per action:
434 *
435 * | Argument Name | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list' |
436 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
437 * | `$slug` | No | Yes | No | No |
438 * | `$per_page` | Yes | No | No | No |
439 * | `$page` | Yes | No | No | No |
440 * | `$number` | No | No | Yes | No |
441 * | `$search` | Yes | No | No | No |
442 * | `$tag` | Yes | No | No | No |
443 * | `$author` | Yes | No | No | No |
444 * | `$user` | Yes | No | No | No |
445 * | `$browse` | Yes | No | No | No |
446 * | `$locale` | Yes | Yes | No | No |
447 * | `$fields` | Yes | Yes | No | No |
448 *
449 * @since 2.8.0
450 *
451 * @param string $action API action to perform: Accepts 'query_themes', 'theme_information',
452 * 'hot_tags' or 'feature_list'.
453 * @param array|object $args {
454 * Optional. Array or object of arguments to serialize for the Themes API. Default empty array.
455 *
456 * @type string $slug The theme slug. Default empty.
457 * @type int $per_page Number of themes per page. Default 24.
458 * @type int $page Number of current page. Default 1.
459 * @type int $number Number of tags to be queried.
460 * @type string $search A search term. Default empty.
461 * @type string $tag Tag to filter themes. Default empty.
462 * @type string $author Username of an author to filter themes. Default empty.
463 * @type string $user Username to query for their favorites. Default empty.
464 * @type string $browse Browse view: 'featured', 'popular', 'updated', 'favorites'.
465 * @type string $locale Locale to provide context-sensitive results. Default is the value of get_locale().
466 * @type array $fields {
467 * Array of fields which should or should not be returned.
468 *
469 * @type bool $description Whether to return the theme full description. Default false.
470 * @type bool $sections Whether to return the theme readme sections: description, installation,
471 * FAQ, screenshots, other notes, and changelog. Default false.
472 * @type bool $rating Whether to return the rating in percent and total number of ratings.
473 * Default false.
474 * @type bool $ratings Whether to return the number of rating for each star (1-5). Default false.
475 * @type bool $downloaded Whether to return the download count. Default false.
476 * @type bool $downloadlink Whether to return the download link for the package. Default false.
477 * @type bool $last_updated Whether to return the date of the last update. Default false.
478 * @type bool $tags Whether to return the assigned tags. Default false.
479 * @type bool $homepage Whether to return the theme homepage link. Default false.
480 * @type bool $screenshots Whether to return the screenshots. Default false.
481 * @type int $screenshot_count Number of screenshots to return. Default 1.
482 * @type bool $screenshot_url Whether to return the URL of the first screenshot. Default false.
483 * @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
484 * @type bool $template Whether to return the slug of the parent theme. Default false.
485 * @type bool $parent Whether to return the slug, name and homepage of the parent theme. Default false.
486 * @type bool $versions Whether to return the list of all available versions. Default false.
487 * @type bool $theme_url Whether to return theme's URL. Default false.
488 * @type bool $extended_author Whether to return nicename or nicename and display name. Default false.
489 * }
490 * }
491 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
492 * {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
493 * for more information on the make-up of possible return objects depending on the value of `$action`.
494 */
495function themes_api( $action, $args = array() ) {
496 if ( is_array( $args ) ) {
497 $args = (object) $args;
498 }
499
500 if ( 'query_themes' === $action ) {
501 if ( ! isset( $args->per_page ) ) {
502 $args->per_page = 24;
503 }
504 }
505
506 if ( ! isset( $args->locale ) ) {
507 $args->locale = get_user_locale();
508 }
509
510 if ( ! isset( $args->wp_version ) ) {
511 $args->wp_version = substr( wp_get_wp_version(), 0, 3 ); // x.y
512 }
513
514 /**
515 * Filters arguments used to query for installer pages from the WordPress.org Themes API.
516 *
517 * Important: An object MUST be returned to this filter.
518 *
519 * @since 2.8.0
520 *
521 * @param object $args Arguments used to query for installer pages from the WordPress.org Themes API.
522 * @param string $action Requested action. Likely values are 'theme_information',
523 * 'feature_list', or 'query_themes'.
524 */
525 $args = apply_filters( 'themes_api_args', $args, $action );
526
527 /**
528 * Filters whether to override the WordPress.org Themes API.
529 *
530 * Returning a non-false value will effectively short-circuit the WordPress.org API request.
531 *
532 * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
533 * be passed. If `$action` is 'hot_tags', an array should be passed.
534 *
535 * @since 2.8.0
536 *
537 * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
538 * @param string $action Requested action. Likely values are 'theme_information',
539 * 'feature_list', or 'query_themes'.
540 * @param object $args Arguments used to query for installer pages from the Themes API.
541 */
542 $res = apply_filters( 'themes_api', false, $action, $args );
543
544 if ( ! $res ) {
545 $url = 'http://api.wordpress.org/themes/info/1.2/';
546 $url = add_query_arg(
547 array(
548 'action' => $action,
549 'request' => $args,
550 ),
551 $url
552 );
553
554 $http_url = $url;
555 $ssl = wp_http_supports( array( 'ssl' ) );
556 if ( $ssl ) {
557 $url = set_url_scheme( $url, 'https' );
558 }
559
560 $http_args = array(
561 'timeout' => 15,
562 'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
563 );
564 $request = wp_remote_get( $url, $http_args );
565
566 if ( $ssl && is_wp_error( $request ) ) {
567 if ( ! wp_doing_ajax() ) {
568 wp_trigger_error(
569 __FUNCTION__,
570 sprintf(
571 /* translators: %s: Support forums URL. */
572 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
573 __( 'https://wordpress.org/support/forums/' )
574 ) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
575 headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
576 );
577 }
578 $request = wp_remote_get( $http_url, $http_args );
579 }
580
581 if ( is_wp_error( $request ) ) {
582 $res = new WP_Error(
583 'themes_api_failed',
584 sprintf(
585 /* translators: %s: Support forums URL. */
586 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
587 __( 'https://wordpress.org/support/forums/' )
588 ),
589 $request->get_error_message()
590 );
591 } else {
592 $res = json_decode( wp_remote_retrieve_body( $request ), true );
593 if ( is_array( $res ) ) {
594 // Object casting is required in order to match the info/1.0 format.
595 $res = (object) $res;
596 } elseif ( null === $res ) {
597 $res = new WP_Error(
598 'themes_api_failed',
599 sprintf(
600 /* translators: %s: Support forums URL. */
601 __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
602 __( 'https://wordpress.org/support/forums/' )
603 ),
604 wp_remote_retrieve_body( $request )
605 );
606 }
607
608 if ( isset( $res->error ) ) {
609 $res = new WP_Error( 'themes_api_failed', $res->error );
610 }
611 }
612
613 if ( ! is_wp_error( $res ) ) {
614 // Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
615 if ( 'query_themes' === $action ) {
616 foreach ( $res->themes as $i => $theme ) {
617 $res->themes[ $i ] = (object) $theme;
618 }
619 }
620
621 // Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
622 if ( 'feature_list' === $action ) {
623 $res = (array) $res;
624 }
625 }
626 }
627
628 /**
629 * Filters the returned WordPress.org Themes API response.
630 *
631 * @since 2.8.0
632 *
633 * @param array|stdClass|WP_Error $res WordPress.org Themes API response.
634 * @param string $action Requested action. Likely values are 'theme_information',
635 * 'feature_list', or 'query_themes'.
636 * @param stdClass $args Arguments used to query for installer pages from the WordPress.org Themes API.
637 */
638 return apply_filters( 'themes_api_result', $res, $action, $args );
639}
640
641/**
642 * Prepares themes for JavaScript.
643 *
644 * @since 3.8.0
645 *
646 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
647 * Defaults to all allowed themes.
648 *
649 * @return array An associative array of theme data, sorted by name.
650 */
651function wp_prepare_themes_for_js( $themes = null ) {
652 $current_theme = get_stylesheet();
653
654 /**
655 * Filters theme data before it is prepared for JavaScript.
656 *
657 * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
658 * early with that value instead.
659 *
660 * @since 4.2.0
661 *
662 * @param array $prepared_themes An associative array of theme data. Default empty array.
663 * @param WP_Theme[]|null $themes An array of theme objects to prepare, if any.
664 * @param string $current_theme The active theme slug.
665 */
666 $prepared_themes = (array) apply_filters( 'pre_prepare_themes_for_js', array(), $themes, $current_theme );
667
668 if ( ! empty( $prepared_themes ) ) {
669 return $prepared_themes;
670 }
671
672 // Make sure the active theme is listed first.
673 $prepared_themes[ $current_theme ] = array();
674
675 if ( null === $themes ) {
676 $themes = wp_get_themes( array( 'allowed' => true ) );
677 if ( ! isset( $themes[ $current_theme ] ) ) {
678 $themes[ $current_theme ] = wp_get_theme();
679 }
680 }
681
682 $updates = array();
683 $no_updates = array();
684 if ( ! is_multisite() && current_user_can( 'update_themes' ) ) {
685 $updates_transient = get_site_transient( 'update_themes' );
686 if ( isset( $updates_transient->response ) ) {
687 $updates = $updates_transient->response;
688 }
689 if ( isset( $updates_transient->no_update ) ) {
690 $no_updates = $updates_transient->no_update;
691 }
692 }
693
694 WP_Theme::sort_by_name( $themes );
695
696 $parents = array();
697
698 $auto_updates = (array) get_site_option( 'auto_update_themes', array() );
699
700 foreach ( $themes as $theme ) {
701 $slug = $theme->get_stylesheet();
702 $encoded_slug = urlencode( $slug );
703
704 $parent = false;
705 if ( $theme->parent() ) {
706 $parent = $theme->parent();
707 $parents[ $slug ] = $parent->get_stylesheet();
708 $parent = $parent->display( 'Name' );
709 }
710
711 $customize_action = null;
712
713 $can_edit_theme_options = current_user_can( 'edit_theme_options' );
714 $can_customize = current_user_can( 'customize' );
715 $is_block_theme = $theme->is_block_theme();
716
717 if ( $is_block_theme && $can_edit_theme_options ) {
718 $customize_action = admin_url( 'site-editor.php' );
719 if ( $current_theme !== $slug ) {
720 $customize_action = add_query_arg( 'wp_theme_preview', $slug, $customize_action );
721 }
722 } elseif ( ! $is_block_theme && $can_customize && $can_edit_theme_options ) {
723 $customize_action = wp_customize_url( $slug );
724 }
725 if ( null !== $customize_action ) {
726 $customize_action = add_query_arg(
727 array(
728 'return' => urlencode( sanitize_url( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ),
729 ),
730 $customize_action
731 );
732 $customize_action = esc_url( $customize_action );
733 }
734
735 $update_requires_wp = isset( $updates[ $slug ]['requires'] ) ? $updates[ $slug ]['requires'] : null;
736 $update_requires_php = isset( $updates[ $slug ]['requires_php'] ) ? $updates[ $slug ]['requires_php'] : null;
737
738 $auto_update = in_array( $slug, $auto_updates, true );
739 $auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';
740
741 if ( isset( $updates[ $slug ] ) ) {
742 $auto_update_supported = true;
743 $auto_update_filter_payload = (object) $updates[ $slug ];
744 } elseif ( isset( $no_updates[ $slug ] ) ) {
745 $auto_update_supported = true;
746 $auto_update_filter_payload = (object) $no_updates[ $slug ];
747 } else {
748 $auto_update_supported = false;
749 /*
750 * Create the expected payload for the auto_update_theme filter, this is the same data
751 * as contained within $updates or $no_updates but used when the Theme is not known.
752 */
753 $auto_update_filter_payload = (object) array(
754 'theme' => $slug,
755 'new_version' => $theme->get( 'Version' ),
756 'url' => '',
757 'package' => '',
758 'requires' => $theme->get( 'RequiresWP' ),
759 'requires_php' => $theme->get( 'RequiresPHP' ),
760 );
761 }
762
763 $auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, $auto_update_filter_payload );
764
765 $prepared_themes[ $slug ] = array(
766 'id' => $slug,
767 'name' => $theme->display( 'Name' ),
768 'screenshot' => array( $theme->get_screenshot() ), // @todo Multiple screenshots.
769 'description' => $theme->display( 'Description' ),
770 'author' => $theme->display( 'Author', false, true ),
771 'authorAndUri' => $theme->display( 'Author' ),
772 'tags' => $theme->display( 'Tags' ),
773 'version' => $theme->get( 'Version' ),
774 'compatibleWP' => is_wp_version_compatible( $theme->get( 'RequiresWP' ) ),
775 'compatiblePHP' => is_php_version_compatible( $theme->get( 'RequiresPHP' ) ),
776 'updateResponse' => array(
777 'compatibleWP' => is_wp_version_compatible( $update_requires_wp ),
778 'compatiblePHP' => is_php_version_compatible( $update_requires_php ),
779 ),
780 'parent' => $parent,
781 'active' => $slug === $current_theme,
782 'hasUpdate' => isset( $updates[ $slug ] ),
783 'hasPackage' => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
784 'update' => get_theme_update_available( $theme ),
785 'autoupdate' => array(
786 'enabled' => $auto_update || $auto_update_forced,
787 'supported' => $auto_update_supported,
788 'forced' => $auto_update_forced,
789 ),
790 'actions' => array(
791 'activate' => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&amp;stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
792 'customize' => $customize_action,
793 'delete' => ( ! is_multisite() && current_user_can( 'delete_themes' ) ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&amp;stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
794 'autoupdate' => wp_is_auto_update_enabled_for_type( 'theme' ) && ! is_multisite() && current_user_can( 'update_themes' )
795 ? wp_nonce_url( admin_url( 'themes.php?action=' . $auto_update_action . '&amp;stylesheet=' . $encoded_slug ), 'updates' )
796 : null,
797 ),
798 'blockTheme' => $theme->is_block_theme(),
799 );
800 }
801
802 // Remove 'delete' action if theme has an active child.
803 if ( ! empty( $parents ) && array_key_exists( $current_theme, $parents ) ) {
804 unset( $prepared_themes[ $parents[ $current_theme ] ]['actions']['delete'] );
805 }
806
807 /**
808 * Filters the themes prepared for JavaScript, for themes.php.
809 *
810 * Could be useful for changing the order, which is by name by default.
811 *
812 * @since 3.8.0
813 *
814 * @param array $prepared_themes Array of theme data.
815 */
816 $prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
817 $prepared_themes = array_values( $prepared_themes );
818 return array_filter( $prepared_themes );
819}
820
821/**
822 * Prints JS templates for the theme-browsing UI in the Customizer.
823 *
824 * @since 4.2.0
825 */
826function customize_themes_print_templates() {
827 ?>
828 <script type="text/html" id="tmpl-customize-themes-details-view">
829 <div class="theme-backdrop"></div>
830 <div class="theme-wrap wp-clearfix" role="document">
831 <div class="theme-header">
832 <button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text">
833 <?php
834 /* translators: Hidden accessibility text. */
835 _e( 'Show previous theme' );
836 ?>
837 </span></button>
838 <button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text">
839 <?php
840 /* translators: Hidden accessibility text. */
841 _e( 'Show next theme' );
842 ?>
843 </span></button>
844 <button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text">
845 <?php
846 /* translators: Hidden accessibility text. */
847 _e( 'Close details dialog' );
848 ?>
849 </span></button>
850 </div>
851 <div class="theme-about wp-clearfix">
852 <div class="theme-screenshots">
853 <# if ( data.screenshot && data.screenshot[0] ) { #>
854 <div class="screenshot"><img src="{{ data.screenshot[0] }}?ver={{ data.version }}" alt="" /></div>
855 <# } else { #>
856 <div class="screenshot blank"></div>
857 <# } #>
858 </div>
859
860 <div class="theme-info">
861 <# if ( data.active ) { #>
862 <span class="current-label"><?php _e( 'Active Theme' ); ?></span>
863 <# } #>
864 <h2 class="theme-name">{{{ data.name }}}<span class="theme-version">
865 <?php
866 /* translators: %s: Theme version. */
867 printf( __( 'Version: %s' ), '{{ data.version }}' );
868 ?>
869 </span></h2>
870 <h3 class="theme-author">
871 <?php
872 /* translators: %s: Theme author link. */
873 printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' );
874 ?>
875 </h3>
876
877 <# if ( data.stars && 0 != data.num_ratings ) { #>
878 <div class="theme-rating">
879 {{{ data.stars }}}
880 <a class="num-ratings" target="_blank" href="{{ data.reviews_url }}">
881 <?php
882 printf(
883 '%1$s <span class="screen-reader-text">%2$s</span>',
884 /* translators: %s: Number of ratings. */
885 sprintf( __( '(%s ratings)' ), '{{ data.num_ratings }}' ),
886 /* translators: Hidden accessibility text. */
887 __( '(opens in a new tab)' )
888 );
889 ?>
890 </a>
891 </div>
892 <# } #>
893
894 <# if ( data.hasUpdate ) { #>
895 <# if ( data.updateResponse.compatibleWP && data.updateResponse.compatiblePHP ) { #>
896 <div class="notice notice-warning notice-alt notice-large" data-slug="{{ data.id }}">
897 <h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
898 {{{ data.update }}}
899 </div>
900 <# } else { #>
901 <div class="notice notice-error notice-alt notice-large" data-slug="{{ data.id }}">
902 <h3 class="notice-title"><?php _e( 'Update Incompatible' ); ?></h3>
903 <p>
904 <# if ( ! data.updateResponse.compatibleWP && ! data.updateResponse.compatiblePHP ) { #>
905 <?php
906 printf(
907 /* translators: %s: Theme name. */
908 __( 'There is a new version of %s available, but it does not work with your versions of WordPress and PHP.' ),
909 '{{{ data.name }}}'
910 );
911 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
912 printf(
913 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
914 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
915 self_admin_url( 'update-core.php' ),
916 esc_url( wp_get_update_php_url() )
917 );
918 wp_update_php_annotation( '</p><p><em>', '</em>' );
919 } elseif ( current_user_can( 'update_core' ) ) {
920 printf(
921 /* translators: %s: URL to WordPress Updates screen. */
922 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
923 self_admin_url( 'update-core.php' )
924 );
925 } elseif ( current_user_can( 'update_php' ) ) {
926 printf(
927 /* translators: %s: URL to Update PHP page. */
928 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
929 esc_url( wp_get_update_php_url() )
930 );
931 wp_update_php_annotation( '</p><p><em>', '</em>' );
932 }
933 ?>
934 <# } else if ( ! data.updateResponse.compatibleWP ) { #>
935 <?php
936 printf(
937 /* translators: %s: Theme name. */
938 __( 'There is a new version of %s available, but it does not work with your version of WordPress.' ),
939 '{{{ data.name }}}'
940 );
941 if ( current_user_can( 'update_core' ) ) {
942 printf(
943 /* translators: %s: URL to WordPress Updates screen. */
944 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
945 self_admin_url( 'update-core.php' )
946 );
947 }
948 ?>
949 <# } else if ( ! data.updateResponse.compatiblePHP ) { #>
950 <?php
951 printf(
952 /* translators: %s: Theme name. */
953 __( 'There is a new version of %s available, but it does not work with your version of PHP.' ),
954 '{{{ data.name }}}'
955 );
956 if ( current_user_can( 'update_php' ) ) {
957 printf(
958 /* translators: %s: URL to Update PHP page. */
959 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
960 esc_url( wp_get_update_php_url() )
961 );
962 wp_update_php_annotation( '</p><p><em>', '</em>' );
963 }
964 ?>
965 <# } #>
966 </p>
967 </div>
968 <# } #>
969 <# } #>
970
971 <# if ( data.parent ) { #>
972 <p class="parent-theme">
973 <?php
974 printf(
975 /* translators: %s: Theme name. */
976 __( 'This is a child theme of %s.' ),
977 '<strong>{{{ data.parent }}}</strong>'
978 );
979 ?>
980 </p>
981 <# } #>
982
983 <# if ( ! data.compatibleWP || ! data.compatiblePHP ) { #>
984 <div class="notice notice-error notice-alt notice-large"><p>
985 <# if ( ! data.compatibleWP && ! data.compatiblePHP ) { #>
986 <?php
987 _e( 'This theme does not work with your versions of WordPress and PHP.' );
988 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
989 printf(
990 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
991 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
992 self_admin_url( 'update-core.php' ),
993 esc_url( wp_get_update_php_url() )
994 );
995 wp_update_php_annotation( '</p><p><em>', '</em>' );
996 } elseif ( current_user_can( 'update_core' ) ) {
997 printf(
998 /* translators: %s: URL to WordPress Updates screen. */
999 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
1000 self_admin_url( 'update-core.php' )
1001 );
1002 } elseif ( current_user_can( 'update_php' ) ) {
1003 printf(
1004 /* translators: %s: URL to Update PHP page. */
1005 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
1006 esc_url( wp_get_update_php_url() )
1007 );
1008 wp_update_php_annotation( '</p><p><em>', '</em>' );
1009 }
1010 ?>
1011 <# } else if ( ! data.compatibleWP ) { #>
1012 <?php
1013 _e( 'This theme does not work with your version of WordPress.' );
1014 if ( current_user_can( 'update_core' ) ) {
1015 printf(
1016 /* translators: %s: URL to WordPress Updates screen. */
1017 ' ' . __( '<a href="%s">Please update WordPress</a>.' ),
1018 self_admin_url( 'update-core.php' )
1019 );
1020 }
1021 ?>
1022 <# } else if ( ! data.compatiblePHP ) { #>
1023 <?php
1024 _e( 'This theme does not work with your version of PHP.' );
1025 if ( current_user_can( 'update_php' ) ) {
1026 printf(
1027 /* translators: %s: URL to Update PHP page. */
1028 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
1029 esc_url( wp_get_update_php_url() )
1030 );
1031 wp_update_php_annotation( '</p><p><em>', '</em>' );
1032 }
1033 ?>
1034 <# } #>
1035 </p></div>
1036 <# } else if ( ! data.active && data.blockTheme ) { #>
1037 <div class="notice notice-error notice-alt notice-large"><p>
1038 <?php
1039 _e( 'This theme doesn\'t support Customizer.' );
1040 ?>
1041 <# if ( data.actions.activate ) { #>
1042 <?php
1043 printf(
1044 /* translators: %s: URL to the themes page (also it activates the theme). */
1045 ' ' . __( 'However, you can still <a href="%s">activate this theme</a>, and use the Site Editor to customize it.' ),
1046 '{{{ data.actions.activate }}}'
1047 );
1048 ?>
1049 <# } #>
1050 </p></div>
1051 <# } #>
1052
1053 <p class="theme-description">{{{ data.description }}}</p>
1054
1055 <# if ( data.tags ) { #>
1056 <p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{{ data.tags }}}</p>
1057 <# } #>
1058 </div>
1059 </div>
1060
1061 <div class="theme-actions">
1062 <# if ( data.active ) { #>
1063 <button type="button" class="button button-primary customize-theme"><?php _e( 'Customize' ); ?></button>
1064 <# } else if ( 'installed' === data.type ) { #>
1065 <div class="theme-inactive-actions">
1066 <# if ( data.blockTheme ) { #>
1067 <?php
1068 /* translators: %s: Theme name. */
1069 $aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' );
1070 ?>
1071 <# if ( data.compatibleWP && data.compatiblePHP && data.actions.activate ) { #>
1072 <a href="{{{ data.actions.activate }}}" class="button button-primary activate" aria-label="<?php echo esc_attr( $aria_label ); ?>"><?php _e( 'Activate' ); ?></a>
1073 <# } #>
1074 <# } else { #>
1075 <# if ( data.compatibleWP && data.compatiblePHP ) { #>
1076 <button type="button" class="button button-primary preview-theme" data-slug="{{ data.id }}"><?php _e( 'Live Preview' ); ?></button>
1077 <# } else { #>
1078 <button class="button button-primary disabled"><?php _e( 'Live Preview' ); ?></button>
1079 <# } #>
1080 <# } #>
1081 </div>
1082 <?php if ( current_user_can( 'delete_themes' ) ) { ?>
1083 <# if ( data.actions && data.actions['delete'] ) { #>
1084 <a href="{{{ data.actions['delete'] }}}" data-slug="{{ data.id }}" class="button button-secondary delete-theme"><?php _e( 'Delete' ); ?></a>
1085 <# } #>
1086 <?php } ?>
1087 <# } else { #>
1088 <# if ( data.compatibleWP && data.compatiblePHP ) { #>
1089 <button type="button" class="button theme-install" data-slug="{{ data.id }}"><?php _e( 'Install' ); ?></button>
1090 <button type="button" class="button button-primary theme-install preview" data-slug="{{ data.id }}"><?php _e( 'Install &amp; Preview' ); ?></button>
1091 <# } else { #>
1092 <button type="button" class="button disabled"><?php _ex( 'Cannot Install', 'theme' ); ?></button>
1093 <button type="button" class="button button-primary disabled"><?php _e( 'Install &amp; Preview' ); ?></button>
1094 <# } #>
1095 <# } #>
1096 </div>
1097 </div>
1098 </script>
1099 <?php
1100}
1101
1102/**
1103 * Determines whether a theme is technically active but was paused while
1104 * loading.
1105 *
1106 * For more information on this and similar theme functions, check out
1107 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
1108 * Conditional Tags} article in the Theme Developer Handbook.
1109 *
1110 * @since 5.2.0
1111 *
1112 * @global WP_Paused_Extensions_Storage $_paused_themes
1113 *
1114 * @param string $theme Path to the theme directory relative to the themes directory.
1115 * @return bool True, if in the list of paused themes. False, not in the list.
1116 */
1117function is_theme_paused( $theme ) {
1118 if ( ! isset( $GLOBALS['_paused_themes'] ) ) {
1119 return false;
1120 }
1121
1122 if ( get_stylesheet() !== $theme && get_template() !== $theme ) {
1123 return false;
1124 }
1125
1126 return array_key_exists( $theme, $GLOBALS['_paused_themes'] );
1127}
1128
1129/**
1130 * Gets the error that was recorded for a paused theme.
1131 *
1132 * @since 5.2.0
1133 *
1134 * @global WP_Paused_Extensions_Storage $_paused_themes
1135 *
1136 * @param string $theme Path to the theme directory relative to the themes
1137 * directory.
1138 * @return array|false Array of error information as it was returned by
1139 * `error_get_last()`, or false if none was recorded.
1140 */
1141function wp_get_theme_error( $theme ) {
1142 if ( ! isset( $GLOBALS['_paused_themes'] ) ) {
1143 return false;
1144 }
1145
1146 if ( ! array_key_exists( $theme, $GLOBALS['_paused_themes'] ) ) {
1147 return false;
1148 }
1149
1150 return $GLOBALS['_paused_themes'][ $theme ];
1151}
1152
1153/**
1154 * Tries to resume a single theme.
1155 *
1156 * If a redirect was provided and a functions.php file was found, we first ensure that
1157 * functions.php file does not throw fatal errors anymore.
1158 *
1159 * The way it works is by setting the redirection to the error before trying to
1160 * include the file. If the theme fails, then the redirection will not be overwritten
1161 * with the success message and the theme will not be resumed.
1162 *
1163 * @since 5.2.0
1164 *
1165 * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
1166 * @global string $wp_template_path Path to current theme's template directory.
1167 *
1168 * @param string $theme Single theme to resume.
1169 * @param string $redirect Optional. URL to redirect to. Default empty string.
1170 * @return bool|WP_Error True on success, false if `$theme` was not paused,
1171 * `WP_Error` on failure.
1172 */
1173function resume_theme( $theme, $redirect = '' ) {
1174 global $wp_stylesheet_path, $wp_template_path;
1175
1176 list( $extension ) = explode( '/', $theme );
1177
1178 /*
1179 * We'll override this later if the theme could be resumed without
1180 * creating a fatal error.
1181 */
1182 if ( ! empty( $redirect ) ) {
1183 $functions_path = '';
1184 if ( str_contains( $wp_stylesheet_path, $extension ) ) {
1185 $functions_path = $wp_stylesheet_path . '/functions.php';
1186 } elseif ( str_contains( $wp_template_path, $extension ) ) {
1187 $functions_path = $wp_template_path . '/functions.php';
1188 }
1189
1190 if ( ! empty( $functions_path ) ) {
1191 wp_redirect(
1192 add_query_arg(
1193 '_error_nonce',
1194 wp_create_nonce( 'theme-resume-error_' . $theme ),
1195 $redirect
1196 )
1197 );
1198
1199 // Load the theme's functions.php to test whether it throws a fatal error.
1200 ob_start();
1201 if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
1202 define( 'WP_SANDBOX_SCRAPING', true );
1203 }
1204 include $functions_path;
1205 ob_clean();
1206 }
1207 }
1208
1209 $result = wp_paused_themes()->delete( $extension );
1210
1211 if ( ! $result ) {
1212 return new WP_Error(
1213 'could_not_resume_theme',
1214 __( 'Could not resume the theme.' )
1215 );
1216 }
1217
1218 return true;
1219}
1220
1221/**
1222 * Renders an admin notice in case some themes have been paused due to errors.
1223 *
1224 * @since 5.2.0
1225 *
1226 * @global string $pagenow The filename of the current screen.
1227 * @global WP_Paused_Extensions_Storage $_paused_themes
1228 */
1229function paused_themes_notice() {
1230 if ( 'themes.php' === $GLOBALS['pagenow'] ) {
1231 return;
1232 }
1233
1234 if ( ! current_user_can( 'resume_themes' ) ) {
1235 return;
1236 }
1237
1238 if ( ! isset( $GLOBALS['_paused_themes'] ) || empty( $GLOBALS['_paused_themes'] ) ) {
1239 return;
1240 }
1241
1242 $message = sprintf(
1243 '<p><strong>%s</strong><br>%s</p><p><a href="%s">%s</a></p>',
1244 __( 'One or more themes failed to load properly.' ),
1245 __( 'You can find more details and make changes on the Themes screen.' ),
1246 esc_url( admin_url( 'themes.php' ) ),
1247 __( 'Go to the Themes screen' )
1248 );
1249 wp_admin_notice(
1250 $message,
1251 array(
1252 'type' => 'error',
1253 'paragraph_wrap' => false,
1254 )
1255 );
1256}
1257
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1