PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.18
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.18
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 / V1 / Taxes_Controller.php

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

235 lines 7.6 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 WCPOS\WooCommercePOS\Services\Permission_Rules;
17 use Exception;
18 use WC_REST_Taxes_Controller;
19 use WCPOS\WooCommercePOS\Logger;
20 use WP_Error;
21 use WP_REST_Request;
22 use WP_REST_Response;
23
24 /**
25 * Product Tgas controller class.
26 *
27 * @NOTE: methods not prefixed with wcpos_ will override WC_REST_Taxes_Controller methods
28 */
29 class Taxes_Controller extends WC_REST_Taxes_Controller {
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 ( Bulk_ID_Fast_Path::supports_request( $request ) ) {
65 return $this->wcpos_get_all_posts( $request );
66 }
67
68 return $dispatch_result;
69 }
70
71 /** Delegate the read decision, preserving WooCommerce's request-dependent checks.
72 *
73 * @param \WP_REST_Request $request Full request details.
74 */
75 public function get_items_permissions_check( $request ) {
76 return Permission_Rules::verdict( 'tax_rates', 'read', (int) $request['id'], 0, 'v1', $request->get_params() );
77 }
78
79 /** Delegate the read decision, preserving WooCommerce's request-dependent checks.
80 *
81 * @param \WP_REST_Request $request Full request details.
82 */
83 public function get_item_permissions_check( $request ) {
84 return Permission_Rules::verdict( 'tax_rates', 'read', (int) $request['id'], 0, 'v1', $request->get_params() );
85 }
86
87 /**
88 * Filter tax object returned from the REST API.
89 *
90 * @param WP_REST_Response $response The response object.
91 * @param \stdClass $tax Tax object used to create response.
92 * @param WP_REST_Request $request Request object.
93 */
94 public function wcpos_prepare_tax_response( $response, $tax, $request ) {
95 $data = $response->get_data();
96
97 /**
98 * Make sure the tax has a uuid
99 * NOTE: we're just using the tax_rate_id as the uuid as we are unlikely to create tax rates via the POS,
100 * and there is no meta_data we're we can eaily store a uuid.
101 */
102 $data['uuid'] = (string) $tax->tax_rate_id;
103
104 // Reset the new response data.
105 $response->set_data( $data );
106
107 return $response;
108 }
109
110 /**
111 * Filter arguments, before passing to $wpdb->get_results(), when querying taxes via the REST API.
112 *
113 * NOTE: tax queries don't have a way to filter the where clause, so to add support for 'include' or 'exclude',
114 * we can either modify the raw query statement, or fetch all and then filter the response.
115 * Both are not ideal, but we'll go with the query modification for now.
116 *
117 * @param array $prepared_args Array of arguments for $wpdb->get_results().
118 * @param WP_REST_Request $request The current request.
119 *
120 * @return array
121 */
122 public function wcpos_tax_query( array $prepared_args, WP_REST_Request $request ) {
123 // Check for wcpos_include/wcpos_exclude parameter.
124 if ( isset( $request['wcpos_include'] ) || isset( $request['wcpos_exclude'] ) ) {
125 // Add a custom WHERE clause to the query.
126 add_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10, 1 );
127 }
128
129 return $prepared_args;
130 }
131
132 /**
133 * Filters the database query.
134 *
135 * This is dangeous filter because it applies to every db query after 'woocommerce_rest_tax_query' is called.
136 * There will be one query for the tax rates table, then many other possible queries for other tables, then once
137 * more query for the tax rates table to get the count.
138 *
139 * NOTE: the count query is just a str_replace on the original query, so we can run once and then remove.
140 *
141 * @param string $query Database query.
142 */
143 public function wcpos_tax_add_include_exclude_to_sql( $query ) {
144 global $wpdb;
145
146 if ( strpos( $query, "{$wpdb->prefix}woocommerce_tax_rates" ) !== false ) {
147 // remove the filter so it doesn't run again.
148 remove_filter( 'query', array( $this, 'wcpos_tax_add_include_exclude_to_sql' ), 10 );
149
150 // Handle include IDs.
151 if ( ! empty( $this->wcpos_request['wcpos_include'] ) ) {
152 $include_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_include'] );
153 $ids_format = implode( ',', $include_ids );
154 $where_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id IN ($ids_format)";
155
156 $query = $this->wcpos_insert_tax_where_clause( $query, $where_in );
157 }
158
159 // Handle exclude IDs.
160 if ( ! empty( $this->wcpos_request['wcpos_exclude'] ) ) {
161 $exclude_ids = array_map( 'intval', (array) $this->wcpos_request['wcpos_exclude'] );
162 $ids_format = implode( ',', $exclude_ids );
163 $where_not_in = "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id NOT IN ($ids_format)";
164
165 $query = $this->wcpos_insert_tax_where_clause( $query, $where_not_in );
166 }
167 }
168
169 return $query;
170 }
171
172 /**
173 * Filters the database query.
174 *
175 * @param string $query Database query.
176 * @param string $condition WHERE condition to insert.
177 *
178 * @return string
179 */
180 private function wcpos_insert_tax_where_clause( $query, $condition ) {
181 global $wpdb;
182
183 if ( strpos( $query, 'WHERE' ) !== false ) {
184 // Insert condition in existing WHERE clause.
185 $query = str_replace( 'WHERE', "WHERE $condition AND", $query );
186 } else {
187 // Insert WHERE clause before ORDER BY or at the end of the query.
188 $pos = strpos( $query, 'ORDER BY' );
189 if ( false !== $pos ) {
190 $query = substr_replace( $query, " WHERE $condition ", $pos, 0 );
191 } else {
192 $query .= " WHERE $condition";
193 }
194 }
195
196 return $query;
197 }
198
199 /**
200 * Returns array of all tax_rate ids.
201 *
202 * @param WP_REST_Request $request Full details about the request.
203 *
204 * @return WP_REST_Response|WP_Error
205 */
206 public function wcpos_get_all_posts( $request ) {
207 global $wpdb;
208
209 $start_time = microtime( true );
210 $modified_after = $request->get_param( 'modified_after' );
211
212 try {
213 /**
214 * Taxes don't have a modified date, so we can't filter by modified_after.
215 *
216 * Ideally WooCommerce would provide a modified_after filter for terms.
217 * For now we'll just return empty for modified terms.
218 *
219 * @TODO Add modified_after support for taxes.
220 */
221 if ( $modified_after ) {
222 $results = array();
223 } else {
224 $sql = 'SELECT tax_rate_id as id FROM ' . $wpdb->prefix . 'woocommerce_tax_rates';
225 $sql = Bulk_ID_Fast_Path::append_id_filters_sql( $sql, $request, "{$wpdb->prefix}woocommerce_tax_rates.tax_rate_id" );
226 $results = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- SQL is built with prepare() above.
227 }
228
229 return Bulk_ID_Fast_Path::response( $this, $results, $start_time );
230 } catch ( Exception $e ) {
231 return Bulk_ID_Fast_Path::fetch_error( 'Error fetching product tax rate IDs: ' . $e->getMessage(), 'Error fetching product tax rate IDs.' );
232 }
233 }
234 }
235