Making WordPress.org

Changeset 12848


Ignore:
Timestamp:
08/17/2023 07:43:02 AM (17 months ago)
Author:
dd32
Message:

Theme Directory: API: Cache a theme not existing, and perform some sanitization on the slug before querying for that theme.

This should have no backwards compatibility issues.

Location:
sites/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/api.wordpress.org/public_html/themes/info/1.0/index.php

    r11200 r12848  
    11<?php
     2namespace WordPressdotorg\API\Themes\Info;
     3use function WordPressdotorg\API\load_wordpress;
     4
     5// This exposes the `load_wordpress()` function mentioned below.
     6require dirname( dirname( dirname( __DIR__ ) ) ) . '/wp-init-ondemand.php';
     7
     8//  wp_cache_switch_to_blog( WPORG_THEME_DIRECTORY_BLOGID ); // Uses is_multisite() which is unavailable.
     9$wp_object_cache->blog_prefix = WPORG_THEME_DIRECTORY_BLOGID;
     10
     11// Helper methods
     12function wp_unslash( $value ) {
     13    if ( is_string( $value ) ) {
     14        return stripslashes( $value );
     15    }
     16    if ( is_array( $value ) ) {
     17        return array_map( __FUNCTION__, $value );
     18    }
     19
     20    return $value;
     21}
     22
     23/**
     24 * Bails out with an error message.
     25 *
     26 * @param string $error Error message.
     27 * @param int    $code  HTTP status code.
     28 */
     29function send_error( $error, $code = 404 ) {
     30    global $format;
     31
     32    header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' ' . $code, true, $code );
     33
     34    $response = (object) [
     35        'error' => $error   
     36    ];
     37
     38    // Browsers get a nicer action not implemented error.
     39    if (
     40        'GET' === $_SERVER['REQUEST_METHOD'] &&
     41        false === strpos( $_SERVER['HTTP_USER_AGENT'] ?? '', 'WordPress/' ) &&
     42        false !== strpos( $error, 'Action not implemented.' )
     43    ) {
     44        header( 'Content-Type: text/html; charset=utf-8' );
     45        die( "<p>{$error}</p>" );
     46    }
     47
     48    // Back-compat behaviour for the 1.0/1.1 API's
     49    if (
     50        defined( 'THEMES_API_VERSION' ) && THEMES_API_VERSION < 1.2 &&
     51        'Theme not found' == $response->error
     52    ) {
     53        $response = false;
     54    }
     55
     56    if ( 'php' === $format ) {
     57        echo serialize( $response );
     58    } else {
     59        // JSON format
     60        echo json_encode( $response );
     61    }
     62
     63    die();
     64}
    265
    366if ( ! defined( 'THEMES_API_VERSION' ) ) {
    467    define( 'THEMES_API_VERSION', '1.0' );
    568}
    6 
    7 // Load WordPress as the Theme Directory in order to avoid having to switch sites after loading.
    8 $wp_init_host = 'https://wordpress.org/themes/';
    9 require dirname( dirname( dirname( __DIR__ ) ) ) . '/wp-init.php';
    1069
    1170// Set up action and request information.
     
    2483}
    2584
    26 $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
     85$action = $_REQUEST['action'] ?? '';
     86
     87// Validate the request.
     88switch ( $action ) {
     89    case 'theme_information':
     90        // Validate the slug provided is valid.
     91        $slug = $request->slug ?? '';
     92        if ( ! $slug ) {
     93            send_error( 'Slug not provided' );
     94        }
     95        if ( ! is_string( $slug ) || ! preg_match( '/^[a-z0-9-]+$/', $slug ) ) {
     96            send_error( 'Invalid slug provided' );
     97        }
     98
     99        // Check to see if this theme has been specified as not existing.
     100        if ( 'not_found' === wp_cache_get( $slug, 'theme_information_error' ) ) {
     101            send_error( 'Theme not found' );
     102        }
     103        break;
     104    case 'query_themes':
     105    case 'hot_tags':
     106    case 'feature_list':
     107    case 'get_commercial_shops':
     108        // No validation for now, but valid endpoints.
     109        break;
     110    default:
     111        send_error( 'Action not implemented. <a href="https://codex.wordpress.org/WordPress.org_API">API Docs</a>' );
     112        die();
     113}
     114
     115/**
     116 * Load WordPress, to serve this request.
     117 *
     118 * TODO: This causes a significant CPU load for the server, this should be cached in Memcache in addition to the existing caching.
     119 */
     120load_wordpress( 'https://wordpress.org/themes/' );
    27121
    28122// Serve an API request.
     
    32126
    33127echo $api->get_result( $format );
     128
     129// Cache when a theme doesn't exist. See the validation handler above.
     130if ( 'theme_information' == $action && 404 == http_response_code() ) {
     131    wp_cache_set( $slug, 'not_found', 'theme_information_error', WEEK_IN_SECONDS );
     132}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/themes-api.php

    r8915 r12848  
    2222
    2323    wp_cache_set( $slug, $theme_meta, $cache_group );
     24
     25    // Delete the error cache if this theme is new.
     26    wp_cache_delete( $slug, 'theme_information_error' );
    2427}
    2528add_action( 'wporg_themes_update_version_live', 'wporg_themes_update_check', 10, 2 );
Note: See TracChangeset for help on using the changeset viewer.