PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.17
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.17
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 1.9.13 All 162 releases
woocommerce-pos / includes / API / V1 / Taxes_Controller.php

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

244 lines 7.7 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\V1;
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\WCPOS_REST_API;
30
31 /**
32 * Endpoint namespace.
33 *
34 * @var string
35 */
36 protected $namespace = 'wcpos/v1';
37
38 /**
39 * Store the request object for use in lifecycle methods.
40 *
41 * @var WP_REST_Request
42 */
43 protected $wcpos_request;
44
45 /**
46 * Dispatch request to parent controller, or override if needed.
47 *
48 * @param mixed $dispatch_result Dispatch result, will be used if not empty.
49 * @param WP_REST_Request $request Request used to generate the response.
50 * @param string $route Route matched for the request.
51 * @param array $handler Route handler used for the request.
52 */
53 public function wcpos_dispatch_request( $dispatch_result, WP_REST_Request $request, $route, $handler ) {
54 $this->wcpos_request = $request;
55
56 add_filter( 'woocommerce_rest_tax_query', array( $this, 'wcpos_tax_query' ), 10, 2 );
57 add_filter( 'woocommerce_rest_prepare_tax', array( $this, 'wcpos_prepare_tax_response' ), 10, 3 );
58
59 /**
60 * Check if the request is for all tax rates and if the 'posts_per_page' is set to -1.
61 * Optimised query for getting all rate IDs.
62 */
63 if ( Bulk_ID_Fast_Path::supports_request( $request ) ) {
64 return $this->wcpos_get_all_posts( $request );
65 }
66
67 return $dispatch_result;
68 }
69
70 /**
71 * Check whether a given request has permission to read taxes.
72 *
73 * @param \WP_REST_Request $request Full details about the request.
74 * @return WP_Error|boolean
75 */
76 public function get_items_permissions_check( $request ) {
77 if ( current_user_can( 'access_woocommerce_pos' ) ) {
78 return true;
79 }
80 return parent::get_items_permissions_check( $request );
81 }
82
83 /**
84 * Check if a given request has access to read a tax.
85 *
86 * @param \WP_REST_Request $request Full details about the request.
87 * @return WP_Error|boolean
88 */
89 public function get_item_permissions_check( $request ) {
90 if ( current_user_can( 'access_woocommerce_pos' ) ) {
91 return true;
92 }
93 return parent::get_item_permissions_check( $request );
94 }
95
96 /**
97 * Filter tax object returned from the REST API.
98 *
99 * @param WP_REST_Response $response The response object.
100 * @param \stdClass $tax Tax object used to create response.
101 * @param WP_REST_Request $request Request object.
102 */
103 public function wcpos_prepare_tax_response( $response, $tax, $request ) {
104 $data = $response->get_data();
105
106 /**
107 * Make sure the tax has a uuid
108 * NOTE: we're just using the tax_rate_id as the uuid as we are unlikely to create tax rates via the POS,
109 * and there is no meta_data we're we can eaily store a uuid.
110 */
111 $data['uuid'] = (string) $tax->tax_rate_id;
112
113 // Reset the new response data.
114 $response->set_data( $data );
115
116 return $response;
117 }
118
119 /**
120 * Filter arguments, before passing to $wpdb->get_results(), when querying taxes via the REST API.
121 *
122 * NOTE: tax queries don't have a way to filter the where clause, so to add support for 'include' or 'exclude',
123 * we can either modify the raw query statement, or fetch all and then filter the response.
124 * Both are not ideal, but we'll go with the query modification for now.
125 *
126 * @param array $prepared_args Array of arguments for $wpdb->get_results().
127 * @param WP_REST_Request $request The current request.
128 *
129 * @return array
130 */
131 public function wcpos_tax_query( array $prepared_args, WP_REST_Request $request ) {
132 // Check for wcpos_include/wcpos_exclude parameter.
133 if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
134 // Add a custom WHERE clause to the query.
135 add_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10, 1 );
136 }
137
138 return $prepared_args;
139 }
140
141 /**
142 * Filters the database query.
143 *
144 * This is dangeous filter because it applies to every db query after 'woocommerce_rest_tax_query' is called.
145 * There will be one query for the tax rates table, then many other possible queries for other tables, then once
146 * more query for the tax rates table to get the count.
147 *
148 * NOTE: the count query is just a str_replace on the original query, so we can run once and then remove.
149 *
150 * @param string $query Database query.
151 */
152 public function wcpos_tax_add_include_exclude_to_sql( $query ) {
153 global $wpdb;
154
155 if ( strpos( $query, "{$wpdb->prefix}woocommerce_tax_rates" ) !== false ) {
156 // remove the filter so it doesn't run again.
157 remove_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10 );
158
159 // Handle include IDs.
160 if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
161 $include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
162 $ids_format = implode( ',', $include_ids );
163 $where_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id IN ($ids_format)";
164
165 $query = $this->wcpos_insert_tax_where_clause( $query, $where_in );
166 }
167
168 // Handle exclude IDs.
169 if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
170 $exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
171 $ids_format = implode( ',', $exclude_ids );
172 $where_not_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id NOT IN ($ids_format)";
173
174 $query = $this->wcpos_insert_tax_where_clause( $query, $where_not_in );
175 }
176 }
177
178 return $query;
179 }
180
181 /**
182 * Filters the database query.
183 *
184 * @param string $query Database query.
185 * @param string $condition WHERE condition to insert.
186 *
187 * @return string
188 */
189 private function wcpos_insert_tax_where_clause( $query, $condition ) {
190 global $wpdb;
191
192 if ( strpos( $query, 'WHERE' ) !== false ) {
193 // Insert condition in existing WHERE clause.
194 $query = str_replace( 'WHERE', "WHERE $condition AND", $query );
195 } else {
196 // Insert WHERE clause before ORDER BY or at the end of the query.
197 $pos = strpos( $query, 'ORDER BY' );
198 if ( false !== $pos ) {
199 $query = substr_replace( $query, " WHERE $condition ", $pos, 0 );
200 } else {
201 $query .= " WHERE $condition";
202 }
203 }
204
205 return $query;
206 }
207
208 /**
209 * Returns array of all tax_rate ids.
210 *
211 * @param WP_REST_Request $request Full details about the request.
212 *
213 * @return WP_REST_Response|WP_Error
214 */
215 public function wcpos_get_all_posts( $request ) {
216 global $wpdb;
217
218 $start_time = microtime( true );
219 $modified_after = $request->get_param( 'modified_after' );
220
221 try {
222 /**
223 * Taxes don't have a modified date, so we can't filter by modified_after.
224 *
225 * Ideally WooCommerce would provide a modified_after filter for terms.
226 * For now we'll just return empty for modified terms.
227 *
228 * @TODO Add modified_after support for taxes.
229 */
230 if ( $modified_after ) {
231 $results = array();
232 } else {
233 $sql = 'SELECT tax_rate_id as id FROM ' . $wpdb->prefix . 'woocommerce_tax_rates';
234 $sql = Bulk_ID_Fast_Path::append_id_filters_sql( $sql, $request, "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id" );
235 $results = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- SQL is built with prepare() above.
236 }
237
238 return Bulk_ID_Fast_Path::response( $this, $results, $start_time );
239 } catch ( Exception $e ) {
240 return Bulk_ID_Fast_Path::fetch_error( 'Error fetching product tax rate IDs: ' . $e->getMessage(), 'Error fetching product tax rate IDs.' );
241 }
242 }
243 }
244