Making WordPress.org

Changeset 13649


Ignore:
Timestamp:
05/02/2024 06:47:34 AM (9 months ago)
Author:
dd32
Message:

Plugin Directory: Review API: Expand the API used for reviews.

  • Make it work for all plugins, regardless of status.
  • Include the ZIPs
  • Include helpful links.

See #7385.

Location:
sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory
Files:
3 edited
1 moved

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/class-base.php

    r13610 r13649  
    4040        new Routes\Plugin_Upload();
    4141        new Routes\Plugin_Blueprint();
    42         new Routes\Pending_Plugin();
     42        new Routes\Plugin_Review();
    4343    }
    4444
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/api/routes/class-plugin-review.php

    r13648 r13649  
    11<?php
    22namespace WordPressdotorg\Plugin_Directory\API\Routes;
     3use WordPressdotorg\Plugin_Directory\Shortcodes\Upload_Handler;
    34use WordPressdotorg\Plugin_Directory\API\Base;
     5use WordPressdotorg\Plugin_Directory\Template;
    46use WP_Error;
    57use WP_REST_Server;
    68
    79/**
    8  * An API Endpoint to expose a single Plugin data via api.wordpress.org/plugins/info/1.x
     10 * Plugin-review related endpoints.
    911 *
    1012 * @package WordPressdotorg_Plugin_Directory
    1113 */
    12 class Pending_Plugin extends Base {
     14class Plugin_Review extends Base {
    1315
    1416    /**
     
    1618     */
    1719    function __construct() {
    18         register_rest_route( 'plugins/v1', '/pending-plugin/(?P<plugin_id>\d+)-(?P<token>[a-f0-9]{32})/?', array(
     20        // An API Endpoint to expose more detailed plugin data for a pending plugin.
     21        register_rest_route( 'plugins/v1', '/plugin-review/(?P<plugin_id>\d+)-(?P<token>[a-f0-9]{32})/?', array(
    1922            'methods'             => WP_REST_Server::READABLE,
    20             'callback'            => array( $this, 'pending_plugin_info' ),
    21             'permission_callback' => array( $this, 'pending_plugin_permission_check' ),
     23            'callback'            => array( $this, 'plugin_review_info' ),
     24            'permission_callback' => array( $this, 'plugin_info_permission_check' ),
    2225        ) );
    2326    }
     
    2932     * @return array A formatted array of all the data for the plugin.
    3033     */
    31     public function pending_plugin_permission_check( $request ) {
     34    public function plugin_info_permission_check( $request ) {
    3235        $post          = get_post( $request['plugin_id'] );
    33         $expected_hash = $post->{'_pending_access_token'} ?? false;
     36        $expected_hash = wp_hash( $post->ID, 'plugin-review' );
    3437
    3538        return (
     
    4245
    4346    /**
     47     * Append a link to the plugin review info endpoint to a URL.
     48     *
     49     * @param string   $url  The URL.
     50     * @param \WP_Post $post The WP post.
     51     * @return string
     52     */
     53    public static function append_plugin_review_info_url( $url, $post ) {
     54        if ( ! $url || ! $post || str_contains( $url, '#wporgapi:' ) ) {
     55            return $url;
     56        }
     57
     58        // Append with a anchor, such that CLI environments don't require special handling.
     59        $url .= '#wporgapi:' . self::get_plugin_review_info_url( $post );
     60
     61        return $url;
     62    }
     63    /**
     64     * Fetch the URL to the plugin review info endpoint.
     65     */
     66    public static function get_plugin_review_info_url( $post ) {
     67        return rest_url( sprintf(
     68            'plugins/v1/plugin-review/%d-%s/',
     69            $post->ID,
     70            wp_hash( $post->ID, 'plugin-review' )
     71        ) );
     72    }
     73
     74    /**
    4475     * Endpoint to retrieve a full plugin representation for a pending plugin.
    4576     *
     
    4778     * @return array A formatted array of all the data for the plugin.
    4879     */
    49     public function pending_plugin_info( $request ) {
     80    public function plugin_review_info( $request ) {
    5081        $post      = get_post( $request['plugin_id'] );
    5182        $submitter = get_user_by( 'id', $post->post_author );
    5283
    53         if ( ! $post || ! in_array( $post->post_status, [ 'new', 'pending', 'rejected', 'approved' ] ) ) {
     84        if ( ! $post ) {
    5485            return new WP_Error( 'plugin_not_found', 'Plugin not found', [ 'status' => 404 ] );
    5586        }
    5687
    57         // Pending plugin specific fields
     88        // Review-specific fields.
    5889        $details = [
    59             'ID'          => $post->ID,
    60             'post_status' => $post->post_status,
    61             'edit_url'    => add_query_arg( [ 'action' => 'edit', 'post' => $post->ID ], admin_url( 'post.php' ) ),
    62             'submitter'   => [
     90            'ID'            => $post->ID,
     91            'post_status'   => $post->post_status,
     92            'edit_url'      => add_query_arg( [ 'action' => 'edit', 'post' => $post->ID ], admin_url( 'post.php' ) ),
     93            'helpscout'     => null, // Link to Review email (or most recent open email)
     94            'submitter'     => [
    6395                'user_login' => $submitter->user_login,
    6496                'user_email' => $submitter->user_email,
    65             ]
     97            ],
     98            'zips'          => [],
    6699        ];
    67100
    68         $plugin_endpoint = new Plugin;
     101        // Append the public api fields.
     102        $details = $details + (new Plugin)->plugin_info_data( $request, $post );
    69103
    70         return $details + $plugin_endpoint->plugin_info_data( $request, $post );
     104        // When the plugin is pre-publish, we'll overwrite some fields.
     105        if ( in_array( $post->post_status, [ 'new', 'pending', 'approved' ] ) ) {
     106            $details['download_link'] = null;
     107            $details['preview_link']  = null;
     108        }
     109
     110        $attachments = get_attached_media( 'application/zip', $post );
     111        if ( $attachments ) {
     112            foreach ( $attachments as $zip_file ) {
     113                $url     = self::append_plugin_review_info_url( wp_get_attachment_url( $zip_file->ID ), $post );
     114                $preview = Template::preview_link_zip( $post->post_name, $zip_file->ID, 'pcp' );
     115
     116                $details['zips'][] = [
     117                    'url'     => $url,
     118                    'name'    => $zip_file->submitted_name ?: preg_split( '/[?#]/', basename( $url ) )[0],
     119                    'date'    => $zip_file->post_date,
     120                    'version' => $zip_file->version,
     121                    'note'    => $zip_file->post_content,
     122                    'preview' => $preview,
     123                ];
     124            }
     125
     126            // Use the last one, which should be the latest.
     127            $details['download_link'] ??= $url;
     128            $details['preview_link']  ??= $preview;
     129        }
     130
     131        // For a published plugin, append the API url.
     132        $details['download_link'] = self::append_plugin_review_info_url( $details['download_link'], $post );
     133
     134        return $details;
    71135    }
    72136}
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/class-plugin-directory.php

    r13640 r13649  
    18471847     * Add additional context to ZIP urls.
    18481848     *
    1849      * The ZIP URL will have a 'info' key attached which is a rest api URL to information about the plugin.
     1849     * The ZIP URL will have URL suffixed which is a rest api URL to information about the plugin.
    18501850     *
    18511851     * @param string $url           The URL to the ZIP file.
    1852      * @param int    $attachment_id The attachment ID.
     1852     * @param int    $attachment_id The attachment ID, or post ID.
    18531853     * @return string The URL to the ZIP file.
    18541854     */
    18551855    public function add_info_to_zip_url( $url, $attachment_id ) {
    1856         $attachment = get_post( $attachment_id );
    1857         $post       = get_post( $attachment->post_parent );
    1858         $token      = $post->{'_pending_access_token'} ?? false;
    1859 
    1860         if ( ! $url || ! $attachment || ! $post || ! $token || ! current_user_can( 'edit_post', $post->ID ) ) {
     1856        $post = get_post( $attachment_id );
     1857        if ( 'attachment' === $post->post_type ) {
     1858            $post = get_post( $post->post_parent );
     1859        }
     1860
     1861        if ( ! $url || ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
    18611862            return $url;
    18621863        }
    18631864
    18641865        // Append with a anchor, such that CLI environments don't require special handling.
    1865         $url .= '#wporgapi:' . rest_url( sprintf(
    1866             'plugins/v1/pending-plugin/%d-%s/',
    1867             $post->ID,
    1868             $token
    1869         ) );
    1870 
    1871         return $url;
     1866        return API\Routes\Plugin_Review::append_plugin_review_info_url( $url, $post );
    18721867    }
    18731868
  • sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload-handler.php

    r13610 r13649  
    469469        // First time submission, track some additional metadata.
    470470        if ( ! $updating_existing ) {
    471             $post_args['meta_input']['_author_ip']            = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
    472             $post_args['meta_input']['_submitted_date']       = time();
    473             $post_args['meta_input']['_used_upload_token']    = $has_upload_token;
    474             $post_args['meta_input']['_pending_access_token'] = md5( wp_generate_password( 32, true, true ) );
     471            $post_args['meta_input']['_author_ip']         = preg_replace( '/[^0-9a-fA-F:., ]/', '', $_SERVER['REMOTE_ADDR'] );
     472            $post_args['meta_input']['_submitted_date']    = time();
     473            $post_args['meta_input']['_used_upload_token'] = $has_upload_token;
    475474        }
    476475
     
    741740        global $wpdb;
    742741
    743         if ( 'pending' !== $post->post_status || ! $post->post_name ) {
     742        if ( ! in_array( $post->post_status, [ 'new', 'pending' ] ) || ! $post->post_name ) {
    744743            return false;
    745744        }
Note: See TracChangeset for help on using the changeset viewer.