PluginProbe
Performance Lab / trunk
Performance Lab vtrunk
trunk 1.0.0 1.0.0-beta.1 1.0.0-beta.2 1.0.0-beta.3 1.0.0-rc.1 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.7.0 2.8.0 All 44 releases
performance-lab / includes / admin / rest-api.php

rest-api.php in Performance Lab trunk, at includes/admin/rest-api.php

188 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST API integration for the plugin.
4 *
5 * @package performance-lab
6 * @since 3.6.0
7 */
8
9 declare( strict_types = 1 );
10
11 // @codeCoverageIgnoreStart
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly.
14 }
15 // @codeCoverageIgnoreEnd
16
17 /**
18 * Namespace for performance-lab REST API.
19 *
20 * @since 3.6.0
21 * @var string
22 */
23 const PERFLAB_REST_API_NAMESPACE = 'performance-lab/v1';
24
25 /**
26 * Route for activating plugin/feature.
27 *
28 * Note the `:activate` art of the endpoint follows Google's guidance in AIP-136 for the use of the POST method in a way
29 * that does not strictly follow the standard usage.
30 *
31 * @since 3.6.0
32 * @link https://google.aip.dev/136
33 * @var string
34 */
35 const PERFLAB_FEATURES_ACTIVATE_ROUTE = '/features/(?P<slug>[a-z0-9_-]+):activate';
36
37 /**
38 * Route for fetching plugin/feature information.
39 *
40 * @since 3.6.0
41 * @var string
42 */
43 const PERFLAB_FEATURES_INFORMATION_ROUTE = '/features/(?P<slug>[a-z0-9_-]+)';
44
45 /**
46 * Registers endpoint for performance-lab REST API.
47 *
48 * @since 3.6.0
49 * @access private
50 */
51 function perflab_register_endpoint(): void {
52 register_rest_route(
53 PERFLAB_REST_API_NAMESPACE,
54 PERFLAB_FEATURES_ACTIVATE_ROUTE,
55 array(
56 'methods' => 'POST',
57 'args' => array(
58 'slug' => array(
59 'type' => 'string',
60 'description' => __( 'Plugin slug of the Performance Lab feature to be activated.', 'performance-lab' ),
61 'required' => true,
62 'validate_callback' => 'perflab_validate_slug_endpoint_arg',
63 ),
64 ),
65 'callback' => 'perflab_handle_feature_activation',
66 'permission_callback' => static function () {
67 // Important: The endpoint calls perflab_install_and_activate_plugin() which does more granular capability checks.
68 if ( current_user_can( 'activate_plugins' ) ) {
69 return true;
70 }
71
72 return new WP_Error( 'cannot_activate', __( 'Sorry, you are not allowed to activate this feature.', 'performance-lab' ) );
73 },
74 )
75 );
76
77 register_rest_route(
78 PERFLAB_REST_API_NAMESPACE,
79 PERFLAB_FEATURES_INFORMATION_ROUTE,
80 array(
81 'methods' => 'GET',
82 'args' => array(
83 'slug' => array(
84 'type' => 'string',
85 'description' => __( 'Plugin slug of plugin/feature whose information is needed.', 'performance-lab' ),
86 'required' => true,
87 'validate_callback' => 'perflab_validate_slug_endpoint_arg',
88 ),
89 ),
90 'callback' => 'perflab_handle_get_feature_information',
91 'permission_callback' => static function () {
92 if ( current_user_can( 'manage_options' ) ) {
93 return true;
94 }
95
96 return new WP_Error( 'cannot_access_plugin_settings_url', __( 'Sorry, you are not allowed to access plugin/feature information on this site.', 'performance-lab' ) );
97 },
98 )
99 );
100 }
101 add_action( 'rest_api_init', 'perflab_register_endpoint' );
102
103 /**
104 * Validates whether the provided plugin slug is a valid Performance Lab plugin.
105 *
106 * Note that an enum is not being used because additional PHP files have to be required to access the necessary functions,
107 * and this would not be ideal to do at rest_api_init.
108 *
109 * @since 3.6.0
110 * @access private
111 *
112 * @param string $slug Plugin slug.
113 * @return bool Whether valid.
114 */
115 function perflab_validate_slug_endpoint_arg( string $slug ): bool {
116 require_once ABSPATH . 'wp-admin/includes/plugin.php';
117 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/load.php';
118 require_once PERFLAB_PLUGIN_DIR_PATH . 'includes/admin/plugins.php';
119 return in_array( $slug, perflab_get_standalone_plugins(), true );
120 }
121
122 /**
123 * Handles REST API request to activate plugin/feature.
124 *
125 * @since 3.6.0
126 * @access private
127 *
128 * @phpstan-param WP_REST_Request<array<string, mixed>> $request
129 *
130 * @param WP_REST_Request $request Request.
131 * @return WP_REST_Response|WP_Error Response.
132 */
133 function perflab_handle_feature_activation( WP_REST_Request $request ) {
134 require_once ABSPATH . 'wp-admin/includes/file.php';
135 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
136 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
137 require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
138
139 // Install and activate the plugin/feature and its dependencies.
140 $result = perflab_install_and_activate_plugin( $request['slug'] );
141 if ( is_wp_error( $result ) ) {
142 switch ( $result->get_error_code() ) {
143 case 'cannot_install_plugin':
144 case 'cannot_activate_plugin':
145 $response_code = rest_authorization_required_code();
146 break;
147 case 'plugin_not_found':
148 $response_code = 404;
149 break;
150 default:
151 $response_code = 500;
152 }
153 return new WP_Error(
154 $result->get_error_code(),
155 $result->get_error_message(),
156 array( 'status' => $response_code )
157 );
158 }
159
160 return new WP_REST_Response(
161 array(
162 'success' => true,
163 )
164 );
165 }
166
167 /**
168 * Handles REST API request to get plugin/feature information.
169 *
170 * @since 3.6.0
171 * @access private
172 *
173 * @phpstan-param WP_REST_Request<array<string, mixed>> $request
174 *
175 * @param WP_REST_Request $request Request.
176 * @return WP_REST_Response Response.
177 */
178 function perflab_handle_get_feature_information( WP_REST_Request $request ): WP_REST_Response {
179 $plugin_settings_url = perflab_get_plugin_settings_url( $request['slug'] );
180
181 return new WP_REST_Response(
182 array(
183 'slug' => $request['slug'],
184 'settingsUrl' => $plugin_settings_url,
185 )
186 );
187 }
188