Making WordPress.org

Changeset 13649


Ignore:
Timestamp:
05/02/2024 06:47:34 AM (2 years 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.