WC_REST_Product_Attributes_V1_Controller

REST API Product Attributes controller class.

Defined (1)

The class is defined in the following location(s).

/includes/api/v1/class-wc-rest-product-attributes-controller.php  
  1. class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller { 
  2.  
  3. /** 
  4. * Endpoint namespace. 
  5. * @var string 
  6. */ 
  7. protected $namespace = 'wc/v1'; 
  8.  
  9. /** 
  10. * Route base. 
  11. * @var string 
  12. */ 
  13. protected $rest_base = 'products/attributes'; 
  14.  
  15. /** 
  16. * Attribute name. 
  17. * @var string 
  18. */ 
  19. protected $attribute = ''; 
  20.  
  21. /** 
  22. * Register the routes for product attributes. 
  23. */ 
  24. public function register_routes() { 
  25. register_rest_route( $this->namespace, '/' . $this->rest_base, array( 
  26. array( 
  27. 'methods' => WP_REST_Server::READABLE,  
  28. 'callback' => array( $this, 'get_items' ),  
  29. 'permission_callback' => array( $this, 'get_items_permissions_check' ),  
  30. 'args' => $this->get_collection_params(),  
  31. ),  
  32. array( 
  33. 'methods' => WP_REST_Server::CREATABLE,  
  34. 'callback' => array( $this, 'create_item' ),  
  35. 'permission_callback' => array( $this, 'create_item_permissions_check' ),  
  36. 'args' => array_merge( $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array( 
  37. 'name' => array( 
  38. 'description' => __( 'Name for the resource.', 'woocommerce' ),  
  39. 'type' => 'string',  
  40. 'required' => true,  
  41. ),  
  42. ) ),  
  43. ),  
  44. 'schema' => array( $this, 'get_public_item_schema' ),  
  45. )); 
  46.  
  47. register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( 
  48. 'args' => array( 
  49. 'id' => array( 
  50. 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),  
  51. 'type' => 'integer',  
  52. ),  
  53. ),  
  54. array( 
  55. 'methods' => WP_REST_Server::READABLE,  
  56. 'callback' => array( $this, 'get_item' ),  
  57. 'permission_callback' => array( $this, 'get_item_permissions_check' ),  
  58. 'args' => array( 
  59. 'context' => $this->get_context_param( array( 'default' => 'view' ) ),  
  60. ),  
  61. ),  
  62. array( 
  63. 'methods' => WP_REST_Server::EDITABLE,  
  64. 'callback' => array( $this, 'update_item' ),  
  65. 'permission_callback' => array( $this, 'update_item_permissions_check' ),  
  66. 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),  
  67. ),  
  68. array( 
  69. 'methods' => WP_REST_Server::DELETABLE,  
  70. 'callback' => array( $this, 'delete_item' ),  
  71. 'permission_callback' => array( $this, 'delete_item_permissions_check' ),  
  72. 'args' => array( 
  73. 'force' => array( 
  74. 'default' => true,  
  75. 'type' => 'boolean',  
  76. 'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),  
  77. ),  
  78. ),  
  79. ),  
  80. 'schema' => array( $this, 'get_public_item_schema' ),  
  81. ) ); 
  82.  
  83. register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array( 
  84. array( 
  85. 'methods' => WP_REST_Server::EDITABLE,  
  86. 'callback' => array( $this, 'batch_items' ),  
  87. 'permission_callback' => array( $this, 'batch_items_permissions_check' ),  
  88. 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),  
  89. ),  
  90. 'schema' => array( $this, 'get_public_batch_schema' ),  
  91. ) ); 
  92.  
  93. /** 
  94. * Check if a given request has access to read the attributes. 
  95. * @param WP_REST_Request $request Full details about the request. 
  96. * @return WP_Error|boolean 
  97. */ 
  98. public function get_items_permissions_check( $request ) { 
  99. if ( ! wc_rest_check_manager_permissions( 'attributes', 'read' ) ) { 
  100. return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  101.  
  102. return true; 
  103.  
  104. /** 
  105. * Check if a given request has access to create a attribute. 
  106. * @param WP_REST_Request $request Full details about the request. 
  107. * @return WP_Error|boolean 
  108. */ 
  109. public function create_item_permissions_check( $request ) { 
  110. if ( ! wc_rest_check_manager_permissions( 'attributes', 'create' ) ) { 
  111. return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you cannot create new resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  112.  
  113. return true; 
  114.  
  115. /** 
  116. * Check if a given request has access to read a attribute. 
  117. * @param WP_REST_Request $request Full details about the request. 
  118. * @return WP_Error|boolean 
  119. */ 
  120. public function get_item_permissions_check( $request ) { 
  121. if ( ! $this->get_taxonomy( $request ) ) { 
  122. return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) ); 
  123.  
  124. if ( ! wc_rest_check_manager_permissions( 'attributes', 'read' ) ) { 
  125. return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  126.  
  127. return true; 
  128.  
  129. /** 
  130. * Check if a given request has access to update a attribute. 
  131. * @param WP_REST_Request $request Full details about the request. 
  132. * @return WP_Error|boolean 
  133. */ 
  134. public function update_item_permissions_check( $request ) { 
  135. if ( ! $this->get_taxonomy( $request ) ) { 
  136. return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) ); 
  137.  
  138. if ( ! wc_rest_check_manager_permissions( 'attributes', 'edit' ) ) { 
  139. return new WP_Error( 'woocommerce_rest_cannot_update', __( 'Sorry, you cannot update resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  140.  
  141. return true; 
  142.  
  143. /** 
  144. * Check if a given request has access to delete a attribute. 
  145. * @param WP_REST_Request $request Full details about the request. 
  146. * @return WP_Error|boolean 
  147. */ 
  148. public function delete_item_permissions_check( $request ) { 
  149. if ( ! $this->get_taxonomy( $request ) ) { 
  150. return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) ); 
  151.  
  152. if ( ! wc_rest_check_manager_permissions( 'attributes', 'delete' ) ) { 
  153. return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  154.  
  155. return true; 
  156.  
  157. /** 
  158. * Check if a given request has access batch create, update and delete items. 
  159. * @param WP_REST_Request $request Full details about the request. 
  160. * @return boolean 
  161. */ 
  162. public function batch_items_permissions_check( $request ) { 
  163. if ( ! wc_rest_check_manager_permissions( 'attributes', 'batch' ) ) { 
  164. return new WP_Error( 'woocommerce_rest_cannot_batch', __( 'Sorry, you are not allowed to batch manipulate this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) ); 
  165.  
  166. return true; 
  167.  
  168. /** 
  169. * Get all attributes. 
  170. * @param WP_REST_Request $request 
  171. * @return array 
  172. */ 
  173. public function get_items( $request ) { 
  174. $attributes = wc_get_attribute_taxonomies(); 
  175. $data = array(); 
  176. foreach ( $attributes as $attribute_obj ) { 
  177. $attribute = $this->prepare_item_for_response( $attribute_obj, $request ); 
  178. $attribute = $this->prepare_response_for_collection( $attribute ); 
  179. $data[] = $attribute; 
  180.  
  181. return rest_ensure_response( $data ); 
  182.  
  183. /** 
  184. * Create a single attribute. 
  185. * @param WP_REST_Request $request Full details about the request. 
  186. * @return WP_REST_Request|WP_Error 
  187. */ 
  188. public function create_item( $request ) { 
  189. global $wpdb; 
  190.  
  191. $args = array( 
  192. 'attribute_label' => $request['name'],  
  193. 'attribute_name' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),  
  194. 'attribute_type' => ! empty( $request['type'] ) ? $request['type'] : 'select',  
  195. 'attribute_orderby' => ! empty( $request['order_by'] ) ? $request['order_by'] : 'menu_order',  
  196. 'attribute_public' => true === $request['has_archives'],  
  197. ); 
  198.  
  199. // Set the attribute slug. 
  200. if ( empty( $args['attribute_name'] ) ) { 
  201. $args['attribute_name'] = wc_sanitize_taxonomy_name( stripslashes( $args['attribute_label'] ) ); 
  202. } else { 
  203. $args['attribute_name'] = preg_replace( '/^pa\_/', '', wc_sanitize_taxonomy_name( stripslashes( $args['attribute_name'] ) ) ); 
  204.  
  205. $valid_slug = $this->validate_attribute_slug( $args['attribute_name'], true ); 
  206. if ( is_wp_error( $valid_slug ) ) { 
  207. return $valid_slug; 
  208.  
  209. $insert = $wpdb->insert( 
  210. $wpdb->prefix . 'woocommerce_attribute_taxonomies',  
  211. $args,  
  212. array( '%s', '%s', '%s', '%s', '%d' ) 
  213. ); 
  214.  
  215. // Checks for errors. 
  216. if ( is_wp_error( $insert ) ) { 
  217. return new WP_Error( 'woocommerce_rest_cannot_create', $insert->get_error_message(), array( 'status' => 400 ) ); 
  218.  
  219. $attribute = $this->get_attribute( $wpdb->insert_id ); 
  220.  
  221. if ( is_wp_error( $attribute ) ) { 
  222. return $attribute; 
  223.  
  224. $this->update_additional_fields_for_object( $attribute, $request ); 
  225.  
  226. /** 
  227. * Fires after a single product attribute is created or updated via the REST API. 
  228. * @param stdObject $attribute Inserted attribute object. 
  229. * @param WP_REST_Request $request Request object. 
  230. * @param boolean $creating True when creating attribute, false when updating. 
  231. */ 
  232. do_action( 'woocommerce_rest_insert_product_attribute', $attribute, $request, true ); 
  233.  
  234. $request->set_param( 'context', 'edit' ); 
  235. $response = $this->prepare_item_for_response( $attribute, $request ); 
  236. $response = rest_ensure_response( $response ); 
  237. $response->set_status( 201 ); 
  238. $response->header( 'Location', rest_url( '/' . $this->namespace . '/' . $this->rest_base . '/' . $attribute->attribute_id ) ); 
  239.  
  240. // Clear transients. 
  241. $this->flush_rewrite_rules(); 
  242. delete_transient( 'wc_attribute_taxonomies' ); 
  243.  
  244. return $response; 
  245.  
  246. /** 
  247. * Get a single attribute. 
  248. * @param WP_REST_Request $request Full details about the request. 
  249. * @return WP_REST_Request|WP_Error 
  250. */ 
  251. public function get_item( $request ) { 
  252. global $wpdb; 
  253.  
  254. $attribute = $this->get_attribute( (int) $request['id'] ); 
  255.  
  256. if ( is_wp_error( $attribute ) ) { 
  257. return $attribute; 
  258.  
  259. $response = $this->prepare_item_for_response( $attribute, $request ); 
  260.  
  261. return rest_ensure_response( $response ); 
  262.  
  263. /** 
  264. * Update a single term from a taxonomy. 
  265. * @param WP_REST_Request $request Full details about the request. 
  266. * @return WP_REST_Request|WP_Error 
  267. */ 
  268. public function update_item( $request ) { 
  269. global $wpdb; 
  270.  
  271. $id = (int) $request['id']; 
  272. $format = array( '%s', '%s', '%s', '%s', '%d' ); 
  273. $args = array( 
  274. 'attribute_label' => $request['name'],  
  275. 'attribute_name' => wc_sanitize_taxonomy_name( stripslashes( $request['slug'] ) ),  
  276. 'attribute_type' => $request['type'],  
  277. 'attribute_orderby' => $request['order_by'],  
  278. 'attribute_public' => $request['has_archives'],  
  279. ); 
  280.  
  281. $i = 0; 
  282. foreach ( $args as $key => $value ) { 
  283. if ( empty( $value ) && ! is_bool( $value ) ) { 
  284. unset( $args[ $key ] ); 
  285. unset( $format[ $i ] ); 
  286.  
  287. $i++; 
  288.  
  289. // Set the attribute slug. 
  290. if ( ! empty( $args['attribute_name'] ) ) { 
  291. $args['attribute_name'] = preg_replace( '/^pa\_/', '', wc_sanitize_taxonomy_name( stripslashes( $args['attribute_name'] ) ) ); 
  292.  
  293. $valid_slug = $this->validate_attribute_slug( $args['attribute_name'], false ); 
  294. if ( is_wp_error( $valid_slug ) ) { 
  295. return $valid_slug; 
  296.  
  297. if ( $args ) { 
  298. $update = $wpdb->update( 
  299. $wpdb->prefix . 'woocommerce_attribute_taxonomies',  
  300. $args,  
  301. array( 'attribute_id' => $id ),  
  302. $format,  
  303. array( '%d' ) 
  304. ); 
  305.  
  306. // Checks for errors. 
  307. if ( false === $update ) { 
  308. return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Could not edit the attribute.', 'woocommerce' ), array( 'status' => 400 ) ); 
  309.  
  310. $attribute = $this->get_attribute( $id ); 
  311.  
  312. if ( is_wp_error( $attribute ) ) { 
  313. return $attribute; 
  314.  
  315. $this->update_additional_fields_for_object( $attribute, $request ); 
  316.  
  317. /** 
  318. * Fires after a single product attribute is created or updated via the REST API. 
  319. * @param stdObject $attribute Inserted attribute object. 
  320. * @param WP_REST_Request $request Request object. 
  321. * @param boolean $creating True when creating attribute, false when updating. 
  322. */ 
  323. do_action( 'woocommerce_rest_insert_product_attribute', $attribute, $request, false ); 
  324.  
  325. $request->set_param( 'context', 'edit' ); 
  326. $response = $this->prepare_item_for_response( $attribute, $request ); 
  327.  
  328. // Clear transients. 
  329. $this->flush_rewrite_rules(); 
  330. delete_transient( 'wc_attribute_taxonomies' ); 
  331.  
  332. return rest_ensure_response( $response ); 
  333.  
  334. /** 
  335. * Delete a single attribute. 
  336. * @param WP_REST_Request $request Full details about the request. 
  337. * @return WP_REST_Response|WP_Error 
  338. */ 
  339. public function delete_item( $request ) { 
  340. global $wpdb; 
  341.  
  342. $force = isset( $request['force'] ) ? (bool) $request['force'] : false; 
  343.  
  344. // We don't support trashing for this type, error out. 
  345. if ( ! $force ) { 
  346. return new WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Resource does not support trashing.', 'woocommerce' ), array( 'status' => 501 ) ); 
  347.  
  348. $attribute = $this->get_attribute( (int) $request['id'] ); 
  349.  
  350. if ( is_wp_error( $attribute ) ) { 
  351. return $attribute; 
  352.  
  353. $request->set_param( 'context', 'edit' ); 
  354. $response = $this->prepare_item_for_response( $attribute, $request ); 
  355.  
  356. $deleted = $wpdb->delete( 
  357. $wpdb->prefix . 'woocommerce_attribute_taxonomies',  
  358. array( 'attribute_id' => $attribute->attribute_id ),  
  359. array( '%d' ) 
  360. ); 
  361.  
  362. if ( false === $deleted ) { 
  363. return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'The resource cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) ); 
  364.  
  365. $taxonomy = wc_attribute_taxonomy_name( $attribute->attribute_name ); 
  366.  
  367. if ( taxonomy_exists( $taxonomy ) ) { 
  368. $terms = get_terms( $taxonomy, 'orderby=name&hide_empty=0' ); 
  369. foreach ( $terms as $term ) { 
  370. wp_delete_term( $term->term_id, $taxonomy ); 
  371.  
  372. /** 
  373. * Fires after a single attribute is deleted via the REST API. 
  374. * @param stdObject $attribute The deleted attribute. 
  375. * @param WP_REST_Response $response The response data. 
  376. * @param WP_REST_Request $request The request sent to the API. 
  377. */ 
  378. do_action( 'woocommerce_rest_delete_product_attribute', $attribute, $response, $request ); 
  379.  
  380. // Fires woocommerce_attribute_deleted hook. 
  381. do_action( 'woocommerce_attribute_deleted', $attribute->attribute_id, $attribute->attribute_name, $taxonomy ); 
  382.  
  383. // Clear transients. 
  384. $this->flush_rewrite_rules(); 
  385. delete_transient( 'wc_attribute_taxonomies' ); 
  386.  
  387. return $response; 
  388.  
  389. /** 
  390. * Prepare a single product attribute output for response. 
  391. * @param obj $item Term object. 
  392. * @param WP_REST_Request $request 
  393. * @return WP_REST_Response $response 
  394. */ 
  395. public function prepare_item_for_response( $item, $request ) { 
  396. $data = array( 
  397. 'id' => (int) $item->attribute_id,  
  398. 'name' => $item->attribute_label,  
  399. 'slug' => wc_attribute_taxonomy_name( $item->attribute_name ),  
  400. 'type' => $item->attribute_type,  
  401. 'order_by' => $item->attribute_orderby,  
  402. 'has_archives' => (bool) $item->attribute_public,  
  403. ); 
  404.  
  405. $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 
  406. $data = $this->add_additional_fields_to_object( $data, $request ); 
  407. $data = $this->filter_response_by_context( $data, $context ); 
  408.  
  409. $response = rest_ensure_response( $data ); 
  410.  
  411. $response->add_links( $this->prepare_links( $item ) ); 
  412.  
  413. /** 
  414. * Filter a attribute item returned from the API. 
  415. * Allows modification of the product attribute data right before it is returned. 
  416. * @param WP_REST_Response $response The response object. 
  417. * @param object $item The original attribute object. 
  418. * @param WP_REST_Request $request Request used to generate the response. 
  419. */ 
  420. return apply_filters( 'woocommerce_rest_prepare_product_attribute', $response, $item, $request ); 
  421.  
  422. /** 
  423. * Prepare links for the request. 
  424. * @param object $attribute Attribute object. 
  425. * @return array Links for the given attribute. 
  426. */ 
  427. protected function prepare_links( $attribute ) { 
  428. $base = '/' . $this->namespace . '/' . $this->rest_base; 
  429. $links = array( 
  430. 'self' => array( 
  431. 'href' => rest_url( trailingslashit( $base ) . $attribute->attribute_id ),  
  432. ),  
  433. 'collection' => array( 
  434. 'href' => rest_url( $base ),  
  435. ),  
  436. ); 
  437.  
  438. return $links; 
  439.  
  440. /** 
  441. * Get the Attribute's schema, conforming to JSON Schema. 
  442. * @return array 
  443. */ 
  444. public function get_item_schema() { 
  445. $schema = array( 
  446. '$schema' => 'http://json-schema.org/draft-04/schema#',  
  447. 'title' => 'product_attribute',  
  448. 'type' => 'object',  
  449. 'properties' => array( 
  450. 'id' => array( 
  451. 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),  
  452. 'type' => 'integer',  
  453. 'context' => array( 'view', 'edit' ),  
  454. 'readonly' => true,  
  455. ),  
  456. 'name' => array( 
  457. 'description' => __( 'Attribute name.', 'woocommerce' ),  
  458. 'type' => 'string',  
  459. 'context' => array( 'view', 'edit' ),  
  460. 'arg_options' => array( 
  461. 'sanitize_callback' => 'sanitize_text_field',  
  462. ),  
  463. ),  
  464. 'slug' => array( 
  465. 'description' => __( 'An alphanumeric identifier for the resource unique to its type.', 'woocommerce' ),  
  466. 'type' => 'string',  
  467. 'context' => array( 'view', 'edit' ),  
  468. 'arg_options' => array( 
  469. 'sanitize_callback' => 'sanitize_title',  
  470. ),  
  471. ),  
  472. 'type' => array( 
  473. 'description' => __( 'Type of attribute.', 'woocommerce' ),  
  474. 'type' => 'string',  
  475. 'default' => 'select',  
  476. 'enum' => array_keys( wc_get_attribute_types() ),  
  477. 'context' => array( 'view', 'edit' ),  
  478. ),  
  479. 'order_by' => array( 
  480. 'description' => __( 'Default sort order.', 'woocommerce' ),  
  481. 'type' => 'string',  
  482. 'default' => 'menu_order',  
  483. 'enum' => array( 'menu_order', 'name', 'name_num', 'id' ),  
  484. 'context' => array( 'view', 'edit' ),  
  485. ),  
  486. 'has_archives' => array( 
  487. 'description' => __( 'Enable/Disable attribute archives.', 'woocommerce' ),  
  488. 'type' => 'boolean',  
  489. 'default' => false,  
  490. 'context' => array( 'view', 'edit' ),  
  491. ),  
  492. ),  
  493. ); 
  494.  
  495. return $this->add_additional_fields_schema( $schema ); 
  496.  
  497. /** 
  498. * Get the query params for collections 
  499. * @return array 
  500. */ 
  501. public function get_collection_params() { 
  502. $params = array(); 
  503. $params['context'] = $this->get_context_param( array( 'default' => 'view' ) ); 
  504.  
  505. return $params; 
  506.  
  507. /** 
  508. * Get attribute name. 
  509. * @param WP_REST_Request $request Full details about the request. 
  510. * @return string 
  511. */ 
  512. protected function get_taxonomy( $request ) { 
  513. if ( '' !== $this->attribute ) { 
  514. return $this->attribute; 
  515.  
  516. if ( $request['id'] ) { 
  517. $name = wc_attribute_taxonomy_name_by_id( (int) $request['id'] ); 
  518.  
  519. $this->attribute = $name; 
  520.  
  521. return $this->attribute; 
  522.  
  523. /** 
  524. * Get attribute data. 
  525. * @param int $id Attribute ID. 
  526. * @return stdClass|WP_Error 
  527. */ 
  528. protected function get_attribute( $id ) { 
  529. global $wpdb; 
  530.  
  531. $attribute = $wpdb->get_row( $wpdb->prepare( " 
  532. SELECT * 
  533. FROM {$wpdb->prefix}woocommerce_attribute_taxonomies 
  534. WHERE attribute_id = %d 
  535. ", $id ) ); 
  536.  
  537. if ( is_wp_error( $attribute ) || is_null( $attribute ) ) { 
  538. return new WP_Error( 'woocommerce_rest_attribute_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) ); 
  539.  
  540. return $attribute; 
  541.  
  542. /** 
  543. * Validate attribute slug. 
  544. * @param string $slug 
  545. * @param bool $new_data 
  546. * @return bool|WP_Error 
  547. */ 
  548. protected function validate_attribute_slug( $slug, $new_data = true ) { 
  549. if ( strlen( $slug ) >= 28 ) { 
  550. return new WP_Error( 'woocommerce_rest_invalid_product_attribute_slug_too_long', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) ); 
  551. } elseif ( wc_check_if_attribute_name_is_reserved( $slug ) ) { 
  552. return new WP_Error( 'woocommerce_rest_invalid_product_attribute_slug_reserved_name', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) ); 
  553. } elseif ( $new_data && taxonomy_exists( wc_attribute_taxonomy_name( $slug ) ) ) { 
  554. return new WP_Error( 'woocommerce_rest_invalid_product_attribute_slug_already_exists', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), $slug ), array( 'status' => 400 ) ); 
  555.  
  556. return true; 
  557.  
  558. /** 
  559. * Schedule to flush rewrite rules. 
  560. * @since 3.0.0 
  561. */ 
  562. protected function flush_rewrite_rules() { 
  563. wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );