/var/www/html_us/wp-content/plugins/woocommerce/src/Internal/Utilities/LegacyRestApiStub.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<?php

namespace Automattic\WooCommerce\Internal\Utilities;

use 
Automattic\WooCommerce\Internal\RegisterHooksInterface;
use 
Automattic\WooCommerce\Utilities\RestApiUtil;

/**
 * The Legacy REST API was removed in WooCommerce 9.0 and is now available as a dedicated extension.
 * A stub is kept in WooCommerce core that acts when the extension is not installed and has two purposes:
 *
 * 1. Return a "The WooCommerce API is disabled on this site" error for any request to the Legacy REST API endpoints.
 *
 * 2. Provide the not-endpoint related utility methods that were previously supplied by the WC_API class,
 *    this is achieved by setting the value of WooCommerce::api (typically accessed via 'WC()->api') to an instance of this class.
 *
 * DO NOT add any additional public method to this class unless the method existed with the same signature in the old WC_API class.
 *
 * See: https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/
 */
class LegacyRestApiStub implements RegisterHooksInterface {

    
/**
     * The instance of RestApiUtil to use.
     *
     * @var RestApiUtil
     */
    
private RestApiUtil $rest_api_util;

    
/**
     * Set up the Legacy REST API endpoints stub.
     */
    
public function register() {
        
add_action'init', array( __CLASS__'add_rewrite_rules_for_legacy_rest_api_stub' ), );
        
add_action'query_vars', array( __CLASS__'add_query_vars_for_legacy_rest_api_stub' ), );
        
add_action'parse_request', array( __CLASS__'parse_legacy_rest_api_request' ), );
    }

    
/**
     * Initialize the class dependencies.
     *
     * @internal
     * @param RestApiUtil $rest_api_util The instance of RestApiUtil to use.
     */
    
final public function initRestApiUtil $rest_api_util ) {
        
$this->rest_api_util $rest_api_util;
    }

    
/**
     * Add the necessary rewrite rules for the Legacy REST API
     * (either the dedicated extension if it's installed, or the stub otherwise).
     *
     * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
     */
    
public static function add_rewrite_rules_for_legacy_rest_api_stub() {
        
add_rewrite_rule'^wc-api/v([1-3]{1})/?$''index.php?wc-api-version=$matches[1]&wc-api-route=/''top' );
        
add_rewrite_rule'^wc-api/v([1-3]{1})(.*)?''index.php?wc-api-version=$matches[1]&wc-api-route=$matches[2]''top' );
        
add_rewrite_endpoint'wc-api'EP_ALL );
    }

    
/**
     * Add the necessary request query variables for the Legacy REST API
     * (either the dedicated extension if it's installed, or the stub otherwise).
     *
     * @param array $vars The query variables array to extend.
     * @return array The extended query variables array.
     *
     * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
     */
    
public static function add_query_vars_for_legacy_rest_api_stub$vars ) {
        
$vars[] = 'wc-api-version';
        
$vars[] = 'wc-api-route';
        
$vars[] = 'wc-api';
        return 
$vars;
    }

    
/**
     * Process an incoming request for the Legacy REST API.
     *
     * If the dedicated Legacy REST API extension is installed and active, this method does nothing.
     * Otherwise it returns a "The WooCommerce API is disabled on this site" error,
     * unless the request contains a "wc-api" variable and the appropriate
     * "woocommerce_api_*" hook is set.
     *
     * @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
     */
    
public static function parse_legacy_rest_api_request() {
        global 
$wp;

        
// The WC_Legacy_REST_API_Plugin class existence means that the Legacy REST API extension is installed and active.
        
if ( class_exists'WC_Legacy_REST_API_Plugin' ) ) {
            return;
        }

        
self::maybe_process_wc_api_query_var();

        
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput

        
if ( ! empty( $_GET['wc-api-version'] ) ) {
            
$wp->query_vars['wc-api-version'] = $_GET['wc-api-version'];
        }

        if ( ! empty( 
$_GET['wc-api-route'] ) ) {
            
$wp->query_vars['wc-api-route'] = $_GET['wc-api-route'];
        }

        if ( ! empty( 
$wp->query_vars['wc-api-version'] ) && ! empty( $wp->query_vars['wc-api-route'] ) ) {
            
header(
                
sprintf(
                    
'Content-Type: %s; charset=%s',
                    isset( 
$_GET['_jsonp'] ) ? 'application/javascript' 'application/json',
                    
get_option'blog_charset' )
                )
            );
            
status_header404 );
            echo 
wp_json_encode(
                array(
                    
'errors' => array(
                        
'code'    => 'woocommerce_api_disabled',
                        
'message' => 'The WooCommerce API is disabled on this site',
                    ),
                )
            );
            exit;
        }

        
// phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput
    
}

    
/**
     * Process a "wc-api" variable if present in the query, by triggering the appropriate hooks.
     */
    
private static function maybe_process_wc_api_query_var() {
        global 
$wp;

        
// phpcs:disable WordPress.Security.NonceVerification.Recommended
        
if ( ! empty( $_GET['wc-api'] ) ) {
            
$wp->query_vars['wc-api'] = sanitize_keywp_unslash$_GET['wc-api'] ) );
        }
        
// phpcs:enable WordPress.Security.NonceVerification.Recommended

        // wc-api endpoint requests.
        
if ( ! empty( $wp->query_vars['wc-api'] ) ) {

            
// Buffer, we won't want any output here.
            
ob_start();

            
// No cache headers.
            
wc_nocache_headers();

            
// Clean the API request.
            
$api_request strtolowerwc_clean$wp->query_vars['wc-api'] ) );

            
// Make sure gateways are available for request.
            
WC()->payment_gateways();

            
// phpcs:disable WooCommerce.Commenting.CommentHooks.HookCommentWrongStyle

            // Trigger generic action before request hook.
            
do_action'woocommerce_api_request'$api_request );

            
// Is there actually something hooked into this API request? If not trigger 400 - Bad request.
            
status_headerhas_action'woocommerce_api_' $api_request ) ? 200 400 );

            
// Trigger an action which plugins can hook into to fulfill the request.
            
do_action'woocommerce_api_' $api_request );

            
// phpcs:enable WooCommerce.Commenting.CommentHooks.HookCommentWrongStyle

            // Done, clear buffer and exit.
            
ob_end_clean();
            die( 
'-1' );
        }
    }

    
/**
     * Get data from a WooCommerce API endpoint.
     * This method used to be part of the WooCommerce Legacy REST API.
     *
     * @since 9.1.0
     *
     * @param string $endpoint Endpoint.
     * @param array  $params Params to pass with request.
     * @return array|\WP_Error
     */
    
public function get_endpoint_data$endpoint$params = array() ) {
        
wc_doing_it_wrong(
            
'get_endpoint_data',
            
"'WC()->api->get_endpoint_data' is deprecated, please use the following instead: wc_get_container()->get(Automattic\WooCommerce\Utilities\RestApiUtil::class)->get_endpoint_data",
            
'9.1.0'
        
);

        return 
$this->rest_api_util->get_endpoint_data$endpoint$params );
    }
}