PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 1.9.1
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v1.9.1
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / database.php

database.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 1.9.1, at includes/database.php

715 lines 24.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly.
7 }
8
9 use StoreEngine\Database\{CreateApiKeys,
10 CreateAttributeTaxonomies,
11 CreateCart,
12 CreateCustomerLookup,
13 CreateDownloadableProductPermissions,
14 CreateDownloadLog,
15 CreateIntegration,
16 CreateLog,
17 CreateOrderAddresses,
18 CreateOrderItems,
19 CreateOrderMetaTable,
20 CreateOrderOperationalData,
21 CreateOrderProductLookup,
22 CreateOrderTable,
23 CreatePaymentTokenMeta,
24 CreatePaymentTokens,
25 CreateProductVariationMetaTable,
26 CreateShippingZoneLocations,
27 CreateVariationsTermsRelationTable,
28 CreateProductDownloadDirectories,
29 CreateProductPriceTable,
30 CreateProductVariationsTable,
31 CreateShippingZoneMethods,
32 CreateShippingZones,
33 CreateTaxRateLocations,
34 CreateTaxRates
35 };
36 use StoreEngine\Classes\enums\ProductDownloadType;
37 use StoreEngine\Classes\enums\ProductTaxStatus;
38 use StoreEngine\Classes\enums\PurchaseRedirectType;
39 use StoreEngine\database\CreateOrderItemMeta;
40 use StoreEngine\Traits\Singleton;
41 use StoreEngine\Classes\Attributes;
42 use StoreEngine\Utils\Helper;
43
44 class Database {
45
46 use Singleton;
47
48 protected function __construct() {
49 $this->register_database_table_name();
50
51 add_action( 'switch_blog', [ $this, 'wpdb_table_fix' ], 0 );
52
53 add_action( 'init', [ $this, 'register_product_post_type' ], 5 );
54 add_action( 'init', [ $this, 'register_coupon_post_type' ], 5 );
55 add_action( 'get_avatar_comment_types', [ $this, 'add_avatar_support_product_comment' ] );
56
57 add_action( 'init', [ $this, 'maybe_flush_rewrite_rules' ], 5 );
58 add_action( 'storeengine/flush_rewrite_rules', [ __CLASS__, 'flush_rewrite_rules' ] );
59
60 add_action( 'rest_api_init', [ $this, 'register_product_meta' ] );
61 add_action( 'rest_api_init', [ $this, 'register_coupon_meta' ] );
62 }
63
64 public function maybe_flush_rewrite_rules() {
65 if ( 'yes' === get_option( 'storeengine_required_rewrite_flush' ) ) {
66 update_option( 'storeengine_required_rewrite_flush', 'no' );
67 self::flush_rewrite_rules();
68 }
69 }
70
71 public static function flush_rewrite_rules() {
72 flush_rewrite_rules();
73 }
74
75 public function register_database_table_name() {
76 global $wpdb;
77
78 // @TODO add all the tables.
79 $tables = [
80 'payment_tokenmeta' => 'storeengine_payment_tokenmeta',
81 'order_itemmeta' => 'storeengine_order_item_meta',
82 'product_meta_lookup' => 'storeengine_product_meta_lookup',
83 'tax_rate_classes' => 'storeengine_tax_rate_classes',
84 'reserved_stock' => 'storeengine_reserved_stock',
85 'store_orders' => 'storeengine_orders',
86 'ordermeta' => 'storeengine_orders_meta',
87 ];
88
89 /**
90 * @XXX make sure to add the meta types for handling cache last change.
91 *
92 * @see Hooks::handle_cache_last_changed()
93 * @see wp_cache_set_last_changed()
94 */
95
96 foreach ( $tables as $name => $table ) {
97 $wpdb->$name = $wpdb->prefix . $table;
98 $wpdb->tables[] = $table;
99 }
100 }
101
102 public function wpdb_table_fix() {
103 $this->register_database_table_name();
104 }
105
106 public static function create_initial_custom_table() {
107 global $wpdb;
108
109 if ( ! function_exists( 'dbDelta' ) ) {
110 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
111 }
112
113 $charset_collate = $wpdb->has_cap( 'collation' ) ? $wpdb->get_charset_collate() : '';
114
115 CreateIntegration::up( $wpdb->prefix, $charset_collate );
116 CreateProductPriceTable::up( $wpdb->prefix, $charset_collate );
117 CreateAttributeTaxonomies::up( $wpdb->prefix, $charset_collate );
118 CreateProductVariationsTable::up( $wpdb->prefix, $charset_collate );
119 CreateProductVariationMetaTable::up( $wpdb->prefix, $charset_collate );
120 CreateVariationsTermsRelationTable::up( $wpdb->prefix, $charset_collate );
121 CreateOrderTable::up( $wpdb->prefix, $charset_collate );
122 CreateOrderMetaTable::up( $wpdb->prefix, $charset_collate );
123 CreateOrderProductLookup::up( $wpdb->prefix, $charset_collate );
124 CreateOrderItems::up( $wpdb->prefix, $charset_collate );
125 CreateOrderItemMeta::up( $wpdb->prefix, $charset_collate );
126 CreateOrderOperationalData::up( $wpdb->prefix, $charset_collate );
127 CreateOrderAddresses::up( $wpdb->prefix, $charset_collate );
128 CreateShippingZoneMethods::up( $wpdb->prefix, $charset_collate );
129 CreateShippingZones::up( $wpdb->prefix, $charset_collate );
130 CreateShippingZoneLocations::up( $wpdb->prefix, $charset_collate );
131 CreateApiKeys::up( $wpdb->prefix, $charset_collate );
132 CreateCart::up( $wpdb->prefix, $charset_collate );
133 CreatePaymentTokens::up( $wpdb->prefix, $charset_collate );
134 CreatePaymentTokenMeta::up( $wpdb->prefix, $charset_collate );
135 CreateTaxRateLocations::up( $wpdb->prefix, $charset_collate );
136 CreateTaxRates::up( $wpdb->prefix, $charset_collate );
137 CreateApiKeys::up( $wpdb->prefix, $charset_collate );
138 CreateLog::up( $wpdb->prefix, $charset_collate );
139 CreateCustomerLookup::up( $wpdb->prefix, $charset_collate );
140 CreateDownloadableProductPermissions::up( $wpdb->prefix, $charset_collate );
141 CreateDownloadLog::up( $wpdb->prefix, $charset_collate );
142 CreateProductDownloadDirectories::up( $wpdb->prefix, $charset_collate );
143
144 // Store DB Version
145 update_option( 'storeengine_db_version', STOREENGINE_DB_VERSION, false );
146 }
147
148 public function register_product_post_type() {
149 $permalinks = Helper::get_permalink_structure();
150 $shop_page_id = Helper::get_settings( 'shop_page' );
151 $has_archive = get_post( $shop_page_id ) ? urldecode( get_page_uri( $shop_page_id ) ) : 'shop';
152
153 // Registering Product CPT
154 register_post_type( Helper::PRODUCT_POST_TYPE, [
155 'labels' => [
156 'name' => esc_html__( 'Products', 'storeengine' ),
157 'add_new' => esc_html__( 'Add New Product', 'storeengine' ),
158 'singular_name' => esc_html__( 'Product', 'storeengine' ),
159 'search_items' => esc_html__( 'Search Products', 'storeengine' ),
160 'parent_item_colon' => esc_html__( 'Parent Products:', 'storeengine' ),
161 'not_found' => esc_html__( 'No Products found.', 'storeengine' ),
162 'not_found_in_trash' => esc_html__( 'No Products found in Trash.', 'storeengine' ),
163 'archives' => esc_html__( 'Product archives', 'storeengine' ),
164 ],
165 'public' => true,
166 'publicly_queryable' => true,
167 'show_ui' => true,
168 'show_in_menu' => false,
169 'show_in_admin_bar' => false,
170 'show_in_nav_menus' => false,
171 'hierarchical' => true,
172 'query_var' => true,
173 'delete_with_user' => false,
174 'supports' => [
175 'title',
176 'editor',
177 'author',
178 'thumbnail',
179 'excerpt',
180 'trackbacks',
181 'custom-fields',
182 'comments',
183 'post-formats',
184 ],
185 'has_archive' => $has_archive,
186 'rewrite' => [ 'slug' => $permalinks['product_rewrite_slug'] ],
187 'show_in_rest' => true,
188 'rest_base' => Helper::PRODUCT_POST_TYPE,
189 'rest_namespace' => STOREENGINE_PLUGIN_SLUG . '/v1',
190 'rest_controller_class' => 'WP_REST_Posts_Controller',
191 'capability_type' => 'post',
192 'capabilities' => [
193 'edit_post' => 'edit_storeengine_product',
194 'read_post' => 'read_storeengine_product',
195 'delete_post' => 'delete_storeengine_product',
196 'edit_posts' => 'edit_storeengine_products',
197 'edit_others_posts' => 'edit_storeengine_others_products',
198 'publish_posts' => 'publish_storeengine_products',
199 'read_private_posts' => 'read_private_storeengine_products',
200 ],
201 ] );
202
203 // Registering Product Category Taxonomy
204 register_taxonomy( Helper::PRODUCT_CATEGORY_TAXONOMY, Helper::PRODUCT_POST_TYPE, [
205 'hierarchical' => true,
206 'query_var' => true,
207 'public' => true,
208 'show_ui' => false,
209 'show_admin_column' => false,
210 '_builtin' => true,
211 'capabilities' => [
212 'manage_terms' => 'manage_categories',
213 'edit_terms' => 'edit_categories',
214 'delete_terms' => 'delete_categories',
215 'assign_terms' => 'assign_categories',
216 ],
217 'show_in_rest' => true,
218 'rest_base' => Helper::PRODUCT_CATEGORY_TAXONOMY,
219 'rest_namespace' => STOREENGINE_PLUGIN_SLUG . '/v1',
220 'rest_controller_class' => 'WP_REST_Terms_Controller',
221 'rewrite' => [
222 'slug' => $permalinks['category_rewrite_slug'],
223 'with_front' => false,
224 'hierarchical' => true,
225 ],
226 ] );
227
228 // Registering Product Tag Taxonomy
229 register_taxonomy( Helper::PRODUCT_TAG_TAXONOMY, Helper::PRODUCT_POST_TYPE, [
230 'hierarchical' => false,
231 'query_var' => true,
232 'public' => true,
233 'show_ui' => false,
234 'show_admin_column' => false,
235 '_builtin' => true,
236 'capabilities' => [
237 'manage_terms' => 'manage_post_tags',
238 'edit_terms' => 'edit_post_tags',
239 'delete_terms' => 'delete_post_tags',
240 'assign_terms' => 'assign_post_tags',
241 ],
242 'show_in_rest' => true,
243 'rest_base' => Helper::PRODUCT_TAG_TAXONOMY,
244 'rest_namespace' => STOREENGINE_PLUGIN_SLUG . '/v1',
245 'rest_controller_class' => 'WP_REST_Terms_Controller',
246 'rewrite' => [
247 'slug' => $permalinks['tag_rewrite_slug'],
248 'with_front' => false,
249 ],
250 ] );
251
252 // Registering Product Attributes As Taxonomy
253 foreach ( ( new Attributes() )->get_all_names() as $slug => ['label' => $label, 'public' => $public] ) {
254 self::register_attribute_taxonomy( $slug, $label, $public );
255 }
256 }
257
258 public function register_coupon_post_type() {
259 register_post_type( Helper::COUPON_POST_TYPE, [
260 'labels' => [
261 'name' => esc_html__( 'Coupon', 'storeengine' ),
262 'add_new' => esc_html__( 'Add New Coupon', 'storeengine' ),
263 'singular_name' => esc_html__( 'Coupon', 'storeengine' ),
264 'search_items' => esc_html__( 'Search Coupon', 'storeengine' ),
265 'parent_item_colon' => esc_html__( 'Parent Coupons:', 'storeengine' ),
266 'not_found' => esc_html__( 'No Coupons found.', 'storeengine' ),
267 'not_found_in_trash' => esc_html__( 'No Coupons found in Trash.', 'storeengine' ),
268 'archives' => esc_html__( 'Coupon archives', 'storeengine' ),
269 ],
270 'public' => true,
271 'publicly_queryable' => true,
272 'show_ui' => true,
273 'show_in_menu' => false,
274 'show_in_admin_bar' => false,
275 'show_in_nav_menus' => false,
276 'hierarchical' => true,
277 'query_var' => true,
278 'delete_with_user' => false,
279 'supports' => [ 'title', 'editor', 'author', 'custom-fields' ],
280 'has_archive' => true,
281 'rewrite' => [ 'slug' => 'coupon' ],
282 'show_in_rest' => true,
283 'rest_base' => Helper::COUPON_POST_TYPE,
284 'rest_namespace' => STOREENGINE_PLUGIN_SLUG . '/v1',
285 'rest_controller_class' => 'WP_REST_Posts_Controller',
286 'capability_type' => 'post',
287 'capabilities' => [
288 'edit_post' => 'edit_storeengine_coupon',
289 'read_post' => 'read_storeengine_coupon',
290 'delete_post' => 'delete_storeengine_coupon',
291 'edit_posts' => 'edit_storeengine_coupons',
292 'edit_others_posts' => 'edit_storeengine_others_coupons',
293 'publish_posts' => 'publish_storeengine_coupons',
294 'read_private_posts' => 'read_private_storeengine_coupons',
295 ],
296 ] );
297 }
298
299 public function add_avatar_support_product_comment( array $comment_types ): array {
300 return array_merge( $comment_types, [ 'storeengine_product' ] );
301 }
302
303 public function register_product_meta() {
304 $product_meta = [
305 '_storeengine_product_shipping_type' => 'string',
306 '_storeengine_product_physical_weight' => 'string',
307 '_storeengine_product_physical_weight_unit' => 'string',
308 '_storeengine_product_physical_length' => 'string',
309 '_storeengine_product_physical_width' => 'string',
310 '_storeengine_product_physical_height' => 'string',
311 '_storeengine_product_physical_dimension_unit' => 'string',
312 '_storeengine_product_digital_auto_complete' => 'boolean',
313 '_storeengine_product_hide' => 'boolean',
314 '_storeengine_product_enable_license_creation' => 'boolean',
315 ];
316
317 foreach ( $product_meta as $meta_key => $product_meta_value_type ) {
318 register_meta( 'post', $meta_key, [
319 'object_subtype' => Helper::PRODUCT_POST_TYPE,
320 'type' => $product_meta_value_type,
321 'single' => true,
322 'show_in_rest' => true,
323 ] );
324 }
325
326 register_meta( 'post', '_storeengine_product_description_editor_type', [
327 'object_subtype' => Helper::PRODUCT_POST_TYPE,
328 'type' => 'string',
329 'single' => true,
330 'show_in_rest' => true,
331 'default' => 'classic',
332 ] );
333
334 register_meta( 'post', '_storeengine_product_gallery_ids', [
335 'object_subtype' => Helper::PRODUCT_POST_TYPE,
336 'type' => 'array',
337 'single' => true,
338 'show_in_rest' => [
339 'schema' => [
340 'title' => __( 'Gallery', 'storeengine' ),
341 'description' => __( 'An array of image IDs for the product.', 'storeengine' ),
342 'context' => [ 'view', 'edit' ],
343 'type' => 'array',
344 'items' => [ 'type' => 'integer' ],
345 ],
346 ],
347 ] );
348
349 register_meta( 'post', '_storeengine_product_tax_status', [
350 'object_subtype' => Helper::PRODUCT_POST_TYPE,
351 'type' => 'string',
352 'single' => true,
353 'show_in_rest' => [
354 'schema' => [
355 'title' => __( 'Tax Status', 'storeengine' ),
356 'description' => __( 'Product tax status.', 'storeengine' ),
357 'context' => [ 'view', 'edit' ],
358 'type' => 'string',
359 'enum' => [ ProductTaxStatus::TAXABLE, ProductTaxStatus::SHIPPING, ProductTaxStatus::NONE ],
360 'default' => ProductTaxStatus::TAXABLE,
361 ],
362 ],
363 ] );
364
365 register_meta( 'post', '_storeengine_product_download_type', [
366 'object_subtype' => Helper::PRODUCT_POST_TYPE,
367 'type' => 'string',
368 'single' => true,
369 'show_in_rest' => [
370 'schema' => [
371 'title' => __( 'Download Type', 'storeengine' ),
372 'description' => __( 'Download type (e.g. versioned).', 'storeengine' ),
373 'context' => [ 'view', 'edit' ],
374 'type' => 'string',
375 'enum' => [ ProductDownloadType::INSTANT, ProductDownloadType::VERSIONED ],
376 'default' => ProductDownloadType::INSTANT,
377 ],
378 ],
379 ] );
380
381 register_meta( 'post', '_storeengine_product_downloadable_files', [
382 'object_subtype' => Helper::PRODUCT_POST_TYPE,
383 'type' => 'array',
384 'single' => true,
385 'show_in_rest' => [
386 'schema' => [
387 'type' => 'array',
388 'items' => [
389 'type' => 'object',
390 'properties' => [
391 'id' => [
392 'type' => 'string',
393 'description' => __( 'The unique identifier for the downloadable file.', 'storeengine' ),
394 ],
395 'attachment_id' => [
396 'type' => 'integer',
397 'description' => __( 'The unique identifier for the downloadable file.', 'storeengine' ),
398 ],
399 'name' => [
400 'type' => 'string',
401 'description' => __( 'The name of the downloadable file.', 'storeengine' ),
402 ],
403 'file' => [
404 'type' => 'string',
405 'format' => 'uri',
406 'description' => __( 'The URL of the downloadable file.', 'storeengine' ),
407 ],
408 'enabled' => [
409 'type' => 'boolean',
410 'description' => __( 'Enable or disable the downloadable file.', 'storeengine' ),
411 ],
412 ],
413 ],
414 'description' => __( 'An array of downloadable files for the product.', 'storeengine' ),
415 'context' => [ 'view', 'edit' ],
416 ],
417 ],
418 ] );
419
420 register_meta( 'post', '_storeengine_upsell_ids', [
421 'object_subtype' => Helper::PRODUCT_POST_TYPE,
422 'type' => 'array',
423 'single' => true,
424 'show_in_rest' => [
425 'schema' => [
426 'type' => 'array',
427 'items' => [
428 'type' => 'integer',
429 ],
430 'description' => 'An array of upsell product IDs for the product',
431 'context' => [ 'view', 'edit' ],
432 ],
433 ],
434 ] );
435
436 register_meta( 'post', '_storeengine_crosssell_ids', [
437 'object_subtype' => Helper::PRODUCT_POST_TYPE,
438 'type' => 'array',
439 'single' => true,
440 'show_in_rest' => [
441 'schema' => [
442 'type' => 'array',
443 'items' => [
444 'type' => 'integer',
445 ],
446 'description' => 'An array of cross-sell product IDs for the product',
447 'context' => [ 'view', 'edit' ],
448 ],
449 ],
450 ] );
451
452 register_meta( 'post', '_storeengine_product_purchase_redirect_type', [
453 'object_subtype' => Helper::PRODUCT_POST_TYPE,
454 'type' => 'string',
455 'single' => true,
456 'show_in_rest' => [
457 'schema' => [
458 'title' => __( 'After Purchase Redirect Type', 'storeengine' ),
459 'description' => __( 'Purchase Redirect Type (e.g. page)', 'storeengine' ),
460 'context' => [ 'view', 'edit' ],
461 'type' => 'string',
462 'enum' => [
463 PurchaseRedirectType::DEFAULT,
464 PurchaseRedirectType::PAGE,
465 PurchaseRedirectType::URL,
466 ],
467 'default' => PurchaseRedirectType::DEFAULT,
468 ],
469 ],
470 ] );
471
472 register_meta( 'post', '_storeengine_product_purchase_redirect_url', [
473 'object_subtype' => Helper::PRODUCT_POST_TYPE,
474 'type' => 'string',
475 'single' => true,
476 'sanitize_callback' => function ( $value ) {
477 // Accept integer IDs
478 if ( is_numeric( $value ) ) {
479 return (string) intval( $value );
480 }
481
482 // Accept valid URLs
483 if ( filter_var( $value, FILTER_VALIDATE_URL ) ) {
484 return esc_url_raw( $value );
485 }
486
487 return '';
488 },
489 'show_in_rest' => [
490 'schema' => [
491 'title' => __( 'After Purchase Redirect URL', 'storeengine' ),
492 'description' => __( 'Redirect specific page/url after product purchase.', 'storeengine' ),
493 'context' => [ 'view', 'edit' ],
494 'type' => 'string',
495 'default' => '',
496 ],
497 ],
498 ] );
499 }
500
501 public function register_coupon_meta() {
502 $course_meta = [
503 '_storeengine_coupon_name' => 'string',
504 '_storeengine_coupon_type' => 'string',
505 '_storeengine_coupon_amount' => 'number',
506 '_storeengine_coupon_time_type' => 'string',
507 '_storeengine_coupon_customer_usage_limit' => 'integer',
508 '_storeengine_coupon_type_of_min_requirement' => 'string',
509 '_storeengine_coupon_min_purchase_quantity' => 'number',
510 '_storeengine_coupon_min_purchase_amount' => 'number',
511 '_storeengine_coupon_who_can_use' => 'string',
512 '_storeengine_coupon_usage_count' => 'number',
513 ];
514
515 foreach ( $course_meta as $meta_key => $meta_value_type ) {
516 register_meta( 'post', $meta_key, [
517 'object_subtype' => Helper::COUPON_POST_TYPE,
518 'type' => $meta_value_type,
519 'single' => true,
520 'show_in_rest' => true,
521 ] );
522 }
523
524 // Coupon Hard limits.
525 foreach ( [ '_storeengine_coupon_usage_limit', '_storeengine_coupon_customer_usage_limit' ] as $limit_type ) {
526 register_meta( 'post', $limit_type, [
527 'object_subtype' => Helper::COUPON_POST_TYPE,
528 'default' => 0,
529 'type' => 'integer',
530 'single' => true,
531 'show_in_rest' => true,
532 ] );
533 }
534
535 // Coupon Used by (user ids).
536 register_meta( 'post', '_storeengine_coupon_used_by', [
537 'object_subtype' => Helper::COUPON_POST_TYPE,
538 'type' => 'number',
539 'single' => false,
540 'show_in_rest' => true,
541 ] );
542
543 // Coupon Start Time
544 register_meta( 'post', '_storeengine_coupon_start_date_time', [
545 'object_subtype' => Helper::COUPON_POST_TYPE,
546 'type' => 'object',
547 'single' => true,
548 'show_in_rest' => [
549 'schema' => [
550 'additionalProperties' => true,
551 'items' => [
552 'type' => 'object',
553 'properties' => [
554 'date' => [ 'type' => 'string' ],
555 'time' => [ 'type' => 'string' ],
556 'timezone' => [ 'type' => 'string' ],
557 ],
558 ],
559 ],
560 ],
561 ] );
562
563 // Coupon End Time
564 register_meta( 'post', '_storeengine_coupon_end_date_time', [
565 'object_subtype' => Helper::COUPON_POST_TYPE,
566 'type' => 'object',
567 'single' => true,
568 'show_in_rest' => [
569 'schema' => [
570 'additionalProperties' => true,
571 'items' => [
572 'type' => 'object',
573 'properties' => [
574 'date' => [ 'type' => 'string' ],
575 'time' => [ 'type' => 'string' ],
576 'timezone' => [ 'type' => 'string' ],
577 ],
578 ],
579 ],
580 ],
581 ] );
582
583 register_meta( 'post', '_storeengine_coupon_valid_customers', [
584 'object_subtype' => Helper::COUPON_POST_TYPE,
585 'type' => 'array',
586 'single' => true,
587 'show_in_rest' => [
588 'schema' => [
589 'type' => 'array',
590 'items' => [
591 'type' => 'integer',
592 ],
593 ],
594 ],
595 'sanitize_callback' => function ( $value ) {
596 return array_values(
597 array_filter(
598 array_map( 'absint', (array) $value )
599 )
600 );
601 }
602 ] );
603
604 register_meta( 'post', '_storeengine_coupon_valid_prices', [
605 'object_subtype' => Helper::COUPON_POST_TYPE,
606 'type' => 'array',
607 'single' => true,
608 'show_in_rest' => [
609 'schema' => [
610 'type' => 'array',
611 'items' => [
612 'type' => 'object',
613 'properties' => [
614 'product_id' => [ 'type' => 'number' ],
615 'price_ids' => [
616 'type' => 'array',
617 'items' => [ 'type' => 'number' ]
618 ],
619 ],
620 ],
621 ],
622 ],
623 'sanitize_callback' => function ( $value ) {
624 if ( ! is_array( $value ) ) {
625 return [];
626 }
627
628 $sanitized = [];
629 foreach ( $value as $row ) {
630 // Each item must be an array/object
631 if ( ! is_array( $row ) ) {
632 continue;
633 }
634
635 $product_id = absint( $row['product_id'] );
636
637 $price_ids = [];
638 if ( isset( $row['price_ids'] ) && is_array( $row['price_ids'] ) ) {
639 $price_ids = array_values(
640 array_unique(
641 array_filter(
642 array_map( 'absint', $row['price_ids'] )
643 )
644 )
645 );
646 }
647
648 $sanitized[] = [
649 'product_id' => $product_id,
650 'price_ids' => $price_ids,
651 ];
652 }
653
654 return $sanitized;
655 }
656 ] );
657 }
658
659 public static function register_attribute_taxonomy( string $name, string $label, bool $public ) {
660 return register_taxonomy( Helper::get_attribute_taxonomy_name( $name ), Helper::PRODUCT_POST_TYPE, [
661 'label' => $label,
662 'labels' => [
663 /* translators: %s: attribute name */
664 'name' => sprintf( _x( 'Product %s', 'Product Attribute', 'storeengine' ), $label ),
665 'singular_name' => $label,
666 /* translators: %s: attribute name */
667 'search_items' => sprintf( __( 'Search %s', 'storeengine' ), $label ),
668 /* translators: %s: attribute name */
669 'all_items' => sprintf( __( 'All %s', 'storeengine' ), $label ),
670 /* translators: %s: attribute name */
671 'parent_item' => sprintf( __( 'Parent %s', 'storeengine' ), $label ),
672 /* translators: %s: attribute name */
673 'parent_item_colon' => sprintf( __( 'Parent %s:', 'storeengine' ), $label ),
674 /* translators: %s: attribute name */
675 'edit_item' => sprintf( _x( 'Edit %s', 'Product attribute edit button label', 'storeengine' ), $label ),
676 /* translators: %s: attribute name */
677 'update_item' => sprintf( __( 'Update %s', 'storeengine' ), $label ),
678 /* translators: %s: attribute name */
679 'add_new_item' => sprintf( __( 'Add new %s', 'storeengine' ), $label ),
680 /* translators: %s: attribute name */
681 'new_item_name' => sprintf( __( 'New %s', 'storeengine' ), $label ),
682 /* translators: %s: attribute name */
683 'not_found' => sprintf( __( 'No &quot;%s&quot; found', 'storeengine' ), $label ),
684 /* translators: %s: attribute name */
685 'back_to_items' => sprintf( __( '&larr; Back to "%s" attributes', 'storeengine' ), $label ),
686 ],
687 'hierarchical' => false,
688 'update_count_callback' => '_update_post_term_count',
689 'show_ui' => false,
690 'show_in_quick_edit' => false,
691 'show_in_menu' => false,
692 'meta_box_cb' => false,
693 'query_var' => $public,
694 'rewrite' => ! $public ? false : apply_filters( 'storeengine/attribute/rewrite_rule', [
695 'slug' => Helper::get_attribute_taxonomy_name( $name ),
696 'with_front' => false,
697 ] ),
698 'sort' => false,
699 'public' => $public,
700 'show_in_nav_menus' => $public && apply_filters( 'storeengine/attribute/show_in_nav_menus', false, $name ),
701 'capabilities' => [
702 'manage_terms' => 'manage_post_tags',
703 'edit_terms' => 'edit_post_tags',
704 'delete_terms' => 'delete_post_tags',
705 'assign_terms' => 'assign_post_tags',
706 ],
707 'show_admin_column' => false,
708 'show_in_rest' => true,
709 'rest_base' => Helper::get_attribute_taxonomy_name( $name ),
710 'rest_namespace' => STOREENGINE_PLUGIN_SLUG . '/v1',
711 'rest_controller_class' => 'WP_REST_Terms_Controller',
712 ] );
713 }
714 }
715