/src/API/NavigationFavorites.php

https://github.com/woocommerce/woocommerce-admin · PHP · 327 lines · 197 code · 42 blank · 88 comment · 12 complexity · a9eaf0dee238823fd67c53981cb72be9 MD5 · raw file

  1. <?php
  2. /**
  3. * REST API Navigation Favorites controller
  4. *
  5. * Handles requests to the navigation favorites endpoint
  6. */
  7. namespace Automattic\WooCommerce\Admin\API;
  8. defined( 'ABSPATH' ) || exit;
  9. use Automattic\WooCommerce\Admin\Features\Navigation\Favorites;
  10. /**
  11. * REST API Favorites controller class.
  12. *
  13. * @extends WC_REST_CRUD_Controller
  14. */
  15. class NavigationFavorites extends \WC_REST_Data_Controller {
  16. /**
  17. * Endpoint namespace.
  18. *
  19. * @var string
  20. */
  21. protected $namespace = 'wc-admin';
  22. /**
  23. * Route base.
  24. *
  25. * @var string
  26. */
  27. protected $rest_base = 'navigation/favorites';
  28. /**
  29. * Error code to status code mapping.
  30. *
  31. * @var array
  32. */
  33. protected $error_to_status_map = array(
  34. 'woocommerce_favorites_invalid_request' => 400,
  35. 'woocommerce_favorites_already_exists' => 409,
  36. 'woocommerce_favorites_does_not_exist' => 404,
  37. 'woocommerce_favorites_invalid_user' => 400,
  38. 'woocommerce_favorites_unauthenticated' => 401,
  39. );
  40. /**
  41. * Register the routes
  42. */
  43. public function register_routes() {
  44. register_rest_route(
  45. $this->namespace,
  46. '/' . $this->rest_base,
  47. array(
  48. array(
  49. 'methods' => \WP_REST_Server::READABLE,
  50. 'callback' => array( $this, 'get_items' ),
  51. 'permission_callback' => array( $this, 'get_items_permissions_check' ),
  52. 'args' => array(
  53. 'user_id' => array(
  54. 'required' => true,
  55. 'validate_callback' => function( $param, $request, $key ) {
  56. return is_numeric( $param );
  57. },
  58. ),
  59. ),
  60. ),
  61. array(
  62. 'methods' => \WP_REST_Server::CREATABLE,
  63. 'callback' => array( $this, 'add_item' ),
  64. 'permission_callback' => array( $this, 'add_item_permissions_check' ),
  65. 'args' => array(
  66. 'item_id' => array(
  67. 'required' => true,
  68. ),
  69. 'user_id' => array(
  70. 'required' => true,
  71. 'validate_callback' => function( $param, $request, $key ) {
  72. return is_numeric( $param );
  73. },
  74. ),
  75. ),
  76. ),
  77. array(
  78. 'methods' => \WP_REST_Server::DELETABLE,
  79. 'callback' => array( $this, 'delete_item' ),
  80. 'permission_callback' => array( $this, 'delete_item_permissions_check' ),
  81. 'args' => array(
  82. 'item_id' => array(
  83. 'required' => true,
  84. ),
  85. 'user_id' => array(
  86. 'required' => true,
  87. 'validate_callback' => function( $param, $request, $key ) {
  88. return is_numeric( $param );
  89. },
  90. ),
  91. ),
  92. ),
  93. 'schema' => array( $this, 'get_public_item_schema' ),
  94. )
  95. );
  96. register_rest_route(
  97. $this->namespace,
  98. '/' . $this->rest_base . '/me',
  99. array(
  100. array(
  101. 'methods' => \WP_REST_Server::READABLE,
  102. 'callback' => array( $this, 'get_items_by_current_user' ),
  103. 'permission_callback' => array( $this, 'current_user_permissions_check' ),
  104. ),
  105. array(
  106. 'methods' => \WP_REST_Server::CREATABLE,
  107. 'callback' => array( $this, 'add_item_by_current_user' ),
  108. 'permission_callback' => array( $this, 'current_user_permissions_check' ),
  109. 'args' => array(
  110. 'item_id' => array(
  111. 'required' => true,
  112. ),
  113. ),
  114. ),
  115. array(
  116. 'methods' => \WP_REST_Server::DELETABLE,
  117. 'callback' => array( $this, 'delete_item_by_current_user' ),
  118. 'permission_callback' => array( $this, 'current_user_permissions_check' ),
  119. 'args' => array(
  120. 'item_id' => array(
  121. 'required' => true,
  122. ),
  123. ),
  124. ),
  125. 'schema' => array( $this, 'get_public_item_schema' ),
  126. )
  127. );
  128. }
  129. /**
  130. * Get all favorites.
  131. *
  132. * @param WP_REST_Request $request Request data.
  133. * @return WP_REST_Response
  134. */
  135. public function get_items( $request ) {
  136. $user_id = $request->get_param( 'user_id' );
  137. $response = Favorites::get_all( $user_id );
  138. if ( is_wp_error( $response ) || ! $response ) {
  139. return rest_ensure_response( $this->prepare_error( $response ) );
  140. }
  141. return rest_ensure_response(
  142. array_map( 'stripslashes', $response )
  143. );
  144. }
  145. /**
  146. * Get all favorites of current user.
  147. *
  148. * @param WP_REST_Request $request Request data.
  149. * @return WP_REST_Response
  150. */
  151. public function get_items_by_current_user( $request ) {
  152. $current_user = get_current_user_id();
  153. if ( ! $current_user ) {
  154. return $this->prepare_error(
  155. new \WP_Error(
  156. 'woocommerce_favorites_unauthenticated',
  157. __( 'You must be authenticated to use this endpoint', 'woocommerce-admin' )
  158. )
  159. );
  160. }
  161. $request->set_param( 'user_id', $current_user );
  162. return $this->get_items( $request );
  163. }
  164. /**
  165. * Add a favorite.
  166. *
  167. * @param WP_REST_Request $request Request data.
  168. * @return WP_REST_Response
  169. */
  170. public function add_item( $request ) {
  171. $user_id = $request->get_param( 'user_id' );
  172. $fav_id = $request->get_param( 'item_id' );
  173. $user = get_userdata( $user_id );
  174. if ( false === $user ) {
  175. return $this->prepare_error(
  176. new \WP_Error(
  177. 'woocommerce_favorites_invalid_user',
  178. __( 'Invalid user_id provided', 'woocommerce-admin' )
  179. )
  180. );
  181. }
  182. $response = Favorites::add_item( $fav_id, $user_id );
  183. if ( is_wp_error( $response ) || ! $response ) {
  184. return rest_ensure_response( $this->prepare_error( $response ) );
  185. }
  186. return rest_ensure_response( Favorites::get_all( $user_id ) );
  187. }
  188. /**
  189. * Add a favorite for current user.
  190. *
  191. * @param WP_REST_Request $request Request data.
  192. * @return WP_REST_Response
  193. */
  194. public function add_item_by_current_user( $request ) {
  195. $current_user = get_current_user_id();
  196. if ( ! $current_user ) {
  197. return $this->prepare_error(
  198. new \WP_Error(
  199. 'woocommerce_favorites_unauthenticated',
  200. __( 'You must be authenticated to use this endpoint', 'woocommerce-admin' )
  201. )
  202. );
  203. }
  204. $request->set_param( 'user_id', get_current_user_id() );
  205. return $this->add_item( $request );
  206. }
  207. /**
  208. * Delete a favorite.
  209. *
  210. * @param WP_REST_Request $request Request data.
  211. * @return WP_REST_Response
  212. */
  213. public function delete_item( $request ) {
  214. $user_id = $request->get_param( 'user_id' );
  215. $fav_id = $request->get_param( 'item_id' );
  216. $response = Favorites::remove_item( $fav_id, $user_id );
  217. if ( is_wp_error( $response ) || ! $response ) {
  218. return rest_ensure_response( $this->prepare_error( $response ) );
  219. }
  220. return rest_ensure_response( Favorites::get_all( $user_id ) );
  221. }
  222. /**
  223. * Delete a favorite for current user.
  224. *
  225. * @param WP_REST_Request $request Request data.
  226. * @return WP_REST_Response
  227. */
  228. public function delete_item_by_current_user( $request ) {
  229. $current_user = get_current_user_id();
  230. if ( ! $current_user ) {
  231. return $this->prepare_error(
  232. new \WP_Error(
  233. 'woocommerce_favorites_unauthenticated',
  234. __( 'You must be authenticated to use this endpoint', 'woocommerce-admin' )
  235. )
  236. );
  237. }
  238. $request->set_param( 'user_id', $current_user );
  239. return $this->delete_item( $request );
  240. }
  241. /**
  242. * Check whether a given request has permission to create favorites.
  243. *
  244. * @param WP_REST_Request $request Full details about the request.
  245. * @return WP_Error|boolean
  246. */
  247. public function add_item_permissions_check( $request ) {
  248. return current_user_can( 'edit_users' );
  249. }
  250. /**
  251. * Check whether a given request has permission to delete notes.
  252. *
  253. * @param WP_REST_Request $request Full details about the request.
  254. * @return WP_Error|boolean
  255. */
  256. public function delete_item_permissions_check( $request ) {
  257. return current_user_can( 'edit_users' );
  258. }
  259. /**
  260. * Always allow for operations that only impact current user
  261. *
  262. * @param WP_REST_Request $request Full details about the request.
  263. * @return WP_Error|boolean
  264. */
  265. public function current_user_permissions_check( $request ) {
  266. return true;
  267. }
  268. /**
  269. * Accept an instance of WP_Error and add the appropriate data for REST transit.
  270. *
  271. * @param WP_Error $error Error to prepare.
  272. * @return WP_Error
  273. */
  274. protected function prepare_error( $error ) {
  275. if ( ! is_wp_error( $error ) ) {
  276. return $error;
  277. }
  278. $error->add_data(
  279. array(
  280. 'status' => $this->error_to_status_map[ $error->get_error_code() ] ?? 500,
  281. )
  282. );
  283. return $error;
  284. }
  285. }