PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce/packages/woocommerce-admin/src/API/Reports/Downloads/Controller.php

https://gitlab.com/campus-academy/krowkaramel
PHP | 439 lines | 337 code | 27 blank | 75 comment | 11 complexity | a7c057ac5e3d35b41ad945550cd5c900 MD5 | raw file
  1. <?php
  2. /**
  3. * REST API Reports downloads controller
  4. *
  5. * Handles requests to the /reports/downloads endpoint.
  6. */
  7. namespace Automattic\WooCommerce\Admin\API\Reports\Downloads;
  8. defined( 'ABSPATH' ) || exit;
  9. use \Automattic\WooCommerce\Admin\API\Reports\Controller as ReportsController;
  10. use \Automattic\WooCommerce\Admin\API\Reports\ExportableInterface;
  11. /**
  12. * REST API Reports downloads controller class.
  13. *
  14. * @extends Automattic\WooCommerce\Admin\API\Reports\Controller
  15. */
  16. class Controller extends ReportsController implements ExportableInterface {
  17. /**
  18. * Endpoint namespace.
  19. *
  20. * @var string
  21. */
  22. protected $namespace = 'wc-analytics';
  23. /**
  24. * Route base.
  25. *
  26. * @var string
  27. */
  28. protected $rest_base = 'reports/downloads';
  29. /**
  30. * Get items.
  31. *
  32. * @param WP_REST_Request $request Request data.
  33. * @return array|WP_Error
  34. */
  35. public function get_items( $request ) {
  36. $args = array();
  37. $registered = array_keys( $this->get_collection_params() );
  38. foreach ( $registered as $param_name ) {
  39. if ( isset( $request[ $param_name ] ) ) {
  40. $args[ $param_name ] = $request[ $param_name ];
  41. }
  42. }
  43. $reports = new Query( $args );
  44. $downloads_data = $reports->get_data();
  45. $data = array();
  46. foreach ( $downloads_data->data as $download_data ) {
  47. $item = $this->prepare_item_for_response( $download_data, $request );
  48. $data[] = $this->prepare_response_for_collection( $item );
  49. }
  50. $response = rest_ensure_response( $data );
  51. $response->header( 'X-WP-Total', (int) $downloads_data->total );
  52. $response->header( 'X-WP-TotalPages', (int) $downloads_data->pages );
  53. $page = $downloads_data->page_no;
  54. $max_pages = $downloads_data->pages;
  55. $base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
  56. if ( $page > 1 ) {
  57. $prev_page = $page - 1;
  58. if ( $prev_page > $max_pages ) {
  59. $prev_page = $max_pages;
  60. }
  61. $prev_link = add_query_arg( 'page', $prev_page, $base );
  62. $response->link_header( 'prev', $prev_link );
  63. }
  64. if ( $max_pages > $page ) {
  65. $next_page = $page + 1;
  66. $next_link = add_query_arg( 'page', $next_page, $base );
  67. $response->link_header( 'next', $next_link );
  68. }
  69. return $response;
  70. }
  71. /**
  72. * Prepare a report object for serialization.
  73. *
  74. * @param Array $report Report data.
  75. * @param WP_REST_Request $request Request object.
  76. * @return WP_REST_Response
  77. */
  78. public function prepare_item_for_response( $report, $request ) {
  79. $data = $report;
  80. $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
  81. $data = $this->add_additional_fields_to_object( $data, $request );
  82. $data = $this->filter_response_by_context( $data, $context );
  83. // Wrap the data in a response object.
  84. $response = rest_ensure_response( $data );
  85. $response->add_links( $this->prepare_links( $report ) );
  86. $response->data['date'] = get_date_from_gmt( $data['date_gmt'], 'Y-m-d H:i:s' );
  87. // Figure out file name.
  88. // Matches https://github.com/woocommerce/woocommerce/blob/4be0018c092e617c5d2b8c46b800eb71ece9ddef/includes/class-wc-download-handler.php#L197.
  89. $product_id = intval( $data['product_id'] );
  90. $_product = wc_get_product( $product_id );
  91. // Make sure the product hasn't been deleted.
  92. if ( $_product ) {
  93. $file_path = $_product->get_file_download_path( $data['download_id'] );
  94. $filename = basename( $file_path );
  95. $response->data['file_name'] = apply_filters( 'woocommerce_file_download_filename', $filename, $product_id );
  96. $response->data['file_path'] = $file_path;
  97. } else {
  98. $response->data['file_name'] = '';
  99. $response->data['file_path'] = '';
  100. }
  101. $customer = new \WC_Customer( $data['user_id'] );
  102. $response->data['username'] = $customer->get_username();
  103. $response->data['order_number'] = $this->get_order_number( $data['order_id'] );
  104. /**
  105. * Filter a report returned from the API.
  106. *
  107. * Allows modification of the report data right before it is returned.
  108. *
  109. * @param WP_REST_Response $response The response object.
  110. * @param object $report The original report object.
  111. * @param WP_REST_Request $request Request used to generate the response.
  112. */
  113. return apply_filters( 'woocommerce_rest_prepare_report_downloads', $response, $report, $request );
  114. }
  115. /**
  116. * Prepare links for the request.
  117. *
  118. * @param Array $object Object data.
  119. * @return array Links for the given post.
  120. */
  121. protected function prepare_links( $object ) {
  122. $links = array(
  123. 'product' => array(
  124. 'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, 'products', $object['product_id'] ) ),
  125. 'embeddable' => true,
  126. ),
  127. );
  128. return $links;
  129. }
  130. /**
  131. * Get the Report's schema, conforming to JSON Schema.
  132. *
  133. * @return array
  134. */
  135. public function get_item_schema() {
  136. $schema = array(
  137. '$schema' => 'http://json-schema.org/draft-04/schema#',
  138. 'title' => 'report_downloads',
  139. 'type' => 'object',
  140. 'properties' => array(
  141. 'id' => array(
  142. 'type' => 'integer',
  143. 'readonly' => true,
  144. 'context' => array( 'view', 'edit' ),
  145. 'description' => __( 'ID.', 'woocommerce' ),
  146. ),
  147. 'product_id' => array(
  148. 'type' => 'integer',
  149. 'readonly' => true,
  150. 'context' => array( 'view', 'edit' ),
  151. 'description' => __( 'Product ID.', 'woocommerce' ),
  152. ),
  153. 'date' => array(
  154. 'description' => __( "The date of the download, in the site's timezone.", 'woocommerce' ),
  155. 'type' => 'date-time',
  156. 'context' => array( 'view', 'edit' ),
  157. 'readonly' => true,
  158. ),
  159. 'date_gmt' => array(
  160. 'description' => __( 'The date of the download, as GMT.', 'woocommerce' ),
  161. 'type' => 'date-time',
  162. 'context' => array( 'view', 'edit' ),
  163. 'readonly' => true,
  164. ),
  165. 'download_id' => array(
  166. 'type' => 'string',
  167. 'readonly' => true,
  168. 'context' => array( 'view', 'edit' ),
  169. 'description' => __( 'Download ID.', 'woocommerce' ),
  170. ),
  171. 'file_name' => array(
  172. 'type' => 'string',
  173. 'readonly' => true,
  174. 'context' => array( 'view', 'edit' ),
  175. 'description' => __( 'File name.', 'woocommerce' ),
  176. ),
  177. 'file_path' => array(
  178. 'type' => 'string',
  179. 'readonly' => true,
  180. 'context' => array( 'view', 'edit' ),
  181. 'description' => __( 'File URL.', 'woocommerce' ),
  182. ),
  183. 'order_id' => array(
  184. 'type' => 'integer',
  185. 'readonly' => true,
  186. 'context' => array( 'view', 'edit' ),
  187. 'description' => __( 'Order ID.', 'woocommerce' ),
  188. ),
  189. 'order_number' => array(
  190. 'type' => 'string',
  191. 'readonly' => true,
  192. 'context' => array( 'view', 'edit' ),
  193. 'description' => __( 'Order Number.', 'woocommerce' ),
  194. ),
  195. 'user_id' => array(
  196. 'type' => 'integer',
  197. 'readonly' => true,
  198. 'context' => array( 'view', 'edit' ),
  199. 'description' => __( 'User ID for the downloader.', 'woocommerce' ),
  200. ),
  201. 'username' => array(
  202. 'type' => 'string',
  203. 'readonly' => true,
  204. 'context' => array( 'view', 'edit' ),
  205. 'description' => __( 'User name of the downloader.', 'woocommerce' ),
  206. ),
  207. 'ip_address' => array(
  208. 'type' => 'string',
  209. 'readonly' => true,
  210. 'context' => array( 'view', 'edit' ),
  211. 'description' => __( 'IP address for the downloader.', 'woocommerce' ),
  212. ),
  213. ),
  214. );
  215. return $this->add_additional_fields_schema( $schema );
  216. }
  217. /**
  218. * Get the query params for collections.
  219. *
  220. * @return array
  221. */
  222. public function get_collection_params() {
  223. $params = array();
  224. $params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
  225. $params['page'] = array(
  226. 'description' => __( 'Current page of the collection.', 'woocommerce' ),
  227. 'type' => 'integer',
  228. 'default' => 1,
  229. 'sanitize_callback' => 'absint',
  230. 'validate_callback' => 'rest_validate_request_arg',
  231. 'minimum' => 1,
  232. );
  233. $params['per_page'] = array(
  234. 'description' => __( 'Maximum number of items to be returned in result set.', 'woocommerce' ),
  235. 'type' => 'integer',
  236. 'default' => 10,
  237. 'minimum' => 1,
  238. 'maximum' => 100,
  239. 'sanitize_callback' => 'absint',
  240. 'validate_callback' => 'rest_validate_request_arg',
  241. );
  242. $params['after'] = array(
  243. 'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
  244. 'type' => 'string',
  245. 'format' => 'date-time',
  246. 'validate_callback' => 'rest_validate_request_arg',
  247. );
  248. $params['before'] = array(
  249. 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
  250. 'type' => 'string',
  251. 'format' => 'date-time',
  252. 'validate_callback' => 'rest_validate_request_arg',
  253. );
  254. $params['order'] = array(
  255. 'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
  256. 'type' => 'string',
  257. 'default' => 'desc',
  258. 'enum' => array( 'asc', 'desc' ),
  259. 'validate_callback' => 'rest_validate_request_arg',
  260. );
  261. $params['orderby'] = array(
  262. 'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
  263. 'type' => 'string',
  264. 'default' => 'date',
  265. 'enum' => array(
  266. 'date',
  267. 'product',
  268. ),
  269. 'validate_callback' => 'rest_validate_request_arg',
  270. );
  271. $params['match'] = array(
  272. 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: products, orders, username, ip_address.', 'woocommerce' ),
  273. 'type' => 'string',
  274. 'default' => 'all',
  275. 'enum' => array(
  276. 'all',
  277. 'any',
  278. ),
  279. 'validate_callback' => 'rest_validate_request_arg',
  280. );
  281. $params['product_includes'] = array(
  282. 'description' => __( 'Limit result set to items that have the specified product(s) assigned.', 'woocommerce' ),
  283. 'type' => 'array',
  284. 'items' => array(
  285. 'type' => 'integer',
  286. ),
  287. 'default' => array(),
  288. 'sanitize_callback' => 'wp_parse_id_list',
  289. 'validate_callback' => 'rest_validate_request_arg',
  290. );
  291. $params['product_excludes'] = array(
  292. 'description' => __( 'Limit result set to items that don\'t have the specified product(s) assigned.', 'woocommerce' ),
  293. 'type' => 'array',
  294. 'items' => array(
  295. 'type' => 'integer',
  296. ),
  297. 'default' => array(),
  298. 'validate_callback' => 'rest_validate_request_arg',
  299. 'sanitize_callback' => 'wp_parse_id_list',
  300. );
  301. $params['order_includes'] = array(
  302. 'description' => __( 'Limit result set to items that have the specified order ids.', 'woocommerce' ),
  303. 'type' => 'array',
  304. 'sanitize_callback' => 'wp_parse_id_list',
  305. 'validate_callback' => 'rest_validate_request_arg',
  306. 'items' => array(
  307. 'type' => 'integer',
  308. ),
  309. );
  310. $params['order_excludes'] = array(
  311. 'description' => __( 'Limit result set to items that don\'t have the specified order ids.', 'woocommerce' ),
  312. 'type' => 'array',
  313. 'sanitize_callback' => 'wp_parse_id_list',
  314. 'validate_callback' => 'rest_validate_request_arg',
  315. 'items' => array(
  316. 'type' => 'integer',
  317. ),
  318. );
  319. $params['customer_includes'] = array(
  320. 'description' => __( 'Limit response to objects that have the specified user ids.', 'woocommerce' ),
  321. 'type' => 'array',
  322. 'sanitize_callback' => 'wp_parse_id_list',
  323. 'validate_callback' => 'rest_validate_request_arg',
  324. 'items' => array(
  325. 'type' => 'integer',
  326. ),
  327. );
  328. $params['customer_excludes'] = array(
  329. 'description' => __( 'Limit response to objects that don\'t have the specified user ids.', 'woocommerce' ),
  330. 'type' => 'array',
  331. 'sanitize_callback' => 'wp_parse_id_list',
  332. 'validate_callback' => 'rest_validate_request_arg',
  333. 'items' => array(
  334. 'type' => 'integer',
  335. ),
  336. );
  337. $params['ip_address_includes'] = array(
  338. 'description' => __( 'Limit response to objects that have a specified ip address.', 'woocommerce' ),
  339. 'type' => 'array',
  340. 'validate_callback' => 'rest_validate_request_arg',
  341. 'items' => array(
  342. 'type' => 'string',
  343. ),
  344. );
  345. $params['ip_address_excludes'] = array(
  346. 'description' => __( 'Limit response to objects that don\'t have a specified ip address.', 'woocommerce' ),
  347. 'type' => 'array',
  348. 'validate_callback' => 'rest_validate_request_arg',
  349. 'items' => array(
  350. 'type' => 'string',
  351. ),
  352. );
  353. return $params;
  354. }
  355. /**
  356. * Get the column names for export.
  357. *
  358. * @return array Key value pair of Column ID => Label.
  359. */
  360. public function get_export_columns() {
  361. $export_columns = array(
  362. 'date' => __( 'Date', 'woocommerce' ),
  363. 'product' => __( 'Product title', 'woocommerce' ),
  364. 'file_name' => __( 'File name', 'woocommerce' ),
  365. 'order_number' => __( 'Order #', 'woocommerce' ),
  366. 'user_id' => __( 'User Name', 'woocommerce' ),
  367. 'ip_address' => __( 'IP', 'woocommerce' ),
  368. );
  369. /**
  370. * Filter to add or remove column names from the downloads report for
  371. * export.
  372. *
  373. * @since 1.6.0
  374. */
  375. return apply_filters(
  376. 'woocommerce_filter_downloads_export_columns',
  377. $export_columns
  378. );
  379. }
  380. /**
  381. * Get the column values for export.
  382. *
  383. * @param array $item Single report item/row.
  384. * @return array Key value pair of Column ID => Row Value.
  385. */
  386. public function prepare_item_for_export( $item ) {
  387. $export_item = array(
  388. 'date' => $item['date'],
  389. 'product' => $item['_embedded']['product'][0]['name'],
  390. 'file_name' => $item['file_name'],
  391. 'order_number' => $item['order_number'],
  392. 'user_id' => $item['username'],
  393. 'ip_address' => $item['ip_address'],
  394. );
  395. /**
  396. * Filter to prepare extra columns in the export item for the downloads
  397. * report.
  398. *
  399. * @since 1.6.0
  400. */
  401. return apply_filters(
  402. 'woocommerce_report_downloads_prepare_export_item',
  403. $export_item,
  404. $item
  405. );
  406. }
  407. }