├── .gitignore ├── README.md ├── api ├── class-wc-rest-dev-coupons-controller.php ├── class-wc-rest-dev-customer-downloads-controller.php ├── class-wc-rest-dev-customers-controller.php ├── class-wc-rest-dev-data-continents-controller.php ├── class-wc-rest-dev-data-controller.php ├── class-wc-rest-dev-data-countries-controller.php ├── class-wc-rest-dev-data-currencies-controller.php ├── class-wc-rest-dev-order-notes-controller.php ├── class-wc-rest-dev-order-refunds-controller.php ├── class-wc-rest-dev-orders-controller.php ├── class-wc-rest-dev-payment-gateways-controller.php ├── class-wc-rest-dev-product-attribute-terms-controller.php ├── class-wc-rest-dev-product-attributes-controller.php ├── class-wc-rest-dev-product-categories-controller.php ├── class-wc-rest-dev-product-reviews-controller.php ├── class-wc-rest-dev-product-shipping-classes-controller.php ├── class-wc-rest-dev-product-tags-controller.php ├── class-wc-rest-dev-product-variations-controller.php ├── class-wc-rest-dev-products-controller.php ├── class-wc-rest-dev-report-sales-controller.php ├── class-wc-rest-dev-report-top-sellers-controller.php ├── class-wc-rest-dev-reports-controller.php ├── class-wc-rest-dev-setting-options-controller.php ├── class-wc-rest-dev-settings-controller.php ├── class-wc-rest-dev-shipping-methods-controller.php ├── class-wc-rest-dev-shipping-zone-locations-controller.php ├── class-wc-rest-dev-shipping-zone-methods-controller.php ├── class-wc-rest-dev-shipping-zones-controller.php ├── class-wc-rest-dev-system-status-controller.php ├── class-wc-rest-dev-system-status-tools-controller.php ├── class-wc-rest-dev-tax-classes-controller.php ├── class-wc-rest-dev-taxes-controller.php └── class-wc-rest-dev-webhooks-controller.php ├── assets ├── icon-128x128.png └── icon-256x256.png ├── composer.json ├── phpunit.xml ├── readme.txt ├── tests ├── bootstrap.php ├── framework │ └── helpers │ │ ├── class-wc-helper-order-note.php │ │ └── class-wc-helper-order-refund.php └── unit-tests │ ├── coupons.php │ ├── customers.php │ ├── data-counts.php │ ├── data.php │ ├── functions.php │ ├── order-notes.php │ ├── order-refunds.php │ ├── orders.php │ ├── payment-gateways.php │ ├── product-reviews.php │ ├── product-variations.php │ ├── products.php │ ├── settings.php │ ├── shipping-methods.php │ ├── shipping-zones.php │ └── system-status.php ├── wc-api-dev-class.php └── wc-api-dev.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Editors 2 | project.xml 3 | project.properties 4 | /nbproject/private/ 5 | .buildpath 6 | .project 7 | .settings* 8 | .idea 9 | 10 | # OS X metadata 11 | .DS_Store 12 | 13 | # Windows junk 14 | Thumbs.db 15 | 16 | # Unit tests 17 | /tmp 18 | /tests/bin/tmp 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WooCommerce API Dev 2 | 3 | This is a repository is obsolete, WooCommerce REST API is now located in https://github.com/woocommerce/woocommerce-rest-api 4 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-coupons-controller.php: -------------------------------------------------------------------------------- 1 | /downloads endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 2.6.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Customers controller class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Customer_Downloads_Controller extends WC_REST_Customer_Downloads_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-customers-controller.php: -------------------------------------------------------------------------------- 1 | namespace, '/' . $this->rest_base, array( 46 | array( 47 | 'methods' => WP_REST_Server::READABLE, 48 | 'callback' => array( $this, 'get_items' ), 49 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 50 | ), 51 | 'schema' => array( $this, 'get_public_item_schema' ), 52 | ) ); 53 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\w-]+)', array( 54 | array( 55 | 'methods' => WP_REST_Server::READABLE, 56 | 'callback' => array( $this, 'get_item' ), 57 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 58 | 'args' => array( 59 | 'continent' => array( 60 | 'description' => __( '2 character continent code.', 'woocommerce' ), 61 | 'type' => 'string', 62 | ), 63 | ), 64 | ), 65 | 'schema' => array( $this, 'get_public_item_schema' ), 66 | ) ); 67 | } 68 | 69 | /** 70 | * Return the list of countries and states for a given continent. 71 | * 72 | * @since 3.1.0 73 | * @param string $continent_code 74 | * @param WP_REST_Request $request 75 | * @return array|mixed Response data, ready for insertion into collection data. 76 | */ 77 | public function get_continent( $continent_code = false, $request ) { 78 | $continents = WC()->countries->get_continents(); 79 | $countries = WC()->countries->get_countries(); 80 | $states = WC()->countries->get_states(); 81 | $locale_info = include WC()->plugin_path() . '/i18n/locale-info.php'; 82 | $data = array(); 83 | 84 | if ( ! array_key_exists( $continent_code, $continents ) ) { 85 | return false; 86 | } 87 | 88 | $continent_list = $continents[ $continent_code ]; 89 | 90 | $continent = array( 91 | 'code' => $continent_code, 92 | 'name' => $continent_list['name'], 93 | ); 94 | 95 | $local_countries = array(); 96 | foreach ( $continent_list['countries'] as $country_code ) { 97 | if ( isset( $countries[ $country_code ] ) ) { 98 | $country = array( 99 | 'code' => $country_code, 100 | 'name' => $countries[ $country_code ], 101 | ); 102 | 103 | // If we have detailed locale information include that in the response 104 | if ( array_key_exists( $country_code, $locale_info ) ) { 105 | // Defensive programming against unexpected changes in locale-info.php 106 | $country_data = wp_parse_args( $locale_info[ $country_code ], array( 107 | 'currency_code' => 'USD', 108 | 'currency_pos' => 'left', 109 | 'decimal_sep' => '.', 110 | 'dimension_unit' => 'in', 111 | 'num_decimals' => 2, 112 | 'thousand_sep' => ',', 113 | 'weight_unit' => 'lbs', 114 | ) ); 115 | 116 | $country = array_merge( $country, $country_data ); 117 | } 118 | 119 | $local_states = array(); 120 | if ( isset( $states[ $country_code ] ) ) { 121 | foreach ( $states[ $country_code ] as $state_code => $state_name ) { 122 | $local_states[] = array( 123 | 'code' => $state_code, 124 | 'name' => $state_name, 125 | ); 126 | } 127 | } 128 | $country['states'] = $local_states; 129 | 130 | // Allow only desired keys (e.g. filter out tax rates) 131 | $allowed = array( 132 | 'code', 133 | 'currency_code', 134 | 'currency_pos', 135 | 'decimal_sep', 136 | 'dimension_unit', 137 | 'name', 138 | 'num_decimals', 139 | 'states', 140 | 'thousand_sep', 141 | 'weight_unit', 142 | ); 143 | $country = array_intersect_key( $country, array_flip( $allowed ) ); 144 | 145 | $local_countries[] = $country; 146 | } 147 | } 148 | 149 | $continent['countries'] = $local_countries; 150 | return $continent; 151 | } 152 | 153 | /** 154 | * Return the list of states for all continents. 155 | * 156 | * @since 3.1.0 157 | * @param WP_REST_Request $request 158 | * @return WP_Error|WP_REST_Response 159 | */ 160 | public function get_items( $request ) { 161 | $continents = WC()->countries->get_continents(); 162 | $data = array(); 163 | 164 | foreach ( array_keys( $continents ) as $continent_code ) { 165 | $continent = $this->get_continent( $continent_code, $request ); 166 | $response = $this->prepare_item_for_response( $continent, $request ); 167 | $data[] = $this->prepare_response_for_collection( $response ); 168 | } 169 | 170 | return rest_ensure_response( $data ); 171 | } 172 | 173 | /** 174 | * Return the list of locations for a given continent. 175 | * 176 | * @since 3.1.0 177 | * @param WP_REST_Request $request 178 | * @return WP_Error|WP_REST_Response 179 | */ 180 | public function get_item( $request ) { 181 | $data = $this->get_continent( strtoupper( $request['location'] ), $request ); 182 | if ( empty( $data ) ) { 183 | return new WP_Error( 'woocommerce_rest_data_invalid_location', __( 'There are no locations matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) ); 184 | } 185 | return $this->prepare_item_for_response( $data, $request ); 186 | } 187 | 188 | /** 189 | * Prepare the data object for response. 190 | * 191 | * @since 3.1.0 192 | * @param object $item Data object. 193 | * @param WP_REST_Request $request Request object. 194 | * @return WP_REST_Response $response Response data. 195 | */ 196 | public function prepare_item_for_response( $item, $request ) { 197 | $data = $this->add_additional_fields_to_object( $item, $request ); 198 | $data = $this->filter_response_by_context( $data, 'view' ); 199 | $response = rest_ensure_response( $data ); 200 | 201 | $response->add_links( $this->prepare_links( $item ) ); 202 | 203 | /** 204 | * Filter the location list returned from the API. 205 | * 206 | * Allows modification of the loction data right before it is returned. 207 | * 208 | * @param WP_REST_Response $response The response object. 209 | * @param array $item The original list of continent(s), countries, and states. 210 | * @param WP_REST_Request $request Request used to generate the response. 211 | */ 212 | return apply_filters( 'woocommerce_rest_prepare_data_continent', $response, $item, $request ); 213 | } 214 | 215 | /** 216 | * Prepare links for the request. 217 | * 218 | * @param object $item Data object. 219 | * @return array Links for the given continent. 220 | */ 221 | protected function prepare_links( $item ) { 222 | $continent_code = strtolower( $item['code'] ); 223 | $links = array( 224 | 'self' => array( 225 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $continent_code ) ), 226 | ), 227 | 'collection' => array( 228 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), 229 | ), 230 | ); 231 | return $links; 232 | } 233 | 234 | /** 235 | * Get the location schema, conforming to JSON Schema. 236 | * 237 | * @since 3.1.0 238 | * @return array 239 | */ 240 | public function get_item_schema() { 241 | $schema = array( 242 | '$schema' => 'http://json-schema.org/draft-04/schema#', 243 | 'title' => 'data_continents', 244 | 'type' => 'object', 245 | 'properties' => array( 246 | 'code' => array( 247 | 'type' => 'string', 248 | 'description' => __( '2 character continent code.', 'woocommerce' ), 249 | 'context' => array( 'view' ), 250 | 'readonly' => true, 251 | ), 252 | 'name' => array( 253 | 'type' => 'string', 254 | 'description' => __( 'Full name of continent.', 'woocommerce' ), 255 | 'context' => array( 'view' ), 256 | 'readonly' => true, 257 | ), 258 | 'countries' => array( 259 | 'type' => 'array', 260 | 'description' => __( 'List of countries on this continent.', 'woocommerce' ), 261 | 'context' => array( 'view' ), 262 | 'readonly' => true, 263 | 'items' => array( 264 | 'type' => 'object', 265 | 'context' => array( 'view' ), 266 | 'readonly' => true, 267 | 'properties' => array( 268 | 'code' => array( 269 | 'type' => 'string', 270 | 'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ), 271 | 'context' => array( 'view' ), 272 | 'readonly' => true, 273 | ), 274 | 'currency_code' => array( 275 | 'type' => 'string', 276 | 'description' => __( 'Default ISO4127 alpha-3 currency code for the country.', 'woocommerce' ), 277 | 'context' => array( 'view' ), 278 | 'readonly' => true, 279 | ), 280 | 'currency_pos' => array( 281 | 'type' => 'string', 282 | 'description' => __( 'Currency symbol position for this country.', 'woocommerce' ), 283 | 'context' => array( 'view' ), 284 | 'readonly' => true, 285 | ), 286 | 'decimal_sep' => array( 287 | 'type' => 'string', 288 | 'description' => __( 'Decimal separator for displayed prices for this country.', 'woocommerce' ), 289 | 'context' => array( 'view' ), 290 | 'readonly' => true, 291 | ), 292 | 'dimension_unit' => array( 293 | 'type' => 'string', 294 | 'description' => __( 'The unit lengths are defined in for this country.', 'woocommerce' ), 295 | 'context' => array( 'view' ), 296 | 'readonly' => true, 297 | ), 298 | 'name' => array( 299 | 'type' => 'string', 300 | 'description' => __( 'Full name of country.', 'woocommerce' ), 301 | 'context' => array( 'view' ), 302 | 'readonly' => true, 303 | ), 304 | 'num_decimals' => array( 305 | 'type' => 'integer', 306 | 'description' => __( 'Number of decimal points shown in displayed prices for this country.', 'woocommerce' ), 307 | 'context' => array( 'view' ), 308 | 'readonly' => true, 309 | ), 310 | 'states' => array( 311 | 'type' => 'array', 312 | 'description' => __( 'List of states in this country.', 'woocommerce' ), 313 | 'context' => array( 'view' ), 314 | 'readonly' => true, 315 | 'items' => array( 316 | 'type' => 'object', 317 | 'context' => array( 'view' ), 318 | 'readonly' => true, 319 | 'properties' => array( 320 | 'code' => array( 321 | 'type' => 'string', 322 | 'description' => __( 'State code.', 'woocommerce' ), 323 | 'context' => array( 'view' ), 324 | 'readonly' => true, 325 | ), 326 | 'name' => array( 327 | 'type' => 'string', 328 | 'description' => __( 'Full name of state.', 'woocommerce' ), 329 | 'context' => array( 'view' ), 330 | 'readonly' => true, 331 | ), 332 | ), 333 | ), 334 | ), 335 | 'thousand_sep' => array( 336 | 'type' => 'string', 337 | 'description' => __( 'Thousands separator for displayed prices in this country.', 'woocommerce' ), 338 | 'context' => array( 'view' ), 339 | 'readonly' => true, 340 | ), 341 | 'weight_unit' => array( 342 | 'type' => 'string', 343 | 'description' => __( 'The unit weights are defined in for this country.', 'woocommerce' ), 344 | 'context' => array( 'view' ), 345 | 'readonly' => true, 346 | ), 347 | ), 348 | ), 349 | ), 350 | ), 351 | ); 352 | 353 | return $this->add_additional_fields_schema( $schema ); 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-data-controller.php: -------------------------------------------------------------------------------- 1 | namespace, '/' . $this->rest_base, array( 46 | array( 47 | 'methods' => WP_REST_Server::READABLE, 48 | 'callback' => array( $this, 'get_items' ), 49 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 50 | ), 51 | 'schema' => array( $this, 'get_public_item_schema' ), 52 | ) ); 53 | } 54 | 55 | /** 56 | * Check whether a given request has permission to read site data. 57 | * 58 | * @param WP_REST_Request $request Full details about the request. 59 | * @return WP_Error|boolean 60 | */ 61 | public function get_items_permissions_check( $request ) { 62 | if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) { 63 | return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 64 | } 65 | 66 | return true; 67 | } 68 | 69 | /** 70 | * Check whether a given request has permission to read site settings. 71 | * 72 | * @param WP_REST_Request $request Full details about the request. 73 | * @return WP_Error|boolean 74 | */ 75 | public function get_item_permissions_check( $request ) { 76 | if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) { 77 | return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 78 | } 79 | 80 | return true; 81 | } 82 | 83 | /** 84 | * Return the list of data resources. 85 | * 86 | * @since 3.1.0 87 | * @param WP_REST_Request $request 88 | * @return WP_Error|WP_REST_Response 89 | */ 90 | public function get_items( $request ) { 91 | $data = array(); 92 | $resources = array( 93 | array( 94 | 'slug' => 'continents', 95 | 'description' => __( 'List of supported continents, countries, and states.', 'woocommerce' ), 96 | ), 97 | array( 98 | 'slug' => 'countries', 99 | 'description' => __( 'List of supported states in a given country.', 'woocommerce' ), 100 | ), 101 | array( 102 | 'slug' => 'currencies', 103 | 'description' => __( 'List of supported currencies.', 'woocommerce' ), 104 | ), 105 | ); 106 | 107 | foreach ( $resources as $resource ) { 108 | $item = $this->prepare_item_for_response( (object) $resource, $request ); 109 | $data[] = $this->prepare_response_for_collection( $item ); 110 | } 111 | 112 | return rest_ensure_response( $data ); 113 | } 114 | 115 | /** 116 | * Prepare a data resource object for serialization. 117 | * 118 | * @param stdClass $report Report data. 119 | * @param WP_REST_Request $request Request object. 120 | * @return WP_REST_Response $response Response data. 121 | */ 122 | public function prepare_item_for_response( $resource, $request ) { 123 | $data = array( 124 | 'slug' => $resource->slug, 125 | 'description' => $resource->description, 126 | ); 127 | 128 | $data = $this->add_additional_fields_to_object( $data, $request ); 129 | $data = $this->filter_response_by_context( $data, 'view' ); 130 | 131 | // Wrap the data in a response object. 132 | $response = rest_ensure_response( $data ); 133 | $response->add_links( $this->prepare_links( $resource ) ); 134 | 135 | return $response; 136 | } 137 | 138 | /** 139 | * Prepare links for the request. 140 | * 141 | * @param object $item Data object. 142 | * @return array Links for the given country. 143 | */ 144 | protected function prepare_links( $item ) { 145 | $links = array( 146 | 'self' => array( 147 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $item->slug ) ), 148 | ), 149 | 'collection' => array( 150 | 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), 151 | ), 152 | ); 153 | 154 | return $links; 155 | } 156 | 157 | /** 158 | * Get the data index schema, conforming to JSON Schema. 159 | * 160 | * @since 3.1.0 161 | * @return array 162 | */ 163 | public function get_item_schema() { 164 | $schema = array( 165 | '$schema' => 'http://json-schema.org/draft-04/schema#', 166 | 'title' => 'data_index', 167 | 'type' => 'object', 168 | 'properties' => array( 169 | 'slug' => array( 170 | 'description' => __( 'Data resource ID.', 'woocommerce' ), 171 | 'type' => 'string', 172 | 'context' => array( 'view' ), 173 | 'readonly' => true, 174 | ), 175 | 'description' => array( 176 | 'description' => __( 'Data resource description.', 'woocommerce' ), 177 | 'type' => 'string', 178 | 'context' => array( 'view' ), 179 | 'readonly' => true, 180 | ), 181 | ), 182 | ); 183 | 184 | return $this->add_additional_fields_schema( $schema ); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-data-countries-controller.php: -------------------------------------------------------------------------------- 1 | namespace, '/' . $this->rest_base, array( 46 | array( 47 | 'methods' => WP_REST_Server::READABLE, 48 | 'callback' => array( $this, 'get_items' ), 49 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 50 | ), 51 | 'schema' => array( $this, 'get_public_item_schema' ), 52 | ) ); 53 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\w-]+)', array( 54 | array( 55 | 'methods' => WP_REST_Server::READABLE, 56 | 'callback' => array( $this, 'get_item' ), 57 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 58 | 'args' => array( 59 | 'location' => array( 60 | 'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ), 61 | 'type' => 'string', 62 | ), 63 | ), 64 | ), 65 | 'schema' => array( $this, 'get_public_item_schema' ), 66 | ) ); 67 | } 68 | 69 | /** 70 | * Get a list of countries and states. 71 | * 72 | * @param string $country_code 73 | * @param WP_REST_Request $request 74 | * @return array|mixed Response data, ready for insertion into collection data. 75 | */ 76 | public function get_country( $country_code = false, $request ) { 77 | $countries = WC()->countries->get_countries(); 78 | $states = WC()->countries->get_states(); 79 | $data = array(); 80 | 81 | if ( ! array_key_exists( $country_code, $countries ) ) { 82 | return false; 83 | } 84 | 85 | $country = array( 86 | 'code' => $country_code, 87 | 'name' => $countries[ $country_code ], 88 | ); 89 | 90 | $local_states = array(); 91 | if ( isset( $states[ $country_code ] ) ) { 92 | foreach ( $states[ $country_code ] as $state_code => $state_name ) { 93 | $local_states[] = array( 94 | 'code' => $state_code, 95 | 'name' => $state_name, 96 | ); 97 | } 98 | } 99 | $country['states'] = $local_states; 100 | return $country; 101 | } 102 | 103 | /** 104 | * Return the list of states for all countries. 105 | * 106 | * @since 3.1.0 107 | * @param WP_REST_Request $request 108 | * @return WP_Error|WP_REST_Response 109 | */ 110 | public function get_items( $request ) { 111 | $countries = WC()->countries->get_countries(); 112 | $data = array(); 113 | 114 | foreach ( array_keys( $countries ) as $country_code ) { 115 | $country = $this->get_country( $country_code, $request ); 116 | $response = $this->prepare_item_for_response( $country, $request ); 117 | $data[] = $this->prepare_response_for_collection( $response ); 118 | } 119 | 120 | return rest_ensure_response( $data ); 121 | } 122 | 123 | /** 124 | * Return the list of states for a given country. 125 | * 126 | * @since 3.1.0 127 | * @param WP_REST_Request $request 128 | * @return WP_Error|WP_REST_Response 129 | */ 130 | public function get_item( $request ) { 131 | $data = $this->get_country( strtoupper( $request['location'] ), $request ); 132 | if ( empty( $data ) ) { 133 | return new WP_Error( 'woocommerce_rest_data_invalid_location', __( 'There are no locations matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) ); 134 | } 135 | return $this->prepare_item_for_response( $data, $request ); 136 | } 137 | 138 | /** 139 | * Prepare the data object for response. 140 | * 141 | * @since 3.1.0 142 | * @param object $item Data object. 143 | * @param WP_REST_Request $request Request object. 144 | * @return WP_REST_Response $response Response data. 145 | */ 146 | public function prepare_item_for_response( $item, $request ) { 147 | $data = $this->add_additional_fields_to_object( $item, $request ); 148 | $data = $this->filter_response_by_context( $data, 'view' ); 149 | $response = rest_ensure_response( $data ); 150 | 151 | $response->add_links( $this->prepare_links( $item ) ); 152 | 153 | /** 154 | * Filter the states list for a country returned from the API. 155 | * 156 | * Allows modification of the loction data right before it is returned. 157 | * 158 | * @param WP_REST_Response $response The response object. 159 | * @param array $data The original country's states list. 160 | * @param WP_REST_Request $request Request used to generate the response. 161 | */ 162 | return apply_filters( 'woocommerce_rest_prepare_data_country', $response, $item, $request ); 163 | } 164 | 165 | /** 166 | * Prepare links for the request. 167 | * 168 | * @param object $item Data object. 169 | * @return array Links for the given country. 170 | */ 171 | protected function prepare_links( $item ) { 172 | $country_code = strtolower( $item['code'] ); 173 | $links = array( 174 | 'self' => array( 175 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $country_code ) ), 176 | ), 177 | 'collection' => array( 178 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), 179 | ), 180 | ); 181 | 182 | return $links; 183 | } 184 | 185 | 186 | /** 187 | * Get the location schema, conforming to JSON Schema. 188 | * 189 | * @since 3.1.0 190 | * @return array 191 | */ 192 | public function get_item_schema() { 193 | $schema = array( 194 | '$schema' => 'http://json-schema.org/draft-04/schema#', 195 | 'title' => 'data_countries', 196 | 'type' => 'object', 197 | 'properties' => array( 198 | 'code' => array( 199 | 'type' => 'string', 200 | 'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ), 201 | 'context' => array( 'view' ), 202 | 'readonly' => true, 203 | ), 204 | 'name' => array( 205 | 'type' => 'string', 206 | 'description' => __( 'Full name of country.', 'woocommerce' ), 207 | 'context' => array( 'view' ), 208 | 'readonly' => true, 209 | ), 210 | 'states' => array( 211 | 'type' => 'array', 212 | 'description' => __( 'List of states in this country.', 'woocommerce' ), 213 | 'context' => array( 'view' ), 214 | 'readonly' => true, 215 | 'items' => array( 216 | 'type' => 'object', 217 | 'context' => array( 'view' ), 218 | 'readonly' => true, 219 | 'properties' => array( 220 | 'code' => array( 221 | 'type' => 'string', 222 | 'description' => __( 'State code.', 'woocommerce' ), 223 | 'context' => array( 'view' ), 224 | 'readonly' => true, 225 | ), 226 | 'name' => array( 227 | 'type' => 'string', 228 | 'description' => __( 'Full name of state.', 'woocommerce' ), 229 | 'context' => array( 'view' ), 230 | 'readonly' => true, 231 | ), 232 | ), 233 | ), 234 | ), 235 | ), 236 | ); 237 | 238 | return $this->add_additional_fields_schema( $schema ); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-data-currencies-controller.php: -------------------------------------------------------------------------------- 1 | namespace, '/' . $this->rest_base, array( 42 | array( 43 | 'methods' => WP_REST_Server::READABLE, 44 | 'callback' => array( $this, 'get_items' ), 45 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), 46 | ), 47 | 'schema' => array( $this, 'get_public_item_schema' ), 48 | ) ); 49 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/current', array( 50 | array( 51 | 'methods' => WP_REST_Server::READABLE, 52 | 'callback' => array( $this, 'get_current_item' ), 53 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), 54 | ), 55 | 'schema' => array( $this, 'get_public_item_schema' ), 56 | ) ); 57 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[\w-]{3})', array( 58 | array( 59 | 'methods' => WP_REST_Server::READABLE, 60 | 'callback' => array( $this, 'get_item' ), 61 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), 62 | 'args' => array( 63 | 'location' => array( 64 | 'description' => __( 'ISO4217 currency code.', 'woocommerce' ), 65 | 'type' => 'string', 66 | ), 67 | ), 68 | ), 69 | 'schema' => array( $this, 'get_public_item_schema' ), 70 | ) ); 71 | } 72 | 73 | /** 74 | * Get currency information. 75 | * 76 | * @param string $code 77 | * @param WP_REST_Request $request 78 | * @return array|mixed Response data, ready for insertion into collection data. 79 | */ 80 | public function get_currency( $code = false, $request ) { 81 | $currencies = get_woocommerce_currencies(); 82 | $data = array(); 83 | 84 | if ( ! array_key_exists( $code, $currencies ) ) { 85 | return false; 86 | } 87 | 88 | $currency = array( 89 | 'code' => $code, 90 | 'name' => $currencies[ $code ], 91 | 'symbol' => get_woocommerce_currency_symbol( $code ), 92 | ); 93 | 94 | return $currency; 95 | } 96 | 97 | /** 98 | * Return the list of currencies. 99 | * 100 | * @param WP_REST_Request $request 101 | * @return WP_Error|WP_REST_Response 102 | */ 103 | public function get_items( $request ) { 104 | $currencies = get_woocommerce_currencies(); 105 | foreach ( array_keys( $currencies ) as $code ) { 106 | $currency = $this->get_currency( $code, $request ); 107 | $response = $this->prepare_item_for_response( $currency, $request ); 108 | $data[] = $this->prepare_response_for_collection( $response ); 109 | } 110 | 111 | return rest_ensure_response( $data ); 112 | } 113 | 114 | /** 115 | * Return information for a specific currency. 116 | * 117 | * @param WP_REST_Request $request 118 | * @return WP_Error|WP_REST_Response 119 | */ 120 | public function get_item( $request ) { 121 | $data = $this->get_currency( strtoupper( $request['currency'] ), $request ); 122 | if ( empty( $data ) ) { 123 | return new WP_Error( 'woocommerce_rest_data_invalid_currency', __( 'There are no currencies matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) ); 124 | } 125 | return $this->prepare_item_for_response( $data, $request ); 126 | } 127 | 128 | /** 129 | * Return information for the current site currency. 130 | * 131 | * @param WP_REST_Request $request 132 | * @return WP_Error|WP_REST_Response 133 | */ 134 | public function get_current_item( $request ) { 135 | $currency = get_option( 'woocommerce_currency' ); 136 | return $this->prepare_item_for_response( $this->get_currency( $currency, $request ), $request ); 137 | } 138 | 139 | /** 140 | * Prepare the data object for response. 141 | * 142 | * @param object $item Data object. 143 | * @param WP_REST_Request $request Request object. 144 | * @return WP_REST_Response $response Response data. 145 | */ 146 | public function prepare_item_for_response( $item, $request ) { 147 | $data = $this->add_additional_fields_to_object( $item, $request ); 148 | $data = $this->filter_response_by_context( $data, 'view' ); 149 | $response = rest_ensure_response( $data ); 150 | 151 | $response->add_links( $this->prepare_links( $item ) ); 152 | 153 | /** 154 | * Filter currency returned from the API. 155 | * 156 | * @param WP_REST_Response $response The response object. 157 | * @param array $item Currency data. 158 | * @param WP_REST_Request $request Request used to generate the response. 159 | */ 160 | return apply_filters( 'woocommerce_rest_prepare_data_currency', $response, $item, $request ); 161 | } 162 | 163 | /** 164 | * Prepare links for the request. 165 | * 166 | * @param object $item Data object. 167 | * @return array Links for the given currency. 168 | */ 169 | protected function prepare_links( $item ) { 170 | $code = strtoupper( $item['code'] ); 171 | $links = array( 172 | 'self' => array( 173 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $code ) ), 174 | ), 175 | 'collection' => array( 176 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), 177 | ), 178 | ); 179 | 180 | return $links; 181 | } 182 | 183 | 184 | /** 185 | * Get the currency schema, conforming to JSON Schema. 186 | * 187 | * @return array 188 | */ 189 | public function get_item_schema() { 190 | $schema = array( 191 | '$schema' => 'http://json-schema.org/draft-04/schema#', 192 | 'title' => 'data_currencies', 193 | 'type' => 'object', 194 | 'properties' => array( 195 | 'code' => array( 196 | 'type' => 'string', 197 | 'description' => __( 'ISO4217 currency code.', 'woocommerce' ), 198 | 'context' => array( 'view' ), 199 | 'readonly' => true, 200 | ), 201 | 'name' => array( 202 | 'type' => 'string', 203 | 'description' => __( 'Full name of currency.', 'woocommerce' ), 204 | 'context' => array( 'view' ), 205 | 'readonly' => true, 206 | ), 207 | 'symbol' => array( 208 | 'type' => 'string', 209 | 'description' => __( 'Currency symbol.', 'woocommerce' ), 210 | 'context' => array( 'view' ), 211 | 'readonly' => true, 212 | ), 213 | ), 214 | ); 215 | 216 | return $this->add_additional_fields_schema( $schema ); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-order-notes-controller.php: -------------------------------------------------------------------------------- 1 | /notes endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 2.6.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Order Notes controller class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Order_Notes_Controller extends WC_REST_Order_Notes_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | 31 | /** 32 | * Prepare a single order note output for response. 33 | * 34 | * @param WP_Comment $note Order note object. 35 | * @param WP_REST_Request $request Request object. 36 | * @return WP_REST_Response $response Response data. 37 | */ 38 | public function prepare_item_for_response( $note, $request ) { 39 | $data = array( 40 | 'id' => (int) $note->comment_ID, 41 | 'author' => __( 'WooCommerce', 'woocommerce' ) === $note->comment_author ? 'system' : $note->comment_author, 42 | 'date_created' => wc_rest_prepare_date_response( $note->comment_date ), 43 | 'date_created_gmt' => wc_rest_prepare_date_response( $note->comment_date_gmt ), 44 | 'note' => $note->comment_content, 45 | 'customer_note' => (bool) get_comment_meta( $note->comment_ID, 'is_customer_note', true ), 46 | ); 47 | 48 | $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 49 | $data = $this->add_additional_fields_to_object( $data, $request ); 50 | $data = $this->filter_response_by_context( $data, $context ); 51 | 52 | // Wrap the data in a response object. 53 | $response = rest_ensure_response( $data ); 54 | 55 | $response->add_links( $this->prepare_links( $note ) ); 56 | 57 | /** 58 | * Filter order note object returned from the REST API. 59 | * 60 | * @param WP_REST_Response $response The response object. 61 | * @param WP_Comment $note Order note object used to create response. 62 | * @param WP_REST_Request $request Request object. 63 | */ 64 | return apply_filters( 'woocommerce_rest_prepare_order_note', $response, $note, $request ); 65 | } 66 | 67 | /** 68 | * Create a single order note. 69 | * 70 | * @param WP_REST_Request $request Full details about the request. 71 | * @return WP_Error|WP_REST_Response 72 | */ 73 | public function create_item( $request ) { 74 | if ( ! empty( $request['id'] ) ) { 75 | /* translators: %s: post type */ 76 | return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) ); 77 | } 78 | 79 | $order = wc_get_order( (int) $request['order_id'] ); 80 | 81 | if ( ! $order || $this->post_type !== $order->get_type() ) { 82 | return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order ID.', 'woocommerce' ), array( 'status' => 404 ) ); 83 | } 84 | 85 | // Create the note. 86 | $note_id = $order->add_order_note( $request['note'], $request['customer_note'], $request['added_by_user'] ); 87 | 88 | if ( ! $note_id ) { 89 | return new WP_Error( 'woocommerce_api_cannot_create_order_note', __( 'Cannot create order note, please try again.', 'woocommerce' ), array( 'status' => 500 ) ); 90 | } 91 | 92 | $note = get_comment( $note_id ); 93 | $this->update_additional_fields_for_object( $note, $request ); 94 | 95 | /** 96 | * Fires after a order note is created or updated via the REST API. 97 | * 98 | * @param WP_Comment $note New order note object. 99 | * @param WP_REST_Request $request Request object. 100 | * @param boolean $creating True when creating item, false when updating. 101 | */ 102 | do_action( 'woocommerce_rest_insert_order_note', $note, $request, true ); 103 | 104 | $request->set_param( 'context', 'edit' ); 105 | $response = $this->prepare_item_for_response( $note, $request ); 106 | $response = rest_ensure_response( $response ); 107 | $response->set_status( 201 ); 108 | $response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, str_replace( '(?P[\d]+)', $order->get_id(), $this->rest_base ), $note_id ) ) ); 109 | 110 | return $response; 111 | } 112 | 113 | /** 114 | * Get the Order Notes schema, conforming to JSON Schema. 115 | * 116 | * @return array 117 | */ 118 | public function get_item_schema() { 119 | $schema = parent::get_item_schema(); 120 | $schema['properties']['author'] = array( 121 | 'description' => __( 'Order note author.', 'woocommerce' ), 122 | 'type' => 'string', 123 | 'readonly' => true, 124 | 'context' => array( 'view', 'edit' ), 125 | ); 126 | $schema['properties']['added_by_user'] = array( 127 | 'description' => __( 'If true, this note will be attributed to the current user. If false, the note will be attributed to the system.', 'woocommerce' ), 128 | 'type' => 'boolean', 129 | 'default' => false, 130 | 'context' => array( 'edit' ), 131 | ); 132 | return $schema; 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-order-refunds-controller.php: -------------------------------------------------------------------------------- 1 | /refunds endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 2.6.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Order Refunds controller class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Order_Refunds_Controller extends WC_REST_Order_Refunds_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | 31 | /** 32 | * Prepares one object for create or update operation. 33 | * 34 | * @since 3.0.0 35 | * @param WP_REST_Request $request Request object. 36 | * @param bool $creating If is creating a new object. 37 | * @return WP_Error|WC_Data The prepared item, or WP_Error object on failure. 38 | */ 39 | protected function prepare_object_for_database( $request, $creating = false ) { 40 | $order = wc_get_order( (int) $request['order_id'] ); 41 | 42 | if ( ! $order ) { 43 | return new WP_Error( 'woocommerce_rest_invalid_order_id', __( 'Invalid order ID.', 'woocommerce' ), 404 ); 44 | } 45 | 46 | if ( 0 > $request['amount'] ) { 47 | return new WP_Error( 'woocommerce_rest_invalid_order_refund', __( 'Refund amount must be greater than zero.', 'woocommerce' ), 400 ); 48 | } 49 | 50 | // Create the refund. 51 | $refund = wc_create_refund( 52 | array( 53 | 'order_id' => $order->get_id(), 54 | 'amount' => $request['amount'], 55 | 'reason' => empty( $request['reason'] ) ? null : $request['reason'], 56 | 'line_items' => empty( $request['line_items'] ) ? array() : $request['line_items'], 57 | 'refund_payment' => is_bool( $request['api_refund'] ) ? $request['api_refund'] : true, 58 | 'restock_items' => true, 59 | ) 60 | ); 61 | 62 | if ( is_wp_error( $refund ) ) { 63 | return new WP_Error( 'woocommerce_rest_cannot_create_order_refund', $refund->get_error_message(), 500 ); 64 | } 65 | 66 | if ( ! $refund ) { 67 | return new WP_Error( 'woocommerce_rest_cannot_create_order_refund', __( 'Cannot create order refund, please try again.', 'woocommerce' ), 500 ); 68 | } 69 | 70 | if ( ! empty( $request['meta_data'] ) && is_array( $request['meta_data'] ) ) { 71 | foreach ( $request['meta_data'] as $meta ) { 72 | $refund->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' ); 73 | } 74 | $refund->save_meta_data(); 75 | } 76 | 77 | /** 78 | * Filters an object before it is inserted via the REST API. 79 | * 80 | * The dynamic portion of the hook name, `$this->post_type`, 81 | * refers to the object type slug. 82 | * 83 | * @param WC_Data $coupon Object object. 84 | * @param WP_REST_Request $request Request object. 85 | * @param bool $creating If is creating a new object. 86 | */ 87 | return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $refund, $request, $creating ); 88 | } 89 | 90 | /** 91 | * Get the Order refund's schema, conforming to JSON Schema. 92 | * 93 | * @return array 94 | */ 95 | public function get_item_schema() { 96 | $params = parent::get_item_schema(); 97 | 98 | $params['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 99 | 100 | $params['properties']['line_items']['items']['properties']['name']['type'] = 'mixed'; 101 | $params['properties']['line_items']['items']['properties']['product_id']['type'] = 'mixed'; 102 | $params['properties']['line_items']['items']['properties']['tax_class']['type'] = 'string'; 103 | $params['properties']['line_items']['items']['properties']['price']['type'] = 'number'; 104 | $params['properties']['line_items']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 105 | 106 | return $params; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-orders-controller.php: -------------------------------------------------------------------------------- 1 | 'any', 67 | 'description' => __( 'Limit result set to orders assigned a specific status.', 'woocommerce' ), 68 | 'type' => 'array', 69 | 'items' => array( 70 | 'type' => 'string', 71 | 'enum' => array_merge( array( 'any' ), $this->get_order_statuses() ), 72 | ), 73 | 'validate_callback' => 'rest_validate_request_arg', 74 | ); 75 | 76 | return $params; 77 | } 78 | 79 | /** 80 | * Get the Order's schema, conforming to JSON Schema. 81 | * 82 | * @return array 83 | */ 84 | public function get_item_schema() { 85 | $params = parent::get_item_schema(); 86 | 87 | $params['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 88 | 89 | $params['properties']['line_items']['items']['properties']['name']['type'] = 'mixed'; 90 | $params['properties']['line_items']['items']['properties']['product_id']['type'] = 'mixed'; 91 | $params['properties']['line_items']['items']['properties']['tax_class']['type'] = 'string'; 92 | $params['properties']['line_items']['items']['properties']['price']['type'] = 'number'; 93 | $params['properties']['line_items']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 94 | 95 | $params['properties']['tax_lines']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 96 | 97 | $params['properties']['shipping_lines']['items']['properties']['method_title']['type'] = 'mixed'; 98 | $params['properties']['shipping_lines']['items']['properties']['method_id']['type'] = 'mixed'; 99 | $params['properties']['shipping_lines']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 100 | 101 | $params['properties']['fee_lines']['items']['properties']['name']['type'] = 'mixed'; 102 | $params['properties']['fee_lines']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 103 | 104 | $params['properties']['coupon_lines']['items']['properties']['code']['type'] = 'mixed'; 105 | $params['properties']['coupon_lines']['items']['properties']['meta_data']['items']['properties']['value']['type'] = 'mixed'; 106 | 107 | return $params; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-payment-gateways-controller.php: -------------------------------------------------------------------------------- 1 | $gateway->id, 40 | 'title' => $gateway->title, 41 | 'description' => $gateway->description, 42 | 'order' => isset( $order[ $gateway->id ] ) ? $order[ $gateway->id ] : '', 43 | 'enabled' => ( 'yes' === $gateway->enabled ), 44 | 'method_title' => $gateway->get_method_title(), 45 | 'method_description' => $gateway->get_method_description(), 46 | 'method_supports' => $gateway->supports, 47 | 'settings' => $this->get_settings( $gateway ), 48 | ); 49 | 50 | $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 51 | $data = $this->add_additional_fields_to_object( $item, $request ); 52 | $data = $this->filter_response_by_context( $data, $context ); 53 | 54 | $response = rest_ensure_response( $data ); 55 | $response->add_links( $this->prepare_links( $gateway, $request ) ); 56 | 57 | /** 58 | * Filter payment gateway objects returned from the REST API. 59 | * 60 | * @param WP_REST_Response $response The response object. 61 | * @param WC_Payment_Gateway $gateway Payment gateway object. 62 | * @param WP_REST_Request $request Request object. 63 | */ 64 | return apply_filters( 'woocommerce_rest_prepare_payment_gateway', $response, $gateway, $request ); 65 | } 66 | 67 | /** 68 | * Return settings associated with this payment gateway. 69 | * 70 | * @param WC_Payment_Gateway $gateway 71 | * 72 | * @return array 73 | */ 74 | public function get_settings( $gateway ) { 75 | $settings = array(); 76 | $gateway->init_form_fields(); 77 | foreach ( $gateway->form_fields as $id => $field ) { 78 | // Make sure we at least have a title and type 79 | if ( empty( $field['title'] ) || empty( $field['type'] ) ) { 80 | continue; 81 | } 82 | // Ignore 'enabled' and 'description' which get included elsewhere. 83 | if ( in_array( $id, array( 'enabled', 'description' ) ) ) { 84 | continue; 85 | } 86 | $data = array( 87 | 'id' => $id, 88 | 'label' => empty( $field['label'] ) ? $field['title'] : $field['label'], 89 | 'description' => empty( $field['description'] ) ? '' : $field['description'], 90 | 'type' => $field['type'], 91 | 'value' => empty( $gateway->settings[ $id ] ) ? '' : $gateway->settings[ $id ], 92 | 'default' => empty( $field['default'] ) ? '' : $field['default'], 93 | 'tip' => empty( $field['description'] ) ? '' : $field['description'], 94 | 'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'], 95 | ); 96 | if ( ! empty( $field['options'] ) ) { 97 | $data['options'] = $field['options']; 98 | } 99 | $settings[ $id ] = $data; 100 | } 101 | return $settings; 102 | } 103 | 104 | /** 105 | * Get the payment gateway schema, conforming to JSON Schema. 106 | * 107 | * @return array 108 | */ 109 | public function get_item_schema() { 110 | $schema = array( 111 | '$schema' => 'http://json-schema.org/draft-04/schema#', 112 | 'title' => 'payment_gateway', 113 | 'type' => 'object', 114 | 'properties' => array( 115 | 'id' => array( 116 | 'description' => __( 'Payment gateway ID.', 'woocommerce' ), 117 | 'type' => 'string', 118 | 'context' => array( 'view', 'edit' ), 119 | 'readonly' => true, 120 | ), 121 | 'title' => array( 122 | 'description' => __( 'Payment gateway title on checkout.', 'woocommerce' ), 123 | 'type' => 'string', 124 | 'context' => array( 'view', 'edit' ), 125 | ), 126 | 'description' => array( 127 | 'description' => __( 'Payment gateway description on checkout.', 'woocommerce' ), 128 | 'type' => 'string', 129 | 'context' => array( 'view', 'edit' ), 130 | ), 131 | 'order' => array( 132 | 'description' => __( 'Payment gateway sort order.', 'woocommerce' ), 133 | 'type' => 'integer', 134 | 'context' => array( 'view', 'edit' ), 135 | 'arg_options' => array( 136 | 'sanitize_callback' => 'absint', 137 | ), 138 | ), 139 | 'enabled' => array( 140 | 'description' => __( 'Payment gateway enabled status.', 'woocommerce' ), 141 | 'type' => 'boolean', 142 | 'context' => array( 'view', 'edit' ), 143 | ), 144 | 'method_title' => array( 145 | 'description' => __( 'Payment gateway method title.', 'woocommerce' ), 146 | 'type' => 'string', 147 | 'context' => array( 'view', 'edit' ), 148 | 'readonly' => true, 149 | ), 150 | 'method_description' => array( 151 | 'description' => __( 'Payment gateway method description.', 'woocommerce' ), 152 | 'type' => 'string', 153 | 'context' => array( 'view', 'edit' ), 154 | 'readonly' => true, 155 | ), 156 | 'method_supports' => array( 157 | 'description' => __( 'Supported features for this payment gateway.', 'woocommerce' ), 158 | 'type' => 'array', 159 | 'context' => array( 'view', 'edit' ), 160 | 'readonly' => true, 161 | 'items' => array( 162 | 'type' => 'string', 163 | ), 164 | ), 165 | 'settings' => array( 166 | 'description' => __( 'Payment gateway settings.', 'woocommerce' ), 167 | 'type' => 'object', 168 | 'context' => array( 'view', 'edit' ), 169 | 'properties' => array( 170 | 'id' => array( 171 | 'description' => __( 'A unique identifier for the setting.', 'woocommerce' ), 172 | 'type' => 'string', 173 | 'context' => array( 'view', 'edit' ), 174 | 'readonly' => true, 175 | ), 176 | 'label' => array( 177 | 'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ), 178 | 'type' => 'string', 179 | 'context' => array( 'view', 'edit' ), 180 | 'readonly' => true, 181 | ), 182 | 'description' => array( 183 | 'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ), 184 | 'type' => 'string', 185 | 'context' => array( 'view', 'edit' ), 186 | 'readonly' => true, 187 | ), 188 | 'type' => array( 189 | 'description' => __( 'Type of setting.', 'woocommerce' ), 190 | 'type' => 'string', 191 | 'context' => array( 'view', 'edit' ), 192 | 'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ), 193 | 'readonly' => true, 194 | ), 195 | 'value' => array( 196 | 'description' => __( 'Setting value.', 'woocommerce' ), 197 | 'type' => 'string', 198 | 'context' => array( 'view', 'edit' ), 199 | ), 200 | 'default' => array( 201 | 'description' => __( 'Default value for the setting.', 'woocommerce' ), 202 | 'type' => 'string', 203 | 'context' => array( 'view', 'edit' ), 204 | 'readonly' => true, 205 | ), 206 | 'tip' => array( 207 | 'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ), 208 | 'type' => 'string', 209 | 'context' => array( 'view', 'edit' ), 210 | 'readonly' => true, 211 | ), 212 | 'placeholder' => array( 213 | 'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ), 214 | 'type' => 'string', 215 | 'context' => array( 'view', 'edit' ), 216 | 'readonly' => true, 217 | ), 218 | ), 219 | ), 220 | ), 221 | ); 222 | 223 | return $this->add_additional_fields_schema( $schema ); 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-product-attribute-terms-controller.php: -------------------------------------------------------------------------------- 1 | /terms endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 2.6.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Product Attribute Terms controller class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Product_Attribute_Terms_Controller extends WC_REST_Product_Attribute_Terms_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | } 31 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-product-attributes-controller.php: -------------------------------------------------------------------------------- 1 | /reviews. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 2.6.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Product Reviews Controller Class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Product_Reviews_Controller extends WC_REST_Product_Reviews_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | } 31 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-product-shipping-classes-controller.php: -------------------------------------------------------------------------------- 1 | 'woocommerce_store_address', 31 | 'type' => 'text', 32 | 'option_key' => 'woocommerce_store_address', 33 | 'default' => '', 34 | ), 35 | array( 36 | 'id' => 'woocommerce_store_address_2', 37 | 'type' => 'text', 38 | 'option_key' => 'woocommerce_store_address_2', 39 | 'default' => '', 40 | ), 41 | array( 42 | 'id' => 'woocommerce_store_city', 43 | 'type' => 'text', 44 | 'option_key' => 'woocommerce_store_city', 45 | 'default' => '', 46 | ), 47 | array( 48 | 'id' => 'woocommerce_store_postcode', 49 | 'type' => 'text', 50 | 'option_key' => 'woocommerce_store_postcode', 51 | 'default' => '', 52 | ), 53 | ); 54 | 55 | // For each of the new settings, make sure the setting id doesn't 56 | // already exist in the settings array and then add it 57 | $ids = array_column( $settings, 'id' ); 58 | foreach ( $new_settings as $new_setting ) { 59 | if ( ! in_array( $new_setting['id'], $ids ) ) { 60 | $settings[] = $new_setting; 61 | } 62 | } 63 | 64 | return $settings; 65 | } 66 | add_filter( 'woocommerce_settings-general', 'wc_rest_dev_add_address_settings_to_settings_general', 999 ); 67 | 68 | /** 69 | * REST API Setting Options controller class. 70 | * 71 | * @package WooCommerce/API 72 | */ 73 | class WC_REST_Dev_Setting_Options_Controller extends WC_REST_Setting_Options_Controller { 74 | 75 | /** 76 | * WP REST API namespace/version. 77 | */ 78 | protected $namespace = 'wc/v3'; 79 | 80 | /** 81 | * Get setting data. 82 | * 83 | * @param string $group_id Group ID. 84 | * @param string $setting_id Setting ID. 85 | * @return stdClass|WP_Error 86 | */ 87 | public function get_setting( $group_id, $setting_id ) { 88 | $setting = parent::get_setting( $group_id, $setting_id ); 89 | if ( is_wp_error( $setting ) ) { 90 | return $setting; 91 | } 92 | $setting['group_id'] = $group_id; 93 | return $setting; 94 | } 95 | 96 | /** 97 | * Callback for allowed keys for each setting response. 98 | * 99 | * @param string $key Key to check 100 | * @return boolean 101 | */ 102 | public function allowed_setting_keys( $key ) { 103 | return in_array( $key, array( 104 | 'id', 105 | 'group_id', 106 | 'label', 107 | 'description', 108 | 'default', 109 | 'tip', 110 | 'placeholder', 111 | 'type', 112 | 'options', 113 | 'value', 114 | 'option_key', 115 | ) ); 116 | } 117 | 118 | /** 119 | * Get all settings in a group. 120 | * 121 | * @param string $group_id Group ID. 122 | * @return array|WP_Error 123 | */ 124 | public function get_group_settings( $group_id ) { 125 | if ( empty( $group_id ) ) { 126 | return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) ); 127 | } 128 | 129 | $settings = apply_filters( 'woocommerce_settings-' . $group_id, array() ); 130 | 131 | if ( empty( $settings ) ) { 132 | return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) ); 133 | } 134 | 135 | $filtered_settings = array(); 136 | foreach ( $settings as $setting ) { 137 | $option_key = $setting['option_key']; 138 | $setting = $this->filter_setting( $setting ); 139 | $default = isset( $setting['default'] ) ? $setting['default'] : ''; 140 | // Get the option value 141 | if ( is_array( $option_key ) ) { 142 | $option = get_option( $option_key[0] ); 143 | $setting['value'] = isset( $option[ $option_key[1] ] ) ? $option[ $option_key[1] ] : $default; 144 | } else { 145 | $admin_setting_value = WC_Admin_Settings::get_option( $option_key, $default ); 146 | $setting['value'] = $admin_setting_value; 147 | } 148 | 149 | if ( 'multi_select_countries' === $setting['type'] ) { 150 | $setting['options'] = WC()->countries->get_countries(); 151 | $setting['type'] = 'multiselect'; 152 | } elseif ( 'single_select_country' === $setting['type'] ) { 153 | $setting['type'] = 'select'; 154 | $setting['options'] = $this->get_countries_and_states(); 155 | } elseif ( 'single_select_page' === $setting['type'] ) { 156 | $pages = get_pages( array( 'sort_column' => 'menu_order', 'sort_order' => 'ASC', 'hierarchical' => 0 ) ); 157 | $options = array(); 158 | foreach ( $pages as $page ) { 159 | $options[ $page->ID ] = ! empty( $page->post_title ) ? $page->post_title : '#' . $page->ID; 160 | } 161 | $setting['type'] = 'select'; 162 | $setting['options'] = $options; 163 | } 164 | 165 | 166 | $filtered_settings[] = $setting; 167 | } 168 | 169 | return $filtered_settings; 170 | } 171 | 172 | /** 173 | * Returns a list of countries and states for use in the base location setting. 174 | * 175 | * @since 3.0.7 176 | * @return array Array of states and countries. 177 | */ 178 | private function get_countries_and_states() { 179 | $countries = WC()->countries->get_countries(); 180 | if ( ! $countries ) { 181 | return array(); 182 | } 183 | $output = array(); 184 | foreach ( $countries as $key => $value ) { 185 | if ( $states = WC()->countries->get_states( $key ) ) { 186 | foreach ( $states as $state_key => $state_value ) { 187 | $output[ $key . ':' . $state_key ] = $value . ' - ' . $state_value; 188 | } 189 | } else { 190 | $output[ $key ] = $value; 191 | } 192 | } 193 | return $output; 194 | } 195 | 196 | /** 197 | * Get the settings schema, conforming to JSON Schema. 198 | * 199 | * @return array 200 | */ 201 | public function get_item_schema() { 202 | $schema = array( 203 | '$schema' => 'http://json-schema.org/draft-04/schema#', 204 | 'title' => 'setting', 205 | 'type' => 'object', 206 | 'properties' => array( 207 | 'id' => array( 208 | 'description' => __( 'A unique identifier for the setting.', 'woocommerce' ), 209 | 'type' => 'string', 210 | 'arg_options' => array( 211 | 'sanitize_callback' => 'sanitize_title', 212 | ), 213 | 'context' => array( 'view', 'edit' ), 214 | 'readonly' => true, 215 | ), 216 | 'group_id' => array( 217 | 'description' => __( 'An identifier for the group this setting belongs to.', 'woocommerce' ), 218 | 'type' => 'string', 219 | 'arg_options' => array( 220 | 'sanitize_callback' => 'sanitize_title', 221 | ), 222 | 'context' => array( 'view', 'edit' ), 223 | 'readonly' => true, 224 | ), 225 | 'label' => array( 226 | 'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ), 227 | 'type' => 'string', 228 | 'arg_options' => array( 229 | 'sanitize_callback' => 'sanitize_text_field', 230 | ), 231 | 'context' => array( 'view', 'edit' ), 232 | 'readonly' => true, 233 | ), 234 | 'description' => array( 235 | 'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ), 236 | 'type' => 'string', 237 | 'arg_options' => array( 238 | 'sanitize_callback' => 'sanitize_text_field', 239 | ), 240 | 'context' => array( 'view', 'edit' ), 241 | 'readonly' => true, 242 | ), 243 | 'value' => array( 244 | 'description' => __( 'Setting value.', 'woocommerce' ), 245 | 'type' => 'mixed', 246 | 'context' => array( 'view', 'edit' ), 247 | ), 248 | 'default' => array( 249 | 'description' => __( 'Default value for the setting.', 'woocommerce' ), 250 | 'type' => 'mixed', 251 | 'context' => array( 'view', 'edit' ), 252 | 'readonly' => true, 253 | ), 254 | 'tip' => array( 255 | 'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ), 256 | 'type' => 'string', 257 | 'arg_options' => array( 258 | 'sanitize_callback' => 'sanitize_text_field', 259 | ), 260 | 'context' => array( 'view', 'edit' ), 261 | 'readonly' => true, 262 | ), 263 | 'placeholder' => array( 264 | 'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ), 265 | 'type' => 'string', 266 | 'arg_options' => array( 267 | 'sanitize_callback' => 'sanitize_text_field', 268 | ), 269 | 'context' => array( 'view', 'edit' ), 270 | 'readonly' => true, 271 | ), 272 | 'type' => array( 273 | 'description' => __( 'Type of setting.', 'woocommerce' ), 274 | 'type' => 'string', 275 | 'arg_options' => array( 276 | 'sanitize_callback' => 'sanitize_text_field', 277 | ), 278 | 'context' => array( 'view', 'edit' ), 279 | 'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ), 280 | 'readonly' => true, 281 | ), 282 | 'options' => array( 283 | 'description' => __( 'Array of options (key value pairs) for inputs such as select, multiselect, and radio buttons.', 'woocommerce' ), 284 | 'type' => 'object', 285 | 'context' => array( 'view', 'edit' ), 286 | 'readonly' => true, 287 | ), 288 | ), 289 | ); 290 | 291 | return $this->add_additional_fields_schema( $schema ); 292 | } 293 | 294 | } 295 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-settings-controller.php: -------------------------------------------------------------------------------- 1 | namespace, '/' . $this->rest_base . '/batch', array( 35 | array( 36 | 'methods' => WP_REST_Server::EDITABLE, 37 | 'callback' => array( $this, 'batch_items' ), 38 | 'permission_callback' => array( $this, 'update_items_permissions_check' ), 39 | ), 40 | 'schema' => array( $this, 'get_public_batch_schema' ), 41 | ) ); 42 | } 43 | 44 | /** 45 | * Makes sure the current user has access to WRITE the settings APIs. 46 | * 47 | * @param WP_REST_Request $request Full data about the request. 48 | * @return WP_Error|boolean 49 | */ 50 | public function update_items_permissions_check( $request ) { 51 | if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) { 52 | return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 53 | } 54 | 55 | return true; 56 | } 57 | 58 | /** 59 | * Update a setting. 60 | * 61 | * @param WP_REST_Request $request 62 | * @return WP_Error|WP_REST_Response 63 | */ 64 | public function update_item( $request ) { 65 | $options_controller = new WC_REST_Dev_Setting_Options_Controller; 66 | $response = $options_controller->update_item( $request ); 67 | return $response; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-shipping-methods-controller.php: -------------------------------------------------------------------------------- 1 | /locations endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 3.0.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Shipping Zone Locations class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Shipping_Zone_Locations_Controller extends WC_REST_Shipping_Zone_Locations_Controller { 23 | /** 24 | * Endpoint namespace. 25 | * 26 | * @var string 27 | */ 28 | protected $namespace = 'wc/v3'; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-shipping-zone-methods-controller.php: -------------------------------------------------------------------------------- 1 | /methods endpoint. 6 | * 7 | * @author WooThemes 8 | * @category API 9 | * @package WooCommerce/API 10 | * @since 3.0.0 11 | */ 12 | 13 | if ( ! defined( 'ABSPATH' ) ) { 14 | exit; 15 | } 16 | 17 | /** 18 | * REST API Shipping Zone Methods class. 19 | * 20 | * @package WooCommerce/API 21 | */ 22 | class WC_REST_Dev_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zone_Methods_Controller { 23 | 24 | /** 25 | * Endpoint namespace. 26 | * 27 | * @var string 28 | */ 29 | protected $namespace = 'wc/v3'; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /api/class-wc-rest-dev-shipping-zones-controller.php: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/unit-tests 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | === WooCommerce API Dev === 2 | Contributors: automattic, woothemes 3 | Tags: woocommerce, rest-api, api 4 | Requires at least: 4.6 5 | Tested up to: 4.9 6 | Stable tag: 1.0.0 7 | License: GPLv2 or later 8 | License URI: http://www.gnu.org/licenses/gpl-2.0.html 9 | 10 | A feature plugin providing a bleeding edge version of the WooCommerce REST API. 11 | 12 | == Description == 13 | 14 | This is a repository for the development version of the WooCommerce REST API. This feature plugin provides a place where the next version of the WooCommerce REST API can be worked on, independent of the current WooCommerce release cycle. These changes are brought over to [WooCommerce core](https://github.com/woocommerce/woocommerce) when they are ready for release. 15 | 16 | * Current stable API version: [**v2**](https://github.com/woocommerce/woocommerce/tree/master/includes/api). 17 | * Current development version: **v3**. 18 | 19 | == Installation == 20 | 21 | This section describes how to install the plugin and get it working. 22 | 23 | 1. Upload the plugin files to the `/wp-content/plugins/plugin-name` directory, or install the plugin through the WordPress plugins screen directly. 24 | 1. Activate the plugin through the 'Plugins' screen in WordPress 25 | 26 | == Changelog == 27 | 28 | = 1.0.0 = 29 | * Bug fixes for WooCommerce 3.6 compatability 30 | 31 | = 0.9.9 = 32 | * More bug fixes for WooCommerce 3.5 compatability 33 | 34 | = 0.9.8 = 35 | * Bug fixes for WooCommerce 3.5 compatability 36 | 37 | = 0.9.7 = 38 | * `data/counts` endpoint removed (moved to wc-calypso-bridge) 39 | * `products/reviews` endpoint removed (moved to wc-calypso-bridge) 40 | 41 | = 0.9.6 = 42 | * new `data/counts` endpoint added 43 | 44 | = 0.9.5 = 45 | * Fixes `single_select_page` settings (like `woocommerce_shop_page_id`) not showing up in responses. 46 | 47 | = 0.9.4 = 48 | * Added currency and dimensions to selected countries in the data/continents response 49 | 50 | = 0.9.3 = 51 | * Removed MailChimp files which are now in wc-calypso-bridge 52 | * Fixed regex issue that caused gutenberg to crash 53 | * Removed webhook test dependencies which are being removed in WooCommerce 3.3 54 | 55 | = 0.9.2 = 56 | * Rest API: Backport woocommerce/woocommerce#17849 to fix schema types in WP 4.9 57 | 58 | = 0.9.1 = 59 | * Rest API: Update the schema types for tax_class and price 60 | 61 | = 0.9.0 = 62 | * Removed all non core wc API logic from the plugin. 63 | * Added Author to note orders/{orderId}/notes responses 64 | 65 | = 0.8.9 = 66 | * Added MailChimp API endpoints for Store on .com 67 | * Added auto db upgrade handling 68 | 69 | = 0.8.8 = 70 | * Added customizer guided tour for nux. 71 | * Added Store menu link to Jetpack Masterbar. 72 | 73 | = 0.8.4 = 74 | * Remove auto-install via github as it is not reliable. 75 | * Add composer autoload support. 76 | * Add check for existing installs to avoid conflicts. 77 | 78 | = 0.8.3 = 79 | * Fix - Update order link in order details emails. 80 | 81 | = 0.8.2 = 82 | * Fix - Don't auto enable the PayPal payment method. 83 | 84 | = 0.8.1 = 85 | * Fix - Fix auto plugin update logic 86 | * Fix - Don't auto enable the cheque payment method. 87 | * Adds a new config constant (WC_API_DEV_ENABLE_HOTFIXES) to make it easy to disable hotfixes. 88 | 89 | = 0.8.0 = 90 | * Update orders endpoint to accept multiple statuses 91 | * Fix - Email subject and footers becoming out of sync 92 | 93 | = 0.7.1 = 94 | * Fix - add another URI to watch for when disabling sync during API requests 95 | 96 | = 0.7.0 = 97 | * Fix - disable jetpack sync during rest api requests to avoid slow responses 98 | 99 | = 0.6.0 = 100 | * Fix value default return on settings endpoints 101 | * Fix broken variation image set 102 | * Add a method supports response to payment methods 103 | * Added the ability to keep this plugin up to date 104 | 105 | = 0.5.0 = 106 | * Added a /settings/batch endpoint 107 | * Fixed broken orders refund endpoint 108 | 109 | = 0.4.0 = 110 | * Adds store address (two lines), city and postcode to the settings/general endpoint 111 | 112 | = 0.3.0 = 113 | * Adds endpoints for getting a list of supported currencies, along with their name and symbol. 114 | * Limit regex check for currency code to 3 characters. 115 | 116 | = 0.2.0 = 117 | * Removes the 'visible' property from the variations endpoint and adds 'status'. (See https://github.com/woocommerce/woocommerce/pull/15216) 118 | * Don't return parent image when no variation image is set. 119 | 120 | = 0.1.0 = 121 | * Initial release 122 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | tests_dir = dirname( __FILE__ ); 38 | $this->plugin_dir = dirname( $this->tests_dir ); 39 | $this->wc_dir = dirname( $this->plugin_dir ) . '/woocommerce'; 40 | $this->wc_tests_dir = dirname( $this->plugin_dir ) . '/woocommerce/tests'; 41 | $this->wp_tests_dir = getenv( 'WP_TESTS_DIR' ) ? getenv( 'WP_TESTS_DIR' ) : '/tmp/wordpress-tests-lib'; 42 | 43 | // load test function so tests_add_filter() is available 44 | require_once( $this->wp_tests_dir . '/includes/functions.php' ); 45 | 46 | // load WC 47 | tests_add_filter( 'muplugins_loaded', array( $this, 'load_wc' ) ); 48 | 49 | // load WC API Dev 50 | tests_add_filter( 'muplugins_loaded', array( $this, 'load_wc_api_dev' ) ); 51 | 52 | // install WC 53 | tests_add_filter( 'setup_theme', array( $this, 'install_wc' ) ); 54 | 55 | // load the WP testing environment 56 | require_once( $this->wp_tests_dir . '/includes/bootstrap.php' ); 57 | 58 | // load WC testing framework 59 | $this->includes(); 60 | } 61 | 62 | /** 63 | * Load WooCommerce. 64 | */ 65 | public function load_wc() { 66 | require_once( $this->wc_dir . '/woocommerce.php' ); 67 | } 68 | 69 | /** 70 | * Load WC API Dev. 71 | */ 72 | public function load_wc_api_dev() { 73 | define( 'WC_API_DEV_ENABLE_HOTFIXES', false ); 74 | require_once( $this->plugin_dir . '/wc-api-dev-class.php' ); 75 | } 76 | 77 | /** 78 | * Install WooCommerce after the test environment and WC have been loaded. 79 | */ 80 | public function install_wc() { 81 | 82 | // Clean existing install first. 83 | define( 'WP_UNINSTALL_PLUGIN', true ); 84 | define( 'WC_REMOVE_ALL_DATA', true ); 85 | include( $this->wc_dir . '/uninstall.php' ); 86 | 87 | WC_Install::install(); 88 | 89 | // Reload capabilities after install, see https://core.trac.wordpress.org/ticket/28374 90 | if ( version_compare( $GLOBALS['wp_version'], '4.7', '<' ) ) { 91 | $GLOBALS['wp_roles']->reinit(); 92 | } else { 93 | $GLOBALS['wp_roles'] = null; 94 | wp_roles(); 95 | } 96 | 97 | echo 'Installing WooCommerce...' . PHP_EOL; 98 | } 99 | 100 | /** 101 | * Load WC-specific test cases and factories. 102 | * If needed, these can also be shipped with the dev plugin and a local copy can be called. 103 | */ 104 | public function includes() { 105 | 106 | // framework 107 | require_once( $this->wc_tests_dir . '/framework/class-wc-unit-test-factory.php' ); 108 | require_once( $this->wc_tests_dir . '/framework/class-wc-mock-session-handler.php' ); 109 | require_once( $this->wc_tests_dir . '/framework/class-wc-mock-wc-data.php' ); 110 | require_once( $this->wc_tests_dir . '/framework/class-wc-mock-wc-object-query.php' ); 111 | require_once( $this->wc_tests_dir . '/framework/class-wc-payment-token-stub.php' ); 112 | require_once( $this->wc_tests_dir . '/framework/vendor/class-wp-test-spy-rest-server.php' ); 113 | 114 | // test cases 115 | require_once( $this->wc_tests_dir . '/framework/class-wc-unit-test-case.php' ); 116 | require_once( $this->wc_tests_dir . '/framework/class-wc-api-unit-test-case.php' ); 117 | require_once( $this->wc_tests_dir . '/framework/class-wc-rest-unit-test-case.php' ); 118 | 119 | // Helpers 120 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-product.php' ); 121 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-coupon.php' ); 122 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-fee.php' ); 123 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-shipping.php' ); 124 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-customer.php' ); 125 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-order.php' ); 126 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-shipping-zones.php' ); 127 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-payment-token.php' ); 128 | require_once( $this->wc_tests_dir . '/framework/helpers/class-wc-helper-settings.php' ); 129 | 130 | // Added helpers 131 | require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-order-note.php' ); 132 | require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-order-refund.php' ); 133 | } 134 | 135 | /** 136 | * Gets the single class instance. 137 | */ 138 | public static function instance() { 139 | if ( is_null( self::$instance ) ) { 140 | self::$instance = new self(); 141 | } 142 | 143 | return self::$instance; 144 | } 145 | } 146 | 147 | WC_API_Dev_Unit_Tests_Bootstrap::instance(); 148 | -------------------------------------------------------------------------------- /tests/framework/helpers/class-wc-helper-order-note.php: -------------------------------------------------------------------------------- 1 | add_order_note( 'This is an order note.', false ); 29 | 30 | if ( ! $note_id ) { 31 | return false; 32 | } 33 | 34 | $note = get_comment( $note_id ); 35 | return $note; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/framework/helpers/class-wc-helper-order-refund.php: -------------------------------------------------------------------------------- 1 | 5.0, 30 | 'reason' => 'Testing', 31 | 'order_id' => $order_id, 32 | ); 33 | $refund_obj = wc_create_refund( $refund ); 34 | 35 | if ( ! $refund_obj || is_wp_error( $refund_obj ) ) { 36 | return false; 37 | } 38 | 39 | return $refund_obj; 40 | } 41 | 42 | /** 43 | * Create an order refund with line_items. 44 | * 45 | * @since 2.4 46 | * 47 | * @param int $order_id 48 | * @param int $customer_id 49 | * 50 | * @return WC_Order_Refund 51 | */ 52 | public static function create_refund_with_items( $order_id, $customer_id = 1 ) { 53 | $order = wc_get_order( $order_id ); 54 | 55 | if ( ! $order ) { 56 | return false; 57 | } 58 | $items = $order->get_items(); 59 | $item_id = key( $items ); 60 | // Create the refund. 61 | $refund = array( 62 | 'amount' => 5.0, 63 | 'reason' => 'Testing', 64 | 'order_id' => $order_id, 65 | 'line_items' => array(), 66 | ); 67 | $refund['line_items'][ $item_id ] = array( 68 | 'qty' => 1, 69 | 'refund_total' => 5.0, 70 | ); 71 | $refund_obj = wc_create_refund( $refund ); 72 | 73 | if ( ! $refund_obj || is_wp_error( $refund_obj ) ) { 74 | return false; 75 | } 76 | 77 | return $refund_obj; 78 | } 79 | 80 | 81 | /** 82 | * Create an array of line_items based on a given order. 83 | * 84 | * @since 2.4 85 | * 86 | * @param int $order_id 87 | * @param int $count 88 | * 89 | * @return array 90 | */ 91 | public static function create_refund_line_items( $order_id, $count ) { 92 | $order = wc_get_order( $order_id ); 93 | $items = $order->get_items(); 94 | $line_items = array(); 95 | 96 | // Create line items up to count, as long as there are items to use. 97 | $item_id = key( $items ); 98 | $i = 0; 99 | while ( $item_id && ( $i < $count ) ) { 100 | $line_items[ $item_id ] = array( 101 | 'qty' => 1, 102 | 'refund_total' => 5.0, 103 | ); 104 | // Next loop… 105 | $item_id = key( $items ); 106 | $i++; 107 | } 108 | return $line_items; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tests/unit-tests/coupons.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Coupons_Controller(); 18 | $this->user = $this->factory->user->create( array( 19 | 'role' => 'administrator', 20 | ) ); 21 | } 22 | 23 | /** 24 | * Test route registration. 25 | * @since 3.0.0 26 | */ 27 | public function test_register_routes() { 28 | $routes = $this->server->get_routes(); 29 | $this->assertArrayHasKey( '/wc/v3/coupons', $routes ); 30 | $this->assertArrayHasKey( '/wc/v3/coupons/(?P[\d]+)', $routes ); 31 | $this->assertArrayHasKey( '/wc/v3/coupons/batch', $routes ); 32 | } 33 | 34 | /** 35 | * Test getting coupons. 36 | * @since 3.0.0 37 | */ 38 | public function test_get_coupons() { 39 | wp_set_current_user( $this->user ); 40 | 41 | $coupon_1 = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 42 | $post_1 = get_post( $coupon_1->get_id() ); 43 | $coupon_2 = WC_Helper_Coupon::create_coupon( 'dummycoupon-2' ); 44 | 45 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons' ) ); 46 | $coupons = $response->get_data(); 47 | 48 | $this->assertEquals( 200, $response->get_status() ); 49 | $this->assertEquals( 2, count( $coupons ) ); 50 | $this->assertContains( array( 51 | 'id' => $coupon_1->get_id(), 52 | 'code' => 'dummycoupon-1', 53 | 'amount' => '1.00', 54 | 'date_created' => wc_rest_prepare_date_response( $post_1->post_date_gmt, false ), 55 | 'date_created_gmt' => wc_rest_prepare_date_response( $post_1->post_date_gmt ), 56 | 'date_modified' => wc_rest_prepare_date_response( $post_1->post_modified_gmt, false ), 57 | 'date_modified_gmt' => wc_rest_prepare_date_response( $post_1->post_modified_gmt ), 58 | 'discount_type' => 'fixed_cart', 59 | 'description' => 'This is a dummy coupon', 60 | 'date_expires' => '', 61 | 'date_expires_gmt' => '', 62 | 'usage_count' => 0, 63 | 'individual_use' => false, 64 | 'product_ids' => array(), 65 | 'excluded_product_ids' => array(), 66 | 'usage_limit' => '', 67 | 'usage_limit_per_user' => '', 68 | 'limit_usage_to_x_items' => null, 69 | 'free_shipping' => false, 70 | 'product_categories' => array(), 71 | 'excluded_product_categories' => array(), 72 | 'exclude_sale_items' => false, 73 | 'minimum_amount' => '0.00', 74 | 'maximum_amount' => '0.00', 75 | 'email_restrictions' => array(), 76 | 'used_by' => array(), 77 | 'meta_data' => array(), 78 | '_links' => array( 79 | 'self' => array( 80 | array( 81 | 'href' => rest_url( '/wc/v3/coupons/' . $coupon_1->get_id() ), 82 | ), 83 | ), 84 | 'collection' => array( 85 | array( 86 | 'href' => rest_url( '/wc/v3/coupons' ), 87 | ), 88 | ), 89 | ), 90 | ), $coupons ); 91 | } 92 | 93 | /** 94 | * Test getting coupons without valid permissions. 95 | * @since 3.0.0 96 | */ 97 | public function test_get_coupons_without_permission() { 98 | wp_set_current_user( 0 ); 99 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons' ) ); 100 | $this->assertEquals( 401, $response->get_status() ); 101 | } 102 | 103 | /** 104 | * Test getting a single coupon. 105 | * @since 3.0.0 106 | */ 107 | public function test_get_coupon() { 108 | wp_set_current_user( $this->user ); 109 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 110 | $post = get_post( $coupon->get_id() ); 111 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons/' . $coupon->get_id() ) ); 112 | $data = $response->get_data(); 113 | 114 | $this->assertEquals( 200, $response->get_status() ); 115 | $this->assertEquals( array( 116 | 'id' => $coupon->get_id(), 117 | 'code' => 'dummycoupon-1', 118 | 'amount' => '1.00', 119 | 'date_created' => wc_rest_prepare_date_response( $post->post_date_gmt, false ), 120 | 'date_created_gmt' => wc_rest_prepare_date_response( $post->post_date_gmt ), 121 | 'date_modified' => wc_rest_prepare_date_response( $post->post_modified_gmt, false ), 122 | 'date_modified_gmt' => wc_rest_prepare_date_response( $post->post_modified_gmt ), 123 | 'discount_type' => 'fixed_cart', 124 | 'description' => 'This is a dummy coupon', 125 | 'date_expires' => null, 126 | 'date_expires_gmt' => null, 127 | 'usage_count' => 0, 128 | 'individual_use' => false, 129 | 'product_ids' => array(), 130 | 'excluded_product_ids' => array(), 131 | 'usage_limit' => null, 132 | 'usage_limit_per_user' => null, 133 | 'limit_usage_to_x_items' => null, 134 | 'free_shipping' => false, 135 | 'product_categories' => array(), 136 | 'excluded_product_categories' => array(), 137 | 'exclude_sale_items' => false, 138 | 'minimum_amount' => '0.00', 139 | 'maximum_amount' => '0.00', 140 | 'email_restrictions' => array(), 141 | 'used_by' => array(), 142 | 'meta_data' => array(), 143 | ), $data ); 144 | } 145 | 146 | /** 147 | * Test getting a single coupon with an invalid ID. 148 | * @since 3.0.0 149 | */ 150 | public function test_get_coupon_invalid_id() { 151 | wp_set_current_user( $this->user ); 152 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons/0' ) ); 153 | $this->assertEquals( 404, $response->get_status() ); 154 | } 155 | 156 | /** 157 | * Test getting a single coupon without valid permissions. 158 | * @since 3.0.0 159 | */ 160 | public function test_get_coupon_without_permission() { 161 | wp_set_current_user( 0 ); 162 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 163 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons/' . $coupon->get_id() ) ); 164 | $this->assertEquals( 401, $response->get_status() ); 165 | } 166 | 167 | /** 168 | * Test creating a single coupon. 169 | * @since 3.0.0 170 | */ 171 | public function test_create_coupon() { 172 | wp_set_current_user( $this->user ); 173 | $request = new WP_REST_Request( 'POST', '/wc/v3/coupons' ); 174 | $request->set_body_params( array( 175 | 'code' => 'test', 176 | 'amount' => '5.00', 177 | 'discount_type' => 'fixed_product', 178 | 'description' => 'Test', 179 | 'usage_limit' => 10, 180 | ) ); 181 | $response = $this->server->dispatch( $request ); 182 | $data = $response->get_data(); 183 | 184 | $this->assertEquals( 201, $response->get_status() ); 185 | $this->assertEquals( array( 186 | 'id' => $data['id'], 187 | 'code' => 'test', 188 | 'amount' => '5.00', 189 | 'date_created' => $data['date_created'], 190 | 'date_created_gmt' => $data['date_created_gmt'], 191 | 'date_modified' => $data['date_modified'], 192 | 'date_modified_gmt' => $data['date_modified_gmt'], 193 | 'discount_type' => 'fixed_product', 194 | 'description' => 'Test', 195 | 'date_expires' => null, 196 | 'date_expires_gmt' => null, 197 | 'usage_count' => 0, 198 | 'individual_use' => false, 199 | 'product_ids' => array(), 200 | 'excluded_product_ids' => array(), 201 | 'usage_limit' => 10, 202 | 'usage_limit_per_user' => null, 203 | 'limit_usage_to_x_items' => null, 204 | 'free_shipping' => false, 205 | 'product_categories' => array(), 206 | 'excluded_product_categories' => array(), 207 | 'exclude_sale_items' => false, 208 | 'minimum_amount' => '0.00', 209 | 'maximum_amount' => '0.00', 210 | 'email_restrictions' => array(), 211 | 'used_by' => array(), 212 | 'meta_data' => array(), 213 | ), $data ); 214 | } 215 | 216 | /** 217 | * Test creating a single coupon with invalid fields. 218 | * @since 3.0.0 219 | */ 220 | public function test_create_coupon_invalid_fields() { 221 | wp_set_current_user( $this->user ); 222 | 223 | // test no code... 224 | $request = new WP_REST_Request( 'POST', '/wc/v3/coupons' ); 225 | $request->set_body_params( array( 226 | 'amount' => '5.00', 227 | 'discount_type' => 'fixed_product', 228 | ) ); 229 | $response = $this->server->dispatch( $request ); 230 | $data = $response->get_data(); 231 | 232 | $this->assertEquals( 400, $response->get_status() ); 233 | } 234 | 235 | /** 236 | * Test creating a single coupon without valid permissions. 237 | * @since 3.0.0 238 | */ 239 | public function test_create_coupon_without_permission() { 240 | wp_set_current_user( 0 ); 241 | 242 | // test no code... 243 | $request = new WP_REST_Request( 'POST', '/wc/v3/coupons' ); 244 | $request->set_body_params( array( 245 | 'code' => 'fail', 246 | 'amount' => '5.00', 247 | 'discount_type' => 'fixed_product', 248 | ) ); 249 | $response = $this->server->dispatch( $request ); 250 | $data = $response->get_data(); 251 | 252 | $this->assertEquals( 401, $response->get_status() ); 253 | } 254 | 255 | /** 256 | * Test updating a single coupon. 257 | * @since 3.0.0 258 | */ 259 | public function test_update_coupon() { 260 | wp_set_current_user( $this->user ); 261 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 262 | $post = get_post( $coupon->get_id() ); 263 | 264 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/coupons/' . $coupon->get_id() ) ); 265 | $data = $response->get_data(); 266 | $this->assertEquals( 'This is a dummy coupon', $data['description'] ); 267 | $this->assertEquals( 'fixed_cart', $data['discount_type'] ); 268 | $this->assertEquals( '1.00', $data['amount'] ); 269 | 270 | $request = new WP_REST_Request( 'PUT', '/wc/v3/coupons/' . $coupon->get_id() ); 271 | $request->set_body_params( array( 272 | 'amount' => '10.00', 273 | 'description' => 'New description', 274 | ) ); 275 | $response = $this->server->dispatch( $request ); 276 | $data = $response->get_data(); 277 | 278 | $this->assertEquals( '10.00', $data['amount'] ); 279 | $this->assertEquals( 'New description', $data['description'] ); 280 | $this->assertEquals( 'fixed_cart', $data['discount_type'] ); 281 | } 282 | 283 | /** 284 | * Test updating a single coupon with an invalid ID. 285 | * @since 3.0.0 286 | */ 287 | public function test_update_coupon_invalid_id() { 288 | wp_set_current_user( $this->user ); 289 | 290 | $request = new WP_REST_Request( 'PUT', '/wc/v3/coupons/0' ); 291 | $request->set_body_params( array( 292 | 'code' => 'tester', 293 | 'amount' => '10.00', 294 | 'description' => 'New description', 295 | ) ); 296 | $response = $this->server->dispatch( $request ); 297 | $data = $response->get_data(); 298 | 299 | $this->assertEquals( 400, $response->get_status() ); 300 | } 301 | 302 | /** 303 | * Test updating a single coupon without valid permissions. 304 | * @since 3.0.0 305 | */ 306 | public function test_update_coupon_without_permission() { 307 | wp_set_current_user( 0 ); 308 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 309 | $post = get_post( $coupon->get_id() ); 310 | 311 | $request = new WP_REST_Request( 'PUT', '/wc/v3/coupons/' . $coupon->get_id() ); 312 | $request->set_body_params( array( 313 | 'amount' => '10.00', 314 | 'description' => 'New description', 315 | ) ); 316 | $response = $this->server->dispatch( $request ); 317 | 318 | $this->assertEquals( 401, $response->get_status() ); 319 | } 320 | 321 | /** 322 | * Test deleting a single coupon. 323 | * @since 3.0.0 324 | */ 325 | public function test_delete_coupon() { 326 | wp_set_current_user( $this->user ); 327 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 328 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/coupons/' . $coupon->get_id() ); 329 | $request->set_param( 'force', true ); 330 | $response = $this->server->dispatch( $request ); 331 | $this->assertEquals( 200, $response->get_status() ); 332 | } 333 | 334 | /** 335 | * Test deleting a single coupon with an invalid ID. 336 | * @since 3.0.0 337 | */ 338 | public function test_delete_coupon_invalid_id() { 339 | wp_set_current_user( $this->user ); 340 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/coupons/0' ); 341 | $request->set_param( 'force', true ); 342 | $response = $this->server->dispatch( $request ); 343 | 344 | $this->assertEquals( 404, $response->get_status() ); 345 | } 346 | 347 | /** 348 | * Test deleting a single coupon without valid permissions. 349 | * @since 3.0.0 350 | */ 351 | public function test_delete_coupon_without_permission() { 352 | wp_set_current_user( 0 ); 353 | $coupon = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 354 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/coupons/' . $coupon->get_id() ); 355 | $response = $this->server->dispatch( $request ); 356 | 357 | $this->assertEquals( 401, $response->get_status() ); 358 | } 359 | 360 | /** 361 | * Test batch operations on coupons. 362 | * @since 3.0.0 363 | */ 364 | public function test_batch_coupon() { 365 | wp_set_current_user( $this->user ); 366 | 367 | $coupon_1 = WC_Helper_Coupon::create_coupon( 'dummycoupon-1' ); 368 | $coupon_2 = WC_Helper_Coupon::create_coupon( 'dummycoupon-2' ); 369 | $coupon_3 = WC_Helper_Coupon::create_coupon( 'dummycoupon-3' ); 370 | $coupon_4 = WC_Helper_Coupon::create_coupon( 'dummycoupon-4' ); 371 | 372 | $request = new WP_REST_Request( 'POST', '/wc/v3/coupons/batch' ); 373 | $request->set_body_params( array( 374 | 'update' => array( 375 | array( 376 | 'id' => $coupon_1->get_id(), 377 | 'amount' => '5.15', 378 | ), 379 | ), 380 | 'delete' => array( 381 | $coupon_2->get_id(), 382 | $coupon_3->get_id(), 383 | ), 384 | 'create' => array( 385 | array( 386 | 'code' => 'new-coupon', 387 | 'amount' => '11.00', 388 | ), 389 | ), 390 | ) ); 391 | $response = $this->server->dispatch( $request ); 392 | $data = $response->get_data(); 393 | 394 | $this->assertEquals( '5.15', $data['update'][0]['amount'] ); 395 | $this->assertEquals( '11.00', $data['create'][0]['amount'] ); 396 | $this->assertEquals( 'new-coupon', $data['create'][0]['code'] ); 397 | $this->assertEquals( $coupon_2->get_id(), $data['delete'][0]['id'] ); 398 | $this->assertEquals( $coupon_3->get_id(), $data['delete'][1]['id'] ); 399 | 400 | $request = new WP_REST_Request( 'GET', '/wc/v3/coupons' ); 401 | $response = $this->server->dispatch( $request ); 402 | $data = $response->get_data(); 403 | 404 | $this->assertEquals( 3, count( $data ) ); 405 | } 406 | 407 | /** 408 | * Test coupon schema. 409 | * @since 3.0.0 410 | */ 411 | public function test_coupon_schema() { 412 | wp_set_current_user( $this->user ); 413 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/coupons' ); 414 | $response = $this->server->dispatch( $request ); 415 | $data = $response->get_data(); 416 | $properties = $data['schema']['properties']; 417 | 418 | $this->assertEquals( 27, count( $properties ) ); 419 | $this->assertArrayHasKey( 'id', $properties ); 420 | $this->assertArrayHasKey( 'code', $properties ); 421 | $this->assertArrayHasKey( 'date_created', $properties ); 422 | $this->assertArrayHasKey( 'date_created_gmt', $properties ); 423 | $this->assertArrayHasKey( 'date_modified', $properties ); 424 | $this->assertArrayHasKey( 'date_modified_gmt', $properties ); 425 | $this->assertArrayHasKey( 'description', $properties ); 426 | $this->assertArrayHasKey( 'discount_type', $properties ); 427 | $this->assertArrayHasKey( 'amount', $properties ); 428 | $this->assertArrayHasKey( 'date_expires', $properties ); 429 | $this->assertArrayHasKey( 'date_expires_gmt', $properties ); 430 | $this->assertArrayHasKey( 'usage_count', $properties ); 431 | $this->assertArrayHasKey( 'individual_use', $properties ); 432 | $this->assertArrayHasKey( 'product_ids', $properties ); 433 | $this->assertArrayHasKey( 'excluded_product_ids', $properties ); 434 | $this->assertArrayHasKey( 'usage_limit', $properties ); 435 | $this->assertArrayHasKey( 'usage_limit_per_user', $properties ); 436 | $this->assertArrayHasKey( 'limit_usage_to_x_items', $properties ); 437 | $this->assertArrayHasKey( 'free_shipping', $properties ); 438 | $this->assertArrayHasKey( 'product_categories', $properties ); 439 | $this->assertArrayHasKey( 'excluded_product_categories', $properties ); 440 | $this->assertArrayHasKey( 'exclude_sale_items', $properties ); 441 | $this->assertArrayHasKey( 'minimum_amount', $properties ); 442 | $this->assertArrayHasKey( 'maximum_amount', $properties ); 443 | $this->assertArrayHasKey( 'email_restrictions', $properties ); 444 | $this->assertArrayHasKey( 'used_by', $properties ); 445 | } 446 | } 447 | -------------------------------------------------------------------------------- /tests/unit-tests/data-counts.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Orders_Controller(); 21 | $this->user = $this->factory->user->create( array( 22 | 'role' => 'administrator', 23 | ) ); 24 | } 25 | 26 | 27 | /** 28 | * Test route registration. 29 | */ 30 | public function test_register_routes() { 31 | $routes = $this->server->get_routes(); 32 | $this->assertArrayHasKey( '/wc/v3/data', $routes ); 33 | $this->assertArrayHasKey( '/wc/v3/data/counts', $routes ); 34 | } 35 | 36 | /** 37 | * Cleanup. 38 | */ 39 | public function stoppit_and_tidyup() { 40 | foreach ( $this->orders as $order ) { 41 | wp_delete_post( $order->get_id(), true ); 42 | } 43 | $this->orders = array(); 44 | } 45 | 46 | /** 47 | * Test getting counts. 48 | */ 49 | public function test_get_counts() { 50 | wp_set_current_user( $this->user ); 51 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/counts' ) ); 52 | $counts = $response->get_data(); 53 | $this->assertEquals( 200, $response->get_status() ); 54 | $this->assertTrue( is_array( $counts ) ); 55 | $this->assertGreaterThan( 1, count( $counts ) ); 56 | $this->assertNotEmpty( $counts['orders'] ); 57 | $this->assertNotEmpty( $counts['products'] ); 58 | $this->assertEquals( $counts['products']['all'], 0 ); 59 | $this->assertNotEmpty( $counts['reviews'] ); 60 | $this->assertEquals( $counts['reviews']['all'], 0 ); 61 | } 62 | 63 | /** 64 | * Test getting counts using the site's data. 65 | */ 66 | public function test_get_order_counts() { 67 | wp_set_current_user( $this->user ); 68 | // Create 10 orders. 69 | for ( $i = 0; $i < 10; $i++ ) { 70 | $this->orders[] = WC_Helper_Order::create_order( $this->user ); 71 | } 72 | 73 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/counts' ) ); 74 | $counts = $response->get_data(); 75 | $this->assertEquals( 200, $response->get_status() ); 76 | $this->assertNotEmpty( $counts['orders'] ); 77 | $this->assertEquals( $counts['orders']['wc-pending'], 10 ); 78 | 79 | $this->stoppit_and_tidyup(); 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /tests/unit-tests/data.php: -------------------------------------------------------------------------------- 1 | user = $this->factory->user->create( array( 16 | 'role' => 'administrator', 17 | ) ); 18 | } 19 | 20 | /** 21 | * Test route registration. 22 | * 23 | * @since 3.1.0 24 | */ 25 | public function test_register_routes() { 26 | $routes = $this->server->get_routes(); 27 | $this->assertArrayHasKey( '/wc/v3/data', $routes ); 28 | $this->assertArrayHasKey( '/wc/v3/data/continents', $routes ); 29 | $this->assertArrayHasKey( '/wc/v3/data/countries', $routes ); 30 | $this->assertArrayHasKey( '/wc/v3/data/currencies', $routes ); 31 | $this->assertArrayHasKey( '/wc/v3/data/currencies/current', $routes ); 32 | $this->assertArrayHasKey( '/wc/v3/data/currencies/(?P[\w-]{3})', $routes ); 33 | } 34 | 35 | /** 36 | * Test getting the data index. 37 | * @since 3.1.0 38 | */ 39 | public function test_get_index() { 40 | wp_set_current_user( $this->user ); 41 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data' ) ); 42 | $index = $response->get_data(); 43 | $this->assertEquals( 200, $response->get_status() ); 44 | $this->assertCount( 4, $index ); 45 | $this->assertEquals( 'continents', $index[0]['slug'] ); 46 | $this->assertEquals( 'countries', $index[1]['slug'] ); 47 | $this->assertEquals( 'counts', $index[2]['slug'] ); 48 | $this->assertEquals( 'currencies', $index[3]['slug'] ); 49 | } 50 | 51 | /** 52 | * Test getting locations. 53 | * @since 3.1.0 54 | */ 55 | public function test_get_locations() { 56 | wp_set_current_user( $this->user ); 57 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/continents' ) ); 58 | $locations = $response->get_data(); 59 | $this->assertEquals( 200, $response->get_status() ); 60 | $this->assertTrue( is_array( $locations ) ); 61 | $this->assertGreaterThan( 1, count( $locations ) ); 62 | $this->assertNotEmpty( $locations[0]['code'] ); 63 | $this->assertNotEmpty( $locations[0]['name'] ); 64 | $this->assertNotEmpty( $locations[0]['countries'] ); 65 | $this->assertNotEmpty( $locations[0]['_links'] ); 66 | 67 | // Make sure North America is in the response 68 | $NA_index = -1; 69 | foreach( $locations as $index => $continent ) { 70 | if ( "NA" === $continent['code'] ) { 71 | $NA_index = $index; 72 | } 73 | } 74 | $this->assertGreaterThan( -1, $NA_index ); 75 | 76 | // Make sure the United States is in the North America part of the response 77 | $US_index = -1; 78 | foreach( $locations[ $NA_index ]['countries'] as $index => $country ) { 79 | if ( "US" === $country['code'] ) { 80 | $US_index = $index; 81 | } 82 | } 83 | $this->assertGreaterThan( -1, $US_index ); 84 | 85 | // Lastly, assertNotEmpty US has currency, dimensions, etc. 86 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['currency_code'] ); 87 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['currency_pos'] ); 88 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['thousand_sep'] ); 89 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['decimal_sep'] ); 90 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['num_decimals'] ); 91 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['dimension_unit'] ); 92 | $this->assertNotEmpty( $locations[ $NA_index ]['countries'][ $US_index ]['weight_unit'] ); 93 | } 94 | 95 | /** 96 | * Test getting locations restricted to one continent. 97 | * @since 3.1.0 98 | */ 99 | public function test_get_locations_from_continent() { 100 | wp_set_current_user( $this->user ); 101 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/continents/na' ) ); 102 | $locations = $response->get_data(); 103 | $this->assertEquals( 200, $response->get_status() ); 104 | $this->assertTrue( is_array( $locations ) ); 105 | $this->assertEquals( 'NA', $locations['code'] ); 106 | $this->assertNotEmpty( $locations['name'] ); 107 | $this->assertNotEmpty( $locations['countries'] ); 108 | $links = $response->get_links(); 109 | $this->assertCount( 2, $links ); 110 | } 111 | 112 | /** 113 | * Test getting locations with no country specified 114 | * @since 3.1.0 115 | */ 116 | public function test_get_locations_all_countries() { 117 | wp_set_current_user( $this->user ); 118 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/countries' ) ); 119 | $locations = $response->get_data(); 120 | $this->assertEquals( 200, $response->get_status() ); 121 | $this->assertGreaterThan( 1, count( $locations ) ); 122 | $this->assertNotEmpty( $locations[0]['code'] ); 123 | $this->assertNotEmpty( $locations[0]['name'] ); 124 | $this->assertArrayHasKey( 'states', $locations[0] ); 125 | $this->assertNotEmpty( $locations[0]['_links'] ); 126 | } 127 | 128 | /** 129 | * Test getting locations restricted to one country. 130 | * Use a country (US) that includes locale info 131 | * @since 3.1.0 132 | */ 133 | public function test_get_locations_from_country() { 134 | wp_set_current_user( $this->user ); 135 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/countries/us' ) ); 136 | $locations = $response->get_data(); 137 | $this->assertEquals( 200, $response->get_status() ); 138 | $this->assertTrue( is_array( $locations ) ); 139 | $this->assertEquals( 'US', $locations['code'] ); 140 | $this->assertNotEmpty( $locations['name'] ); 141 | $this->assertCount( 54, $locations['states'] ); 142 | $links = $response->get_links(); 143 | $this->assertCount( 2, $links ); 144 | } 145 | 146 | /** 147 | * Test getting locations from an invalid code. 148 | * @since 3.1.0 149 | */ 150 | public function test_get_locations_from_invalid_continent() { 151 | wp_set_current_user( $this->user ); 152 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/continents/xx' ) ); 153 | $this->assertEquals( 404, $response->get_status() ); 154 | } 155 | 156 | /** 157 | * Test getting locations from an invalid code. 158 | * @since 3.1.0 159 | */ 160 | public function test_get_locations_from_invalid_country() { 161 | wp_set_current_user( $this->user ); 162 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/countries/xx' ) ); 163 | $this->assertEquals( 404, $response->get_status() ); 164 | } 165 | 166 | /** 167 | * Test getting locations without permissions. 168 | * @since 3.1.0 169 | */ 170 | public function test_get_continents_without_permission() { 171 | wp_set_current_user( 0 ); 172 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/continents' ) ); 173 | $this->assertEquals( 401, $response->get_status() ); 174 | } 175 | 176 | /** 177 | * Test getting locations without permissions. 178 | * @since 3.1.0 179 | */ 180 | public function test_get_countries_without_permission() { 181 | wp_set_current_user( 0 ); 182 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/countries' ) ); 183 | $this->assertEquals( 401, $response->get_status() ); 184 | } 185 | 186 | /** 187 | * Test getting currencies. 188 | */ 189 | public function test_get_currencies() { 190 | wp_set_current_user( $this->user ); 191 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies' ) ); 192 | $currencies = $response->get_data(); 193 | $this->assertEquals( 200, $response->get_status() ); 194 | $this->assertTrue( is_array( $currencies ) ); 195 | $this->assertGreaterThan( 1, count( $currencies ) ); 196 | $this->assertNotEmpty( $currencies[0]['code'] ); 197 | $this->assertNotEmpty( $currencies[0]['name'] ); 198 | $this->assertNotEmpty( $currencies[0]['symbol'] ); 199 | $this->assertNotEmpty( $currencies[0]['_links'] ); 200 | } 201 | 202 | /** 203 | * Test getting a single currency. 204 | */ 205 | public function test_get_currency() { 206 | wp_set_current_user( $this->user ); 207 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies/CAD' ) ); 208 | $currency = $response->get_data(); 209 | $this->assertEquals( 200, $response->get_status() ); 210 | $this->assertEquals( 'CAD', $currency['code'] ); 211 | $this->assertEquals( 'Canadian dollar', $currency['name'] ); 212 | $this->assertEquals( '$', $currency['symbol'] ); 213 | $links = $response->get_links(); 214 | $this->assertCount( 2, $links ); 215 | } 216 | 217 | /** 218 | * Test getting current currency. 219 | */ 220 | public function test_get_current_currency() { 221 | $current = get_option( 'woocommerce_currency' ); 222 | update_option( 'woocommerce_currency', 'BTC' ); 223 | 224 | wp_set_current_user( $this->user ); 225 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies/current' ) ); 226 | $currency = $response->get_data(); 227 | $this->assertEquals( 200, $response->get_status() ); 228 | $this->assertEquals( 'BTC', $currency['code'] ); 229 | $this->assertEquals( 'Bitcoin', $currency['name'] ); 230 | $this->assertEquals( '฿', $currency['symbol'] ); 231 | $links = $response->get_links(); 232 | $this->assertCount( 2, $links ); 233 | 234 | update_option( 'woocommerce_currency', $current ); 235 | } 236 | 237 | /** 238 | * Test getting currency from an invalid code. 239 | */ 240 | public function test_get_currency_from_invalid_code() { 241 | wp_set_current_user( $this->user ); 242 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies/xxy' ) ); 243 | $this->assertEquals( 404, $response->get_status() ); 244 | $this->assertEquals( 'woocommerce_rest_data_invalid_currency', $response->data['code'] ); 245 | } 246 | 247 | /** 248 | * Test getting currency from an code that is too long. 249 | */ 250 | public function test_get_currency_from_long_code() { 251 | wp_set_current_user( $this->user ); 252 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies/xxyy' ) ); 253 | $this->assertEquals( 404, $response->get_status() ); 254 | $this->assertEquals( 'rest_no_route', $response->data['code'] ); 255 | } 256 | 257 | /** 258 | * Test getting currencies without permissions. 259 | */ 260 | public function test_get_currency_without_permission() { 261 | wp_set_current_user( 0 ); 262 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/data/currencies' ) ); 263 | $this->assertEquals( 401, $response->get_status() ); 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /tests/unit-tests/functions.php: -------------------------------------------------------------------------------- 1 | assertEquals( '2016-06-06T06:06:06', wc_rest_prepare_date_response( '2016-06-06 06:06:06' ) ); 17 | } 18 | 19 | /** 20 | * Test wc_rest_upload_image_from_url(). 21 | * 22 | * @since 2.6.0 23 | */ 24 | public function test_wc_rest_upload_image_from_url() { 25 | // Only test the error, no need to upload images. 26 | $this->assertIsWPError( wc_rest_upload_image_from_url( 'thing' ) ); 27 | } 28 | 29 | /** 30 | * Test wc_rest_set_uploaded_image_as_attachment(). 31 | * 32 | * @since 2.6.0 33 | */ 34 | public function test_wc_rest_set_uploaded_image_as_attachment() { 35 | $this->assertInternalType( 'int', wc_rest_set_uploaded_image_as_attachment( array( 'file' => '', 'url' => '' ) ) ); 36 | } 37 | 38 | /** 39 | * Test wc_rest_validate_reports_request_arg(). 40 | * 41 | * @since 2.6.0 42 | */ 43 | public function test_wc_rest_validate_reports_request_arg() { 44 | $request = new WP_REST_Request( 'GET', '/wc/v2/foo', array( 45 | 'args' => array( 46 | 'date' => array( 47 | 'type' => 'string', 48 | 'format' => 'date', 49 | ), 50 | ), 51 | ) ); 52 | 53 | // Success. 54 | $this->assertTrue( wc_rest_validate_reports_request_arg( '2016-06-06', $request, 'date' ) ); 55 | 56 | // Error. 57 | $error = wc_rest_validate_reports_request_arg( 'foo', $request, 'date' ); 58 | $this->assertEquals( 'The date you provided is invalid.', $error->get_error_message() ); 59 | } 60 | 61 | /** 62 | * Test wc_rest_urlencode_rfc3986(). 63 | * 64 | * @since 2.6.0 65 | */ 66 | public function test_wc_rest_urlencode_rfc3986() { 67 | $this->assertEquals( 'https%3A%2F%2Fwoocommerce.com%2F', wc_rest_urlencode_rfc3986( 'https://woocommerce.com/' ) ); 68 | } 69 | 70 | /** 71 | * Test wc_rest_check_post_permissions(). 72 | * 73 | * @since 2.6.0 74 | */ 75 | public function test_wc_rest_check_post_permissions() { 76 | $this->isFalse( wc_rest_check_post_permissions( 'shop_order' ) ); 77 | } 78 | 79 | /** 80 | * Test wc_rest_check_user_permissions(). 81 | * 82 | * @since 2.6.0 83 | */ 84 | public function test_wc_rest_check_user_permissions() { 85 | $this->isFalse( wc_rest_check_user_permissions() ); 86 | } 87 | 88 | /** 89 | * Test wc_rest_check_product_term_permissions(). 90 | * 91 | * @since 2.6.0 92 | */ 93 | public function test_wc_rest_check_product_term_permissions() { 94 | $this->isFalse( wc_rest_check_product_term_permissions( 'product_cat' ) ); 95 | } 96 | 97 | /** 98 | * Test wc_rest_check_manager_permissions(). 99 | * 100 | * @since 2.6.0 101 | */ 102 | public function test_wc_rest_check_manager_permissions() { 103 | $this->isFalse( wc_rest_check_manager_permissions( 'reports' ) ); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /tests/unit-tests/order-notes.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Orders_Controller(); 28 | $this->user = $this->factory->user->create( array( 29 | 'role' => 'administrator', 30 | ) ); 31 | $order = WC_Helper_Order::create_order(); 32 | $this->order_id = $order->get_id(); 33 | } 34 | 35 | /** 36 | * Cleanup. 37 | */ 38 | public function stoppit_and_tidyup() { 39 | wp_delete_post( $this->order_id, true ); 40 | foreach ( $this->notes as $note ) { 41 | wc_delete_order_note( $note->comment_ID ); 42 | } 43 | $this->notes = array(); 44 | } 45 | 46 | /** 47 | * Test route registration. 48 | * @since 3.0.0 49 | */ 50 | public function test_register_routes() { 51 | $routes = $this->server->get_routes(); 52 | $this->assertArrayHasKey( '/wc/v3/orders/(?P[\d]+)/notes', $routes ); 53 | $this->assertArrayHasKey( '/wc/v3/orders/(?P[\d]+)/notes/(?P[\d]+)', $routes ); 54 | } 55 | 56 | /** 57 | * Test getting all notes for an order. 58 | * @since 3.0.0 59 | */ 60 | public function test_get_items() { 61 | wp_set_current_user( $this->user ); 62 | 63 | // Create 3 order notes. 64 | for ( $i = 0; $i < 3; $i++ ) { 65 | $this->notes[] = WC_Helper_Order_Note::create_note( $this->order_id, $this->user ); 66 | } 67 | 68 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', "/wc/v3/orders/$this->order_id/notes" ) ); 69 | $notes = $response->get_data(); 70 | 71 | $this->assertEquals( 200, $response->get_status() ); 72 | $this->assertEquals( 3, count( $notes ) ); 73 | $this->stoppit_and_tidyup(); 74 | } 75 | 76 | /** 77 | * Tests to make sure order notes cannot be viewed without valid permissions. 78 | * 79 | * @since 3.0.0 80 | */ 81 | public function test_get_items_without_permission() { 82 | wp_set_current_user( 0 ); 83 | $this->notes[] = WC_Helper_Order_Note::create_note( $this->order_id ); 84 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', "/wc/v3/orders/$this->order_id/notes" ) ); 85 | $this->assertEquals( 401, $response->get_status() ); 86 | $this->stoppit_and_tidyup(); 87 | } 88 | 89 | /** 90 | * Tests getting a single order note. 91 | * @since 3.0.0 92 | */ 93 | public function test_get_item() { 94 | wp_set_current_user( $this->user ); 95 | $note = WC_Helper_Order_Note::create_note( $this->order_id, $this->user ); 96 | $this->notes[] = $note; 97 | $request = new WP_REST_Request( 'GET', "/wc/v3/orders/$this->order_id/notes/$note->comment_ID" ); 98 | $response = $this->server->dispatch( $request ); 99 | $data = $response->get_data(); 100 | 101 | $this->assertEquals( 200, $response->get_status() ); 102 | $this->assertEquals( $note->comment_ID, $data['id'] ); 103 | $this->assertArrayHasKey( 'customer_note', $data ); 104 | $this->assertArrayHasKey( 'date_created', $data ); 105 | $this->assertArrayHasKey( 'author', $data ); 106 | $this->assertArrayHasKey( 'note', $data ); 107 | $this->assertEquals( $data['author'], 'system' ); 108 | $this->assertEquals( $data['note'], 'This is an order note.' ); 109 | $this->stoppit_and_tidyup(); 110 | } 111 | 112 | /** 113 | * Tests creating an order note by a given user. 114 | * @since 3.0.0 115 | */ 116 | public function test_create_note() { 117 | wp_set_current_user( $this->user ); 118 | $request = new WP_REST_Request( 'POST', "/wc/v3/orders/$this->order_id/notes" ); 119 | $request->set_body_params( array( 120 | 'customer_note' => false, 121 | 'added_by_user' => true, 122 | 'note' => 'This is testing content.', 123 | ) ); 124 | $response = $this->server->dispatch( $request ); 125 | $data = $response->get_data(); 126 | $note = wc_get_order_note( $data['id'] ); 127 | $user = get_user_by( 'id', get_current_user_id() ); 128 | 129 | $this->assertEquals( 201, $response->get_status() ); 130 | // Verify the API response has correct data 131 | $this->assertArrayHasKey( 'customer_note', $data ); 132 | $this->assertArrayHasKey( 'date_created', $data ); 133 | $this->assertArrayHasKey( 'note', $data ); 134 | $this->assertArrayHasKey( 'author', $data ); 135 | $this->assertEquals( $data['note'], 'This is testing content.' ); 136 | $this->assertEquals( $data['author'], $user->display_name ); 137 | 138 | // Verify that Note object has correct data 139 | $this->assertEquals( $note->customer_note, false ); 140 | $this->assertEquals( $note->added_by, $user->display_name ); 141 | $this->assertEquals( $note->content, 'This is testing content.' ); 142 | 143 | wc_delete_order_note( $data['id'] ); 144 | } 145 | 146 | /** 147 | * Tests creating an order note by the "system". 148 | * @since 3.0.0 149 | */ 150 | public function test_create_system_note() { 151 | wp_set_current_user( $this->user ); 152 | $request = new WP_REST_Request( 'POST', "/wc/v3/orders/$this->order_id/notes" ); 153 | $request->set_body_params( array( 154 | 'customer_note' => true, 155 | 'note' => 'This is testing content.', 156 | ) ); 157 | $response = $this->server->dispatch( $request ); 158 | $data = $response->get_data(); 159 | $note = wc_get_order_note( $data['id'] ); 160 | 161 | $this->assertEquals( 201, $response->get_status() ); 162 | // Verify the API response has correct data 163 | $this->assertArrayHasKey( 'customer_note', $data ); 164 | $this->assertArrayHasKey( 'date_created', $data ); 165 | $this->assertArrayHasKey( 'note', $data ); 166 | $this->assertArrayHasKey( 'author', $data ); 167 | $this->assertEquals( $data['note'], 'This is testing content.' ); 168 | $this->assertEquals( $data['author'], 'system' ); 169 | 170 | // Verify that Note object has correct data 171 | $this->assertEquals( $note->customer_note, true ); 172 | $this->assertEquals( $note->added_by, 'system' ); 173 | $this->assertEquals( $note->content, 'This is testing content.' ); 174 | 175 | wc_delete_order_note( $data['id'] ); 176 | } 177 | 178 | /** 179 | * Tests creating an order note without required fields. 180 | * @since 3.0.0 181 | */ 182 | public function test_create_order_note_invalid_fields() { 183 | wp_set_current_user( $this->user ); 184 | $request = new WP_REST_Request( 'POST', "/wc/v3/orders/$this->order_id/notes" ); 185 | $request->set_body_params( array( 186 | 'customer_note' => false, 187 | ) ); 188 | $response = $this->server->dispatch( $request ); 189 | $this->assertEquals( 400, $response->get_status() ); 190 | } 191 | 192 | /** 193 | * Test deleting an order note. 194 | * @since 3.0.0 195 | */ 196 | public function test_delete_order_note() { 197 | wp_set_current_user( $this->user ); 198 | $note = WC_Helper_Order_Note::create_note( $this->order_id, $this->user ); 199 | $request = new WP_REST_Request( 'DELETE', "/wc/v3/orders/$this->order_id/notes/$note->comment_ID" ); 200 | $request->set_param( 'force', true ); 201 | $response = $this->server->dispatch( $request ); 202 | $this->assertEquals( 200, $response->get_status() ); 203 | $this->assertEquals( null, wc_get_order_note( $note->comment_ID ) ); 204 | } 205 | 206 | /** 207 | * Test deleting an order note without permission/creds. 208 | * @since 3.0.0 209 | */ 210 | public function test_delete_order_note_without_permission() { 211 | wp_set_current_user( 0 ); 212 | $note = WC_Helper_Order_Note::create_note( $this->order_id ); 213 | $request = new WP_REST_Request( 'DELETE', "/wc/v3/orders/$this->order_id/notes/$note->comment_ID" ); 214 | $request->set_param( 'force', true ); 215 | $response = $this->server->dispatch( $request ); 216 | $this->assertEquals( 401, $response->get_status() ); 217 | wc_delete_order_note( $note->comment_ID ); 218 | } 219 | 220 | /** 221 | * Test deleting an order note with an invalid id. 222 | * 223 | * @since 3.0.0 224 | */ 225 | public function test_delete_order_note_invalid_id() { 226 | wp_set_current_user( $this->user ); 227 | $request = new WP_REST_Request( 'DELETE', "/wc/v3/orders/$this->order_id/notes/9999999" ); 228 | $request->set_param( 'force', true ); 229 | $response = $this->server->dispatch( $request ); 230 | $this->assertEquals( 404, $response->get_status() ); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /tests/unit-tests/order-refunds.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Orders_Controller(); 28 | $this->user = $this->factory->user->create( array( 29 | 'role' => 'administrator', 30 | ) ); 31 | $order = WC_Helper_Order::create_order(); 32 | $this->order_id = $order->get_id(); 33 | } 34 | 35 | /** 36 | * Cleanup. 37 | */ 38 | public function stoppit_and_tidyup() { 39 | wp_delete_post( $this->order_id, true ); 40 | foreach ( $this->refunds as $refund ) { 41 | $refund->delete(); 42 | } 43 | $this->refunds = array(); 44 | } 45 | 46 | /** 47 | * Test route registration. 48 | * @since 3.0.0 49 | */ 50 | public function test_register_routes() { 51 | $routes = $this->server->get_routes(); 52 | $this->assertArrayHasKey( '/wc/v3/orders/(?P[\d]+)/refunds', $routes ); 53 | $this->assertArrayHasKey( '/wc/v3/orders/(?P[\d]+)/refunds/(?P[\d]+)', $routes ); 54 | } 55 | 56 | /** 57 | * Test getting all refunds for an order. 58 | * @since 3.0.0 59 | */ 60 | public function test_get_items() { 61 | wp_set_current_user( $this->user ); 62 | 63 | // Create 2 partial order refunds. 64 | for ( $i = 0; $i < 2; $i++ ) { 65 | $this->refunds[] = WC_Helper_Order_Refund::create_refund( $this->order_id, $this->user ); 66 | } 67 | 68 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', "/wc/v3/orders/$this->order_id/refunds" ) ); 69 | $refunds = $response->get_data(); 70 | 71 | $this->assertEquals( 200, $response->get_status() ); 72 | $this->assertEquals( 2, count( $refunds ) ); 73 | $this->stoppit_and_tidyup(); 74 | } 75 | 76 | /** 77 | * Tests getting a single order refund. 78 | * @since 3.0.0 79 | */ 80 | public function test_get_item() { 81 | wp_set_current_user( $this->user ); 82 | $refund = WC_Helper_Order_Refund::create_refund_with_items( $this->order_id, $this->user ); 83 | $this->refunds[] = $refund; 84 | 85 | $request = new WP_REST_Request( 'GET', "/wc/v3/orders/$this->order_id/refunds/" . $refund->get_id() ); 86 | $response = $this->server->dispatch( $request ); 87 | $data = $response->get_data(); 88 | 89 | $this->assertEquals( 200, $response->get_status() ); 90 | $this->assertArrayHasKey( 'date_created', $data ); 91 | $this->assertEquals( $data['amount'], '5.00' ); 92 | $this->assertEquals( $data['reason'], 'Testing' ); 93 | $this->assertArrayHasKey( 'line_items', $data ); 94 | $this->assertEquals( 1, count( $data['line_items'] ) ); 95 | 96 | $this->stoppit_and_tidyup(); 97 | } 98 | 99 | /** 100 | * Tests creating an order refund by a given user. 101 | * @since 3.0.0 102 | */ 103 | public function test_create_refund() { 104 | wp_set_current_user( $this->user ); 105 | $request = new WP_REST_Request( 'POST', "/wc/v3/orders/$this->order_id/refunds" ); 106 | $request->set_body_params( array( 107 | 'amount' => '5.0', 108 | 'reason' => 'This is testing content.', 109 | 'api_refund' => false, 110 | ) ); 111 | $response = $this->server->dispatch( $request ); 112 | $data = $response->get_data(); 113 | $refund = new WC_Order_Refund( $data['id'] ); 114 | 115 | $this->assertEquals( 201, $response->get_status() ); 116 | // Verify the API response has correct data 117 | $this->assertArrayHasKey( 'date_created', $data ); 118 | $this->assertEquals( $data['amount'], '5.00' ); 119 | $this->assertEquals( $data['reason'], 'This is testing content.' ); 120 | $this->assertEquals( $data['refunded_by'], get_current_user_id() ); 121 | 122 | // Verify that Note object has correct data 123 | $this->assertEquals( $refund->get_amount(), '5.00' ); 124 | $this->assertEquals( $refund->get_reason(), 'This is testing content.' ); 125 | 126 | $refund->delete(); 127 | } 128 | 129 | /** 130 | * Tests creating an order refund by a given user. 131 | * @since 3.0.0 132 | */ 133 | public function test_create_refund_with_items() { 134 | wp_set_current_user( $this->user ); 135 | $line_items = WC_Helper_Order_Refund::create_refund_line_items( $this->order_id, 1 ); 136 | $request = new WP_REST_Request( 'POST', "/wc/v3/orders/$this->order_id/refunds" ); 137 | $request->set_body_params( array( 138 | 'amount' => '5.0', 139 | 'reason' => 'This is testing content.', 140 | 'api_refund' => false, 141 | 'line_items' => $line_items, 142 | ) ); 143 | $response = $this->server->dispatch( $request ); 144 | $data = $response->get_data(); 145 | $refund = new WC_Order_Refund( $data['id'] ); 146 | 147 | $this->assertEquals( 201, $response->get_status() ); 148 | // Verify the API response has correct data 149 | $this->assertArrayHasKey( 'date_created', $data ); 150 | $this->assertArrayHasKey( 'line_items', $data ); 151 | $this->assertEquals( $data['amount'], '5.00' ); 152 | $this->assertEquals( $data['reason'], 'This is testing content.' ); 153 | $this->assertEquals( $data['refunded_by'], get_current_user_id() ); 154 | $this->assertEquals( 1, count( $data['line_items'] ) ); 155 | 156 | // Verify that Note object has correct data 157 | $this->assertEquals( $refund->get_amount(), '5.00' ); 158 | $this->assertEquals( $refund->get_reason(), 'This is testing content.' ); 159 | $items = $refund->get_items(); 160 | $this->assertEquals( 1, count( $items ) ); 161 | 162 | $refund->delete(); 163 | } 164 | } -------------------------------------------------------------------------------- /tests/unit-tests/orders.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Orders_Controller(); 22 | $this->user = $this->factory->user->create( array( 23 | 'role' => 'administrator', 24 | ) ); 25 | } 26 | 27 | /** 28 | * Test route registration. 29 | * @since 3.0.0 30 | */ 31 | public function test_register_routes() { 32 | $routes = $this->server->get_routes(); 33 | $this->assertArrayHasKey( '/wc/v3/orders', $routes ); 34 | $this->assertArrayHasKey( '/wc/v3/orders/batch', $routes ); 35 | $this->assertArrayHasKey( '/wc/v3/orders/(?P[\d]+)', $routes ); 36 | } 37 | 38 | /** 39 | * Cleanup. 40 | */ 41 | public function stoppit_and_tidyup() { 42 | foreach ( $this->orders as $order ) { 43 | wp_delete_post( $order->get_id(), true ); 44 | } 45 | $this->orders = array(); 46 | } 47 | 48 | /** 49 | * Test getting all orders. 50 | * @since 3.0.0 51 | */ 52 | public function test_get_items() { 53 | wp_set_current_user( $this->user ); 54 | 55 | // Create 10 orders. 56 | for ( $i = 0; $i < 10; $i++ ) { 57 | $this->orders[] = WC_Helper_Order::create_order( $this->user ); 58 | } 59 | 60 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/orders' ) ); 61 | $orders = $response->get_data(); 62 | 63 | $this->assertEquals( 200, $response->get_status() ); 64 | $this->assertEquals( 10, count( $orders ) ); 65 | $this->stoppit_and_tidyup(); 66 | } 67 | 68 | /** 69 | * Tests to make sure orders cannot be viewed without valid permissions. 70 | * 71 | * @since 3.0.0 72 | */ 73 | public function test_get_items_without_permission() { 74 | wp_set_current_user( 0 ); 75 | $this->orders[] = WC_Helper_Order::create_order(); 76 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/orders' ) ); 77 | $this->assertEquals( 401, $response->get_status() ); 78 | $this->stoppit_and_tidyup(); 79 | } 80 | 81 | /** 82 | * Tests getting a single order. 83 | * @since 3.0.0 84 | */ 85 | public function test_get_item() { 86 | wp_set_current_user( $this->user ); 87 | $order = WC_Helper_Order::create_order(); 88 | $this->orders[] = $order; 89 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/orders/' . $order->get_id() ) ); 90 | $data = $response->get_data(); 91 | 92 | $this->assertEquals( 200, $response->get_status() ); 93 | $this->assertEquals( $order->get_id(), $data['id'] ); 94 | $this->stoppit_and_tidyup(); 95 | } 96 | 97 | /** 98 | * Tests getting a single order without the correct permissions. 99 | * @since 3.0.0 100 | */ 101 | public function test_get_item_without_permission() { 102 | wp_set_current_user( 0 ); 103 | $order = WC_Helper_Order::create_order(); 104 | $this->orders[] = $order; 105 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/orders/' . $order->get_id() ) ); 106 | $this->assertEquals( 401, $response->get_status() ); 107 | $this->stoppit_and_tidyup(); 108 | } 109 | 110 | /** 111 | * Tests getting an order with an invalid ID. 112 | * @since 3.0.0 113 | */ 114 | public function test_get_item_invalid_id() { 115 | wp_set_current_user( $this->user ); 116 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/orders/99999999' ) ); 117 | $this->assertEquals( 404, $response->get_status() ); 118 | } 119 | 120 | /** 121 | * Tests creating an order. 122 | * @since 3.0.0 123 | */ 124 | public function test_create_order() { 125 | wp_set_current_user( $this->user ); 126 | $product = WC_Helper_Product::create_simple_product(); 127 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders' ); 128 | $request->set_body_params( array( 129 | 'payment_method' => 'bacs', 130 | 'payment_method_title' => 'Direct Bank Transfer', 131 | 'set_paid' => true, 132 | 'billing' => array( 133 | 'first_name' => 'John', 134 | 'last_name' => 'Doe', 135 | 'address_1' => '969 Market', 136 | 'address_2' => '', 137 | 'city' => 'San Francisco', 138 | 'state' => 'CA', 139 | 'postcode' => '94103', 140 | 'country' => 'US', 141 | 'email' => 'john.doe@example.com', 142 | 'phone' => '(555) 555-5555', 143 | ), 144 | 'shipping' => array( 145 | 'first_name' => 'John', 146 | 'last_name' => 'Doe', 147 | 'address_1' => '969 Market', 148 | 'address_2' => '', 149 | 'city' => 'San Francisco', 150 | 'state' => 'CA', 151 | 'postcode' => '94103', 152 | 'country' => 'US', 153 | ), 154 | 'line_items' => array( 155 | array( 156 | 'product_id' => $product->get_id(), 157 | 'quantity' => 2, 158 | ), 159 | ), 160 | 'shipping_lines' => array( 161 | array( 162 | 'method_id' => 'flat_rate', 163 | 'method_title' => 'Flat rate', 164 | 'total' => '10', 165 | ), 166 | ), 167 | ) ); 168 | $response = $this->server->dispatch( $request ); 169 | $data = $response->get_data(); 170 | 171 | $this->assertNotEmpty( $data['id'] ); 172 | 173 | $order = wc_get_order( $data['id'] ); 174 | $this->assertEquals( 201, $response->get_status() ); 175 | $this->assertEquals( $order->get_payment_method(), $data['payment_method'] ); 176 | $this->assertEquals( $order->get_payment_method_title(), $data['payment_method_title'] ); 177 | $this->assertEquals( $order->get_billing_first_name(), $data['billing']['first_name'] ); 178 | $this->assertEquals( $order->get_billing_last_name(), $data['billing']['last_name'] ); 179 | $this->assertEquals( '', $data['billing']['company'] ); 180 | $this->assertEquals( $order->get_billing_address_1(), $data['billing']['address_1'] ); 181 | $this->assertEquals( $order->get_billing_address_2(), $data['billing']['address_2'] ); 182 | $this->assertEquals( $order->get_billing_city(), $data['billing']['city'] ); 183 | $this->assertEquals( $order->get_billing_state(), $data['billing']['state'] ); 184 | $this->assertEquals( $order->get_billing_postcode(), $data['billing']['postcode'] ); 185 | $this->assertEquals( $order->get_billing_country(), $data['billing']['country'] ); 186 | $this->assertEquals( $order->get_billing_email(), $data['billing']['email'] ); 187 | $this->assertEquals( $order->get_billing_phone(), $data['billing']['phone'] ); 188 | $this->assertEquals( $order->get_shipping_first_name(), $data['shipping']['first_name'] ); 189 | $this->assertEquals( $order->get_shipping_last_name(), $data['shipping']['last_name'] ); 190 | $this->assertEquals( '', $data['shipping']['company'] ); 191 | $this->assertEquals( $order->get_shipping_address_1(), $data['shipping']['address_1'] ); 192 | $this->assertEquals( $order->get_shipping_address_2(), $data['shipping']['address_2'] ); 193 | $this->assertEquals( $order->get_shipping_city(), $data['shipping']['city'] ); 194 | $this->assertEquals( $order->get_shipping_state(), $data['shipping']['state'] ); 195 | $this->assertEquals( $order->get_shipping_postcode(), $data['shipping']['postcode'] ); 196 | $this->assertEquals( $order->get_shipping_country(), $data['shipping']['country'] ); 197 | $this->assertEquals( 1, count( $data['line_items'] ) ); 198 | $this->assertEquals( 1, count( $data['shipping_lines'] ) ); 199 | 200 | wp_delete_post( $product->get_id(), true ); 201 | wp_delete_post( $data['id'], true ); 202 | } 203 | 204 | /** 205 | * Tests creating an order without required fields. 206 | * @since 3.0.0 207 | */ 208 | public function test_create_order_invalid_fields() { 209 | wp_set_current_user( $this->user ); 210 | $product = WC_Helper_Product::create_simple_product(); 211 | 212 | // non-existant customer 213 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders' ); 214 | $request->set_body_params( array( 215 | 'payment_method' => 'bacs', 216 | 'payment_method_title' => 'Direct Bank Transfer', 217 | 'set_paid' => true, 218 | 'customer_id' => 99999, 219 | 'billing' => array( 220 | 'first_name' => 'John', 221 | 'last_name' => 'Doe', 222 | 'address_1' => '969 Market', 223 | 'address_2' => '', 224 | 'city' => 'San Francisco', 225 | 'state' => 'CA', 226 | 'postcode' => '94103', 227 | 'country' => 'US', 228 | 'email' => 'john.doe@example.com', 229 | 'phone' => '(555) 555-5555', 230 | ), 231 | 'shipping' => array( 232 | 'first_name' => 'John', 233 | 'last_name' => 'Doe', 234 | 'address_1' => '969 Market', 235 | 'address_2' => '', 236 | 'city' => 'San Francisco', 237 | 'state' => 'CA', 238 | 'postcode' => '94103', 239 | 'country' => 'US', 240 | ), 241 | 'line_items' => array( 242 | array( 243 | 'product_id' => $product->get_id(), 244 | 'quantity' => 2, 245 | ), 246 | ), 247 | 'shipping_lines' => array( 248 | array( 249 | 'method_id' => 'flat_rate', 250 | 'method_title' => 'Flat rate', 251 | 'total' => '10', 252 | ), 253 | ), 254 | ) ); 255 | $response = $this->server->dispatch( $request ); 256 | $data = $response->get_data(); 257 | $this->assertEquals( 400, $response->get_status() ); 258 | wp_delete_post( $product->get_id(), true ); 259 | } 260 | 261 | /** 262 | * Tests updating an order. 263 | * @since 3.0.0 264 | */ 265 | public function test_update_order() { 266 | wp_set_current_user( $this->user ); 267 | $order = WC_Helper_Order::create_order(); 268 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders/' . $order->get_id() ); 269 | $request->set_body_params( array( 270 | 'payment_method' => 'test-update', 271 | 'billing' => array( 272 | 'first_name' => 'Fish', 273 | 'last_name' => 'Face', 274 | ), 275 | ) ); 276 | $response = $this->server->dispatch( $request ); 277 | $data = $response->get_data(); 278 | 279 | $this->assertEquals( 200, $response->get_status() ); 280 | $this->assertEquals( 'test-update', $data['payment_method'] ); 281 | $this->assertEquals( 'Fish', $data['billing']['first_name'] ); 282 | $this->assertEquals( 'Face', $data['billing']['last_name'] ); 283 | 284 | wp_delete_post( $order->get_id(), true ); 285 | } 286 | 287 | /** 288 | * Tests updating an order without the correct permissions. 289 | * @since 3.0.0 290 | */ 291 | public function test_update_order_without_permission() { 292 | wp_set_current_user( 0 ); 293 | $order = WC_Helper_Order::create_order(); 294 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders/' . $order->get_id() ); 295 | $request->set_body_params( array( 296 | 'payment_method' => 'test-update', 297 | 'billing' => array( 298 | 'first_name' => 'Fish', 299 | 'last_name' => 'Face', 300 | ), 301 | ) ); 302 | $response = $this->server->dispatch( $request ); 303 | $this->assertEquals( 401, $response->get_status() ); 304 | } 305 | 306 | /** 307 | * Tests that updating an order with an invalid id fails. 308 | * @since 3.0.0 309 | */ 310 | public function test_update_order_invalid_id() { 311 | wp_set_current_user( $this->user ); 312 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders/999999' ); 313 | $request->set_body_params( array( 314 | 'payment_method' => 'test-update', 315 | 'billing' => array( 316 | 'first_name' => 'Fish', 317 | 'last_name' => 'Face', 318 | ), 319 | ) ); 320 | $response = $this->server->dispatch( $request ); 321 | $this->assertEquals( 400, $response->get_status() ); 322 | } 323 | 324 | /** 325 | * Test deleting an order. 326 | * @since 3.0.0 327 | */ 328 | public function test_delete_order() { 329 | wp_set_current_user( $this->user ); 330 | $order = WC_Helper_Order::create_order(); 331 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/orders/' . $order->get_id() ); 332 | $request->set_param( 'force', true ); 333 | $response = $this->server->dispatch( $request ); 334 | $this->assertEquals( 200, $response->get_status() ); 335 | $this->assertEquals( null, get_post( $order->get_id() ) ); 336 | } 337 | 338 | /** 339 | * Test deleting an order without permission/creds. 340 | * @since 3.0.0 341 | */ 342 | public function test_delete_order_without_permission() { 343 | wp_set_current_user( 0 ); 344 | $order = WC_Helper_Order::create_order(); 345 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/orders/' . $order->get_id() ); 346 | $request->set_param( 'force', true ); 347 | $response = $this->server->dispatch( $request ); 348 | $this->assertEquals( 401, $response->get_status() ); 349 | wp_delete_post( $order->get_id(), true ); 350 | } 351 | 352 | /** 353 | * Test deleting an order with an invalid id. 354 | * 355 | * @since 3.0.0 356 | */ 357 | public function test_delete_order_invalid_id() { 358 | wp_set_current_user( $this->user ); 359 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/orders/9999999' ); 360 | $request->set_param( 'force', true ); 361 | $response = $this->server->dispatch( $request ); 362 | $this->assertEquals( 404, $response->get_status() ); 363 | } 364 | 365 | /** 366 | * Test batch managing product reviews. 367 | */ 368 | public function test_orders_batch() { 369 | wp_set_current_user( $this->user ); 370 | 371 | // Delete any existing orders 372 | $request = new WP_REST_Request( 'GET', '/wc/v3/orders' ); 373 | $response = $this->server->dispatch( $request ); 374 | $orders = $response->get_data(); 375 | foreach ( $orders as $order ) { 376 | wp_delete_post( $order['id'], true ); 377 | } 378 | 379 | $order1 = WC_Helper_Order::create_order(); 380 | $order2 = WC_Helper_Order::create_order(); 381 | $order3 = WC_Helper_Order::create_order(); 382 | 383 | $request = new WP_REST_Request( 'POST', '/wc/v3/orders/batch' ); 384 | $request->set_body_params( array( 385 | 'update' => array( 386 | array( 387 | 'id' => $order1->get_id(), 388 | 'payment_method' => 'updated', 389 | ), 390 | ), 391 | 'delete' => array( 392 | $order2->get_id(), 393 | $order3->get_id(), 394 | ), 395 | ) ); 396 | $response = $this->server->dispatch( $request ); 397 | $data = $response->get_data(); 398 | 399 | $this->assertEquals( 'updated', $data['update'][0]['payment_method'] ); 400 | $this->assertEquals( $order2->get_id(), $data['delete'][0]['id'] ); 401 | $this->assertEquals( $order3->get_id(), $data['delete'][1]['id'] ); 402 | 403 | $request = new WP_REST_Request( 'GET', '/wc/v3/orders' ); 404 | $response = $this->server->dispatch( $request ); 405 | $data = $response->get_data(); 406 | $this->assertEquals( 1, count( $data ) ); 407 | 408 | wp_delete_post( $order1->get_id(), true ); 409 | wp_delete_post( $order2->get_id(), true ); 410 | wp_delete_post( $order3->get_id(), true ); 411 | } 412 | 413 | /** 414 | * Test the order schema. 415 | * @since 3.0.0 416 | */ 417 | public function test_order_schema() { 418 | wp_set_current_user( $this->user ); 419 | $order = WC_Helper_Order::create_order(); 420 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/orders/' . $order->get_id() ); 421 | $response = $this->server->dispatch( $request ); 422 | $data = $response->get_data(); 423 | $properties = $data['schema']['properties']; 424 | 425 | $this->assertEquals( 42, count( $properties ) ); 426 | $this->assertArrayHasKey( 'id', $properties ); 427 | wp_delete_post( $order->get_id(), true ); 428 | } 429 | } 430 | -------------------------------------------------------------------------------- /tests/unit-tests/payment-gateways.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Payment_Gateways_Controller(); 17 | $this->user = $this->factory->user->create( array( 18 | 'role' => 'administrator', 19 | ) ); 20 | } 21 | 22 | /** 23 | * Test route registration. 24 | * 25 | * @since 3.0.0 26 | */ 27 | public function test_register_routes() { 28 | $routes = $this->server->get_routes(); 29 | $this->assertArrayHasKey( '/wc/v3/payment_gateways', $routes ); 30 | $this->assertArrayHasKey( '/wc/v3/payment_gateways/(?P[\w-]+)', $routes ); 31 | } 32 | 33 | /** 34 | * Test getting all payment gateways. 35 | * 36 | * @since 3.0.0 37 | */ 38 | public function test_get_payment_gateways() { 39 | wp_set_current_user( $this->user ); 40 | 41 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways' ) ); 42 | $gateways = $response->get_data(); 43 | 44 | $wc_gateways = WC()->payment_gateways->payment_gateways(); 45 | 46 | $this->assertEquals( 200, $response->get_status() ); 47 | $this->assertEquals( count( $wc_gateways ), count( $gateways ) ); 48 | $this->assertNotEmpty( $gateways[0]['id'] ); 49 | } 50 | 51 | /** 52 | * Tests to make sure payment gateways cannot viewed without valid permissions. 53 | * 54 | * @since 3.0.0 55 | */ 56 | public function test_get_payment_gateways_without_permission() { 57 | wp_set_current_user( 0 ); 58 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways' ) ); 59 | $this->assertEquals( 401, $response->get_status() ); 60 | } 61 | 62 | /** 63 | * Test getting a single payment gateway. 64 | * 65 | * @since 3.0.0 66 | */ 67 | public function test_get_payment_gateway() { 68 | wp_set_current_user( $this->user ); 69 | 70 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways/paypal' ) ); 71 | $paypal = $response->get_data(); 72 | 73 | $this->assertEquals( 200, $response->get_status() ); 74 | $this->assertEquals( 'paypal', $paypal['id'] ); 75 | $this->assertEquals( 'PayPal', $paypal['title'] ); 76 | } 77 | 78 | /** 79 | * Test getting a payment gateway without valid permissions. 80 | * 81 | * @since 3.0.0 82 | */ 83 | public function test_get_payment_gateway_without_permission() { 84 | wp_set_current_user( 0 ); 85 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways/paypal' ) ); 86 | $this->assertEquals( 401, $response->get_status() ); 87 | } 88 | 89 | /** 90 | * Test getting a payment gateway with an invalid id. 91 | * 92 | * @since 3.0.0 93 | */ 94 | public function test_get_payment_gateway_invalid_id() { 95 | wp_set_current_user( $this->user ); 96 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways/totally_fake_method' ) ); 97 | $this->assertEquals( 404, $response->get_status() ); 98 | } 99 | 100 | /** 101 | * Test updating a single payment gateway. 102 | * 103 | * @since 3.0.0 104 | */ 105 | public function test_update_payment_gateway() { 106 | wp_set_current_user( $this->user ); 107 | 108 | // Test defaults 109 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/payment_gateways/paypal' ) ); 110 | $paypal = $response->get_data(); 111 | 112 | $this->assertEquals( 'PayPal', $paypal['settings']['title']['value'] ); 113 | $this->assertEquals( 'admin@example.org', $paypal['settings']['email']['value'] ); 114 | $this->assertEquals( 'no', $paypal['settings']['testmode']['value'] ); 115 | 116 | // test updating single setting 117 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 118 | $request->set_body_params( array( 119 | 'settings' => array( 120 | 'email' => 'woo@woo.local', 121 | ), 122 | ) ); 123 | $response = $this->server->dispatch( $request ); 124 | $paypal = $response->get_data(); 125 | 126 | $this->assertEquals( 200, $response->get_status() ); 127 | $this->assertEquals( 'PayPal', $paypal['settings']['title']['value'] ); 128 | $this->assertEquals( 'woo@woo.local', $paypal['settings']['email']['value'] ); 129 | $this->assertEquals( 'no', $paypal['settings']['testmode']['value'] ); 130 | 131 | // test updating multiple settings 132 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 133 | $request->set_body_params( array( 134 | 'settings' => array( 135 | 'testmode' => 'yes', 136 | 'title' => 'PayPal - New Title', 137 | ), 138 | ) ); 139 | $response = $this->server->dispatch( $request ); 140 | $paypal = $response->get_data(); 141 | 142 | $this->assertEquals( 200, $response->get_status() ); 143 | $this->assertEquals( 'PayPal - New Title', $paypal['settings']['title']['value'] ); 144 | $this->assertEquals( 'woo@woo.local', $paypal['settings']['email']['value'] ); 145 | $this->assertEquals( 'yes', $paypal['settings']['testmode']['value'] ); 146 | 147 | // Test other parameters, and recheck settings 148 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 149 | $request->set_body_params( array( 150 | 'enabled' => false, 151 | 'order' => 2, 152 | ) ); 153 | $response = $this->server->dispatch( $request ); 154 | $paypal = $response->get_data(); 155 | 156 | $this->assertFalse( $paypal['enabled'] ); 157 | $this->assertEquals( 2, $paypal['order'] ); 158 | $this->assertEquals( 'PayPal - New Title', $paypal['settings']['title']['value'] ); 159 | $this->assertEquals( 'woo@woo.local', $paypal['settings']['email']['value'] ); 160 | $this->assertEquals( 'yes', $paypal['settings']['testmode']['value'] ); 161 | 162 | // test bogus 163 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 164 | $request->set_body_params( array( 165 | 'settings' => array( 166 | 'paymentaction' => 'afasfasf', 167 | ), 168 | ) ); 169 | $response = $this->server->dispatch( $request ); 170 | $this->assertEquals( 400, $response->get_status() ); 171 | 172 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 173 | $request->set_body_params( array( 174 | 'settings' => array( 175 | 'paymentaction' => 'authorization', 176 | ), 177 | ) ); 178 | $response = $this->server->dispatch( $request ); 179 | $paypal = $response->get_data(); 180 | $this->assertEquals( 'authorization', $paypal['settings']['paymentaction']['value'] ); 181 | } 182 | 183 | /** 184 | * Test updating a payment gateway without valid permissions. 185 | * 186 | * @since 3.0.0 187 | */ 188 | public function test_update_payment_gateway_without_permission() { 189 | wp_set_current_user( 0 ); 190 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/paypal' ); 191 | $request->set_body_params( array( 192 | 'settings' => array( 193 | 'testmode' => 'yes', 194 | 'title' => 'PayPal - New Title', 195 | ), 196 | ) ); 197 | $response = $this->server->dispatch( $request ); 198 | $this->assertEquals( 401, $response->get_status() ); 199 | } 200 | 201 | /** 202 | * Test updating a payment gateway with an invalid id. 203 | * 204 | * @since 3.0.0 205 | */ 206 | public function test_update_payment_gateway_invalid_id() { 207 | wp_set_current_user( $this->user ); 208 | $request = new WP_REST_Request( 'POST', '/wc/v3/payment_gateways/totally_fake_method' ); 209 | $request->set_body_params( array( 210 | 'enabled' => true, 211 | ) ); 212 | $response = $this->server->dispatch( $request ); 213 | $this->assertEquals( 404, $response->get_status() ); 214 | } 215 | 216 | /** 217 | * Test the payment gateway schema. 218 | * 219 | * @since 3.0.0 220 | */ 221 | public function test_payment_gateway_schema() { 222 | wp_set_current_user( $this->user ); 223 | 224 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/payment_gateways' ); 225 | $response = $this->server->dispatch( $request ); 226 | $data = $response->get_data(); 227 | $properties = $data['schema']['properties']; 228 | 229 | $this->assertEquals( 9, count( $properties ) ); 230 | $this->assertArrayHasKey( 'id', $properties ); 231 | $this->assertArrayHasKey( 'title', $properties ); 232 | $this->assertArrayHasKey( 'description', $properties ); 233 | $this->assertArrayHasKey( 'order', $properties ); 234 | $this->assertArrayHasKey( 'enabled', $properties ); 235 | $this->assertArrayHasKey( 'method_title', $properties ); 236 | $this->assertArrayHasKey( 'method_description', $properties ); 237 | $this->assertArrayHasKey( 'method_supports', $properties ); 238 | $this->assertArrayHasKey( 'settings', $properties ); 239 | } 240 | 241 | /** 242 | * Loads a particular gateway's settings so we can correctly test API output. 243 | * 244 | * @since 3.0.0 245 | * @param string $gateway_class Name of WC_Payment_Gateway class. 246 | */ 247 | private function get_settings( $gateway_class ) { 248 | $gateway = new $gateway_class; 249 | $settings = array(); 250 | $gateway->init_form_fields(); 251 | foreach ( $gateway->form_fields as $id => $field ) { 252 | // Make sure we at least have a title and type 253 | if ( empty( $field['title'] ) || empty( $field['type'] ) ) { 254 | continue; 255 | } 256 | // Ignore 'title' settings/fields -- they are UI only 257 | if ( 'title' === $field['type'] ) { 258 | continue; 259 | } 260 | $data = array( 261 | 'id' => $id, 262 | 'label' => empty( $field['label'] ) ? $field['title'] : $field['label'], 263 | 'description' => empty( $field['description'] ) ? '' : $field['description'], 264 | 'type' => $field['type'], 265 | 'value' => $gateway->settings[ $id ], 266 | 'default' => empty( $field['default'] ) ? '' : $field['default'], 267 | 'tip' => empty( $field['description'] ) ? '' : $field['description'], 268 | 'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'], 269 | ); 270 | if ( ! empty( $field['options'] ) ) { 271 | $data['options'] = $field['options']; 272 | } 273 | $settings[ $id ] = $data; 274 | } 275 | return $settings; 276 | } 277 | 278 | } 279 | -------------------------------------------------------------------------------- /tests/unit-tests/product-variations.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Product_Variations_Controller(); 17 | $this->user = $this->factory->user->create( array( 18 | 'role' => 'administrator', 19 | ) ); 20 | } 21 | 22 | /** 23 | * Test route registration. 24 | * 25 | * @since 3.0.0 26 | */ 27 | public function test_register_routes() { 28 | $routes = $this->server->get_routes(); 29 | $this->assertArrayHasKey( '/wc/v3/products/(?P[\d]+)/variations', $routes ); 30 | $this->assertArrayHasKey( '/wc/v3/products/(?P[\d]+)/variations/(?P[\d]+)', $routes ); 31 | $this->assertArrayHasKey( '/wc/v3/products/(?P[\d]+)/variations/batch', $routes ); 32 | } 33 | 34 | /** 35 | * Test getting variations. 36 | * 37 | * @since 3.0.0 38 | */ 39 | public function test_get_variations() { 40 | wp_set_current_user( $this->user ); 41 | $product = WC_Helper_Product::create_variation_product(); 42 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ) ); 43 | $variations = $response->get_data(); 44 | $this->assertEquals( 200, $response->get_status() ); 45 | $this->assertEquals( 2, count( $variations ) ); 46 | $this->assertEquals( 'DUMMY SKU VARIABLE LARGE', $variations[0]['sku'] ); 47 | $this->assertEquals( 'size', $variations[0]['attributes'][0]['name'] ); 48 | $product->delete( true ); 49 | } 50 | 51 | /** 52 | * Test getting variations without permission. 53 | * 54 | * @since 3.0.0 55 | */ 56 | public function test_get_variations_without_permission() { 57 | wp_set_current_user( 0 ); 58 | $product = WC_Helper_Product::create_variation_product(); 59 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ) ); 60 | $this->assertEquals( 401, $response->get_status() ); 61 | $product->delete( true ); 62 | } 63 | 64 | /** 65 | * Test getting a single variation. 66 | * 67 | * @since 3.0.0 68 | */ 69 | public function test_get_variation() { 70 | wp_set_current_user( $this->user ); 71 | $product = WC_Helper_Product::create_variation_product(); 72 | $children = $product->get_children(); 73 | $variation_id = $children[0]; 74 | 75 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ) ); 76 | $variation = $response->get_data(); 77 | 78 | $this->assertEquals( 200, $response->get_status() ); 79 | $this->assertEquals( $variation_id, $variation['id'] ); 80 | $this->assertEquals( 'size', $variation['attributes'][0]['name'] ); 81 | $product->delete( true ); 82 | } 83 | 84 | /** 85 | * Test getting single variation without permission. 86 | * 87 | * @since 3.0.0 88 | */ 89 | public function test_get_variation_without_permission() { 90 | wp_set_current_user( 0 ); 91 | $product = WC_Helper_Product::create_variation_product(); 92 | $children = $product->get_children(); 93 | $variation_id = $children[0]; 94 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ) ); 95 | $this->assertEquals( 401, $response->get_status() ); 96 | $product->delete( true ); 97 | } 98 | 99 | /** 100 | * Test deleting a single variation. 101 | * 102 | * @since 3.0.0 103 | */ 104 | public function test_delete_variation() { 105 | wp_set_current_user( $this->user ); 106 | $product = WC_Helper_Product::create_variation_product(); 107 | $children = $product->get_children(); 108 | $variation_id = $children[0]; 109 | 110 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ); 111 | $request->set_param( 'force', true ); 112 | $response = $this->server->dispatch( $request ); 113 | $this->assertEquals( 200, $response->get_status() ); 114 | 115 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ) ); 116 | $variations = $response->get_data(); 117 | $this->assertEquals( 1, count( $variations ) ); 118 | $product->delete( true ); 119 | } 120 | 121 | /** 122 | * Test deleting a single variation without permission. 123 | * 124 | * @since 3.0.0 125 | */ 126 | public function test_delete_variation_without_permission() { 127 | wp_set_current_user( 0 ); 128 | $product = WC_Helper_Product::create_variation_product(); 129 | $children = $product->get_children(); 130 | $variation_id = $children[0]; 131 | 132 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ); 133 | $request->set_param( 'force', true ); 134 | $response = $this->server->dispatch( $request ); 135 | $this->assertEquals( 401, $response->get_status() ); 136 | $product->delete( true ); 137 | } 138 | 139 | /** 140 | * Test deleting a single variation with an invalid ID. 141 | * 142 | * @since 3.0.0 143 | */ 144 | public function test_delete_variation_with_invalid_id() { 145 | wp_set_current_user( 0 ); 146 | $product = WC_Helper_Product::create_variation_product(); 147 | $request = new WP_REST_Request( 'DELETE', '/wc/v3/products/' . $product->get_id() . '/variations/0' ); 148 | $request->set_param( 'force', true ); 149 | $response = $this->server->dispatch( $request ); 150 | $this->assertEquals( 404, $response->get_status() ); 151 | $product->delete( true ); 152 | } 153 | 154 | /** 155 | * Test editing a single variation. 156 | * 157 | * @since 3.0.0 158 | */ 159 | public function test_update_variation() { 160 | wp_set_current_user( $this->user ); 161 | $product = WC_Helper_Product::create_variation_product(); 162 | $children = $product->get_children(); 163 | $variation_id = $children[0]; 164 | 165 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ) ); 166 | $variation = $response->get_data(); 167 | 168 | $this->assertEquals( 'DUMMY SKU VARIABLE SMALL', $variation['sku'] ); 169 | $this->assertEquals( 10, $variation['regular_price'] ); 170 | $this->assertEmpty( $variation['sale_price'] ); 171 | $this->assertEquals( 'small', $variation['attributes'][0]['option'] ); 172 | $this->assertEquals( 'publish', $variation['status'] ); 173 | 174 | $request = new WP_REST_Request( 'PUT', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ); 175 | $request->set_body_params( array( 176 | 'sku' => 'FIXED-SKU', 177 | 'sale_price' => '8', 178 | 'description' => 'O_O', 179 | 'image' => array( 'position' => 0, 'src' => 'https://cldup.com/Dr1Bczxq4q.png', 'alt' => 'test upload image' ), 180 | 'attributes' => array( array( 'name' => 'pa_size', 'option' => 'medium' ) ), 181 | 'status' => 'private', 182 | ) ); 183 | $response = $this->server->dispatch( $request ); 184 | $variation = $response->get_data(); 185 | 186 | $this->assertContains( 'O_O', $variation['description'] ); 187 | $this->assertEquals( '8', $variation['price'] ); 188 | $this->assertEquals( '8', $variation['sale_price'] ); 189 | $this->assertEquals( '10', $variation['regular_price'] ); 190 | $this->assertEquals( 'FIXED-SKU', $variation['sku'] ); 191 | $this->assertEquals( 'medium', $variation['attributes'][0]['option'] ); 192 | $this->assertContains( 'Dr1Bczxq4q', $variation['image']['src'] ); 193 | $this->assertContains( 'test upload image', $variation['image']['alt'] ); 194 | $this->assertEquals( 'private', $variation['status'] ); 195 | $product->delete( true ); 196 | } 197 | 198 | /** 199 | * Test setting variation image from ID. (src is tested in `test_update_variation`) 200 | */ 201 | public function test_set_variation_image_from_id() { 202 | wp_set_current_user( $this->user ); 203 | 204 | $orig_file = dirname( __FILE__ ) . '/../../assets/icon-128x128.png'; 205 | $this->test_file = '/tmp/icon.png'; 206 | copy( $orig_file, $this->test_file ); 207 | 208 | $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); 209 | $request->set_header( 'Content-Type', 'image/png' ); 210 | $request->set_header( 'Content-Disposition', 'attachment; filename=icon.png' ); 211 | $request->set_body( file_get_contents( $this->test_file ) ); 212 | $response = $this->server->dispatch( $request ); 213 | $image = $response->get_data(); 214 | 215 | $product = WC_Helper_Product::create_variation_product(); 216 | $children = $product->get_children(); 217 | $variation_id = $children[0]; 218 | 219 | $request = new WP_REST_Request( 'PUT', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ); 220 | $request->set_body_params( array( 221 | 'image' => array( 'id' => $image['id'] ), 222 | ) ); 223 | $response = $this->server->dispatch( $request ); 224 | $variation = $response->get_data(); 225 | 226 | $this->assertNotEmpty( $variation['image'] ); 227 | $this->assertEquals( $image['id'], $variation['image']['id'] ); 228 | 229 | $product->delete( true ); 230 | if ( file_exists( $this->test_file ) ) { 231 | unlink( $this->test_file ); 232 | } 233 | } 234 | 235 | /** 236 | * Test updating a single variation without permission. 237 | * 238 | * @since 3.0.0 239 | */ 240 | public function test_update_variation_without_permission() { 241 | wp_set_current_user( 0 ); 242 | $product = WC_Helper_Product::create_variation_product(); 243 | $children = $product->get_children(); 244 | $variation_id = $children[0]; 245 | 246 | $request = new WP_REST_Request( 'PUT', '/wc/v3/products/' . $product->get_id() . '/variations/' . $variation_id ); 247 | $request->set_body_params( array( 248 | 'sku' => 'FIXED-SKU-NO-PERMISSION', 249 | ) ); 250 | $response = $this->server->dispatch( $request ); 251 | $this->assertEquals( 401, $response->get_status() ); 252 | $product->delete( true ); 253 | } 254 | 255 | /** 256 | * Test updating a single variation with an invalid ID. 257 | * 258 | * @since 3.0.0 259 | */ 260 | public function test_update_variation_with_invalid_id() { 261 | wp_set_current_user( $this->user ); 262 | $product = WC_Helper_Product::create_variation_product(); 263 | $request = new WP_REST_Request( 'PUT', '/wc/v3/products/' . $product->get_id() . '/variations/0' ); 264 | $request->set_body_params( array( 265 | 'sku' => 'FIXED-SKU-NO-PERMISSION', 266 | ) ); 267 | $response = $this->server->dispatch( $request ); 268 | $this->assertEquals( 400, $response->get_status() ); 269 | $product->delete( true ); 270 | } 271 | 272 | /** 273 | * Test creating a single variation. 274 | * 275 | * @since 3.0.0 276 | */ 277 | public function test_create_variation() { 278 | wp_set_current_user( $this->user ); 279 | $product = WC_Helper_Product::create_variation_product(); 280 | 281 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ) ); 282 | $variations = $response->get_data(); 283 | $this->assertEquals( 2, count( $variations ) ); 284 | 285 | $request = new WP_REST_Request( 'POST', '/wc/v3/products/' . $product->get_id() . '/variations' ); 286 | $request->set_body_params( array( 287 | 'sku' => 'DUMMY SKU VARIABLE MEDIUM', 288 | 'regular_price' => '12', 289 | 'description' => 'A medium size.', 290 | 'attributes' => array( array( 'name' => 'pa_size', 'option' => 'medium' ) ), 291 | ) ); 292 | $response = $this->server->dispatch( $request ); 293 | $variation = $response->get_data(); 294 | 295 | $this->assertContains( 'A medium size.', $variation['description'] ); 296 | $this->assertEquals( '12', $variation['price'] ); 297 | $this->assertEquals( '12', $variation['regular_price'] ); 298 | $this->assertTrue( $variation['purchasable'] ); 299 | $this->assertEquals( 'DUMMY SKU VARIABLE MEDIUM', $variation['sku'] ); 300 | $this->assertEquals( 'medium', $variation['attributes'][0]['option'] ); 301 | 302 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ) ); 303 | $variations = $response->get_data(); 304 | $this->assertEquals( 3, count( $variations ) ); 305 | $product->delete( true ); 306 | } 307 | 308 | /** 309 | * Test creating a single variation without permission. 310 | * 311 | * @since 3.0.0 312 | */ 313 | public function test_create_variation_without_permission() { 314 | wp_set_current_user( 0 ); 315 | $product = WC_Helper_Product::create_variation_product(); 316 | 317 | $request = new WP_REST_Request( 'POST', '/wc/v3/products/' . $product->get_id() . '/variations' ); 318 | $request->set_body_params( array( 319 | 'sku' => 'DUMMY SKU VARIABLE MEDIUM', 320 | 'regular_price' => '12', 321 | 'description' => 'A medium size.', 322 | 'attributes' => array( array( 'name' => 'pa_size', 'option' => 'medium' ) ), 323 | ) ); 324 | $response = $this->server->dispatch( $request ); 325 | $this->assertEquals( 401, $response->get_status() ); 326 | $product->delete( true ); 327 | } 328 | 329 | /** 330 | * Test batch managing product variations. 331 | */ 332 | public function test_product_variations_batch() { 333 | wp_set_current_user( $this->user ); 334 | $product = WC_Helper_Product::create_variation_product(); 335 | $children = $product->get_children(); 336 | $request = new WP_REST_Request( 'POST', '/wc/v3/products/' . $product->get_id() . '/variations/batch' ); 337 | $request->set_body_params( array( 338 | 'update' => array( 339 | array( 340 | 'id' => $children[0], 341 | 'description' => 'Updated description.', 342 | 'image' => array( 'position' => 0, 'src' => 'https://cldup.com/Dr1Bczxq4q.png', 'alt' => 'test upload image' ), 343 | ), 344 | ), 345 | 'delete' => array( 346 | $children[1], 347 | ), 348 | 'create' => array( 349 | array( 350 | 'sku' => 'DUMMY SKU VARIABLE MEDIUM', 351 | 'regular_price' => '12', 352 | 'description' => 'A medium size.', 353 | 'attributes' => array( array( 'name' => 'pa_size', 'option' => 'medium' ) ), 354 | ), 355 | ), 356 | ) ); 357 | $response = $this->server->dispatch( $request ); 358 | $data = $response->get_data(); 359 | 360 | $this->assertContains( 'Updated description.', $data['update'][0]['description'] ); 361 | $this->assertEquals( 'DUMMY SKU VARIABLE MEDIUM', $data['create'][0]['sku'] ); 362 | $this->assertEquals( 'medium', $data['create'][0]['attributes'][0]['option'] ); 363 | $this->assertEquals( $children[1], $data['delete'][0]['id'] ); 364 | 365 | $request = new WP_REST_Request( 'GET', '/wc/v3/products/' . $product->get_id() . '/variations' ); 366 | $response = $this->server->dispatch( $request ); 367 | $data = $response->get_data(); 368 | 369 | $this->assertEquals( 2, count( $data ) ); 370 | $product->delete( true ); 371 | } 372 | 373 | /** 374 | * Test variation schema. 375 | * 376 | * @since 3.0.0 377 | */ 378 | public function test_variation_schema() { 379 | wp_set_current_user( $this->user ); 380 | $product = WC_Helper_Product::create_simple_product(); 381 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/products/' . $product->get_id() . '/variations' ); 382 | $response = $this->server->dispatch( $request ); 383 | $data = $response->get_data(); 384 | $properties = $data['schema']['properties']; 385 | 386 | $this->assertEquals( 37, count( $properties ) ); 387 | $this->assertArrayHasKey( 'id', $properties ); 388 | $this->assertArrayHasKey( 'date_created', $properties ); 389 | $this->assertArrayHasKey( 'date_modified', $properties ); 390 | $this->assertArrayHasKey( 'description', $properties ); 391 | $this->assertArrayHasKey( 'permalink', $properties ); 392 | $this->assertArrayHasKey( 'sku', $properties ); 393 | $this->assertArrayHasKey( 'price', $properties ); 394 | $this->assertArrayHasKey( 'regular_price', $properties ); 395 | $this->assertArrayHasKey( 'sale_price', $properties ); 396 | $this->assertArrayHasKey( 'date_on_sale_from', $properties ); 397 | $this->assertArrayHasKey( 'date_on_sale_to', $properties ); 398 | $this->assertArrayHasKey( 'on_sale', $properties ); 399 | $this->assertArrayHasKey( 'purchasable', $properties ); 400 | $this->assertArrayHasKey( 'virtual', $properties ); 401 | $this->assertArrayHasKey( 'downloadable', $properties ); 402 | $this->assertArrayHasKey( 'downloads', $properties ); 403 | $this->assertArrayHasKey( 'download_limit', $properties ); 404 | $this->assertArrayHasKey( 'download_expiry', $properties ); 405 | $this->assertArrayHasKey( 'status', $properties ); 406 | $this->assertArrayHasKey( 'tax_status', $properties ); 407 | $this->assertArrayHasKey( 'tax_class', $properties ); 408 | $this->assertArrayHasKey( 'manage_stock', $properties ); 409 | $this->assertArrayHasKey( 'stock_quantity', $properties ); 410 | $this->assertArrayHasKey( 'in_stock', $properties ); 411 | $this->assertArrayHasKey( 'backorders', $properties ); 412 | $this->assertArrayHasKey( 'backorders_allowed', $properties ); 413 | $this->assertArrayHasKey( 'backordered', $properties ); 414 | $this->assertArrayHasKey( 'weight', $properties ); 415 | $this->assertArrayHasKey( 'dimensions', $properties ); 416 | $this->assertArrayHasKey( 'shipping_class', $properties ); 417 | $this->assertArrayHasKey( 'shipping_class_id', $properties ); 418 | $this->assertArrayHasKey( 'image', $properties ); 419 | $this->assertArrayHasKey( 'attributes', $properties ); 420 | $this->assertArrayHasKey( 'menu_order', $properties ); 421 | $this->assertArrayHasKey( 'meta_data', $properties ); 422 | $product->delete( true ); 423 | } 424 | 425 | } 426 | -------------------------------------------------------------------------------- /tests/unit-tests/shipping-methods.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_Shipping_Methods_Controller(); 17 | $this->user = $this->factory->user->create( array( 18 | 'role' => 'administrator', 19 | ) ); 20 | } 21 | 22 | /** 23 | * Test route registration. 24 | * 25 | * @since 3.0.0 26 | */ 27 | public function test_register_routes() { 28 | $routes = $this->server->get_routes(); 29 | $this->assertArrayHasKey( '/wc/v3/shipping_methods', $routes ); 30 | $this->assertArrayHasKey( '/wc/v3/shipping_methods/(?P[\w-]+)', $routes ); 31 | } 32 | 33 | /** 34 | * Test getting all shipping methods. 35 | * 36 | * @since 3.0.0 37 | */ 38 | public function test_get_shipping_methods() { 39 | wp_set_current_user( $this->user ); 40 | 41 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/shipping_methods' ) ); 42 | $methods = $response->get_data(); 43 | 44 | $this->assertEquals( 200, $response->get_status() ); 45 | $this->assertContains( array( 46 | 'id' => 'free_shipping', 47 | 'title' => 'Free shipping', 48 | 'description' => 'Free shipping is a special method which can be triggered with coupons and minimum spends.', 49 | '_links' => array( 50 | 'self' => array( 51 | array( 52 | 'href' => rest_url( '/wc/v3/shipping_methods/free_shipping' ), 53 | ), 54 | ), 55 | 'collection' => array( 56 | array( 57 | 'href' => rest_url( '/wc/v3/shipping_methods' ), 58 | ), 59 | ), 60 | ), 61 | ), $methods ); 62 | } 63 | 64 | /** 65 | * Tests to make sure shipping methods cannot viewed without valid permissions. 66 | * 67 | * @since 3.0.0 68 | */ 69 | public function test_get_shipping_methods_without_permission() { 70 | wp_set_current_user( 0 ); 71 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/shipping_methods' ) ); 72 | $this->assertEquals( 401, $response->get_status() ); 73 | } 74 | 75 | /** 76 | * Tests getting a single shipping method. 77 | * 78 | * @since 3.0.0 79 | */ 80 | public function test_get_shipping_method() { 81 | wp_set_current_user( $this->user ); 82 | 83 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/shipping_methods/local_pickup' ) ); 84 | $method = $response->get_data(); 85 | 86 | $this->assertEquals( 200, $response->get_status() ); 87 | $this->assertEquals( array( 88 | 'id' => 'local_pickup', 89 | 'title' => 'Local pickup', 90 | 'description' => 'Allow customers to pick up orders themselves. By default, when using local pickup store base taxes will apply regardless of customer address.', 91 | ), $method ); 92 | } 93 | 94 | /** 95 | * Tests getting a single shipping method without the correct permissions. 96 | * 97 | * @since 3.0.0 98 | */ 99 | public function test_get_shipping_method_without_permission() { 100 | wp_set_current_user( 0 ); 101 | 102 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/shipping_methods/local_pickup' ) ); 103 | $this->assertEquals( 401, $response->get_status() ); 104 | } 105 | 106 | /** 107 | * Tests getting a shipping method with an invalid ID. 108 | * 109 | * @since 3.0.0 110 | */ 111 | public function test_get_shipping_method_invalid_id() { 112 | wp_set_current_user( $this->user ); 113 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/shipping_methods/fake_method' ) ); 114 | $this->assertEquals( 404, $response->get_status() ); 115 | } 116 | 117 | /** 118 | * Test the shipping method schema. 119 | * 120 | * @since 3.0.0 121 | */ 122 | public function test_shipping_method_schema() { 123 | wp_set_current_user( $this->user ); 124 | 125 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/shipping_methods' ); 126 | $response = $this->server->dispatch( $request ); 127 | $data = $response->get_data(); 128 | $properties = $data['schema']['properties']; 129 | 130 | $this->assertEquals( 3, count( $properties ) ); 131 | $this->assertArrayHasKey( 'id', $properties ); 132 | $this->assertArrayHasKey( 'title', $properties ); 133 | $this->assertArrayHasKey( 'description', $properties ); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /tests/unit-tests/system-status.php: -------------------------------------------------------------------------------- 1 | endpoint = new WC_REST_DEV_System_Status_Controller(); 15 | $this->user = $this->factory->user->create( array( 16 | 'role' => 'administrator', 17 | ) ); 18 | } 19 | 20 | /** 21 | * Test route registration. 22 | */ 23 | public function test_register_routes() { 24 | $routes = $this->server->get_routes(); 25 | $this->assertArrayHasKey( '/wc/v3/system_status', $routes ); 26 | $this->assertArrayHasKey( '/wc/v3/system_status/tools', $routes ); 27 | $this->assertArrayHasKey( '/wc/v3/system_status/tools/(?P[\w-]+)', $routes ); 28 | } 29 | 30 | /** 31 | * Test to make sure system status cannot be accessed without valid creds 32 | * 33 | * @since 3.0.0 34 | */ 35 | public function test_get_system_status_info_without_permission() { 36 | wp_set_current_user( 0 ); 37 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 38 | $this->assertEquals( 401, $response->get_status() ); 39 | } 40 | 41 | /** 42 | * Test to make sure root properties are present. 43 | * (environment, theme, database, etc). 44 | * 45 | * @since 3.0.0 46 | */ 47 | public function test_get_system_status_info_returns_root_properties() { 48 | wp_set_current_user( $this->user ); 49 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 50 | $data = $response->get_data(); 51 | 52 | $this->assertArrayHasKey( 'environment', $data ); 53 | $this->assertArrayHasKey( 'database', $data ); 54 | $this->assertArrayHasKey( 'active_plugins', $data ); 55 | $this->assertArrayHasKey( 'theme', $data ); 56 | $this->assertArrayHasKey( 'settings', $data ); 57 | $this->assertArrayHasKey( 'security', $data ); 58 | $this->assertArrayHasKey( 'pages', $data ); 59 | } 60 | 61 | /** 62 | * Test to make sure environment response is correct. 63 | * 64 | * @since 3.0.0 65 | */ 66 | public function test_get_system_status_info_environment() { 67 | wp_set_current_user( $this->user ); 68 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 69 | $data = $response->get_data(); 70 | $environment = (array) $data['environment']; 71 | 72 | $system_status = new WC_REST_System_Status_Controller; 73 | $environment_rows = count( $system_status->get_environment_info() ); 74 | 75 | // Make sure all expected data is present 76 | $this->assertEquals( $environment_rows, count( $environment ) ); 77 | 78 | // Test some responses to make sure they match up 79 | $this->assertEquals( get_option( 'home' ), $environment['home_url'] ); 80 | $this->assertEquals( get_option( 'siteurl' ), $environment['site_url'] ); 81 | $this->assertEquals( WC()->version, $environment['version'] ); 82 | } 83 | 84 | /** 85 | * Test to make sure database response is correct. 86 | * 87 | * @since 3.0.0 88 | */ 89 | public function test_get_system_status_info_database() { 90 | global $wpdb; 91 | wp_set_current_user( $this->user ); 92 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 93 | $data = $response->get_data(); 94 | $database = (array) $data['database']; 95 | 96 | $this->assertEquals( get_option( 'woocommerce_db_version' ), $database['wc_database_version'] ); 97 | $this->assertEquals( $wpdb->prefix, $database['database_prefix'] ); 98 | $this->assertEquals( WC_Geolocation::get_local_database_path(), $database['maxmind_geoip_database'] ); 99 | $this->assertArrayHasKey( $wpdb->prefix . 'woocommerce_payment_tokens', $database['database_tables']['woocommerce'] ); 100 | } 101 | 102 | /** 103 | * Test to make sure active plugins response is correct. 104 | * 105 | * @since 3.0.0 106 | */ 107 | public function test_get_system_status_info_active_plugins() { 108 | wp_set_current_user( $this->user ); 109 | 110 | $actual_plugins = array( 'hello.php' ); 111 | update_option( 'active_plugins', $actual_plugins ); 112 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 113 | update_option( 'active_plugins', array() ); 114 | 115 | $data = $response->get_data(); 116 | $plugins = (array) $data['active_plugins']; 117 | 118 | $this->assertEquals( 1, count( $plugins ) ); 119 | $this->assertEquals( 'Hello Dolly', $plugins[0]['name'] ); 120 | } 121 | 122 | /** 123 | * Test to make sure theme response is correct. 124 | * 125 | * @since 3.0.0 126 | */ 127 | public function test_get_system_status_info_theme() { 128 | wp_set_current_user( $this->user ); 129 | $active_theme = wp_get_theme(); 130 | 131 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 132 | $data = $response->get_data(); 133 | $theme = (array) $data['theme']; 134 | 135 | $this->assertEquals( 13, count( $theme ) ); 136 | $this->assertEquals( $active_theme->Name, $theme['name'] ); 137 | } 138 | 139 | /** 140 | * Test to make sure settings response is correct. 141 | * 142 | * @since 3.0.0 143 | */ 144 | public function test_get_system_status_info_settings() { 145 | wp_set_current_user( $this->user ); 146 | 147 | $term_response = array(); 148 | $terms = get_terms( 'product_type', array( 'hide_empty' => 0 ) ); 149 | foreach ( $terms as $term ) { 150 | $term_response[ $term->slug ] = strtolower( $term->name ); 151 | } 152 | 153 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 154 | $data = $response->get_data(); 155 | $settings = (array) $data['settings']; 156 | 157 | $this->assertEquals( 11, count( $settings ) ); 158 | $this->assertEquals( ( 'yes' === get_option( 'woocommerce_api_enabled' ) ), $settings['api_enabled'] ); 159 | $this->assertEquals( get_woocommerce_currency(), $settings['currency'] ); 160 | $this->assertEquals( $term_response, $settings['taxonomies'] ); 161 | } 162 | 163 | /** 164 | * Test to make sure security response is correct. 165 | * 166 | * @since 3.0.0 167 | */ 168 | public function test_get_system_status_info_security() { 169 | wp_set_current_user( $this->user ); 170 | 171 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 172 | $data = $response->get_data(); 173 | $settings = (array) $data['security']; 174 | 175 | $this->assertEquals( 2, count( $settings ) ); 176 | $this->assertEquals( 'https' === substr( get_permalink( wc_get_page_id( 'shop' ) ), 0, 5 ), $settings['secure_connection'] ); 177 | $this->assertEquals( ! ( defined( 'WP_DEBUG' ) && defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG && WP_DEBUG_DISPLAY ) || 0 === intval( ini_get( 'display_errors' ) ), $settings['hide_errors'] ); 178 | } 179 | 180 | /** 181 | * Test to make sure pages response is correct. 182 | * 183 | * @since 3.0.0 184 | */ 185 | public function test_get_system_status_info_pages() { 186 | wp_set_current_user( $this->user ); 187 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status' ) ); 188 | $data = $response->get_data(); 189 | $pages = $data['pages']; 190 | $this->assertEquals( 5, count( $pages ) ); 191 | } 192 | 193 | /** 194 | * Test system status schema. 195 | * 196 | * @since 3.0.0 197 | */ 198 | public function test_system_status_schema() { 199 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/system_status' ); 200 | $response = $this->server->dispatch( $request ); 201 | $data = $response->get_data(); 202 | $properties = $data['schema']['properties']; 203 | $this->assertEquals( 7, count( $properties ) ); 204 | $this->assertArrayHasKey( 'environment', $properties ); 205 | $this->assertArrayHasKey( 'database', $properties ); 206 | $this->assertArrayHasKey( 'active_plugins', $properties ); 207 | $this->assertArrayHasKey( 'theme', $properties ); 208 | $this->assertArrayHasKey( 'settings', $properties ); 209 | $this->assertArrayHasKey( 'security', $properties ); 210 | $this->assertArrayHasKey( 'pages', $properties ); 211 | } 212 | 213 | /** 214 | * Test to make sure get_items (all tools) response is correct. 215 | * 216 | * @since 3.0.0 217 | */ 218 | public function test_get_system_tools() { 219 | wp_set_current_user( $this->user ); 220 | 221 | $tools_controller = new WC_REST_System_Status_Tools_Controller; 222 | $raw_tools = $tools_controller->get_tools(); 223 | 224 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status/tools' ) ); 225 | $data = $response->get_data(); 226 | 227 | $this->assertEquals( 200, $response->get_status() ); 228 | $this->assertEquals( count( $raw_tools ), count( $data ) ); 229 | 230 | $this->assertContains( array( 231 | 'id' => 'reset_tracking', 232 | 'name' => 'Reset usage tracking', 233 | 'action' => 'Reset', 234 | 'description' => 'This will reset your usage tracking settings, causing it to show the opt-in banner again and not sending any data.', 235 | '_links' => array( 236 | 'item' => array( 237 | array( 238 | 'href' => rest_url( '/wc/v3/system_status/tools/reset_tracking' ), 239 | 'embeddable' => true, 240 | ), 241 | ), 242 | ), 243 | ), $data ); 244 | } 245 | 246 | /** 247 | * Test to make sure system status tools cannot be accessed without valid creds 248 | * 249 | * @since 3.0.0 250 | */ 251 | public function test_get_system_status_tools_without_permission() { 252 | wp_set_current_user( 0 ); 253 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status/tools' ) ); 254 | $this->assertEquals( 401, $response->get_status() ); 255 | } 256 | 257 | /** 258 | * Test to make sure we can load a single tool correctly. 259 | * 260 | * @since 3.0.0 261 | */ 262 | public function test_get_system_tool() { 263 | wp_set_current_user( $this->user ); 264 | 265 | $tools_controller = new WC_REST_System_Status_Tools_Controller; 266 | $raw_tools = $tools_controller->get_tools(); 267 | $raw_tool = $raw_tools['recount_terms']; 268 | 269 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status/tools/recount_terms' ) ); 270 | $data = $response->get_data(); 271 | 272 | $this->assertEquals( 200, $response->get_status() ); 273 | 274 | $this->assertEquals( 'recount_terms', $data['id'] ); 275 | $this->assertEquals( 'Term counts', $data['name'] ); 276 | $this->assertEquals( 'Recount terms', $data['action'] ); 277 | $this->assertEquals( 'This tool will recount product terms - useful when changing your settings in a way which hides products from the catalog.', $data['description'] ); 278 | } 279 | 280 | /** 281 | * Test to make sure a single system status toolscannot be accessed without valid creds. 282 | * 283 | * @since 3.0.0 284 | */ 285 | public function test_get_system_status_tool_without_permission() { 286 | wp_set_current_user( 0 ); 287 | $response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v3/system_status/tools/recount_terms' ) ); 288 | $this->assertEquals( 401, $response->get_status() ); 289 | } 290 | 291 | /** 292 | * Test to make sure we can RUN a tool correctly. 293 | * 294 | * @since 3.0.0 295 | */ 296 | public function test_execute_system_tool() { 297 | wp_set_current_user( $this->user ); 298 | 299 | $tools_controller = new WC_REST_System_Status_Tools_Controller; 300 | $raw_tools = $tools_controller->get_tools(); 301 | $raw_tool = $raw_tools['recount_terms']; 302 | 303 | $response = $this->server->dispatch( new WP_REST_Request( 'POST', '/wc/v3/system_status/tools/recount_terms' ) ); 304 | $data = $response->get_data(); 305 | 306 | $this->assertEquals( 'recount_terms', $data['id'] ); 307 | $this->assertEquals( 'Term counts', $data['name'] ); 308 | $this->assertEquals( 'Recount terms', $data['action'] ); 309 | $this->assertEquals( 'This tool will recount product terms - useful when changing your settings in a way which hides products from the catalog.', $data['description'] ); 310 | $this->assertTrue( $data['success'] ); 311 | 312 | $response = $this->server->dispatch( new WP_REST_Request( 'POST', '/wc/v3/system_status/tools/not_a_real_tool' ) ); 313 | $this->assertEquals( 404, $response->get_status() ); 314 | } 315 | 316 | /** 317 | * Test to make sure a tool cannot be run without valid creds. 318 | * 319 | * @since 3.0.0 320 | */ 321 | public function test_execute_system_status_tool_without_permission() { 322 | wp_set_current_user( 0 ); 323 | $response = $this->server->dispatch( new WP_REST_Request( 'POST', '/wc/v3/system_status/tools/recount_terms' ) ); 324 | $this->assertEquals( 401, $response->get_status() ); 325 | } 326 | 327 | /** 328 | * Test system status schema. 329 | * 330 | * @since 3.0.0 331 | */ 332 | public function test_system_status_tool_schema() { 333 | $request = new WP_REST_Request( 'OPTIONS', '/wc/v3/system_status/tools' ); 334 | $response = $this->server->dispatch( $request ); 335 | $data = $response->get_data(); 336 | $properties = $data['schema']['properties']; 337 | $this->assertEquals( 6, count( $properties ) ); 338 | $this->assertArrayHasKey( 'id', $properties ); 339 | $this->assertArrayHasKey( 'name', $properties ); 340 | $this->assertArrayHasKey( 'action', $properties ); 341 | $this->assertArrayHasKey( 'description', $properties ); 342 | $this->assertArrayHasKey( 'success', $properties ); 343 | $this->assertArrayHasKey( 'message', $properties ); 344 | } 345 | } 346 | -------------------------------------------------------------------------------- /wc-api-dev-class.php: -------------------------------------------------------------------------------- 1 | is_woocommerce_valid() ) { 35 | add_action( 'rest_api_init', array( $this, 'register_routes' ), 10 ); 36 | } 37 | } 38 | 39 | /** 40 | * Makes sure WooCommerce is installed and up to date. 41 | */ 42 | public function is_woocommerce_valid() { 43 | return ( 44 | class_exists( 'woocommerce' ) && 45 | version_compare( 46 | get_option( 'woocommerce_db_version' ), 47 | WC_API_Dev::WC_MIN_VERSION, 48 | '>=' 49 | ) 50 | ); 51 | } 52 | 53 | /** 54 | * REST API includes. 55 | * New endpoints/controllers can be added here. 56 | * 57 | * Controllers for the feature plugin are prefixed with WC_REST_DEV (rather than WC_REST) 58 | * so that this plugin can play nice with the WooCommerce Core classes. 59 | * They would be renamed on future sync to WooCommerce. 60 | */ 61 | public function includes() { 62 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-coupons-controller.php' ); 63 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-customer-downloads-controller.php' ); 64 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-customers-controller.php' ); 65 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-data-controller.php' ); 66 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-data-continents-controller.php' ); 67 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-data-countries-controller.php' ); 68 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-data-currencies-controller.php' ); 69 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-orders-controller.php' ); 70 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-order-notes-controller.php' ); 71 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-order-refunds-controller.php' ); 72 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-attribute-terms-controller.php' ); 73 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-attributes-controller.php' ); 74 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-categories-controller.php' ); 75 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-reviews-controller.php' ); 76 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-shipping-classes-controller.php' ); 77 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-tags-controller.php' ); 78 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-products-controller.php' ); 79 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-product-variations-controller.php' ); 80 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-report-sales-controller.php' ); 81 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-report-top-sellers-controller.php' ); 82 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-reports-controller.php' ); 83 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-settings-controller.php' ); 84 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-setting-options-controller.php' ); 85 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-shipping-zones-controller.php' ); 86 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-shipping-zone-locations-controller.php' ); 87 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-shipping-zone-methods-controller.php' ); 88 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-tax-classes-controller.php' ); 89 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-taxes-controller.php' ); 90 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-webhooks-controller.php' ); 91 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-system-status-controller.php' ); 92 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-system-status-tools-controller.php' ); 93 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-shipping-methods-controller.php' ); 94 | include_once( dirname( __FILE__ ) . '/api/class-wc-rest-dev-payment-gateways-controller.php' ); 95 | } 96 | 97 | /** 98 | * Register REST API routes. 99 | * 100 | * New endpoints/controllers can be added here. 101 | */ 102 | public function register_routes() { 103 | $this->includes(); 104 | $controllers = array( 105 | 'WC_REST_Dev_Coupons_Controller', 106 | 'WC_REST_Dev_Customer_Downloads_Controller', 107 | 'WC_REST_Dev_Customers_Controller', 108 | 'WC_REST_Dev_Data_Controller', 109 | 'WC_REST_Dev_Data_Continents_Controller', 110 | 'WC_REST_Dev_Data_Countries_Controller', 111 | 'WC_REST_Dev_Data_Currencies_Controller', 112 | 'WC_REST_Dev_Order_Notes_Controller', 113 | 'WC_REST_Dev_Order_Refunds_Controller', 114 | 'WC_REST_Dev_Orders_Controller', 115 | 'WC_REST_Dev_Product_Attribute_Terms_Controller', 116 | 'WC_REST_Dev_Product_Attributes_Controller', 117 | 'WC_REST_Dev_Product_Categories_Controller', 118 | 'WC_REST_Dev_Product_Reviews_Controller', 119 | 'WC_REST_Dev_Product_Shipping_Classes_Controller', 120 | 'WC_REST_Dev_Product_Tags_Controller', 121 | 'WC_REST_Dev_Products_Controller', 122 | 'WC_REST_Dev_Product_Variations_Controller', 123 | 'WC_REST_Dev_Report_Sales_Controller', 124 | 'WC_REST_Dev_Report_Top_Sellers_Controller', 125 | 'WC_REST_Dev_Reports_Controller', 126 | 'WC_REST_Dev_Settings_Controller', 127 | 'WC_REST_Dev_Setting_Options_Controller', 128 | 'WC_REST_Dev_Shipping_Zones_Controller', 129 | 'WC_REST_Dev_Shipping_Zone_Locations_Controller', 130 | 'WC_REST_Dev_Shipping_Zone_Methods_Controller', 131 | 'WC_REST_Dev_Tax_Classes_Controller', 132 | 'WC_REST_Dev_Taxes_Controller', 133 | 'WC_REST_Dev_Webhooks_Controller', 134 | 'WC_REST_Dev_System_Status_Controller', 135 | 'WC_REST_Dev_System_Status_Tools_Controller', 136 | 'WC_REST_Dev_Shipping_Methods_Controller', 137 | 'WC_REST_Dev_Payment_Gateways_Controller', 138 | ); 139 | 140 | foreach ( $controllers as $controller ) { 141 | $this->$controller = new $controller(); 142 | $this->$controller->register_routes(); 143 | } 144 | 145 | } 146 | 147 | /** 148 | * Class instance. 149 | */ 150 | public static function instance() { 151 | if ( is_null( self::$instance ) ) { 152 | self::$instance = new self(); 153 | } 154 | 155 | return self::$instance; 156 | } 157 | } 158 | 159 | WC_API_Dev::instance(); 160 | -------------------------------------------------------------------------------- /wc-api-dev.php: -------------------------------------------------------------------------------- 1 |