PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/woocommerce/includes/wc-rest-functions.php

https://gitlab.com/campus-academy/krowkaramel
PHP | 364 lines | 201 code | 50 blank | 113 comment | 33 complexity | f5b37dbc804b6a9b3f4e8bbfc142065e MD5 | raw file
  1. <?php
  2. /**
  3. * WooCommerce REST Functions
  4. *
  5. * Functions for REST specific things.
  6. *
  7. * @package WooCommerce\Functions
  8. * @version 2.6.0
  9. */
  10. defined( 'ABSPATH' ) || exit;
  11. /**
  12. * Parses and formats a date for ISO8601/RFC3339.
  13. *
  14. * Required WP 4.4 or later.
  15. * See https://developer.wordpress.org/reference/functions/mysql_to_rfc3339/
  16. *
  17. * @since 2.6.0
  18. * @param string|null|WC_DateTime $date Date.
  19. * @param bool $utc Send false to get local/offset time.
  20. * @return string|null ISO8601/RFC3339 formatted datetime.
  21. */
  22. function wc_rest_prepare_date_response( $date, $utc = true ) {
  23. if ( is_numeric( $date ) ) {
  24. $date = new WC_DateTime( "@$date", new DateTimeZone( 'UTC' ) );
  25. $date->setTimezone( new DateTimeZone( wc_timezone_string() ) );
  26. } elseif ( is_string( $date ) ) {
  27. $date = new WC_DateTime( $date, new DateTimeZone( 'UTC' ) );
  28. $date->setTimezone( new DateTimeZone( wc_timezone_string() ) );
  29. }
  30. if ( ! is_a( $date, 'WC_DateTime' ) ) {
  31. return null;
  32. }
  33. // Get timestamp before changing timezone to UTC.
  34. return gmdate( 'Y-m-d\TH:i:s', $utc ? $date->getTimestamp() : $date->getOffsetTimestamp() );
  35. }
  36. /**
  37. * Returns image mime types users are allowed to upload via the API.
  38. *
  39. * @since 2.6.4
  40. * @return array
  41. */
  42. function wc_rest_allowed_image_mime_types() {
  43. return apply_filters(
  44. 'woocommerce_rest_allowed_image_mime_types',
  45. array(
  46. 'jpg|jpeg|jpe' => 'image/jpeg',
  47. 'gif' => 'image/gif',
  48. 'png' => 'image/png',
  49. 'bmp' => 'image/bmp',
  50. 'tiff|tif' => 'image/tiff',
  51. 'ico' => 'image/x-icon',
  52. )
  53. );
  54. }
  55. /**
  56. * Upload image from URL.
  57. *
  58. * @since 2.6.0
  59. * @param string $image_url Image URL.
  60. * @return array|WP_Error Attachment data or error message.
  61. */
  62. function wc_rest_upload_image_from_url( $image_url ) {
  63. $parsed_url = wp_parse_url( $image_url );
  64. // Check parsed URL.
  65. if ( ! $parsed_url || ! is_array( $parsed_url ) ) {
  66. /* translators: %s: image URL */
  67. return new WP_Error( 'woocommerce_rest_invalid_image_url', sprintf( __( 'Invalid URL %s.', 'woocommerce' ), $image_url ), array( 'status' => 400 ) );
  68. }
  69. // Ensure url is valid.
  70. $image_url = esc_url_raw( $image_url );
  71. // download_url function is part of wp-admin.
  72. if ( ! function_exists( 'download_url' ) ) {
  73. include_once ABSPATH . 'wp-admin/includes/file.php';
  74. }
  75. $file_array = array();
  76. $file_array['name'] = basename( current( explode( '?', $image_url ) ) );
  77. // Download file to temp location.
  78. $file_array['tmp_name'] = download_url( $image_url );
  79. // If error storing temporarily, return the error.
  80. if ( is_wp_error( $file_array['tmp_name'] ) ) {
  81. return new WP_Error(
  82. 'woocommerce_rest_invalid_remote_image_url',
  83. /* translators: %s: image URL */
  84. sprintf( __( 'Error getting remote image %s.', 'woocommerce' ), $image_url ) . ' '
  85. /* translators: %s: error message */
  86. . sprintf( __( 'Error: %s', 'woocommerce' ), $file_array['tmp_name']->get_error_message() ),
  87. array( 'status' => 400 )
  88. );
  89. }
  90. // Do the validation and storage stuff.
  91. $file = wp_handle_sideload(
  92. $file_array,
  93. array(
  94. 'test_form' => false,
  95. 'mimes' => wc_rest_allowed_image_mime_types(),
  96. ),
  97. current_time( 'Y/m' )
  98. );
  99. if ( isset( $file['error'] ) ) {
  100. @unlink( $file_array['tmp_name'] ); // @codingStandardsIgnoreLine.
  101. /* translators: %s: error message */
  102. return new WP_Error( 'woocommerce_rest_invalid_image', sprintf( __( 'Invalid image: %s', 'woocommerce' ), $file['error'] ), array( 'status' => 400 ) );
  103. }
  104. do_action( 'woocommerce_rest_api_uploaded_image_from_url', $file, $image_url );
  105. return $file;
  106. }
  107. /**
  108. * Set uploaded image as attachment.
  109. *
  110. * @since 2.6.0
  111. * @param array $upload Upload information from wp_upload_bits.
  112. * @param int $id Post ID. Default to 0.
  113. * @return int Attachment ID
  114. */
  115. function wc_rest_set_uploaded_image_as_attachment( $upload, $id = 0 ) {
  116. $info = wp_check_filetype( $upload['file'] );
  117. $title = '';
  118. $content = '';
  119. if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
  120. include_once ABSPATH . 'wp-admin/includes/image.php';
  121. }
  122. $image_meta = wp_read_image_metadata( $upload['file'] );
  123. if ( $image_meta ) {
  124. if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
  125. $title = wc_clean( $image_meta['title'] );
  126. }
  127. if ( trim( $image_meta['caption'] ) ) {
  128. $content = wc_clean( $image_meta['caption'] );
  129. }
  130. }
  131. $attachment = array(
  132. 'post_mime_type' => $info['type'],
  133. 'guid' => $upload['url'],
  134. 'post_parent' => $id,
  135. 'post_title' => $title ? $title : basename( $upload['file'] ),
  136. 'post_content' => $content,
  137. );
  138. $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $id );
  139. if ( ! is_wp_error( $attachment_id ) ) {
  140. wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ) );
  141. }
  142. return $attachment_id;
  143. }
  144. /**
  145. * Validate reports request arguments.
  146. *
  147. * @since 2.6.0
  148. * @param mixed $value Value to valdate.
  149. * @param WP_REST_Request $request Request instance.
  150. * @param string $param Param to validate.
  151. * @return WP_Error|boolean
  152. */
  153. function wc_rest_validate_reports_request_arg( $value, $request, $param ) {
  154. $attributes = $request->get_attributes();
  155. if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
  156. return true;
  157. }
  158. $args = $attributes['args'][ $param ];
  159. if ( 'string' === $args['type'] && ! is_string( $value ) ) {
  160. /* translators: 1: param 2: type */
  161. return new WP_Error( 'woocommerce_rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'woocommerce' ), $param, 'string' ) );
  162. }
  163. if ( 'date' === $args['format'] ) {
  164. $regex = '#^\d{4}-\d{2}-\d{2}$#';
  165. if ( ! preg_match( $regex, $value, $matches ) ) {
  166. return new WP_Error( 'woocommerce_rest_invalid_date', __( 'The date you provided is invalid.', 'woocommerce' ) );
  167. }
  168. }
  169. return true;
  170. }
  171. /**
  172. * Encodes a value according to RFC 3986.
  173. * Supports multidimensional arrays.
  174. *
  175. * @since 2.6.0
  176. * @param string|array $value The value to encode.
  177. * @return string|array Encoded values.
  178. */
  179. function wc_rest_urlencode_rfc3986( $value ) {
  180. if ( is_array( $value ) ) {
  181. return array_map( 'wc_rest_urlencode_rfc3986', $value );
  182. }
  183. return str_replace( array( '+', '%7E' ), array( ' ', '~' ), rawurlencode( $value ) );
  184. }
  185. /**
  186. * Check permissions of posts on REST API.
  187. *
  188. * @since 2.6.0
  189. * @param string $post_type Post type.
  190. * @param string $context Request context.
  191. * @param int $object_id Post ID.
  192. * @return bool
  193. */
  194. function wc_rest_check_post_permissions( $post_type, $context = 'read', $object_id = 0 ) {
  195. $contexts = array(
  196. 'read' => 'read_private_posts',
  197. 'create' => 'publish_posts',
  198. 'edit' => 'edit_post',
  199. 'delete' => 'delete_post',
  200. 'batch' => 'edit_others_posts',
  201. );
  202. if ( 'revision' === $post_type ) {
  203. $permission = false;
  204. } else {
  205. $cap = $contexts[ $context ];
  206. $post_type_object = get_post_type_object( $post_type );
  207. $permission = current_user_can( $post_type_object->cap->$cap, $object_id );
  208. }
  209. return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, $post_type );
  210. }
  211. /**
  212. * Check permissions of users on REST API.
  213. *
  214. * @since 2.6.0
  215. * @param string $context Request context.
  216. * @param int $object_id Post ID.
  217. * @return bool
  218. */
  219. function wc_rest_check_user_permissions( $context = 'read', $object_id = 0 ) {
  220. $contexts = array(
  221. 'read' => 'list_users',
  222. 'create' => 'promote_users', // Check if current user can create users, shop managers are not allowed to create users.
  223. 'edit' => 'edit_users',
  224. 'delete' => 'delete_users',
  225. 'batch' => 'promote_users',
  226. );
  227. // Check to allow shop_managers to manage only customers.
  228. if ( in_array( $context, array( 'edit', 'delete' ), true ) && wc_current_user_has_role( 'shop_manager' ) ) {
  229. $permission = false;
  230. $user_data = get_userdata( $object_id );
  231. $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) );
  232. if ( isset( $user_data->roles ) ) {
  233. $can_manage_users = array_intersect( $user_data->roles, array_unique( $shop_manager_editable_roles ) );
  234. // Check if Shop Manager can edit customer or with the is same shop manager.
  235. if ( 0 < count( $can_manage_users ) || intval( $object_id ) === intval( get_current_user_id() ) ) {
  236. $permission = current_user_can( $contexts[ $context ], $object_id );
  237. }
  238. }
  239. } else {
  240. $permission = current_user_can( $contexts[ $context ], $object_id );
  241. }
  242. return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, 'user' );
  243. }
  244. /**
  245. * Check permissions of product terms on REST API.
  246. *
  247. * @since 2.6.0
  248. * @param string $taxonomy Taxonomy.
  249. * @param string $context Request context.
  250. * @param int $object_id Post ID.
  251. * @return bool
  252. */
  253. function wc_rest_check_product_term_permissions( $taxonomy, $context = 'read', $object_id = 0 ) {
  254. $contexts = array(
  255. 'read' => 'manage_terms',
  256. 'create' => 'edit_terms',
  257. 'edit' => 'edit_terms',
  258. 'delete' => 'delete_terms',
  259. 'batch' => 'edit_terms',
  260. );
  261. $cap = $contexts[ $context ];
  262. $taxonomy_object = get_taxonomy( $taxonomy );
  263. $permission = current_user_can( $taxonomy_object->cap->$cap, $object_id );
  264. return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, $taxonomy );
  265. }
  266. /**
  267. * Check manager permissions on REST API.
  268. *
  269. * @since 2.6.0
  270. * @param string $object Object.
  271. * @param string $context Request context.
  272. * @return bool
  273. */
  274. function wc_rest_check_manager_permissions( $object, $context = 'read' ) {
  275. $objects = array(
  276. 'reports' => 'view_woocommerce_reports',
  277. 'settings' => 'manage_woocommerce',
  278. 'system_status' => 'manage_woocommerce',
  279. 'attributes' => 'manage_product_terms',
  280. 'shipping_methods' => 'manage_woocommerce',
  281. 'payment_gateways' => 'manage_woocommerce',
  282. 'webhooks' => 'manage_woocommerce',
  283. );
  284. $permission = current_user_can( $objects[ $object ] );
  285. return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, 0, $object );
  286. }
  287. /**
  288. * Check product reviews permissions on REST API.
  289. *
  290. * @since 3.5.0
  291. * @param string $context Request context.
  292. * @param string $object_id Object ID.
  293. * @return bool
  294. */
  295. function wc_rest_check_product_reviews_permissions( $context = 'read', $object_id = 0 ) {
  296. $permission = false;
  297. $contexts = array(
  298. 'read' => 'moderate_comments',
  299. 'create' => 'edit_products',
  300. 'edit' => 'edit_products',
  301. 'delete' => 'edit_products',
  302. 'batch' => 'edit_products',
  303. );
  304. if ( $object_id > 0 ) {
  305. $object = get_comment( $object_id );
  306. if ( ! is_a( $object, 'WP_Comment' ) || get_comment_type( $object ) !== 'review' ) {
  307. return false;
  308. }
  309. }
  310. if ( isset( $contexts[ $context ] ) ) {
  311. $permission = current_user_can( $contexts[ $context ], $object_id );
  312. }
  313. return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, 'product_review' );
  314. }