PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.9.16
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.9.16
1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 1.9.14 All 163 releases
woocommerce-pos / includes / API / Taxes_Controller.php

Taxes_Controller.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.9.16, at includes/API/Taxes_Controller.php

272 lines 8.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Taxes_Controller.
4 *
5 * @package WCPOS\WooCommercePOS
6 */
7
8 namespace WCPOS\WooCommercePOS\API;
9
10 \defined( 'ABSPATH' ) || die;
11
12 if ( ! class_exists( 'WC_REST_Taxes_Controller' ) ) {
13 return;
14 }
15
16 use Exception;
17 use WC_REST_Taxes_Controller;
18 use WCPOS\WooCommercePOS\Logger;
19 use WP_Error;
20 use WP_REST_Request;
21 use WP_REST_Response;
22
23 /**
24 * Product Tgas controller class.
25 *
26 * @NOTE: methods not prefixed with wcpos_ will override WC_REST_Taxes_Controller methods
27 */
28 class Taxes_Controller extends WC_REST_Taxes_Controller {
29 use Traits\Uuid_Handler;
30 use Traits\WCPOS_REST_API;
31
32 /**
33 * Endpoint namespace.
34 *
35 * @var string
36 */
37 protected $namespace = 'wcpos/v1';
38
39 /**
40 * Store the request object for use in lifecycle methods.
41 *
42 * @var WP_REST_Request
43 */
44 protected $wcpos_request;
45
46 /**
47 * Dispatch request to parent controller, or override if needed.
48 *
49 * @param mixed $dispatch_result Dispatch result, will be used if not empty.
50 * @param WP_REST_Request $request Request used to generate the response.
51 * @param string $route Route matched for the request.
52 * @param array $handler Route handler used for the request.
53 */
54 public function wcpos_dispatch_request( $dispatch_result, WP_REST_Request $request, $route, $handler ) {
55 $this->wcpos_request = $request;
56
57 add_filter( 'woocommerce_rest_tax_query', array( $this, 'wcpos_tax_query' ), 10, 2 );
58 add_filter( 'woocommerce_rest_prepare_tax', array( $this, 'wcpos_prepare_tax_response' ), 10, 3 );
59
60 /**
61 * Check if the request is for all tax rates and if the 'posts_per_page' is set to -1.
62 * Optimised query for getting all rate IDs.
63 */
64 if ( $request->get_param( 'posts_per_page' ) == -1 && $request->get_param( 'fields' ) !== null ) {
65 return $this->wcpos_get_all_posts( $request );
66 }
67
68 return $dispatch_result;
69 }
70
71 /**
72 * Check whether a given request has permission to read taxes.
73 *
74 * @param \WP_REST_Request $request Full details about the request.
75 * @return WP_Error|boolean
76 */
77 public function get_items_permissions_check( $request ) {
78 if ( current_user_can( 'access_woocommerce_pos' ) ) {
79 return true;
80 }
81 return parent::get_items_permissions_check( $request );
82 }
83
84 /**
85 * Check if a given request has access to read a tax.
86 *
87 * @param \WP_REST_Request $request Full details about the request.
88 * @return WP_Error|boolean
89 */
90 public function get_item_permissions_check( $request ) {
91 if ( current_user_can( 'access_woocommerce_pos' ) ) {
92 return true;
93 }
94 return parent::get_item_permissions_check( $request );
95 }
96
97 /**
98 * Filter tax object returned from the REST API.
99 *
100 * @param WP_REST_Response $response The response object.
101 * @param \stdClass $tax Tax object used to create response.
102 * @param WP_REST_Request $request Request object.
103 */
104 public function wcpos_prepare_tax_response( $response, $tax, $request ) {
105 $data = $response->get_data();
106
107 /**
108 * Make sure the tax has a uuid
109 * NOTE: we're just using the tax_rate_id as the uuid as we are unlikely to create tax rates via the POS,
110 * and there is no meta_data we're we can eaily store a uuid.
111 */
112 $data['uuid'] = (string) $tax->tax_rate_id;
113
114 // Reset the new response data.
115 $response->set_data( $data );
116
117 return $response;
118 }
119
120 /**
121 * Filter arguments, before passing to $wpdb->get_results(), when querying taxes via the REST API.
122 *
123 * NOTE: tax queries don't have a way to filter the where clause, so to add support for 'include' or 'exclude',
124 * we can either modify the raw query statement, or fetch all and then filter the response.
125 * Both are not ideal, but we'll go with the query modification for now.
126 *
127 * @param array $prepared_args Array of arguments for $wpdb->get_results().
128 * @param WP_REST_Request $request The current request.
129 *
130 * @return array
131 */
132 public function wcpos_tax_query( array $prepared_args, WP_REST_Request $request ) {
133 // Check for wcpos_include/wcpos_exclude parameter.
134 if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
135 // Add a custom WHERE clause to the query.
136 add_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10, 1 );
137 }
138
139 return $prepared_args;
140 }
141
142 /**
143 * Filters the database query.
144 *
145 * This is dangeous filter because it applies to every db query after 'woocommerce_rest_tax_query' is called.
146 * There will be one query for the tax rates table, then many other possible queries for other tables, then once
147 * more query for the tax rates table to get the count.
148 *
149 * NOTE: the count query is just a str_replace on the original query, so we can run once and then remove.
150 *
151 * @param string $query Database query.
152 */
153 public function wcpos_tax_add_include_exclude_to_sql( $query ) {
154 global $wpdb;
155
156 if ( strpos( $query, "{$wpdb->prefix}woocommerce_tax_rates" ) !== false ) {
157 // remove the filter so it doesn't run again.
158 remove_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10 );
159
160 // Handle include IDs.
161 if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
162 $include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
163 $ids_format = implode( ',', $include_ids );
164 $where_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id IN ($ids_format)";
165
166 $query = $this->wcpos_insert_tax_where_clause( $query, $where_in );
167 }
168
169 // Handle exclude IDs.
170 if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
171 $exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
172 $ids_format = implode( ',', $exclude_ids );
173 $where_not_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id NOT IN ($ids_format)";
174
175 $query = $this->wcpos_insert_tax_where_clause( $query, $where_not_in );
176 }
177 }
178
179 return $query;
180 }
181
182 /**
183 * Filters the database query.
184 *
185 * @param string $query Database query.
186 * @param string $condition WHERE condition to insert.
187 *
188 * @return string
189 */
190 private function wcpos_insert_tax_where_clause( $query, $condition ) {
191 global $wpdb;
192
193 if ( strpos( $query, 'WHERE' ) !== false ) {
194 // Insert condition in existing WHERE clause.
195 $query = str_replace( 'WHERE', "WHERE $condition AND", $query );
196 } else {
197 // Insert WHERE clause before ORDER BY or at the end of the query.
198 $pos = strpos( $query, 'ORDER BY' );
199 if ( false !== $pos ) {
200 $query = substr_replace( $query, " WHERE $condition ", $pos, 0 );
201 } else {
202 $query .= " WHERE $condition";
203 }
204 }
205
206 return $query;
207 }
208
209 /**
210 * Returns array of all tax_rate ids.
211 *
212 * @param WP_REST_Request $request Full details about the request.
213 *
214 * @return WP_REST_Response|WP_Error
215 */
216 public function wcpos_get_all_posts( $request ) {
217 global $wpdb;
218
219 // Start timing execution.
220 $start_time = microtime( true );
221 $modified_after = $request->get_param( 'modified_after' );
222
223 try {
224 /**
225 * Taxes don't have a modified date, so we can't filter by modified_after.
226 *
227 * Ideally WooCommerce would provide a modified_after filter for terms.
228 * For now we'll just return empty for modified terms.
229 *
230 * @TODO Add modified_after support for taxes.
231 */
232 $results = $modified_after ? array() : $wpdb->get_results(
233 '
234 SELECT tax_rate_id as id FROM ' . $wpdb->prefix . 'woocommerce_tax_rates
235 ',
236 ARRAY_A
237 );
238
239 // Format the response.
240 $formatted_results = array_map(
241 function ( $item ) {
242 return array( 'id' => (int) $item['id'] );
243 },
244 $results
245 );
246
247 // Get the total number of orders for the given criteria.
248 $total = count( $formatted_results );
249
250 // Collect execution time and server load.
251 $execution_time = microtime( true ) - $start_time;
252 $execution_time_ms = number_format( $execution_time * 1000, 2 );
253 $server_load = $this->get_server_load();
254
255 $response = rest_ensure_response( $formatted_results );
256 $response->header( 'X-WP-Total', (string) $total );
257 $response->header( 'X-Execution-Time', $execution_time_ms . ' ms' );
258 $response->header( 'X-Server-Load', json_encode( $server_load ) );
259
260 return $response;
261 } catch ( Exception $e ) {
262 Logger::log( 'Error fetching product tax rate IDs: ' . $e->getMessage() );
263
264 return new \WP_Error(
265 'woocommerce_pos_rest_cannot_fetch',
266 'Error fetching product tax rate IDs.',
267 array( 'status' => 500 )
268 );
269 }
270 }
271 }
272