PluginProbe
Tiered Pricing Table for WooCommerce / 8.1.0
Tiered Pricing Table for WooCommerce v8.1.0
8.1.0 8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 All 92 releases
tier-pricing-table / src / Addons / Tools / API / ToolsEndpoints.php

ToolsEndpoints.php in Tiered Pricing Table for WooCommerce 8.1.0, at src/Addons/Tools/API/ToolsEndpoints.php

446 lines 13.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php namespace TierPricingTable\Addons\Tools\API;
2
3 use TierPricingTable\Addons\GlobalTieredPricing\CPT\GlobalTieredPricingCPT;
4 use TierPricingTable\Addons\Tools\PricingTest\PricingTester;
5 use WP_Error;
6 use WP_REST_Request;
7
8 class ToolsEndpoints {
9
10 const NAMESPACE = 'tier-pricing-table/features/tools/v1';
11
12 public function __construct() {
13 add_action( 'rest_api_init', array( $this, 'registerRoutes' ) );
14 }
15
16 public function registerRoutes() {
17
18 register_rest_route( self::NAMESPACE, '/cleanup', array(
19 array(
20 'methods' => 'POST',
21 'callback' => array( $this, 'cleanupData' ),
22 'permission_callback' => function () {
23 return current_user_can( 'manage_options' );
24 },
25 ),
26 ) );
27
28 register_rest_route( self::NAMESPACE, '/reset_settings', array(
29 array(
30 'methods' => 'POST',
31 'callback' => array( $this, 'resetSettings' ),
32 'permission_callback' => function () {
33 return current_user_can( 'manage_options' );
34 },
35 ),
36 ) );
37
38 register_rest_route( self::NAMESPACE, '/delete_global_rules', array(
39 array(
40 'methods' => 'POST',
41 'callback' => array( $this, 'deleteGlobalRules' ),
42 'permission_callback' => function () {
43 return current_user_can( 'manage_options' );
44 },
45 ),
46 ) );
47
48 register_rest_route( self::NAMESPACE, '/pricing_test', array(
49 array(
50 'methods' => 'POST',
51 'callback' => array( $this, 'pricingTest' ),
52 'permission_callback' => function () {
53 return current_user_can( 'manage_woocommerce' );
54 },
55 'args' => array(
56 'product_id' => array( 'type' => 'integer', 'required' => true ),
57 'user_id' => array( 'type' => 'integer', 'default' => 0 ),
58 'rule_id' => array( 'type' => 'integer', 'default' => 0 ),
59 ),
60 ),
61 ) );
62
63 register_rest_route( self::NAMESPACE, '/roles', array(
64 array(
65 'methods' => 'GET',
66 'callback' => array( $this, 'getRoles' ),
67 'permission_callback' => function () {
68 return current_user_can( 'manage_options' );
69 },
70 ),
71 ) );
72
73 register_rest_route( self::NAMESPACE, '/roles_capabilities', array(
74 array(
75 'methods' => 'GET',
76 'callback' => array( $this, 'getRolesAndCapabilities' ),
77 'permission_callback' => function () {
78 return current_user_can( 'manage_options' );
79 },
80 ),
81 array(
82 'methods' => 'POST',
83 'callback' => array( $this, 'createRole' ),
84 'permission_callback' => function () {
85 return current_user_can( 'manage_options' );
86 },
87 ),
88 array(
89 'methods' => 'PUT',
90 'callback' => array( $this, 'updateRoleCapabilities' ),
91 'permission_callback' => function () {
92 return current_user_can( 'manage_options' );
93 },
94 ),
95 array(
96 'methods' => 'DELETE',
97 'callback' => array( $this, 'deleteRole' ),
98 'permission_callback' => function () {
99 return current_user_can( 'manage_options' );
100 },
101 ),
102 ) );
103 }
104
105 /**
106 * The Pricing test: what a customer (0 = visitor) gets for a product, and which global rules apply.
107 */
108 public function pricingTest( WP_REST_Request $request ) {
109 $productId = absint( $request->get_param( 'product_id' ) );
110 $userId = absint( $request->get_param( 'user_id' ) );
111 $ruleId = absint( $request->get_param( 'rule_id' ) );
112
113 if ( ! $productId ) {
114 return new WP_Error( 'tpt_pricing_test_product', __( 'Pick a product first.', 'tier-pricing-table' ), array( 'status' => 400 ) );
115 }
116
117 if ( $userId && ! get_user_by( 'id', $userId ) ) {
118 return new WP_Error( 'tpt_pricing_test_customer', __( 'The customer could not be loaded.', 'tier-pricing-table' ), array( 'status' => 400 ) );
119 }
120
121 $result = ( new PricingTester() )->run( $productId, $userId, $ruleId );
122
123 if ( isset( $result['error'] ) ) {
124 return new WP_Error( 'tpt_pricing_test', $result['error'], array( 'status' => 400 ) );
125 }
126
127 return rest_ensure_response( $result );
128 }
129
130 public function getRoles() {
131 global $wp_roles;
132 if ( ! isset( $wp_roles ) ) {
133 $wp_roles = new \WP_Roles();
134 }
135 $roles = $wp_roles->get_names();
136
137 $response = array();
138 foreach ( $roles as $key => $name ) {
139 $response[] = array(
140 'value' => $key,
141 'label' => $name,
142 );
143 }
144
145 return rest_ensure_response( $response );
146 }
147
148 public function cleanupData( WP_REST_Request $request ) {
149 $cleanStandard = filter_var( $request->get_param( 'clean_standard' ), FILTER_VALIDATE_BOOLEAN );
150 $cleanUsers = filter_var( $request->get_param( 'clean_users' ), FILTER_VALIDATE_BOOLEAN );
151 $cleanAllRoles = filter_var( $request->get_param( 'clean_all_roles' ), FILTER_VALIDATE_BOOLEAN );
152
153 if ( $cleanAllRoles ) {
154 global $wp_roles;
155 if ( ! isset( $wp_roles ) ) {
156 $wp_roles = new \WP_Roles();
157 }
158 $roles = array_keys( $wp_roles->get_names() );
159 } else {
160 $roles = $request->get_param( 'roles' ); // array of role keys
161 }
162
163 $categories = $request->get_param( 'categories' ); // array of term ids
164 $products = $request->get_param( 'products' ); // array of product ids
165
166 $metaKeysToDelete = array();
167
168 if ( $cleanStandard ) {
169 $metaKeysToDelete = array_merge( $metaKeysToDelete, array(
170 '_fixed_price_rules',
171 '_percentage_price_rules',
172 '_tiered_price_rules_type',
173 '_tiered_price_minimum_qty',
174 '_tiered_pricing_maximum_quantity',
175 '_tiered_pricing_group_of_quantity',
176 '_tiered_pricing_template',
177 '_tiered_pricing_base_unit_name',
178 '_tiered_pricing_default_variation_id',
179 '_tiered_pricing_variable_product_same_prices',
180 ) );
181 }
182
183 if ( ! empty( $roles ) && is_array( $roles ) ) {
184 foreach ( $roles as $roleKey ) {
185 $roleKey = sanitize_key( $roleKey );
186 $metaKeysToDelete = array_merge( $metaKeysToDelete, array(
187 "_{$roleKey}_tiered_price_pricing_type",
188 "_{$roleKey}_tiered_price_regular_price",
189 "_{$roleKey}_tiered_price_sale_price",
190 "_{$roleKey}_tiered_price_discount",
191 "_{$roleKey}_tiered_price_discount_type",
192 "_{$roleKey}_tiered_price_rules_type",
193 "_{$roleKey}_percentage_price_rules",
194 "_{$roleKey}_fixed_price_rules",
195 "_{$roleKey}_tiered_price_minimum_qty",
196 "_{$roleKey}_tiered_pricing_maximum_quantity",
197 "_{$roleKey}_tiered_pricing_group_of_quantity",
198 ) );
199 }
200 }
201
202 $deletedCount = 0;
203
204 if ( ! empty( $metaKeysToDelete ) ) {
205 global $wpdb;
206 $metaKeysIn = "'" . implode( "','", array_map( 'esc_sql', $metaKeysToDelete ) ) . "'";
207
208 $postIds = array();
209
210 if ( ! empty( $products ) && is_array( $products ) ) {
211 $postIds = array_map( 'intval', $products );
212 }
213
214 if ( ! empty( $categories ) && is_array( $categories ) ) {
215 $categoryIds = array_map( 'intval', $categories );
216 $args = array(
217 'limit' => - 1,
218 'return' => 'ids',
219 'category' => array_map( function ( $id ) {
220 $term = get_term( $id, 'product_cat' );
221
222 return $term ? $term->slug : '';
223 }, $categoryIds ),
224 );
225
226 $catProducts = wc_get_products( $args );
227 $postIds = array_unique( array_merge( $postIds, $catProducts ) );
228 }
229
230 if ( empty( $products ) && empty( $categories ) ) {
231 $query = "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ($metaKeysIn)";
232 $deletedCount = $wpdb->query( $query );
233 } else {
234 if ( ! empty( $postIds ) ) {
235 $postIdsIn = implode( ',', $postIds );
236 $query = "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ($metaKeysIn) AND post_id IN ($postIdsIn)";
237 $deletedCount = $wpdb->query( $query );
238 }
239 }
240
241 if ( $deletedCount === false ) {
242 return rest_ensure_response( array(
243 'success' => false,
244 'message' => 'Database error during cleanup.',
245 ) );
246 }
247 }
248
249 if ( $cleanUsers ) {
250 global $wpdb;
251
252 $userMetaLikeQueries = array(
253 "meta_key LIKE '\_user\_%\_tiered_price\_pricing\_type'",
254 "meta_key LIKE '\_user\_%\_tiered_price\_regular\_price'",
255 "meta_key LIKE '\_user\_%\_tiered_price\_sale\_price'",
256 "meta_key LIKE '\_user\_%\_tiered_price\_discount'",
257 "meta_key LIKE '\_user\_%\_tiered_price\_discount\_type'",
258 "meta_key LIKE '\_user\_%\_tiered_price\_rules\_type'",
259 "meta_key LIKE '\_user\_%\_percentage\_price\_rules'",
260 "meta_key LIKE '\_user\_%\_fixed\_price\_rules'",
261 "meta_key LIKE '\_user\_%\_tiered_price\_minimum\_qty'",
262 "meta_key LIKE '\_user\_%\_tiered_price\_tax\_status'",
263 "meta_key LIKE '\_user\_%\_tiered_price\_tax\_class'"
264 );
265
266 $likeQuery = implode( ' OR ', $userMetaLikeQueries );
267
268 if ( empty( $products ) && empty( $categories ) ) {
269 $query = "DELETE FROM {$wpdb->postmeta} WHERE ($likeQuery)";
270 $userDeletedCount = $wpdb->query( $query );
271 } else {
272 if ( ! empty( $postIds ) ) {
273 $postIdsIn = implode( ',', $postIds );
274 $query = "DELETE FROM {$wpdb->postmeta} WHERE ($likeQuery) AND post_id IN ($postIdsIn)";
275 $userDeletedCount = $wpdb->query( $query );
276 }
277 }
278
279 if ( $userDeletedCount !== false ) {
280 $deletedCount += $userDeletedCount;
281 }
282 }
283
284 delete_option( \TierPricingTable\Admin\Tips\Tip::SEEN_TIPS_OPTION_KEY );
285
286 $message = sprintf( 'Successfully cleaned up %d product records.', $deletedCount );
287
288 return rest_ensure_response( array(
289 'success' => true,
290 'deleted_rows' => $deletedCount,
291 'message' => $message,
292 ) );
293 }
294
295 public function resetSettings( WP_REST_Request $request ) {
296 global $wpdb;
297
298 if ( class_exists( '\TierPricingTable\Settings\Settings' ) ) {
299 \TierPricingTable\Settings\Settings::deleteOptions();
300 }
301
302 // Wipe all other plugin settings that might be stored via different addons
303 $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'tier_pricing_table_%'" );
304 $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'tiered_pricing_table/%'" );
305 $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'tpt_custom_table_columns%'" );
306
307 return rest_ensure_response( array(
308 'success' => true,
309 'message' => 'Plugin settings were successfully reset to defaults.',
310 ) );
311 }
312
313 public function deleteGlobalRules( WP_REST_Request $request ) {
314 $globalRules = get_posts( array(
315 'numberposts' => - 1,
316 'post_type' => GlobalTieredPricingCPT::SLUG,
317 'post_status' => 'any',
318 'fields' => 'ids',
319 ) );
320
321 $deletedCount = 0;
322 foreach ( $globalRules as $ruleId ) {
323 if ( wp_delete_post( $ruleId, true ) ) {
324 $deletedCount ++;
325 }
326 }
327
328 return rest_ensure_response( array(
329 'success' => true,
330 'deleted_rows' => $deletedCount,
331 'message' => sprintf( 'Successfully deleted %d global rules.', $deletedCount ),
332 ) );
333 }
334
335 public function getRolesAndCapabilities() {
336 global $wp_roles;
337 if ( ! isset( $wp_roles ) ) {
338 $wp_roles = new \WP_Roles();
339 }
340
341 $allRoles = $wp_roles->roles;
342
343 $allCapabilities = array();
344 foreach ( $allRoles as $role ) {
345 if ( ! empty( $role['capabilities'] ) ) {
346 foreach ( $role['capabilities'] as $cap => $granted ) {
347 $allCapabilities[ $cap ] = true;
348 }
349 }
350 }
351
352 $rolesResponse = array();
353 foreach ( $allRoles as $key => $roleData ) {
354 $rolesResponse[] = array(
355 'key' => $key,
356 'name' => $roleData['name'],
357 'capabilities' => ! empty( $roleData['capabilities'] ) ? $roleData['capabilities'] : array(),
358 );
359 }
360
361 $capabilitiesList = array_keys( $allCapabilities );
362 sort( $capabilitiesList );
363
364 return rest_ensure_response( array(
365 'roles' => $rolesResponse,
366 'all_capabilities' => $capabilitiesList,
367 ) );
368 }
369
370 public function createRole( WP_REST_Request $request ) {
371 $roleKey = sanitize_key( $request->get_param( 'key' ) );
372 $roleName = sanitize_text_field( $request->get_param( 'name' ) );
373 $capabilities = $request->get_param( 'capabilities' );
374
375 if ( empty( $roleKey ) || empty( $roleName ) ) {
376 return rest_ensure_response( array( 'success' => false, 'message' => 'Role key and name are required.' ) );
377 }
378
379 if ( get_role( $roleKey ) ) {
380 return rest_ensure_response( array( 'success' => false, 'message' => 'Role already exists.' ) );
381 }
382
383 $capsToSave = array();
384 if ( ! empty( $capabilities ) && is_array( $capabilities ) ) {
385 foreach ( $capabilities as $cap ) {
386 $capsToSave[ $cap ] = true;
387 }
388 }
389
390 $result = add_role( $roleKey, $roleName, $capsToSave );
391
392 if ( null !== $result ) {
393 return rest_ensure_response( array( 'success' => true, 'message' => 'Role created successfully.' ) );
394 }
395
396 return rest_ensure_response( array( 'success' => false, 'message' => 'Failed to create role.' ) );
397 }
398
399 public function updateRoleCapabilities( WP_REST_Request $request ) {
400 $roleKey = sanitize_key( $request->get_param( 'key' ) );
401 $capabilities = $request->get_param( 'capabilities' );
402
403 $role = get_role( $roleKey );
404 if ( ! $role ) {
405 return rest_ensure_response( array( 'success' => false, 'message' => 'Role not found.' ) );
406 }
407
408 foreach ( $role->capabilities as $cap => $granted ) {
409 $role->remove_cap( $cap );
410 }
411
412 if ( ! empty( $capabilities ) && is_array( $capabilities ) ) {
413 foreach ( $capabilities as $cap ) {
414 $role->add_cap( $cap );
415 }
416 }
417
418 return rest_ensure_response( array( 'success' => true, 'message' => 'Role capabilities updated.' ) );
419 }
420
421 public function deleteRole( WP_REST_Request $request ) {
422 $roleKey = sanitize_key( $request->get_param( 'key' ) );
423
424 if ( empty( $roleKey ) ) {
425 return rest_ensure_response( array( 'success' => false, 'message' => 'Role key is required.' ) );
426 }
427
428 $protected_roles = array( 'administrator', 'editor', 'author', 'contributor', 'subscriber' );
429 if ( in_array( $roleKey, $protected_roles ) ) {
430 return rest_ensure_response( array(
431 'success' => false,
432 'message' => 'Cannot delete a core WordPress role.',
433 ) );
434 }
435
436 $role = get_role( $roleKey );
437 if ( ! $role ) {
438 return rest_ensure_response( array( 'success' => false, 'message' => 'Role not found.' ) );
439 }
440
441 remove_role( $roleKey );
442
443 return rest_ensure_response( array( 'success' => true, 'message' => 'Role deleted successfully.' ) );
444 }
445 }
446