Complex classes like WPCOM_REST_API_V2_Endpoint_External_Media often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use WPCOM_REST_API_V2_Endpoint_External_Media, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
16 | class WPCOM_REST_API_V2_Endpoint_External_Media extends WP_REST_Controller { |
||
17 | |||
18 | /** |
||
19 | * Media argument schema for /copy endpoint. |
||
20 | * |
||
21 | * @var array |
||
22 | */ |
||
23 | public $media_schema = array( |
||
24 | 'type' => 'object', |
||
25 | 'required' => true, |
||
26 | 'properties' => array( |
||
27 | 'caption' => array( |
||
28 | 'type' => 'string', |
||
29 | ), |
||
30 | 'guid' => array( |
||
31 | 'items' => array( |
||
32 | 'caption' => array( |
||
33 | 'type' => 'string', |
||
34 | ), |
||
35 | 'name' => array( |
||
36 | 'type' => 'string', |
||
37 | ), |
||
38 | 'title' => array( |
||
39 | 'type' => 'string', |
||
40 | ), |
||
41 | 'url' => array( |
||
42 | 'format' => 'uri', |
||
43 | 'type' => 'string', |
||
44 | ), |
||
45 | ), |
||
46 | 'type' => 'array', |
||
47 | ), |
||
48 | 'title' => array( |
||
49 | 'type' => 'string', |
||
50 | ), |
||
51 | ), |
||
52 | ); |
||
53 | |||
54 | /** |
||
55 | * Service regex. |
||
56 | * |
||
57 | * @var string |
||
58 | */ |
||
59 | private static $services_regex = '(?P<service>google_photos|pexels)'; |
||
60 | |||
61 | /** |
||
62 | * Temporary filename. |
||
63 | * |
||
64 | * Needed to cope with Google's very long file names. |
||
65 | * |
||
66 | * @var string |
||
67 | */ |
||
68 | private $tmp_name; |
||
69 | |||
70 | /** |
||
71 | * Constructor. |
||
72 | */ |
||
73 | public function __construct() { |
||
79 | |||
80 | /** |
||
81 | * Registers the routes for external media. |
||
82 | */ |
||
83 | public function register_routes() { |
||
156 | |||
157 | /** |
||
158 | * Checks if a given request has access to external media libraries. |
||
159 | */ |
||
160 | public function permission_callback() { |
||
163 | |||
164 | /** |
||
165 | * Checks if a given request has access to create an attachment. |
||
166 | * |
||
167 | * @param WP_REST_Request $request Full details about the request. |
||
168 | * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. |
||
169 | */ |
||
170 | public function create_item_permissions_check( $request ) { |
||
199 | |||
200 | /** |
||
201 | * Sanitization callback for media parameter. |
||
202 | * |
||
203 | * @param array $param Media parameter. |
||
204 | * @return true|\WP_Error |
||
205 | */ |
||
206 | public function sanitize_media( $param ) { |
||
211 | |||
212 | /** |
||
213 | * Validation callback for media parameter. |
||
214 | * |
||
215 | * @param array $param Media parameter. |
||
216 | * @return true|\WP_Error |
||
217 | */ |
||
218 | public function validate_media( $param ) { |
||
223 | |||
224 | /** |
||
225 | * Decodes guid json and sets parameter defaults. |
||
226 | * |
||
227 | * @param array $param Media parameter. |
||
228 | * @return array |
||
229 | */ |
||
230 | private function prepare_media_param( $param ) { |
||
246 | |||
247 | /** |
||
248 | * Retrieves media items from external libraries. |
||
249 | * |
||
250 | * @param \WP_REST_Request $request Full details about the request. |
||
251 | * @return array|\WP_Error|mixed |
||
252 | */ |
||
253 | public function get_external_media( \WP_REST_Request $request ) { |
||
254 | $params = $request->get_params(); |
||
255 | $wpcom_path = sprintf( '/meta/external-media/%s', rawurlencode( $params['service'] ) ); |
||
256 | |||
257 | if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
||
258 | $request = new \WP_REST_Request( 'GET', '/' . $this->namespace . $wpcom_path ); |
||
259 | $request->set_query_params( $params ); |
||
260 | |||
261 | return rest_do_request( $request ); |
||
262 | } |
||
263 | |||
264 | // Build query string to pass to wpcom endpoint. |
||
265 | $service_args = array_filter( |
||
266 | $params, |
||
267 | function ( $key ) { |
||
268 | return in_array( $key, array( 'search', 'number', 'path', 'page_handle', 'filter' ), true ); |
||
269 | }, |
||
270 | ARRAY_FILTER_USE_KEY |
||
271 | ); |
||
272 | if ( ! empty( $service_args ) ) { |
||
273 | $wpcom_path .= '?' . http_build_query( $service_args ); |
||
274 | } |
||
275 | |||
276 | $response = Client::wpcom_json_api_request_as_user( $wpcom_path ); |
||
277 | |||
278 | switch ( wp_remote_retrieve_response_code( $response ) ) { |
||
279 | case 200: |
||
280 | $response = json_decode( wp_remote_retrieve_body( $response ), true ); |
||
281 | break; |
||
282 | |||
283 | case 401: |
||
284 | $response = new WP_Error( |
||
285 | 'authorization_required', |
||
286 | __( 'You are not connected to that service.', 'jetpack' ), |
||
287 | array( 'status' => 403 ) |
||
288 | ); |
||
289 | break; |
||
290 | |||
291 | case 403: |
||
292 | $error = json_decode( wp_remote_retrieve_body( $response ) ); |
||
293 | $response = new WP_Error( $error->code, $error->message, $error->data ); |
||
294 | break; |
||
295 | |||
296 | default: |
||
297 | if ( is_wp_error( $response ) ) { |
||
298 | $response->add_data( array( 'status' => 400 ) ); |
||
299 | break; |
||
300 | } |
||
301 | $response = new WP_Error( |
||
302 | 'rest_request_error', |
||
303 | __( 'An unknown error has occurred. Please try again later.', 'jetpack' ), |
||
304 | array( 'status' => wp_remote_retrieve_response_code( $response ) ) |
||
305 | ); |
||
306 | } |
||
307 | |||
308 | return $response; |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Saves an external media item to the media library. |
||
313 | * |
||
314 | * @param \WP_REST_Request $request Full details about the request. |
||
315 | * @return array|\WP_Error|mixed |
||
316 | */ |
||
317 | public function copy_external_media( \WP_REST_Request $request ) { |
||
347 | |||
348 | /** |
||
349 | * Gets connection authorization details. |
||
350 | * |
||
351 | * @param \WP_REST_Request $request Full details about the request. |
||
352 | * @return array|\WP_Error|mixed |
||
353 | */ |
||
354 | public function get_connection_details( \WP_REST_Request $request ) { |
||
369 | |||
370 | /** |
||
371 | * Deletes a Google Photos connection. |
||
372 | * |
||
373 | * @param WP_REST_Request $request Full details about the request. |
||
374 | * @return array|WP_Error|WP_REST_Response |
||
375 | */ |
||
376 | public function delete_connection( WP_REST_Request $request ) { |
||
397 | |||
398 | /** |
||
399 | * Filter callback to provide a shorter file name for google images. |
||
400 | * |
||
401 | * @return string |
||
402 | */ |
||
403 | public function tmp_name() { |
||
406 | |||
407 | /** |
||
408 | * Returns a download URL, dealing with Google's long file names. |
||
409 | * |
||
410 | * @param array $guid Media information. |
||
411 | * @return string|\WP_Error |
||
412 | */ |
||
413 | public function get_download_url( $guid ) { |
||
425 | |||
426 | /** |
||
427 | * Uploads media file and creates attachment object. |
||
428 | * |
||
429 | * @param string $file_name Name of media file. |
||
430 | * @param string $download_url Download URL. |
||
431 | * @param int $post_id The ID of the post to attach the image to. |
||
432 | * |
||
433 | * @return int|\WP_Error |
||
434 | */ |
||
435 | public function sideload_media( $file_name, $download_url, $post_id = 0 ) { |
||
449 | |||
450 | /** |
||
451 | * Updates attachment meta data for media item. |
||
452 | * |
||
453 | * @param int $id Attachment ID. |
||
454 | * @param array $item Media item. |
||
455 | */ |
||
456 | public function update_attachment_meta( $id, $item ) { |
||
471 | |||
472 | /** |
||
473 | * Retrieves attachment data for media item. |
||
474 | * |
||
475 | * @param int $id Attachment ID. |
||
476 | * @param array $item Media item. |
||
477 | * |
||
478 | * @return array|\WP_REST_Response Attachment data on success, WP_Error on failure. |
||
479 | */ |
||
480 | public function get_attachment_data( $id, $item ) { |
||
501 | } |
||
502 | |||
504 |
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.