1 | <?php |
---|
2 | |
---|
3 | /** |
---|
4 | * WP.org Themes' functions and definitions. |
---|
5 | * |
---|
6 | * @package wporg-themes |
---|
7 | */ |
---|
8 | |
---|
9 | /** |
---|
10 | * Sets up theme defaults and registers support for various WordPress features. |
---|
11 | * |
---|
12 | * Note that this function is hooked into the after_setup_theme hook, which |
---|
13 | * runs before the init hook. The init hook is too late for some features, such |
---|
14 | * as indicating support for post thumbnails. |
---|
15 | */ |
---|
16 | function wporg_themes_setup() { |
---|
17 | global $themes_allowedtags; |
---|
18 | |
---|
19 | load_theme_textdomain( 'wporg-themes' ); |
---|
20 | |
---|
21 | add_theme_support( 'html5', array( |
---|
22 | 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption' |
---|
23 | ) ); |
---|
24 | |
---|
25 | add_theme_support( 'title-tag' ); |
---|
26 | |
---|
27 | // No need for canonical lookups |
---|
28 | remove_action( 'template_redirect', 'redirect_canonical' ); |
---|
29 | remove_action( 'template_redirect', 'wp_old_slug_redirect' ); |
---|
30 | |
---|
31 | add_action( 'template_redirect', 'wporg_themes_canonical_redirects' ); |
---|
32 | |
---|
33 | add_theme_support( 'wp4-styles' ); |
---|
34 | } |
---|
35 | add_action( 'after_setup_theme', 'wporg_themes_setup' ); |
---|
36 | |
---|
37 | /** |
---|
38 | * Handle redirects which redirect_canonical() usually would (or should) do. |
---|
39 | */ |
---|
40 | function wporg_themes_canonical_redirects() { |
---|
41 | |
---|
42 | // always include the trailing slash for the Site URL |
---|
43 | if ( '/themes' === $_SERVER['REQUEST_URI'] ) { |
---|
44 | wp_safe_redirect( '/themes/', 301 ); |
---|
45 | die(); |
---|
46 | } |
---|
47 | |
---|
48 | // We don't need any urls such as /themes/index.php/twentyten/ working |
---|
49 | if ( false !== stripos( $_SERVER['REQUEST_URI'], '/index.php' ) ) { |
---|
50 | $url = str_ireplace( '/index.php', '/', $_SERVER['REQUEST_URI'] ); |
---|
51 | wp_safe_redirect( $url, 301 ); |
---|
52 | die(); |
---|
53 | } |
---|
54 | |
---|
55 | // We don't support pagination on the directory at present. |
---|
56 | if ( get_query_var( 'paged' ) || get_query_var( 'page' ) ) { |
---|
57 | $url = remove_query_arg( [ 'paged', 'page' ] ); |
---|
58 | $url = preg_replace( '!(page/\d+|/\d+/?$)!i', '', $url ); |
---|
59 | |
---|
60 | // Remove any double slashes |
---|
61 | $url = preg_replace( '!/{2,}!', '/', $url ); |
---|
62 | |
---|
63 | wp_safe_redirect( $url ); // Not 301, as paginated requests will one day be supported hopefully. |
---|
64 | die(); |
---|
65 | } |
---|
66 | |
---|
67 | // Searches should be redirected to canonical location. |
---|
68 | if ( isset( $_GET['s'] ) ) { |
---|
69 | wp_safe_redirect( home_url( '/search/' . urlencode( get_query_var( 's' ) ) . '/' ), 301 ); |
---|
70 | die(); |
---|
71 | } |
---|
72 | |
---|
73 | // Redirect direct queries for a theme by ID to it's post. |
---|
74 | if ( |
---|
75 | isset( $_GET['p'] ) && |
---|
76 | ( $post = get_post( $_GET['p'] ) ) |
---|
77 | ) { |
---|
78 | wp_safe_redirect( get_permalink( $post ), 301 ); |
---|
79 | die(); |
---|
80 | } |
---|
81 | |
---|
82 | // Handle 404 pages where it's a singular theme followed by junk, for example, /themes/twentyten/junk/input/ |
---|
83 | if ( is_404() ) { |
---|
84 | $path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ); |
---|
85 | if ( preg_match( '!^/themes/([^/]+)/.+!i', $path, $m ) ) { |
---|
86 | $posts = get_posts( [ |
---|
87 | 'name' => $m[1], |
---|
88 | 'post_type' => 'repopackage', |
---|
89 | 'post_status' => 'publish' |
---|
90 | ] ); |
---|
91 | |
---|
92 | if ( $posts ) { |
---|
93 | wp_safe_redirect( get_permalink( $posts[0] ), 301 ); |
---|
94 | die(); |
---|
95 | } |
---|
96 | } |
---|
97 | } |
---|
98 | |
---|
99 | // Uppercase characters in URLs tend to lead to broken JS pages. |
---|
100 | // Redirect all paths to the lower-case variant, excluding searches.. |
---|
101 | $path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ); |
---|
102 | if ( |
---|
103 | $path && |
---|
104 | $path !== strtolower( $path ) && |
---|
105 | ( trailingslashit( $path ) !== '/themes/search/' . get_query_var( 's' ) . '/' ) |
---|
106 | ) { |
---|
107 | $url = preg_replace( |
---|
108 | '|^' . preg_quote( $path, '|' ) . '|', |
---|
109 | trailingslashit( strtolower( $path ) ), |
---|
110 | $_SERVER['REQUEST_URI'] |
---|
111 | ); |
---|
112 | wp_safe_redirect( $url, 301 ); |
---|
113 | die(); |
---|
114 | } |
---|
115 | |
---|
116 | // Redirect /browse/featured/ to the front-page temporarily, as it's showing in Google results. |
---|
117 | if ( '/themes/browse/featured' === substr( $path, 0, 23 ) ) { |
---|
118 | wp_safe_redirect( home_url( '/' ), 302 ); |
---|
119 | die(); |
---|
120 | } |
---|
121 | |
---|
122 | // Ensure all requests are trailingslash'd. |
---|
123 | if ( $path && '/' !== substr( $path, -1 ) && '.xml' !== substr( $path, -4 ) ) { |
---|
124 | $url = str_replace( $path, $path . '/', $_SERVER['REQUEST_URI'] ); |
---|
125 | wp_safe_redirect( $url, 301 ); |
---|
126 | die(); |
---|
127 | } |
---|
128 | } |
---|
129 | |
---|
130 | /** |
---|
131 | * Enqueue scripts and styles. |
---|
132 | */ |
---|
133 | function wporg_themes_scripts() { |
---|
134 | $script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG; |
---|
135 | $suffix = $script_debug ? '' : '.min'; |
---|
136 | |
---|
137 | // Concatenates core scripts when possible. |
---|
138 | if ( ! $script_debug ) { |
---|
139 | $GLOBALS['concatenate_scripts'] = true; |
---|
140 | } |
---|
141 | |
---|
142 | wp_enqueue_style( 'wporg-themes', get_theme_file_uri( '/css/style.css' ), [ 'dashicons', 'open-sans' ], '20220525' ); |
---|
143 | wp_style_add_data( 'wporg-themes', 'rtl', 'replace' ); |
---|
144 | |
---|
145 | if ( ! is_singular( 'page' ) ) { |
---|
146 | wp_enqueue_script( 'google-charts-loader', 'https://www.gstatic.com/charts/loader.js', array(), null, true ); |
---|
147 | wp_enqueue_script( 'wporg-theme', get_stylesheet_directory_uri() . "/js/theme{$suffix}.js", array( 'wp-backbone' ), '20210303', true ); |
---|
148 | |
---|
149 | // Use the Rosetta-specific site name. Ie. "WordPress.org $LOCALE" |
---|
150 | $title_suffix = isset( $GLOBALS['wporg_global_header_options']['rosetta_title'] ) ? $GLOBALS['wporg_global_header_options']['rosetta_title'] : 'WordPress.org'; |
---|
151 | |
---|
152 | $api_endpoints = [ |
---|
153 | 'query' => 'https://api.wordpress.org/themes/info/1.2/', |
---|
154 | 'favorite' => 'https://api.wordpress.org/themes/theme-directory/1.0/', |
---|
155 | ]; |
---|
156 | if ( 'local' === wp_get_environment_type() ) { |
---|
157 | $api_endpoints['query'] = rest_url( 'themes/1.2/query' ); |
---|
158 | } |
---|
159 | |
---|
160 | wp_localize_script( 'wporg-theme', '_wpThemeSettings', array( |
---|
161 | 'themes' => false, |
---|
162 | 'query' => wporg_themes_get_themes_for_query(), |
---|
163 | 'settings' => array( |
---|
164 | 'title' => array( |
---|
165 | 'default' => "%s | ${title_suffix}", |
---|
166 | 'home' => __( 'WordPress Themes', 'wporg-themes' ) . " | ${title_suffix}", |
---|
167 | 'theme' => '%s - ' . __( 'WordPress theme', 'wporg-themes' ) . " | ${title_suffix}", |
---|
168 | /* translators: %s: theme author name */ |
---|
169 | 'author' => sprintf( |
---|
170 | __( 'Themes by %s', 'wporg-themes' ), |
---|
171 | // The Javascript doesn't handle the author route, so we can just hard-code the author name in here for now. |
---|
172 | is_author() ? ( get_queried_object()->display_name ?: get_queried_object()->user_nicename ) : '%s' |
---|
173 | ) . " | ${title_suffix}", |
---|
174 | /* translators: %s: Category/Browse section */ |
---|
175 | 'tax' => __( 'WordPress Themes: %s Free', 'wporg-themes' ) . " | ${title_suffix}", |
---|
176 | /* translators: %s: Search term */ |
---|
177 | 'search' => __( 'Search Results for “%s”', 'wporg-themes' ) . " | ${title_suffix}", |
---|
178 | 'notfound' => __( 'Page not found', 'wporg-themes' ) . " | ${title_suffix}", |
---|
179 | ), |
---|
180 | 'isMobile' => wp_is_mobile(), |
---|
181 | 'postsPerPage' => get_option( 'posts_per_page' ), |
---|
182 | 'path' => trailingslashit( parse_url( home_url(), PHP_URL_PATH ) ), |
---|
183 | 'locale' => get_locale(), |
---|
184 | 'favorites' => array( |
---|
185 | 'api' => $api_endpoints['favorite'], |
---|
186 | 'themes' => wporg_themes_get_user_favorites(), |
---|
187 | 'user' => wp_get_current_user()->user_login, |
---|
188 | 'nonce' => is_user_logged_in() ? wp_create_nonce( 'modify-theme-favorite' ) : false, |
---|
189 | ), |
---|
190 | 'browseDefault'=> WPORG_THEMES_DEFAULT_BROWSE, |
---|
191 | 'apiEndpoint' => $api_endpoints['query'], |
---|
192 | ), |
---|
193 | 'l10n' => array( |
---|
194 | 'locale' => str_replace( '_', '-', get_locale() ), |
---|
195 | 'search' => __( 'Search Themes', 'wporg-themes' ), |
---|
196 | 'searchPlaceholder' => __( 'Search themes...', 'wporg-themes' ), // placeholder (no ellipsis) |
---|
197 | 'error' => __( 'An unexpected error occurred.', 'wporg-themes' ), |
---|
198 | |
---|
199 | // Downloads Graph |
---|
200 | 'date' => __( 'Date', 'wporg-themes' ), |
---|
201 | 'downloads' => __( 'Downloads', 'wporg-themes' ), |
---|
202 | |
---|
203 | // Tags |
---|
204 | 'tags' => wporg_themes_get_tag_translations(), |
---|
205 | |
---|
206 | // Active Installs |
---|
207 | 'active_installs_less_than_10' => __( 'Less than 10', 'wporg-themes' ), |
---|
208 | 'active_installs_1_million' => __( '1+ million', 'wporg-themes' ), |
---|
209 | ), |
---|
210 | ) ); |
---|
211 | } |
---|
212 | |
---|
213 | // No emoji support needed. |
---|
214 | remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); |
---|
215 | remove_action( 'wp_print_styles', 'print_emoji_styles' ); |
---|
216 | |
---|
217 | // No Jetpack styles needed. |
---|
218 | add_filter( 'jetpack_implode_frontend_css', '__return_false' ); |
---|
219 | |
---|
220 | /* |
---|
221 | * No Grofiles needed. |
---|
222 | * |
---|
223 | * Enqueued so that it's overridden in the global footer. |
---|
224 | */ |
---|
225 | wp_register_script( 'grofiles-cards', false ); |
---|
226 | wp_enqueue_script( 'grofiles-cards' ); |
---|
227 | } |
---|
228 | add_action( 'wp_enqueue_scripts', 'wporg_themes_scripts' ); |
---|
229 | |
---|
230 | // Disable mentions script in Theme Directory. |
---|
231 | add_filter( 'jetpack_mentions_should_load_ui', '__return_false', 11 ); |
---|
232 | |
---|
233 | /** |
---|
234 | * Extend the default WordPress body classes. |
---|
235 | * |
---|
236 | * Adds body classes to |
---|
237 | * 1. denote singular themes. |
---|
238 | * 2. Identify IE8. |
---|
239 | * 3. denote if no themes were found. |
---|
240 | * |
---|
241 | * @param array $classes A list of existing body class values. |
---|
242 | * @return array The filtered body class list. |
---|
243 | */ |
---|
244 | function wporg_themes_body_class( $classes ) { |
---|
245 | |
---|
246 | if ( ! is_page() && get_query_var( 'name' ) && ! is_404() ) { |
---|
247 | $classes[] = 'modal-open'; |
---|
248 | } |
---|
249 | |
---|
250 | if ( $GLOBALS['is_IE'] && false !== strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE 8' ) ) { |
---|
251 | $classes[] = 'ie8'; |
---|
252 | } |
---|
253 | |
---|
254 | if ( empty( $GLOBALS['themes']['themes'] ) && ! is_singular( 'page' ) ) { |
---|
255 | $classes[] = 'no-results'; |
---|
256 | } |
---|
257 | |
---|
258 | return $classes; |
---|
259 | } |
---|
260 | add_filter( 'body_class', 'wporg_themes_body_class' ); |
---|
261 | |
---|
262 | /** |
---|
263 | * Append an optimized site name. |
---|
264 | * |
---|
265 | * @param array $title { |
---|
266 | * The document title parts. |
---|
267 | * |
---|
268 | * @type string $title Title of the viewed page. |
---|
269 | * @type string $page Optional. Page number if paginated. |
---|
270 | * @type string $tagline Optional. Site description when on home page. |
---|
271 | * @type string $site Optional. Site title when not on home page. |
---|
272 | * } |
---|
273 | * @return array Filtered title parts. |
---|
274 | */ |
---|
275 | function wporg_themes_document_title( $title ) { |
---|
276 | if ( is_front_page() ) { |
---|
277 | $title['title'] = __( 'WordPress Themes', 'wporg-themes' ); |
---|
278 | $title['tagline'] = __( 'WordPress.org', 'wporg-themes' ); |
---|
279 | } elseif ( is_category() || is_tag() || is_tax() ) { |
---|
280 | /* translators: Category or tag name */ |
---|
281 | $title['title'] = sprintf( |
---|
282 | __( 'WordPress Themes: %s Free', 'wporg-themes' ), |
---|
283 | single_term_title( '', false ) |
---|
284 | ); |
---|
285 | } elseif ( is_author() ) { |
---|
286 | $title['title'] = sprintf( |
---|
287 | __( 'Themes by %s', 'wporg-themes' ), |
---|
288 | get_queried_object()->display_name ?: get_queried_object()->user_nicename |
---|
289 | ); |
---|
290 | } |
---|
291 | |
---|
292 | if ( ! is_front_page() ) { |
---|
293 | if ( is_singular( 'repopackage' ) ) { |
---|
294 | $title['title'] .= ' - ' . __( 'WordPress theme', 'wporg-themes' ); |
---|
295 | } |
---|
296 | $title['site'] = __( 'WordPress.org', 'wporg-themes' ); |
---|
297 | } |
---|
298 | |
---|
299 | return $title; |
---|
300 | } |
---|
301 | add_filter( 'document_title_parts', 'wporg_themes_document_title' ); |
---|
302 | |
---|
303 | /** |
---|
304 | * Set the separator for the document title. |
---|
305 | * |
---|
306 | * @return string Document title separator. |
---|
307 | */ |
---|
308 | add_filter( 'document_title_separator', function() { |
---|
309 | return '|'; |
---|
310 | } ); |
---|
311 | |
---|
312 | /** |
---|
313 | * Adds meta description for front page. |
---|
314 | * |
---|
315 | * @param array $tags Array that consists of meta name and meta content pairs. |
---|
316 | */ |
---|
317 | function wporg_themes_meta_tags( $tags ) { |
---|
318 | if ( is_front_page() ) { |
---|
319 | $tags['description'] = __( 'Find the perfect theme for your WordPress website. Choose from thousands of stunning designs with a wide variety of features and customization options.', 'wporg-themes' ); |
---|
320 | } elseif ( is_author() ) { |
---|
321 | $tags['description'] = sprintf( |
---|
322 | __( 'See all WordPress themes developed by %s.', 'wporg-themes' ), |
---|
323 | get_queried_object()->display_name ?: get_queried_object()->user_nicename |
---|
324 | ); |
---|
325 | } |
---|
326 | |
---|
327 | return $tags; |
---|
328 | } |
---|
329 | add_filter( 'jetpack_seo_meta_tags', 'wporg_themes_meta_tags' ); |
---|
330 | |
---|
331 | /** |
---|
332 | * Overrides feeds to use a custom RSS2 feed which contains the current requests themes. |
---|
333 | */ |
---|
334 | function wporg_themes_custom_feed() { |
---|
335 | if ( ! is_feed() ) { |
---|
336 | return; |
---|
337 | } |
---|
338 | if ( 'repopackage' != get_query_var( 'post_type' ) ) { |
---|
339 | return; |
---|
340 | } |
---|
341 | |
---|
342 | include __DIR__ . '/rss.php'; |
---|
343 | die(); |
---|
344 | } |
---|
345 | add_filter( 'template_redirect', 'wporg_themes_custom_feed', 9999 ); |
---|
346 | |
---|
347 | /** |
---|
348 | * Include view templates in the footer. |
---|
349 | */ |
---|
350 | function wporg_themes_view_templates() { |
---|
351 | if ( ! is_singular( 'page' ) ) { |
---|
352 | get_template_part( 'view-templates/theme' ); |
---|
353 | get_template_part( 'view-templates/theme-preview' ); |
---|
354 | get_template_part( 'view-templates/theme-single' ); |
---|
355 | } |
---|
356 | } |
---|
357 | add_action( 'wp_footer', 'wporg_themes_view_templates' ); |
---|
358 | |
---|
359 | /** |
---|
360 | * This is a copy of get_theme_feature_list(), but with the wporg-themes text domain |
---|
361 | * |
---|
362 | * @param string $include Optional. Type of list: 'active', 'deprecated' or 'all'. Default 'active'. |
---|
363 | * @return array List of features. |
---|
364 | */ |
---|
365 | function wporg_themes_get_feature_list( $include = 'active' ) { |
---|
366 | $features = array(); |
---|
367 | |
---|
368 | if ( 'active' === $include || 'all' === $include ) { |
---|
369 | $features = array( |
---|
370 | __( 'Layout', 'wporg-themes' ) => array( |
---|
371 | 'grid-layout' => __( 'Grid Layout', 'wporg-themes' ), |
---|
372 | 'one-column' => __( 'One Column', 'wporg-themes' ), |
---|
373 | 'two-columns' => __( 'Two Columns', 'wporg-themes' ), |
---|
374 | 'three-columns' => __( 'Three Columns', 'wporg-themes' ), |
---|
375 | 'four-columns' => __( 'Four Columns', 'wporg-themes' ), |
---|
376 | 'left-sidebar' => __( 'Left Sidebar', 'wporg-themes' ), |
---|
377 | 'right-sidebar' => __( 'Right Sidebar', 'wporg-themes' ), |
---|
378 | 'wide-blocks' => __( 'Wide Blocks', 'wporg-themes' ), |
---|
379 | ), |
---|
380 | __( 'Features', 'wporg-themes' ) => array( |
---|
381 | 'accessibility-ready' => __( 'Accessibility Ready', 'wporg-themes' ), |
---|
382 | 'block-patterns' => __( 'Block Editor Patterns', 'wporg-themes' ), |
---|
383 | 'block-styles' => __( 'Block Editor Styles', 'wporg-themes' ), |
---|
384 | 'buddypress' => __( 'BuddyPress', 'wporg-themes' ), |
---|
385 | 'custom-background' => __( 'Custom Background', 'wporg-themes' ), |
---|
386 | 'custom-colors' => __( 'Custom Colors', 'wporg-themes' ), |
---|
387 | 'custom-header' => __( 'Custom Header', 'wporg-themes' ), |
---|
388 | 'custom-logo' => __( 'Custom Logo', 'wporg-themes' ), |
---|
389 | 'custom-menu' => __( 'Custom Menu', 'wporg-themes' ), |
---|
390 | 'editor-style' => __( 'Editor Style', 'wporg-themes' ), |
---|
391 | 'featured-image-header' => __( 'Featured Image Header', 'wporg-themes' ), |
---|
392 | 'featured-images' => __( 'Featured Images', 'wporg-themes' ), |
---|
393 | 'flexible-header' => __( 'Flexible Header', 'wporg-themes' ), |
---|
394 | 'footer-widgets' => __( 'Footer Widgets', 'wporg-themes' ), |
---|
395 | 'front-page-post-form' => __( 'Front Page Posting', 'wporg-themes' ), |
---|
396 | 'full-site-editing' => __( 'Full Site Editing', 'wporg-themes' ), |
---|
397 | 'full-width-template' => __( 'Full Width Template', 'wporg-themes' ), |
---|
398 | 'microformats' => __( 'Microformats', 'wporg-themes' ), |
---|
399 | 'post-formats' => __( 'Post Formats', 'wporg-themes' ), |
---|
400 | 'rtl-language-support' => __( 'RTL Language Support', 'wporg-themes' ), |
---|
401 | 'sticky-post' => __( 'Sticky Post', 'wporg-themes' ), |
---|
402 | 'template-editing' => __( 'Template Editing', 'wporg-themes' ), |
---|
403 | 'theme-options' => __( 'Theme Options', 'wporg-themes' ), |
---|
404 | 'threaded-comments' => __( 'Threaded Comments', 'wporg-themes' ), |
---|
405 | 'translation-ready' => __( 'Translation Ready', 'wporg-themes' ), |
---|
406 | ), |
---|
407 | __( 'Subject', 'wporg-themes' ) => array( |
---|
408 | 'blog' => __( 'Blog', 'wporg-themes' ), |
---|
409 | 'e-commerce' => __( 'E-Commerce', 'wporg-themes' ), |
---|
410 | 'education' => __( 'Education', 'wporg-themes' ), |
---|
411 | 'entertainment' => __( 'Entertainment', 'wporg-themes' ), |
---|
412 | 'food-and-drink' => __( 'Food & Drink', 'wporg-themes' ), |
---|
413 | 'holiday' => __( 'Holiday', 'wporg-themes' ), |
---|
414 | 'news' => __( 'News', 'wporg-themes' ), |
---|
415 | 'photography' => __( 'Photography', 'wporg-themes' ), |
---|
416 | 'portfolio' => __( 'Portfolio', 'wporg-themes' ), |
---|
417 | ), |
---|
418 | ); |
---|
419 | } |
---|
420 | |
---|
421 | if ( 'deprecated' === $include || 'all' === $include ) { |
---|
422 | $features[ __( 'Colors', 'wporg-themes' ) ] = array( |
---|
423 | 'black' => __( 'Black', 'wporg-themes' ), |
---|
424 | 'blue' => __( 'Blue', 'wporg-themes' ), |
---|
425 | 'brown' => __( 'Brown', 'wporg-themes' ), |
---|
426 | 'gray' => __( 'Gray', 'wporg-themes' ), |
---|
427 | 'green' => __( 'Green', 'wporg-themes' ), |
---|
428 | 'orange' => __( 'Orange', 'wporg-themes' ), |
---|
429 | 'pink' => __( 'Pink', 'wporg-themes' ), |
---|
430 | 'purple' => __( 'Purple', 'wporg-themes' ), |
---|
431 | 'red' => __( 'Red', 'wporg-themes' ), |
---|
432 | 'silver' => __( 'Silver', 'wporg-themes' ), |
---|
433 | 'tan' => __( 'Tan', 'wporg-themes' ), |
---|
434 | 'white' => __( 'White', 'wporg-themes' ), |
---|
435 | 'yellow' => __( 'Yellow', 'wporg-themes' ), |
---|
436 | 'dark' => __( 'Dark', 'wporg-themes' ), |
---|
437 | 'light' => __( 'Light', 'wporg-themes' ), |
---|
438 | ); |
---|
439 | |
---|
440 | if ( 'deprecated' === $include ) { |
---|
441 | // Initialize arrays. |
---|
442 | $features[ __( 'Layout', 'wporg-themes' ) ] = array(); |
---|
443 | $features[ __( 'Features', 'wporg-themes' ) ] = array(); |
---|
444 | $features[ __( 'Subject', 'wporg-themes' ) ] = array(); |
---|
445 | } |
---|
446 | |
---|
447 | $features[ __( 'Layout', 'wporg-themes' ) ] = array_merge( $features[ __( 'Layout', 'wporg-themes' ) ], array( |
---|
448 | 'fixed-layout' => __( 'Fixed Layout', 'wporg-themes' ), |
---|
449 | 'fluid-layout' => __( 'Fluid Layout', 'wporg-themes' ), |
---|
450 | 'responsive-layout' => __( 'Responsive Layout', 'wporg-themes' ), |
---|
451 | ) ); |
---|
452 | |
---|
453 | $features[ __( 'Features', 'wporg-themes' ) ] = array_merge( $features[ __( 'Features', 'wporg-themes' ) ], array( |
---|
454 | 'blavatar' => __( 'Blavatar', 'wporg-themes' ), |
---|
455 | ) ); |
---|
456 | |
---|
457 | $features[ __( 'Subject', 'wporg-themes' ) ] = array_merge( $features[ __( 'Subject', 'wporg-themes' ) ], array( |
---|
458 | 'photoblogging' => __( 'Photoblogging', 'wporg-themes' ), |
---|
459 | 'seasonal' => __( 'Seasonal', 'wporg-themes' ), |
---|
460 | ) ); |
---|
461 | } |
---|
462 | |
---|
463 | return $features; |
---|
464 | } |
---|
465 | |
---|
466 | /** |
---|
467 | * Returns an array of [ tag_slug => translated_tag_name] tags for translation within JS |
---|
468 | * |
---|
469 | * @return array List of features. |
---|
470 | */ |
---|
471 | function wporg_themes_get_tag_translations() { |
---|
472 | $translations = array(); |
---|
473 | foreach ( wporg_themes_get_feature_list( 'all' ) as $group => $tags ) { |
---|
474 | $translations = array_merge( $translations, $tags ); |
---|
475 | } |
---|
476 | return $translations; |
---|
477 | } |
---|
478 | |
---|
479 | if ( class_exists( 'Jetpack' ) ) { |
---|
480 | include_once WP_CONTENT_DIR . '/plugins/jetpack/modules/seo-tools/jetpack-seo.php'; |
---|
481 | include_once WP_CONTENT_DIR . '/plugins/jetpack/modules/seo-tools/jetpack-seo-posts.php'; |
---|
482 | include_once WP_CONTENT_DIR . '/plugins/jetpack/modules/seo-tools/jetpack-seo-titles.php'; |
---|
483 | include_once WP_CONTENT_DIR . '/plugins/jetpack/modules/seo-tools/jetpack-seo-utils.php'; |
---|
484 | |
---|
485 | if ( class_exists( 'Jetpack_SEO' ) ) { |
---|
486 | new Jetpack_SEO; |
---|
487 | } |
---|
488 | } |
---|
489 | |
---|
490 | /** |
---|
491 | * Prints markup information in the head of a page. |
---|
492 | * |
---|
493 | * @link http://schema.org/SoftwareApplication |
---|
494 | * @link https://developers.google.com/search/docs/data-types/software-apps |
---|
495 | */ |
---|
496 | function wporg_themes_json_ld_schema() { |
---|
497 | $schema = false; |
---|
498 | |
---|
499 | // Schema for the front page. |
---|
500 | if ( is_front_page() ) { |
---|
501 | $schema = [ |
---|
502 | "@context" => "http://schema.org", |
---|
503 | "@type" => "WebSite", |
---|
504 | "name" => __( 'WordPress Themes', 'wporg-themes' ), |
---|
505 | "url" => home_url( '/' ), |
---|
506 | "potentialAction" => [ |
---|
507 | [ |
---|
508 | "@type" => "SearchAction", |
---|
509 | "target" => home_url( '/search/{search_term_string}' ), |
---|
510 | "query-input" => "required name=search_term_string" |
---|
511 | ] |
---|
512 | ] |
---|
513 | ]; |
---|
514 | |
---|
515 | // Schema for theme pages. |
---|
516 | } elseif ( is_singular( 'repopackage' ) && 'publish' === get_post_status( get_queried_object_id() ) ) { |
---|
517 | $schema = wporg_themes_json_jd_schema( get_queried_object() ); |
---|
518 | } |
---|
519 | |
---|
520 | // Print the schema. |
---|
521 | if ( $schema ) { |
---|
522 | echo PHP_EOL, '<script type="application/ld+json">', PHP_EOL; |
---|
523 | // Output URLs without escaping the slashes, and print it human readable. |
---|
524 | echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT ); |
---|
525 | echo PHP_EOL, '</script>', PHP_EOL; |
---|
526 | } |
---|
527 | } |
---|
528 | add_action( 'wp_head', 'wporg_themes_json_ld_schema' ); |
---|
529 | |
---|
530 | /** |
---|
531 | * Fetches JSON LD schema for a specific theme. |
---|
532 | * |
---|
533 | * @static |
---|
534 | * |
---|
535 | * @param \WP_Post $post Plugin to output JSON LD Schema for. |
---|
536 | * @return array Schema object. |
---|
537 | */ |
---|
538 | function wporg_themes_json_jd_schema( $post ) { |
---|
539 | |
---|
540 | $theme = wporg_themes_theme_information( $post->post_name ); |
---|
541 | |
---|
542 | $schema = []; |
---|
543 | |
---|
544 | // Add the theme 'SoftwareApplication' node. |
---|
545 | $software_application = [ |
---|
546 | "@context" => "http://schema.org", |
---|
547 | "@type" => [ |
---|
548 | "SoftwareApplication", |
---|
549 | "Product" |
---|
550 | ], |
---|
551 | "applicationCategory" => "OtherApplication", |
---|
552 | "operatingSystem" => "WordPress", |
---|
553 | "name" => $theme->name, |
---|
554 | "url" => get_permalink( $post ), |
---|
555 | "description" => $theme->description, |
---|
556 | "softwareVersion" => $theme->version, |
---|
557 | "fileFormat" => "application/zip", |
---|
558 | "downloadUrl" => $theme->download_link, |
---|
559 | "dateModified" => get_post_modified_time( 'c', false, $post ), |
---|
560 | "aggregateRating" => [ |
---|
561 | "@type" => "AggregateRating", |
---|
562 | "worstRating" => 1, |
---|
563 | "bestRating" => 5, |
---|
564 | "ratingValue" => round( $theme->rating / 20 / 0.5 )*0.5, |
---|
565 | "ratingCount" => (int) $theme->num_ratings, |
---|
566 | "reviewCount" => (int) $theme->num_ratings, |
---|
567 | ], |
---|
568 | "interactionStatistic" => [ |
---|
569 | "@type" => "InteractionCounter", |
---|
570 | "interactionType" => "http://schema.org/DownloadAction", |
---|
571 | "userInteractionCount" => $theme->downloaded, |
---|
572 | ], |
---|
573 | "image" => $theme->screenshot_url, |
---|
574 | "offers" => [ |
---|
575 | "@type" => "Offer", |
---|
576 | "url" => get_permalink( $post ), |
---|
577 | "price" => "0.00", |
---|
578 | "priceCurrency" => "USD", |
---|
579 | "seller" => [ |
---|
580 | "@type" => "Organization", |
---|
581 | "name" => "WordPress.org", |
---|
582 | "url" => "https://wordpress.org" |
---|
583 | ] |
---|
584 | ] |
---|
585 | ]; |
---|
586 | |
---|
587 | // Remove the aggregateRating node if there's no reviews. |
---|
588 | if ( ! $software_application['aggregateRating']['ratingCount'] ) { |
---|
589 | unset( $software_application['aggregateRating'] ); |
---|
590 | } |
---|
591 | |
---|
592 | $schema[] = $software_application; |
---|
593 | |
---|
594 | return $schema; |
---|
595 | } |
---|
596 | |
---|
597 | /** |
---|
598 | * Use the index.php template for various WordPress views that would otherwise be handled by the parent theme. |
---|
599 | */ |
---|
600 | function use_index_php_as_template() { |
---|
601 | return __DIR__ . '/index.php'; |
---|
602 | } |
---|
603 | add_filter( 'single_template', 'use_index_php_as_template' ); |
---|
604 | add_filter( 'archive_template', 'use_index_php_as_template' ); |
---|