Making WordPress.org

source: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-themes/functions.php

Last change on this file was 11883, checked in by dufresnesteven, 6 weeks ago

wporg-themes: Remove block from theme, prefer block plugin

Related: r18887

  • Property svn:eol-style set to native
File size: 20.8 KB
Line 
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 */
16function 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}
35add_action( 'after_setup_theme', 'wporg_themes_setup' );
36
37/**
38 * Handle redirects which redirect_canonical() usually would (or should) do.
39 */
40function 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 */
133function 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 &#124; ${title_suffix}",
166                                        'home'     => __( 'WordPress Themes', 'wporg-themes' ) . " &#124; ${title_suffix}",
167                                        'theme'    => '%s - ' . __( 'WordPress theme', 'wporg-themes' ) . " &#124; ${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                                        ) . " &#124; ${title_suffix}",
174                                        /* translators: %s: Category/Browse section */
175                                        'tax'      => __( 'WordPress Themes: %s Free', 'wporg-themes' ) . " &#124; ${title_suffix}",
176                                        /* translators: %s: Search term */
177                                        'search'   => __( 'Search Results for &#8220;%s&#8221;', 'wporg-themes' ) . " &#124; ${title_suffix}",
178                                        'notfound' => __( 'Page not found', 'wporg-themes' ) . " &#124; ${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}
228add_action( 'wp_enqueue_scripts', 'wporg_themes_scripts' );
229
230// Disable mentions script in Theme Directory.
231add_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 */
244function 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}
260add_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 */
275function 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}
301add_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 */
308add_filter( 'document_title_separator', function() {
309        return '&#124;';
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 */
317function 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}
329add_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 */
334function 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}
345add_filter( 'template_redirect', 'wporg_themes_custom_feed', 9999 );
346
347/**
348 * Include view templates in the footer.
349 */
350function 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}
357add_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 */
365function 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 */
471function 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
479if ( 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 */
496function 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}
528add_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 */
538function 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 */
600function use_index_php_as_template() {
601        return __DIR__ . '/index.php';
602}
603add_filter( 'single_template',  'use_index_php_as_template' );
604add_filter( 'archive_template', 'use_index_php_as_template' );
Note: See TracBrowser for help on using the repository browser.