Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Update_Cloud_CSS
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 5
342
0.00% covered (danger)
0.00%
0 / 1
 name
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 request_methods
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 response
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
182
 flatten_url_errors
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 permissions
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Save generated cloud critical CSS.
4 *
5 * This endpoint is used by WP.com to push the generated CSS to the boost plugin.
6 */
7
8namespace Automattic\Jetpack_Boost\REST_API\Endpoints;
9
10use Automattic\Jetpack_Boost\Lib\Critical_CSS\Critical_CSS_State;
11use Automattic\Jetpack_Boost\Lib\Critical_CSS\Critical_CSS_Storage;
12use Automattic\Jetpack_Boost\REST_API\Contracts\Endpoint;
13use Automattic\Jetpack_Boost\REST_API\Permissions\Signed_With_Blog_Token;
14use WP_REST_Server;
15
16/**
17 * Handler for POST cloud-css/update. Expects the following body params:
18 * - success: boolean - False if the whole Critical CSS job failed.
19 * - message: string containing an error message if success is false.
20 * - providers: Object containing one result for each provider_key:
21 *
22 * Each provider key contains:
23 * - success: boolean - False if this provider key failed.
24 * - data: Either a successful CSS block, or a CSS error.
25 *
26 * Each CSS block looks like:
27 * - css: string - containing CSS data.
28 *
29 * Each CSS error looks like:
30 * - urls: Object describing each URL which failed. Keys are URLs.
31 *
32 * Each URL failure looks like:
33 * - message: string - containing an error message.
34 * - type: string - machine readable error type.
35 * - meta: Object - JSON string compatible object containing extra metadata for consumption in the UI.
36 */
37class Update_Cloud_CSS implements Endpoint {
38
39    public function name() {
40        return 'cloud-css/update';
41    }
42
43    public function request_methods() {
44        return WP_REST_Server::EDITABLE;
45    }
46
47    public function response( $request ) {
48        $state          = new Critical_CSS_State();
49        $storage        = new Critical_CSS_Storage();
50        $params         = $request->get_params();
51        $providers      = empty( $params['providers'] ) || ! is_array( $params['providers'] ) ? array() : $params['providers'];
52        $api_successful = array( 'success' => true );
53
54        // If success is false, the whole Cloud CSS generation process failed.
55        if ( empty( $params['success'] ) ) {
56            if ( empty( $params['message'] ) || ! is_string( $params['message'] ) ) {
57                $error = __( 'An unknown error occurred', 'jetpack-boost' );
58            } else {
59                $error = $params['message'];
60            }
61
62            $state->set_error( $error );
63            $state->save();
64
65            return $api_successful;
66        }
67
68        // Update each provider.
69        foreach ( $providers as $provider_key => $result ) {
70            if ( ! isset( $result['data'] ) ) {
71                return new \WP_Error( 'invalid_data', __( 'Invalid request; missing data element', 'jetpack-boost' ) );
72            }
73
74            $data = $result['data'];
75
76            // Success
77            if ( ! empty( $result['success'] ) && ! empty( $data['css'] ) && is_string( $data['css'] ) ) {
78                $storage->store_css( $provider_key, $data['css'] );
79                $state->set_provider_success( $provider_key );
80                continue;
81            }
82
83            // Failures must have an array of urls.
84            if ( empty( $data['urls'] ) || ! is_array( $data['urls'] ) ) {
85                return new \WP_Error( 'invalid_data', __( 'Invalid request; missing urls element', 'jetpack-boost' ) );
86            }
87
88            $state->set_provider_errors( $provider_key, $this->flatten_url_errors( $data['urls'] ) );
89        }
90
91        // Save the state changes.
92        $state->save();
93
94        return $api_successful;
95    }
96
97    /**
98     * Errors arrive from Shield in an associative array with the URL as the key.
99     * This function flattens the array into a list of assoc arrays with the URL in each member.
100     */
101    private function flatten_url_errors( $errors ) {
102        $flat_errors = array();
103
104        foreach ( $errors as $url => $error ) {
105            $flat_errors[] = array_merge( array( 'url' => $url ), $error );
106        }
107
108        return $flat_errors;
109    }
110
111    public function permissions() {
112        return array(
113            new Signed_With_Blog_Token(),
114        );
115    }
116}