Making WordPress.org


Ignore:
Timestamp:
09/04/2025 04:46:46 AM (3 months ago)
Author:
dd32
Message:

Theme Directory: Upgrade the blueprint used for Theme Review live previews.

This removes the blueprint from being static in the trac ticket, allowing for future maintenance not to break older links.

Fixes #8077.
Merges https://github.com/WordPress/wordpress.org/pull/506.
See https://github.com/WordPress/wordpress-playground/issues/2548.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/rest-api/class-theme-preview.php

    r13854 r14523  
    1212            'callback'            => array( $this, 'preview' ),
    1313            'permission_callback' => '__return_true',
     14            'args'                => array(
     15                'slug' => array(
     16                    'type'              => 'string',
     17                    'required'          => 'true',
     18                    'sanitize_callback' => 'sanitize_key',
     19                ),
     20            ),
     21        ) );
     22
     23        register_rest_route( 'themes/v1', 'review-blueprint/((?<post_id>[\d]+)-)?(?<slug>[^/]+)/(?<version>[0-9a-z.-_]+)?', array(
     24            'methods'             => WP_REST_Server::READABLE,
     25            'callback'            => array( $this, 'review' ),
     26            'permission_callback' => '__return_true',
     27            'args'                => array(
     28                // If the theme isn't (yet) published, this can be set to force loading the post.
     29                'post_id' => array(
     30                    'type'              => 'integer',
     31                    'required'          => false,
     32                    'sanitize_callback' => 'absint',
     33                ),
     34                'slug' => array(
     35                    'type'              => 'string',
     36                    'required'          => true,
     37                    'sanitize_callback' => 'sanitize_key',
     38                ),
     39                'version' => array(
     40                    'type'     => 'string',
     41                    'required' => false,
     42                ),
     43            ),
    1444        ) );
    1545
     
    1747            'methods'             => WP_REST_Server::CREATABLE,
    1848            'callback'            => array( $this, 'set_blueprint' ),
     49            'args'                => array(
     50                'slug' => array(
     51                    'type'              => 'string',
     52                    'required'          => 'true',
     53                    'sanitize_callback' => 'sanitize_key',
     54                ),
     55            ),
    1956            'permission_callback' => function( $request ) {
    2057                $theme_data    = wporg_themes_theme_information( $request['slug'] );
     
    4481
    4582        return $this->build_blueprint( $theme_data );
     83    }
     84
     85    /**
     86     * Generate a Blueprint for a theme review.
     87     */
     88    function review( $request ) {
     89        // If the theme isn't (yet) published, use the post_id hint.
     90        $preview_post = get_post( (int) $request->get_param( 'post_id' ) );
     91        if (
     92            $preview_post &&
     93            'repopackage' === $preview_post->post_type &&
     94            'publish' !== $preview_post->post_status &&
     95            $preview_post->post_name === $request->get_param( 'slug' )
     96        ) {
     97            $GLOBALS['post'] = $preview_post;
     98        }
     99
     100        $theme_data = wporg_themes_theme_information( $request->get_param( 'slug' ) );
     101
     102        return $this->build_blueprint(
     103            $theme_data,
     104            [
     105                'version' => $request->get_param( 'version' ),
     106                'review'  => true,
     107            ]
     108        );
    46109    }
    47110
     
    75138    /**
    76139     * Generate a blueprint for previewing a theme.
     140     *
     141     * @param object $theme_data Theme data as returned by wporg_themes_theme_information
     142     * @param array $params {
     143     *      Optional parameters.
     144     *      @type bool $review If true, generate a blueprint for theme review.
     145     *      @type string $version Optional. The version string, empty for latest version.
     146     * }
     147     * @return array The blueprint.
    77148     */
    78     function build_blueprint( $theme_data ) {
    79         $theme_package   = new WPORG_Themes_Repo_Package( $theme_data->slug );
     149    function build_blueprint( $theme_data, $params = array() ) {
     150        $is_theme_review = $params['review'] ?? false;
     151        $version         = $params['version'] ?? false;
     152        $theme_package   = new WPORG_Themes_Repo_Package( $theme_data->slug, $version );
    80153        $parent_package  = $theme_data->template ? new WPORG_Themes_Repo_Package( $theme_data->template ) : false;
    81154        $theme_blueprint = $theme_package->preview_blueprint;
     
    84157        $blueprint = [
    85158            'preferredVersions' => [
    86                 'php' => '8.0',
     159                'php' => defined( 'RECOMMENDED_PHP' ) ? RECOMMENDED_PHP : substr( phpversion(), 0, 3 ),
    87160                'wp'  => 'latest'
    88161            ],
     
    140213                'step'    => 'setSiteOptions',
    141214                'options' => [
    142                     'blogname'        => $theme_data->name,
     215                    'blogname'        => $theme_data->name . ( $version ? " $version" : '' ),
    143216                    'blogdescription' => preg_replace( '![.].+$!',  '.', $theme_data->sections['description'] ), // First sentence only.
     217                ]
     218            ],
     219            // Special case: BuddyPress.
     220            ! ( $theme_data->tags && in_array( 'buddypress', $theme_data->tags, true ) ) ? false : [
     221                'step' => 'installPlugin',
     222                'pluginData' => [
     223                    'resource' => 'wordpress.org/plugins',
     224                    'slug'     => 'buddypress',
     225                ],
     226                'options' => [
     227                    'activate' => true
    144228                ]
    145229            ],
     
    148232            empty( $theme_data->template ) ? false : [
    149233                'step'         => 'installTheme',
    150                 'themeZipFile' => [
     234                'themeData' => [
    151235                    'resource' => 'url',
    152236                    'url'      => $parent_package->download_url(),
     
    160244            [
    161245                'step'         => 'installTheme',
    162                 'themeZipFile' => [
     246                'themeData' => [
    163247                    'resource' => 'url',
    164248                    'url'      => $theme_package->download_url(),
    165                     'caption'  => "Downloading {$theme_package->post_title}",
     249                    'caption'  => "Downloading {$theme_package->post_title}" . ( $version ? " $version" : '' ),
     250                ],
     251                'options' => [
     252                    // Import the Starter Content if the theme didn't provide a blueprint.
     253                    'importStarterContent' => ( ! $theme_blueprint ),
    166254                ]
    167255            ]
     
    175263                if (
    176264                    ! empty( $step['themeZipFile']['url'] ) ||
    177                     ! empty( $step['pluginZipFile']['url'] )
     265                    ! empty( $step['themeData']['url'] ) ||
     266                    ! empty( $step['pluginZipFile']['url'] ) ||
     267                    ! empty( $step['pluginData']['url'] )
    178268                ) {
    179269                    return false;
     
    182272                // Don't need to install the theme again.
    183273                if ( 'installTheme' === $step['step'] ) {
    184                     if ( $theme_data->slug === ( $step['themeZipFile']['slug'] ?? '' ) ) {
     274                    if (
     275                        $theme_data->slug === ( $step['themeZipFile']['slug'] ?? '' ) ||
     276                        $theme_data->slug === ( $step['themeData']['slug'] ?? '' )
     277                    ) {
    185278                        return false;
    186279                    }
    187                     if ( ! empty( $theme_data->template ) && $theme_data->template === ( $step['themeZipFile']['slug'] ?? '' ) ) {
     280                    if (
     281                        ! empty( $theme_data->template ) &&
     282                        (
     283                            $theme_data->template === ( $step['themeZipFile']['slug'] ?? '' ) ||
     284                            $theme_data->template === ( $step['themeData']['slug'] ?? '' )
     285                        )
     286                    ) {
    188287                        return false;
    189288                    }
     
    194293        );
    195294
    196         // Fill in a theme starter content step if specified.
    197         // See: `installThemeStarterContent`. https://github.com/WordPress/wordpress-playground/pull/1521
    198         foreach ( $theme_steps as $i => $step ) {
    199             if ( 'installThemeStarterContent' === $step['step'] ) {
    200                 $theme_steps[ $i ] = $this->get_install_starter_content_step();
    201             }
    202         }
    203 
    204         // If the theme didn't provide a blueprint, we'll also install the Starter Content. This must be done last.
    205         // See also: `installThemeStarterContent`. https://github.com/WordPress/wordpress-playground/pull/1521
    206         if ( ! $theme_blueprint ) {
    207             $final_steps[] = $this->get_install_starter_content_step();
    208         }
    209 
    210         /*
    211          * TODO: These artifacts need to be hosted somewhere better.
    212          */
    213         $final_steps[] = [
    214             'step' => 'installPlugin',
    215             'pluginZipFile' => [
    216                 'resource' => 'url',
    217                 'url'      => 'https://raw.githubusercontent.com/WordPress/wordpress.org/trunk/wp-themes.com/public_html/wp-content/plugins/pattern-page.zip',
    218             ],
    219         ];
    220         $final_steps[] = [
    221             'step' => 'installPlugin',
    222             'pluginZipFile' => [
    223                 'resource' => 'url',
    224                 'url'      => 'https://raw.githubusercontent.com/WordPress/wordpress.org/trunk/wp-themes.com/public_html/wp-content/plugins/style-variations.zip',
    225             ],
    226         ];
     295        // Install the Theme Previewer plugins.
     296        if ( ! $is_theme_review ) {
     297            /*
     298             * TODO: These artifacts need to be hosted somewhere better.
     299             */
     300
     301            $final_steps[] = [
     302                'step' => 'installPlugin',
     303                'pluginData' => [
     304                    'resource' => 'url',
     305                    'url'      => 'https://raw.githubusercontent.com/WordPress/wordpress.org/trunk/wp-themes.com/public_html/wp-content/plugins/pattern-page.zip',
     306                ],
     307            ];
     308            $final_steps[] = [
     309                'step' => 'installPlugin',
     310                'pluginData' => [
     311                    'resource' => 'url',
     312                    'url'      => 'https://raw.githubusercontent.com/WordPress/wordpress.org/trunk/wp-themes.com/public_html/wp-content/plugins/style-variations.zip',
     313                ],
     314            ];
     315        }
     316
     317        // Theme Review specifics.
     318        if ( $is_theme_review ) {
     319            // Enable Debug mode.
     320            $final_steps[] = [
     321                'step' => 'defineWpConfigConsts',
     322                'consts' => [
     323                    'WP_DEBUG' => true
     324                ]
     325            ];
     326
     327            // Install Theme Check.
     328            $final_steps[] = [
     329                'step' => 'installPlugin',
     330                'pluginData' => [
     331                    'resource' => 'wordpress.org/plugins',
     332                    'slug'     => 'theme-check',
     333                ],
     334                'options' => [
     335                    'activate' => true
     336                ]
     337            ];
     338
     339            // Install the test content.
     340            $final_steps[] = [
     341                'step' => 'importWxr',
     342                'file' => [
     343                    'resource' => 'url',
     344                    'url'      => 'https://raw.githubusercontent.com/WordPress/theme-test-data/master/themeunittestdata.wordpress.xml',
     345                    'caption'  => 'Downloading theme testing content'
     346                ]
     347            ];
     348        }
    227349
    228350        // Set the steps.
     
    235357        return $blueprint;
    236358    }
    237 
    238     /**
    239      * Returns a formed step to install the starter content.
    240      */
    241     function get_install_starter_content_step() {
    242         return [
    243             'step' => 'runPHP',
    244             'code' => '<?php
    245                 playground_add_filter( "plugins_loaded", "importThemeStarterContent_plugins_loaded", 0 );
    246                 function importThemeStarterContent_plugins_loaded() {
    247                     /* Set as the admin user, this ensures we can customize the site. */
    248                     wp_set_current_user(
    249                         get_users( [ "role" => "Administrator" ] )[0]
    250                     );
    251 
    252                     /*
    253                      * Simulate this request as a ajax customizer save, with the current theme in preview mode.
    254                      *
    255                      * See _wp_customize_include()
    256                      */
    257                     add_filter( "wp_doing_ajax", "__return_true" );
    258                     $_REQUEST["action"]          = "customize_save";
    259                     $_REQUEST["wp_customize"]    = "on";
    260                     $_REQUEST["customize_theme"] = get_stylesheet();
    261                     $_GET                        = $_REQUEST;
    262 
    263                     /* Force the site to be fresh, although it should already be, some themes require this. */
    264                     add_filter( "pre_option_fresh_site", "__return_true" );
    265                 }
    266 
    267                 require "/wordpress/wp-load.php";
    268 
    269                 if ( ! get_theme_starter_content() ) {
    270                     return;
    271                 }
    272 
    273                 /* Import the Starter Content. */
    274                 $wp_customize->import_theme_starter_content();
    275 
    276                 /* Publish the changeset, which publishes the starter content. */
    277                 wp_publish_post( $wp_customize->changeset_post_id() );
    278             '
    279         ];
    280     }
    281359}
    282360new Theme_Preview();
Note: See TracChangeset for help on using the changeset viewer.