Changeset 14523
- Timestamp:
- 09/04/2025 04:46:46 AM (10 months ago)
- Location:
- sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory
- Files:
-
- 3 edited
-
class-wporg-themes-repo-package.php (modified) (5 diffs)
-
class-wporg-themes-upload.php (modified) (1 diff)
-
rest-api/class-theme-preview.php (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-repo-package.php
r13853 r14523 17 17 18 18 /** 19 * Holds the Version string for this instance of the class. 20 * 21 * NOTE: This may not be the latest version of the theme. 22 * 23 * @var string 24 */ 25 public $version = ''; 26 27 /** 19 28 * Construct a new Package for the given post ID or object. 20 29 * 21 30 * @param WP_Post|int|slug $wp_post The Post object, Post ID, or theme slug of the package. 31 * @param string|bool $version Optional. The version string, or false for latest version. 22 32 */ 23 public function __construct( $wp_post = 0 ) {33 public function __construct( $wp_post = 0, $version = false ) { 24 34 global $post; 25 35 if ( ! $wp_post ) { … … 53 63 } 54 64 } 65 66 $this->version = $version; 67 if ( $this->wp_post ) { 68 if ( ! $version || 'latest' === $version || 'latest-stable' === $version ) { 69 $this->version = $this->latest_version(); 70 } 71 } 55 72 } 56 73 … … 61 78 */ 62 79 public function screenshot_url() { 63 $screen = 'screenshot.png'; 64 $version = $this->latest_version(); 80 $screen = 'screenshot.png'; 65 81 66 if ( ! empty( $this->wp_post->_screenshot[ $ version ] ) ) {67 $screen = $this->wp_post->_screenshot[ $ version ];82 if ( ! empty( $this->wp_post->_screenshot[ $this->version ] ) ) { 83 $screen = $this->wp_post->_screenshot[ $this->version ]; 68 84 } 69 85 70 86 return sprintf( 'https://i0.wp.com/themes.svn.wordpress.org/%1$s/%2$s/%3$s', 71 87 $this->wp_post->post_name, 72 $ version,88 $this->version, 73 89 $screen 74 90 ); … … 109 125 * @return string 110 126 */ 111 public function download_url( $version = 'latest-stable' ) { 127 public function download_url( $version = false ) { 128 $version = $version ?: $this->version; 112 129 if ( 'latest-stable' === $version ) { 113 130 $version = $this->latest_version(); … … 137 154 */ 138 155 public function __get( $name ) { 139 $version = $this->latest_version();140 156 switch ( $name ) { 141 157 case 'version' : 142 158 return $version; 143 159 case 'theme-url' : 144 return $this->wp_post->_theme_url[ $ version ] ?? '';160 return $this->wp_post->_theme_url[ $this->version ] ?? ''; 145 161 case 'author-url' : 146 return $this->wp_post->_author_url[ $ version ] ?? '';162 return $this->wp_post->_author_url[ $this->version ] ?? ''; 147 163 case 'ticket' : 148 return $this->wp_post->_ticket_id[ $ version ] ?? '';164 return $this->wp_post->_ticket_id[ $this->version ] ?? ''; 149 165 case 'requires': 150 return $this->wp_post->_requires[ $ version ] ?? '';166 return $this->wp_post->_requires[ $this->version ] ?? ''; 151 167 case 'requires-php': 152 return $this->wp_post->_requires_php[ $ version ] ?? '';168 return $this->wp_post->_requires_php[ $this->version ] ?? ''; 153 169 default: 154 170 return $this->wp_post->$name; -
sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php
r14512 r14523 1160 1160 $theme_zip_link = "https://downloads.wordpress.org/theme/{$this->theme_slug}.{$this->theme->display( 'Version' )}.zip?nostats=1"; 1161 1161 1162 // Build the Live Preview Blueprint & URL. 1163 $blueprint_parent_step = ''; 1164 if ( 1165 $this->theme->parent() && 1166 in_array( 'buddypress', $this->theme->get( 'Tags' ) ) 1167 ) { 1168 $blueprint_parent_step = <<<BLUEPRINT_PARENT_BP 1169 { 1170 "step": "installPlugin", 1171 "pluginZipFile": { 1172 "resource": "wordpress.org/plugins", 1173 "slug": "buddypress" 1174 }, 1175 "options": { 1176 "activate": true 1177 } 1178 }, 1179 BLUEPRINT_PARENT_BP; 1180 } elseif ( $this->theme->parent() ) { 1181 $blueprint_parent_step = <<<BLUEPRINT_PARENT_THEME 1182 { 1183 "step": "installTheme", 1184 "themeZipFile": { 1185 "resource": "wordpress.org/themes", 1186 "slug": "{$this->theme->get_template()}" 1187 } 1188 }, 1189 BLUEPRINT_PARENT_THEME; 1190 } 1191 1192 // NOTE: The username + password included below are only used for the local in-browser environment, and are not a secret. 1193 $blueprint = <<<BLUEPRINT 1194 { 1195 "preferredVersions": { 1196 "php": "7.4", 1197 "wp": "latest" 1198 }, 1199 "steps": [ 1200 { 1201 "step": "login", 1202 "username": "admin", 1203 "password": "password" 1204 }, 1205 { 1206 "step": "defineWpConfigConsts", 1207 "consts": { 1208 "WP_DEBUG": true 1209 } 1210 }, 1211 { 1212 "step": "importFile", 1213 "file": { 1214 "resource": "url", 1215 "url": "https://raw.githubusercontent.com/WordPress/theme-test-data/master/themeunittestdata.wordpress.xml", 1216 "caption": "Downloading theme testing content" 1217 }, 1218 "progress": { 1219 "caption": "Installing theme testing content" 1220 } 1221 }, 1222 { 1223 "step": "installPlugin", 1224 "pluginZipFile": { 1225 "resource": "wordpress.org/plugins", 1226 "slug": "theme-check" 1227 }, 1228 "options": { 1229 "activate": true 1230 } 1231 }, 1232 {$blueprint_parent_step} 1233 { 1234 "step": "installTheme", 1235 "themeZipFile": { 1236 "resource": "url", 1237 "url": "{$theme_zip_link}", 1238 "caption": "Downloading the theme" 1239 } 1240 } 1241 ] 1242 } 1243 BLUEPRINT; 1244 1245 // NOTE: The json_encode( json_decode() ) is to remove the whitespaces used above for readability. 1246 $live_preview_link = 'https://playground.wordpress.net/#' . json_encode( json_decode( $blueprint ) ); 1162 $live_preview_link = add_query_arg( 1163 'blueprint-url', 1164 urlencode( rest_url( 'themes/v1/review-blueprint/' . $this->theme_post->ID . '-' . $this->theme_slug . '/' . $this->theme->display( 'Version' ) ) ), 1165 'https://playground.wordpress.net/' 1166 ); 1247 1167 1248 1168 // Hacky way to prevent a problem with xml-rpc. -
sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/rest-api/class-theme-preview.php
r13854 r14523 12 12 'callback' => array( $this, 'preview' ), 13 13 '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 ), 14 44 ) ); 15 45 … … 17 47 'methods' => WP_REST_Server::CREATABLE, 18 48 'callback' => array( $this, 'set_blueprint' ), 49 'args' => array( 50 'slug' => array( 51 'type' => 'string', 52 'required' => 'true', 53 'sanitize_callback' => 'sanitize_key', 54 ), 55 ), 19 56 'permission_callback' => function( $request ) { 20 57 $theme_data = wporg_themes_theme_information( $request['slug'] ); … … 44 81 45 82 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 ); 46 109 } 47 110 … … 75 138 /** 76 139 * 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. 77 148 */ 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 ); 80 153 $parent_package = $theme_data->template ? new WPORG_Themes_Repo_Package( $theme_data->template ) : false; 81 154 $theme_blueprint = $theme_package->preview_blueprint; … … 84 157 $blueprint = [ 85 158 'preferredVersions' => [ 86 'php' => '8.0',159 'php' => defined( 'RECOMMENDED_PHP' ) ? RECOMMENDED_PHP : substr( phpversion(), 0, 3 ), 87 160 'wp' => 'latest' 88 161 ], … … 140 213 'step' => 'setSiteOptions', 141 214 'options' => [ 142 'blogname' => $theme_data->name ,215 'blogname' => $theme_data->name . ( $version ? " $version" : '' ), 143 216 '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 144 228 ] 145 229 ], … … 148 232 empty( $theme_data->template ) ? false : [ 149 233 'step' => 'installTheme', 150 'theme ZipFile' => [234 'themeData' => [ 151 235 'resource' => 'url', 152 236 'url' => $parent_package->download_url(), … … 160 244 [ 161 245 'step' => 'installTheme', 162 'theme ZipFile' => [246 'themeData' => [ 163 247 'resource' => 'url', 164 248 '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 ), 166 254 ] 167 255 ] … … 175 263 if ( 176 264 ! empty( $step['themeZipFile']['url'] ) || 177 ! empty( $step['pluginZipFile']['url'] ) 265 ! empty( $step['themeData']['url'] ) || 266 ! empty( $step['pluginZipFile']['url'] ) || 267 ! empty( $step['pluginData']['url'] ) 178 268 ) { 179 269 return false; … … 182 272 // Don't need to install the theme again. 183 273 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 ) { 185 278 return false; 186 279 } 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 ) { 188 287 return false; 189 288 } … … 194 293 ); 195 294 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 } 227 349 228 350 // Set the steps. … … 235 357 return $blueprint; 236 358 } 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' => '<?php245 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 }281 359 } 282 360 new Theme_Preview();
Note: See TracChangeset
for help on using the changeset viewer.