PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.2
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.2
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / inc / modules / volume-discounts / admin / options.php

options.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 2.3.2, at inc/modules/volume-discounts/admin/options.php

1,125 lines 43.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Volume Discounts — Option group definitions.
5 *
6 * Pure data file. Returns the option groups array
7 * consumed by init_option_groups().
8 *
9 * @package Merchant
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly
14 }
15
16 return array(
17 array(
18 'title' => esc_html__( 'Offers', 'merchant' ),
19 'module' => Merchant_Volume_Discounts::MODULE_ID,
20 'fields' => array(
21 array(
22 'id' => 'offers',
23 'type' => 'flexible_content',
24 'button_label' => esc_html__( 'Add New Offer', 'merchant' ),
25 'style' => Merchant_Volume_Discounts::MODULE_ID . '-style default',
26 'sorting' => true,
27 'accordion' => true,
28 'duplicate' => true,
29 'layouts' => array(
30 'offer-details' => array(
31 'title' => esc_html__( 'Create Discount Tiers', 'merchant' ),
32 'title-field' => 'offer-title', // text field ID to use as title for the layout
33 'status-field' => 'campaign_status',
34 'fields' => array(
35 array(
36 'id' => 'campaign_status',
37 'type' => 'select',
38 'title' => esc_html__( 'Status', 'merchant' ),
39 'options' => array(
40 'active' => esc_html__( 'Active', 'merchant' ),
41 'inactive' => esc_html__( 'Inactive', 'merchant' ),
42 ),
43 'default' => 'active',
44 'ai_meta' => array(
45 'usage_hint' => 'Controls whether this campaign is active or inactive. Set to active to enable, inactive to disable.',
46 ),
47 ),
48 array(
49 'id' => 'offer-title',
50 'type' => 'text',
51 'title' => esc_html__( 'Offer name', 'merchant' ),
52 'default' => esc_html__( 'Campaign', 'merchant' ),
53 ),
54 array(
55 'id' => 'rules_to_display',
56 'type' => 'select',
57 'title' => esc_html__( 'Offered product(s)', 'merchant' ),
58 'options' => array(
59 'all' => esc_html__( 'All Products', 'merchant' ),
60 'products' => esc_html__( 'Specific Products', 'merchant' ),
61 'categories' => esc_html__( 'Specific Categories', 'merchant' ),
62 'tags' => esc_html__( 'Specific Tags', 'merchant' ),
63 'brands' => esc_html__( 'Specific Brands', 'merchant' ),
64 ),
65 'default' => 'products',
66 'ai_meta' => array(
67 'semantic_group' => 'product_targeting',
68 'usage_hint' => 'Controls which products this campaign applies to. Set this BEFORE setting product_id, category_slugs, tag_slugs, or brand_slugs — those fields are conditional on this value.',
69 ),
70 ),
71 array(
72 'id' => 'include_all_cart_products',
73 'type' => 'switcher',
74 'title' => esc_html__( 'Include all cart products', 'merchant' ),
75 'desc' => esc_html__( 'Apply the discount based on the total quantity of products added to the cart, rather than requiring a specific quantity of each individual product.', 'merchant' ),
76 'default' => false,
77 'condition' => array( 'rules_to_display', '==', 'all' ),
78 'ai_meta' => array(
79 'usage_hint' => 'When enabled, quantity thresholds count total cart items rather than per-product. Only applies when rules_to_display=all.',
80 ),
81 ),
82 array(
83 'id' => 'product_id',
84 'type' => 'products_selector',
85 //'title' => esc_html__( 'Select product', 'merchant' ),
86 'multiple' => true,
87 'desc' => esc_html__( 'Select the product that the customer will get a discount on when they purchase the minimum required quantity.',
88 'merchant' ),
89 'allowed_types' => array( 'simple', 'variable' ),
90 'condition' => array( 'rules_to_display', '==', 'products' ),
91 'ai_meta' => array(
92 'entity' => 'product',
93 'reference_type' => 'static',
94 'value_format' => 'product_id',
95 'semantic_group' => 'product_targeting',
96 'abstraction_level' => 1,
97 'usage_hint' => 'Use when targeting specific individual products by name. Requires rules_to_display=products.',
98 ),
99 ),
100 array(
101 'id' => 'category_slugs',
102 'type' => 'select_ajax',
103 'title' => esc_html__( 'Categories', 'merchant' ),
104 'source' => 'options',
105 'multiple' => true,
106 'options' => Merchant_Admin_Options::get_category_select2_choices(),
107 'placeholder' => esc_html__( 'Select categories', 'merchant' ),
108 'desc' => esc_html__( 'Select the product categories that will show the offer.', 'merchant' ),
109 'condition' => array( 'rules_to_display', '==', 'categories' ),
110 'ai_meta' => array(
111 'entity' => 'category',
112 'reference_type' => 'dynamic',
113 'taxonomy' => 'product_cat',
114 'value_format' => 'slug',
115 'semantic_group' => 'product_targeting',
116 'abstraction_level' => 3,
117 'usage_hint' => 'Use when targeting products by category. Dynamic: future products added to the category are included. Requires rules_to_display=categories.',
118 ),
119 ),
120 array(
121 'id' => 'include_all_category_products',
122 'type' => 'switcher',
123 'title' => esc_html__( 'Include all category products', 'merchant' ),
124 'desc' => esc_html__( 'Apply the discount based on the total quantity of products within the same category added to the cart, rather than requiring a specific quantity of each individual product.', 'merchant' ),
125 'default' => false,
126 'condition' => array( 'rules_to_display', '==', 'categories' ),
127 'ai_meta' => array(
128 'usage_hint' => 'When enabled, quantity thresholds count all products within the selected categories rather than per-product. Only applies when rules_to_display=categories.',
129 ),
130 ),
131 array(
132 'id' => 'include_all_products_info',
133 'type' => 'info',
134 'content' => esc_html__( 'When configuring offer priorities, consider the order in which they are applied. Typically, more general offers should be prioritized higher to ensure consistent discount application. You can control the priority by sorting the offers—offers listed at the top have the highest priority. However, note that this setup will not work on the thank you page.',
135 'merchant' ),
136 'conditions' => array(
137 'relation' => 'OR', // AND/OR, If not provided, only first term will be considered
138 'terms' => array(
139 array(
140 'relation' => 'AND', // AND/OR, If not provided, only first term will be considered
141 'terms' => array(
142 array(
143 'field' => 'rules_to_display', // field ID
144 'operator' => '===', // Available operators: ===, !==, >, <, >=, <=, in, !in, contains, !contains
145 'value' => 'categories', // can be a single value or an array of string/number/int
146 ),
147 array(
148 'field' => 'include_all_category_products', // field ID
149 'operator' => '===', // Available operators: ===, !==, >, <, >=, <=, in, !in, contains, !contains
150 'value' => true, // can be a single value or an array of string/number/int
151 ),
152 ),
153 ),
154 array(
155 'relation' => 'AND', // AND/OR, If not provided, only first term will be considered
156 'terms' => array(
157 array(
158 'field' => 'rules_to_display', // field ID
159 'operator' => '===', // Available operators: ===, !==, >, <, >=, <=, in, !in, contains, !contains
160 'value' => 'all', // can be a single value or an array of string/number/int
161 ),
162 array(
163 'field' => 'include_all_cart_products', // field ID
164 'operator' => '===', // Available operators: ===, !==, >, <, >=, <=, in, !in, contains, !contains
165 'value' => true, // can be a single value or an array of string/number/int
166 ),
167 ),
168 ),
169 ),
170 ),
171 ),
172 array(
173 'id' => 'tag_slugs',
174 'type' => 'select_ajax',
175 'title' => esc_html__( 'Tags', 'merchant' ),
176 'source' => 'options',
177 'multiple' => true,
178 'options' => Merchant_Admin_Options::get_tag_select2_choices(),
179 'placeholder' => esc_html__( 'Select tags', 'merchant' ),
180 'desc' => esc_html__( 'Select the product tags that will show the offer.', 'merchant' ),
181 'condition' => array( 'rules_to_display', '==', 'tags' ),
182 'ai_meta' => array(
183 'entity' => 'tag',
184 'reference_type' => 'dynamic',
185 'taxonomy' => 'product_tag',
186 'value_format' => 'slug',
187 'semantic_group' => 'product_targeting',
188 'abstraction_level' => 2,
189 'usage_hint' => 'Use when targeting products by tag. Dynamic: future products added to the tag are included. Requires rules_to_display=tags.',
190 ),
191 ),
192 array(
193 'id' => 'brand_slugs',
194 'type' => 'select_ajax',
195 'title' => esc_html__( 'Brands', 'merchant' ),
196 'source' => 'options',
197 'multiple' => true,
198 'options' => Merchant_Admin_Options::get_brand_select2_choices(),
199 'placeholder' => esc_html__( 'Select brands', 'merchant' ),
200 'desc' => esc_html__( 'Select the product brands that will show the offer.', 'merchant' ),
201 'condition' => array( 'rules_to_display', '==', 'brands' ),
202 'ai_meta' => array(
203 'entity' => 'brand',
204 'reference_type' => 'dynamic',
205 'taxonomy' => 'product_brand',
206 'value_format' => 'slug',
207 'semantic_group' => 'product_targeting',
208 'abstraction_level' => 4,
209 'usage_hint' => 'Use when targeting products by brand. Dynamic: future products added to the brand are included. Requires rules_to_display=brands.',
210 ),
211 ),
212
213 array(
214 'id' => 'exclude_products_toggle',
215 'type' => 'switcher',
216 'title' => esc_html__( 'Exclude products', 'merchant' ),
217 'default' => 0,
218 'conditions' => array(
219 'relation' => 'AND',
220 'terms' => array(
221 array(
222 'field' => 'rules_to_display',
223 'operator' => 'in',
224 'value' => array( 'all', 'categories', 'tags', 'brands' ),
225 ),
226 ),
227 ),
228 'ai_meta' => array(
229 'toggle_for' => 'excluded_products',
230 'semantic_group' => 'product_exclusion',
231 'usage_hint' => 'Enable this toggle before setting excluded_products. Only available when rules_to_display is all, categories, tags, or brands.',
232 ),
233 ),
234
235 array(
236 'id' => 'excluded_products',
237 'type' => 'products_selector',
238 'title' => esc_html__( 'Exclude Products', 'merchant' ),
239 'multiple' => true,
240 'desc' => esc_html__( 'Exclude products from this campaign.', 'merchant' ),
241 'conditions' => array(
242 'relation' => 'AND',
243 'terms' => array(
244 array(
245 'field' => 'rules_to_display',
246 'operator' => 'in',
247 'value' => array( 'all', 'categories', 'tags', 'brands' ),
248 ),
249 array(
250 'field' => 'exclude_products_toggle',
251 'operator' => '===',
252 'value' => true,
253 ),
254 ),
255 ),
256 'ai_meta' => array(
257 'entity' => 'product',
258 'reference_type' => 'static',
259 'value_format' => 'product_id',
260 'semantic_group' => 'product_exclusion',
261 'abstraction_level' => 1,
262 'toggled_by' => 'exclude_products_toggle',
263 'usage_hint' => 'Use ONLY for excluding specific individual products. For brand/category/tag exclusions, prefer excluded_brands/excluded_categories/excluded_tags — they are dynamic and auto-exclude future products.',
264 ),
265 ),
266
267 array(
268 'id' => 'exclude_categories_toggle',
269 'type' => 'switcher',
270 'title' => esc_html__( 'Exclude categories', 'merchant' ),
271 'default' => 0,
272 'conditions' => array(
273 'relation' => 'AND',
274 'terms' => array(
275 array(
276 'field' => 'rules_to_display',
277 'operator' => 'in',
278 'value' => array( 'all', 'tags', 'brands' ),
279 ),
280 ),
281 ),
282 'ai_meta' => array(
283 'toggle_for' => 'excluded_categories',
284 'semantic_group' => 'product_exclusion',
285 'usage_hint' => 'Enable this toggle before setting excluded_categories. Only available when rules_to_display is all, tags, or brands.',
286 ),
287 ),
288
289 array(
290 'id' => 'excluded_categories',
291 'type' => 'select_ajax',
292 'title' => esc_html__( 'Excluded Categories List', 'merchant' ),
293 'source' => 'options',
294 'multiple' => true,
295 'options' => Merchant_Admin_Options::get_category_select2_choices(),
296 'placeholder' => esc_html__( 'Select categories', 'merchant' ),
297 'desc' => esc_html__( 'Exclude categories from this campaign.', 'merchant' ),
298 'conditions' => array(
299 'relation' => 'AND',
300 'terms' => array(
301 array(
302 'field' => 'rules_to_display',
303 'operator' => 'in',
304 'value' => array( 'all', 'tags', 'brands' ),
305 ),
306 array(
307 'field' => 'exclude_categories_toggle',
308 'operator' => '===',
309 'value' => true,
310 ),
311 ),
312 ),
313 'ai_meta' => array(
314 'entity' => 'category',
315 'reference_type' => 'dynamic',
316 'taxonomy' => 'product_cat',
317 'value_format' => 'slug',
318 'semantic_group' => 'product_exclusion',
319 'abstraction_level' => 3,
320 'toggled_by' => 'exclude_categories_toggle',
321 'usage_hint' => 'Use when excluding products by category. Dynamic: future products added to the category are automatically excluded.',
322 ),
323 ),
324
325 array(
326 'id' => 'exclude_tags_toggle',
327 'type' => 'switcher',
328 'title' => esc_html__( 'Exclude product tags', 'merchant' ),
329 'default' => 0,
330 'conditions' => array(
331 'relation' => 'AND',
332 'terms' => array(
333 array(
334 'field' => 'rules_to_display',
335 'operator' => 'in',
336 'value' => array( 'all', 'categories', 'brands' ),
337 ),
338 ),
339 ),
340 'ai_meta' => array(
341 'toggle_for' => 'excluded_tags',
342 'semantic_group' => 'product_exclusion',
343 'usage_hint' => 'Enable this toggle before setting excluded_tags. Only available when rules_to_display is all, categories, or brands.',
344 ),
345 ),
346
347 array(
348 'id' => 'excluded_tags',
349 'type' => 'select_ajax',
350 'title' => esc_html__( 'Excluded Tags List', 'merchant' ),
351 'source' => 'options',
352 'multiple' => true,
353 'options' => Merchant_Admin_Options::get_tag_select2_choices(),
354 'placeholder' => esc_html__( 'Select tags', 'merchant' ),
355 'desc' => esc_html__( 'Exclude tags from this campaign.', 'merchant' ),
356 'conditions' => array(
357 'relation' => 'AND',
358 'terms' => array(
359 array(
360 'field' => 'rules_to_display',
361 'operator' => 'in',
362 'value' => array( 'all', 'categories', 'brands' ),
363 ),
364 array(
365 'field' => 'exclude_tags_toggle',
366 'operator' => '===',
367 'value' => true,
368 ),
369 ),
370 ),
371 'ai_meta' => array(
372 'entity' => 'tag',
373 'reference_type' => 'dynamic',
374 'taxonomy' => 'product_tag',
375 'value_format' => 'slug',
376 'semantic_group' => 'product_exclusion',
377 'abstraction_level' => 2,
378 'toggled_by' => 'exclude_tags_toggle',
379 'usage_hint' => 'Use when excluding products by tag. Dynamic: future products added to the tag are automatically excluded.',
380 ),
381 ),
382
383 array(
384 'id' => 'exclude_brands_toggle',
385 'type' => 'switcher',
386 'title' => esc_html__( 'Exclude brands', 'merchant' ),
387 'default' => 0,
388 'conditions' => array(
389 'relation' => 'AND',
390 'terms' => array(
391 array(
392 'field' => 'rules_to_display',
393 'operator' => 'in',
394 'value' => array( 'all', 'categories', 'tags' ),
395 ),
396 ),
397 ),
398 'ai_meta' => array(
399 'toggle_for' => 'excluded_brands',
400 'semantic_group' => 'product_exclusion',
401 'usage_hint' => 'Enable this toggle before setting excluded_brands. Only available when rules_to_display is all, categories, or tags.',
402 ),
403 ),
404
405 array(
406 'id' => 'excluded_brands',
407 'type' => 'select_ajax',
408 'title' => esc_html__( 'Excluded Brands List', 'merchant' ),
409 'source' => 'options',
410 'multiple' => true,
411 'options' => Merchant_Admin_Options::get_brand_select2_choices(),
412 'placeholder' => esc_html__( 'Select brands', 'merchant' ),
413 'desc' => esc_html__( 'Exclude brands from this campaign.', 'merchant' ),
414 'conditions' => array(
415 'relation' => 'AND',
416 'terms' => array(
417 array(
418 'field' => 'rules_to_display',
419 'operator' => 'in',
420 'value' => array( 'all', 'categories', 'tags' ),
421 ),
422 array(
423 'field' => 'exclude_brands_toggle',
424 'operator' => '===',
425 'value' => true,
426 ),
427 ),
428 ),
429 'ai_meta' => array(
430 'entity' => 'brand',
431 'reference_type' => 'dynamic',
432 'taxonomy' => 'product_brand',
433 'value_format' => 'slug',
434 'semantic_group' => 'product_exclusion',
435 'abstraction_level' => 4,
436 'toggled_by' => 'exclude_brands_toggle',
437 'usage_hint' => 'Use when excluding products by brand. Dynamic: future products added to the brand are automatically excluded. Prefer this over excluded_products when intent is brand-level.',
438 ),
439 ),
440
441 array(
442 'id' => 'exclude_onsale_products_toggle',
443 'type' => 'switcher',
444 'title' => esc_html__( 'Exclude On-Sale products', 'merchant' ),
445 'default' => 0,
446 'conditions' => array(
447 'relation' => 'AND',
448 'terms' => array(
449 array(
450 'field' => 'rules_to_display',
451 'operator' => 'in',
452 'value' => array( 'all', 'categories', 'tags', 'brands' ),
453 ),
454 ),
455 ),
456 'ai_meta' => array(
457 'semantic_group' => 'product_exclusion',
458 'usage_hint' => 'When enabled, products currently on sale are excluded from this campaign. Standalone flag — no additional data field required.',
459 ),
460 ),
461
462 array(
463 'id' => 'include_subcategories',
464 'type' => 'switcher',
465 'title' => esc_html__( 'Include subcategories', 'merchant' ),
466 'desc' => esc_html__( 'When enabled, selecting a parent category also applies to all of its child categories.', 'merchant' ),
467 'default' => 0,
468 'conditions' => array(
469 'relation' => 'OR',
470 'terms' => array(
471 array(
472 'field' => 'rules_to_display',
473 'operator' => '===',
474 'value' => 'categories',
475 ),
476 array(
477 'field' => 'exclude_categories_toggle',
478 'operator' => '===',
479 'value' => true,
480 ),
481 ),
482 ),
483 'ai_meta' => array(
484 'semantic_group' => 'product_targeting',
485 'usage_hint' => 'Enable so selected parent categories also cover their child categories, for both targeting and exclusion. Off by default, which matches only the exact categories chosen.',
486 ),
487 ),
488
489 array(
490 'id' => 'quantity',
491 'type' => 'number',
492 'title' => esc_html__( 'Quantity', 'merchant' ),
493 'min' => 1,
494 'default' => 2,
495 'ai_meta' => array(
496 'semantic_group' => 'offer_rules',
497 'usage_hint' => 'Minimum quantity to trigger this tier discount.',
498 ),
499 ),
500
501 array(
502 'id' => 'discount_type',
503 'type' => 'radio',
504 'title' => esc_html__( 'Discount', 'merchant' ),
505 'options' => array(
506 'percentage_discount' => esc_html__( 'Percentage', 'merchant' ),
507 'fixed_discount' => esc_html__( 'Fixed', 'merchant' ),
508 ),
509 'default' => 'percentage_discount',
510 'ai_meta' => array(
511 'usage_hint' => 'Choose percentage_discount for relative discounts or fixed_discount for absolute amounts.',
512 ),
513 ),
514 array(
515 'id' => 'discount',
516 'type' => 'number',
517 'step' => 0.01,
518 'default' => 10,
519 'ai_meta' => array(
520 'semantic_group' => 'offer_rules',
521 'usage_hint' => 'The discount amount. Percentage (e.g. 10 for 10% off) or fixed currency amount, depending on discount_type.',
522 ),
523 ),
524
525 array(
526 'id' => 'discount_target',
527 'type' => 'select',
528 'title' => esc_html__( 'Apply discount to', 'merchant' ),
529 'options' => array(
530 'regular' => esc_html__( 'Regular Price', 'merchant' ),
531 'sale' => esc_html__( 'Sale Price', 'merchant' ),
532 ),
533 'default' => 'sale',
534 'ai_meta' => array(
535 'semantic_group' => 'offer_rules',
536 'usage_hint' => 'Whether the discount is calculated from the regular price or the sale price.',
537 ),
538 ),
539
540 array(
541 'id' => 'exclude_coupon',
542 'type' => 'switcher',
543 'title' => esc_html__( 'Exclude coupons', 'merchant' ),
544 'desc' => esc_html__( 'Coupon codes will not be applicable on top of this offer campaign.', 'merchant' ),
545 'default' => false,
546 'ai_meta' => array(
547 'usage_hint' => 'When enabled, coupon codes cannot be stacked on top of this volume discount campaign.',
548 ),
549 ),
550
551 array(
552 'id' => 'user_condition',
553 'type' => 'select',
554 'title' => esc_html__( 'User Condition', 'merchant' ),
555 'options' => array(
556 'all' => esc_html__( 'All Users', 'merchant' ),
557 'customers' => esc_html__( 'Selected Users', 'merchant' ),
558 'roles' => esc_html__( 'Selected Roles', 'merchant' ),
559 ),
560 'default' => 'all',
561 'ai_meta' => array(
562 'semantic_group' => 'user_targeting',
563 'usage_hint' => 'Controls which users see this campaign. Set this BEFORE setting user_condition_roles or user_condition_users.',
564 ),
565 ),
566
567 array(
568 'id' => 'user_condition_roles',
569 'type' => 'select_ajax',
570 'title' => esc_html__( 'User Roles', 'merchant' ),
571 'desc' => esc_html__( 'This will limit the offer to users with these roles.', 'merchant' ),
572 'source' => 'options',
573 'multiple' => true,
574 'classes' => array( 'flex-grow' ),
575 'options' => Merchant_Admin_Options::get_user_roles_select2_choices(),
576 'condition' => array( 'user_condition', '==', 'roles' ),
577 'ai_meta' => array(
578 'entity' => 'role',
579 'reference_type' => 'dynamic',
580 'value_format' => 'role_slug',
581 'semantic_group' => 'user_targeting',
582 'abstraction_level' => 2,
583 'usage_hint' => 'Use when targeting users by role. Dynamic: future users assigned the role are included. Requires user_condition=roles.',
584 ),
585 ),
586
587 array(
588 'id' => 'user_condition_users',
589 'type' => 'select_ajax',
590 'title' => esc_html__( 'Users', 'merchant' ),
591 'desc' => esc_html__( 'This will limit the offer to the selected customers.', 'merchant' ),
592 'source' => 'user',
593 'multiple' => true,
594 'classes' => array( 'flex-grow' ),
595 'condition' => array( 'user_condition', '==', 'customers' ),
596 'ai_meta' => array(
597 'entity' => 'user',
598 'reference_type' => 'static',
599 'value_format' => 'user_id',
600 'semantic_group' => 'user_targeting',
601 'abstraction_level' => 1,
602 'usage_hint' => 'Use when targeting specific individual users. Static: only selected users, not future users. Requires user_condition=customers.',
603 ),
604 ),
605
606 array(
607 'id' => 'user_exclusion_enabled',
608 'type' => 'switcher',
609 'title' => esc_html__( 'Exclusion List', 'merchant' ),
610 'desc' => esc_html__( 'Select the users that will not show the offer.', 'merchant' ),
611 'default' => 0,
612 'conditions' => array(
613 'relation' => 'AND',
614 'terms' => array(
615 array(
616 'field' => 'user_condition',
617 'operator' => 'in',
618 'value' => array( 'all', 'roles' ),
619 ),
620 ),
621 ),
622 'ai_meta' => array(
623 'toggle_for' => 'exclude_roles',
624 'semantic_group' => 'user_exclusion',
625 'usage_hint' => 'Enable this toggle before setting exclude_roles or exclude_users. Gates both user exclusion fields.',
626 ),
627 ),
628
629 array(
630 'id' => 'exclude_roles',
631 'type' => 'select_ajax',
632 'title' => esc_html__( 'Exclude Roles', 'merchant' ),
633 'desc' => esc_html__( 'This will exclude the offer for users with these roles.', 'merchant' ),
634 'source' => 'options',
635 'multiple' => true,
636 'classes' => array( 'flex-grow' ),
637 'options' => Merchant_Admin_Options::get_user_roles_select2_choices(),
638 'conditions' => array(
639 'relation' => 'AND',
640 'terms' => array(
641 array(
642 'field' => 'user_condition',
643 'operator' => 'in',
644 'value' => array( 'all' ),
645 ),
646 array(
647 'field' => 'user_exclusion_enabled',
648 'operator' => '===',
649 'value' => true,
650 ),
651 ),
652 ),
653 'ai_meta' => array(
654 'entity' => 'role',
655 'reference_type' => 'dynamic',
656 'value_format' => 'role_slug',
657 'semantic_group' => 'user_exclusion',
658 'abstraction_level' => 2,
659 'toggled_by' => 'user_exclusion_enabled',
660 'usage_hint' => 'Use when excluding users by role. Dynamic: future users assigned the role are excluded. Prefer over exclude_users for role-level exclusions.',
661 ),
662 ),
663
664 array(
665 'id' => 'exclude_users',
666 'type' => 'select_ajax',
667 'title' => esc_html__( 'Exclude Users', 'merchant' ),
668 'desc' => esc_html__( 'This will exclude the offer for the selected customers.', 'merchant' ),
669 'source' => 'user',
670 'multiple' => true,
671 'classes' => array( 'flex-grow' ),
672 'conditions' => array(
673 'relation' => 'AND',
674 'terms' => array(
675 array(
676 'field' => 'user_condition',
677 'operator' => 'in',
678 'value' => array( 'all', 'roles' ),
679 ),
680 array(
681 'field' => 'user_exclusion_enabled',
682 'operator' => '===',
683 'value' => true,
684 ),
685 ),
686 ),
687 'ai_meta' => array(
688 'entity' => 'user',
689 'reference_type' => 'static',
690 'value_format' => 'user_id',
691 'semantic_group' => 'user_exclusion',
692 'abstraction_level' => 1,
693 'toggled_by' => 'user_exclusion_enabled',
694 'usage_hint' => 'Use ONLY for excluding specific individual users. For role-level exclusions, prefer exclude_roles.',
695 ),
696 ),
697
698 array(
699 'id' => 'product_single_page',
700 'type' => 'fields_group',
701 'title' => esc_html__( 'Product Single Page', 'merchant' ),
702 'sub-desc' => esc_html__( 'Use these settings to control how bulk discount offers appear on product pages.', 'merchant' ),
703 'state' => 'open',
704 'accordion' => true,
705 'display_status' => true,
706 'default' => 'active',
707 'fields' => array(
708 array(
709 'id' => 'single_product_placement',
710 'type' => 'radio',
711 'title' => esc_html__( 'Placement on product page', 'merchant' ),
712 'options' => array(
713 'before-cart-form' => esc_html__( 'Before add to cart', 'merchant' ),
714 'after-cart-form' => esc_html__( 'After add to cart', 'merchant' ),
715 ),
716 'default' => 'before-cart-form',
717 ),
718
719 // text formatting
720 array(
721 'id' => 'table_title',
722 'type' => 'text',
723 'title' => esc_html__( 'Offer title', 'merchant' ),
724 'default' => __( 'Buy more, save more!', 'merchant' ),
725 ),
726
727 // `hidden_desc` depends on `desc`
728 array(
729 'id' => 'save_label',
730 'type' => 'text',
731 'title' => esc_html__( 'Save label', 'merchant' ),
732 'default' => esc_html__( 'Save {amount}', 'merchant' ),
733 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
734 'hidden_desc' => sprintf(
735 /* Translators: %1$s: Discount amount, %2$s: Discount percentage */
736 __( '<strong>%1$s:</strong> to show discount amount<br><strong>%2$s:</strong> to show discount percentage', 'merchant' ),
737 '{amount}',
738 '{percent}'
739 ),
740 ),
741
742 array(
743 'id' => 'buy_text',
744 'type' => 'text',
745 'title' => esc_html__( 'Tier format text', 'merchant' ),
746 'default' => esc_html__( 'Buy {quantity}, get {discount} off each', 'merchant' ),
747 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
748 'hidden_desc' => sprintf(
749 /* Translators: %1$s: Discount percentage, %2$s: Quantity, %3$s: Discount amount */
750 __( '<strong>%1$s:</strong> to show discount percentage<br><strong>%2$s:</strong> to show the number of items needed to buy to get the discount<br><strong>%3$s:</strong> to show discount amount on each item',
751 'merchant' ),
752 '{percent}',
753 '{quantity}',
754 '{discount}'
755 ),
756 ),
757
758 array(
759 'id' => 'item_text',
760 'type' => 'text',
761 'title' => esc_html__( 'Item text', 'merchant' ),
762 'default' => esc_html__( 'Per item:', 'merchant' ),
763 ),
764
765 array(
766 'id' => 'total_text',
767 'type' => 'text',
768 'title' => esc_html__( 'Total text', 'merchant' ),
769 'default' => esc_html__( 'Total price:', 'merchant' ),
770 ),
771
772 array(
773 'id' => 'cart_title_text',
774 'type' => 'text',
775 'title' => esc_html__( 'Cart item discount title', 'merchant' ),
776 'default' => esc_html__( 'Discount', 'merchant' ),
777 'desc' => esc_html__( 'This is displayed on the cart page.', 'merchant' ),
778 ),
779
780 array(
781 'id' => 'cart_description_text',
782 'type' => 'text',
783 'title' => esc_html__( 'Cart item discount description', 'merchant' ),
784 'default' => esc_html__( 'A discount of {amount} has been applied.', 'merchant' ),
785 'desc' => __( 'This is displayed on the cart page. You can use these codes in the content.', 'merchant' ),
786 'hidden_desc' => sprintf(
787 /* Translators: %1$s: Discount amount, %2$s: Discount percentage */
788 __( '<strong>%1$s:</strong> to show discount amount<br><strong>%2$s:</strong> to show discount percentage', 'merchant' ),
789 '{amount}',
790 '{percent}'
791 ),
792 ),
793
794 // style settings
795 array(
796 'id' => 'title_font_size',
797 'type' => 'range',
798 'title' => esc_html__( 'Title font size', 'merchant' ),
799 'min' => 0,
800 'max' => 100,
801 'step' => 1,
802 'unit' => 'px',
803 'default' => 16,
804 ),
805
806 array(
807 'id' => 'title_font_weight',
808 'type' => 'select',
809 'title' => esc_html__( 'Title font weight', 'merchant' ),
810 'options' => array(
811 'lighter' => esc_html__( 'Light', 'merchant' ),
812 'normal' => esc_html__( 'Normal', 'merchant' ),
813 'bold' => esc_html__( 'Bold', 'merchant' ),
814 ),
815 'default' => 'normal',
816 ),
817
818 array(
819 'id' => 'title_text_color',
820 'type' => 'color',
821 'title' => esc_html__( 'Title text color', 'merchant' ),
822 'default' => '#212121',
823 ),
824
825 array(
826 'id' => 'title_text_color_hover',
827 'type' => 'color',
828 'title' => esc_html__( 'Title text color hover', 'merchant' ),
829 'default' => '#212121',
830 ),
831
832 array(
833 'id' => 'table_item_bg_color',
834 'type' => 'color',
835 'title' => esc_html__( 'Background color', 'merchant' ),
836 'default' => '#fcf0f1',
837 ),
838
839 array(
840 'id' => 'table_item_bg_color_hover',
841 'type' => 'color',
842 'title' => esc_html__( 'Background color hover', 'merchant' ),
843 'default' => '#fcf0f1',
844 ),
845
846 array(
847 'id' => 'table_item_border_color',
848 'type' => 'color',
849 'title' => esc_html__( 'Border color', 'merchant' ),
850 'default' => '#d83b3b',
851 ),
852
853 array(
854 'id' => 'table_item_border_color_hover',
855 'type' => 'color',
856 'title' => esc_html__( 'Border color hover', 'merchant' ),
857 'default' => '#d83b3b',
858 ),
859
860 array(
861 'id' => 'table_item_text_color',
862 'type' => 'color',
863 'title' => esc_html__( 'Text color', 'merchant' ),
864 'default' => '#3c434a',
865 ),
866
867 array(
868 'id' => 'table_item_text_color_hover',
869 'type' => 'color',
870 'title' => esc_html__( 'Text color hover', 'merchant' ),
871 'default' => '#3c434a',
872 ),
873
874 array(
875 'id' => 'table_label_bg_color',
876 'type' => 'color',
877 'title' => esc_html__( 'Label background color', 'merchant' ),
878 'default' => '#d83b3b',
879 ),
880
881 array(
882 'id' => 'table_label_text_color',
883 'type' => 'color',
884 'title' => esc_html__( 'Label text color', 'merchant' ),
885 'default' => '#ffffff',
886 ),
887 ),
888 ),
889 array(
890 'id' => 'cart_page',
891 'type' => 'fields_group',
892 'title' => esc_html__( 'Cart Page', 'merchant' ),
893 'sub-desc' => esc_html__( 'Use these settings to control how bulk discount offers appear on the cart page.', 'merchant' ),
894 'state' => 'closed',
895 'accordion' => true,
896 'display_status' => true,
897 'default' => 'inactive',
898 'fields' => array(
899 // Text Formatting Settings
900 array(
901 'id' => 'title',
902 'type' => 'text',
903 'title' => esc_html__( 'Offer title', 'merchant' ),
904 'default' => esc_html__( 'Add {quantity} more to get a {discount} discount off each', 'merchant' ),
905 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
906 'hidden_desc' => sprintf(
907 /* Translators: %1$s: offer quantity, %2$s: discount amount */
908 __(
909 '<strong>%1$s:</strong> to show offer quantity<br><strong>%2$s:</strong> to show discount amount',
910 'merchant'
911 ),
912 '{quantity}',
913 '{discount}'
914 ),
915 ),
916
917 array(
918 'id' => 'button_text',
919 'type' => 'text',
920 'title' => esc_html__( 'Button text', 'merchant' ),
921 'default' => esc_html__( 'Add To Cart', 'merchant' ),
922 ),
923 ),
924 ),
925 array(
926 'id' => 'checkout_page',
927 'type' => 'fields_group',
928 'title' => esc_html__( 'Checkout Page', 'merchant' ),
929 'sub-desc' => esc_html__( 'Use these settings to control how bulk discount offers appear on the checkout page.', 'merchant' ),
930 'state' => 'closed',
931 'default' => 'inactive',
932 'accordion' => true,
933 'display_status' => true,
934 'fields' => array(
935 array(
936 'id' => 'placement',
937 'type' => 'select',
938 'title' => esc_html__( 'Placement', 'merchant' ),
939 'options' => array(
940 'before_billing_details' => esc_html__( 'Before Billing Details', 'merchant' ),
941 'after_billing_details' => esc_html__( 'After Billing Details', 'merchant' ),
942 'before_order_details' => esc_html__( 'Before Order Details', 'merchant' ),
943 'before_payment_options' => esc_html__( 'Before Payment Gateways', 'merchant' ),
944 'before_order_placement_btn' => esc_html__( 'Before Order Placement Button', 'merchant' ),
945 'after_order_placement_btn' => esc_html__( 'After Order Placement Button', 'merchant' ),
946 ),
947 'default' => 'before_billing_details',
948 ),
949 array(
950 'id' => 'title',
951 'type' => 'text',
952 'title' => esc_html__( 'Offer title', 'merchant' ),
953 'default' => esc_html__( 'Add {quantity} more to get {discount} off', 'merchant' ),
954 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
955 'hidden_desc' => sprintf(
956 /* Translators: %1$s: offer quantity, %2$s: discount amount */
957 __(
958 '<strong>%1$s:</strong> to show offer quantity<br><strong>%2$s:</strong> to show discount amount',
959 'merchant'
960 ),
961 '{quantity}',
962 '{discount}'
963 ),
964 ),
965 array(
966 'id' => 'discount_text',
967 'type' => 'text',
968 'title' => esc_html__( 'Discount text', 'merchant' ),
969 'default' => esc_html__( '{product_price}', 'merchant' ),
970 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
971 'hidden_desc' => sprintf(
972 /* Translators: %1$s: product price */
973 __(
974 '<strong>%1$s:</strong> to show product price<br><strong>%2$s:</strong> to show offer discount amount',
975 'merchant'
976 ),
977 '{product_price}',
978 '{discount}'
979 ),
980 ),
981 array(
982 'id' => 'button_text',
983 'type' => 'text',
984 'title' => esc_html__( 'Button text', 'merchant' ),
985 'default' => esc_html__( 'Add To Cart', 'merchant' ),
986 ),
987 ),
988 ),
989 array(
990 'id' => 'thank_you_page',
991 'type' => 'fields_group',
992 'title' => esc_html__( 'Thank You Page', 'merchant' ),
993 'sub-desc' => esc_html__( 'Use these settings to control how bulk discount offers appear on the thank you page.', 'merchant' ),
994 'state' => 'closed',
995 'accordion' => true,
996 'display_status' => true,
997 'default' => 'inactive',
998 'fields' => array(
999 // Text Formatting Settings
1000 array(
1001 'id' => 'title',
1002 'type' => 'text',
1003 'title' => esc_html__( 'Offer title', 'merchant' ),
1004 'default' => esc_html__( 'Add {quantity} more to get {discount} off', 'merchant' ),
1005 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
1006 'hidden_desc' => sprintf(
1007 /* Translators: %1$s: quantity, %2$s: post purchase discount, %3$s: In Stock, %4$s: Total quantity */
1008 __(
1009 '<strong>%1$s:</strong> to show product quantity<br><strong>%2$s:</strong> to show the discount amount',
1010 'merchant'
1011 ),
1012 '{quantity}',
1013 '{discount}'
1014 ),
1015 ),
1016
1017 array(
1018 'id' => 'placement',
1019 'type' => 'select',
1020 'title' => esc_html__( 'Placement', 'merchant' ),
1021 'options' => array(
1022 'on_top' => esc_html__( 'On Top', 'merchant' ),
1023 'before_order_details' => esc_html__( 'Before Order details', 'merchant' ),
1024 'after_order_details' => esc_html__( 'After Order details', 'merchant' ),
1025 ),
1026 'default' => 'before_order_details',
1027 ),
1028
1029 array(
1030 'id' => 'discount_text',
1031 'type' => 'text',
1032 'title' => esc_html__( 'Discount text', 'merchant' ),
1033 'default' => esc_html__( '{product_price}', 'merchant' ),
1034 'desc' => __( 'You can use these codes in the content.', 'merchant' ),
1035 'hidden_desc' => sprintf(
1036 /* Translators: %1$s: Discount amount, %2$s: product price */
1037 __(
1038 '<strong>%1$s:</strong> to show the discount amount<br><strong>%2$s:</strong> to show the product price before and after the offer discount',
1039 'merchant'
1040 ),
1041 '{discount}',
1042 '{product_price}'
1043 ),
1044 ),
1045
1046 array(
1047 'id' => 'bonus_tip_text',
1048 'type' => 'text',
1049 'title' => esc_html__( 'Bonus tip text', 'merchant' ),
1050 'default' => esc_html__( 'Bonus: You will also receive this discount off each item you just purchased as part of this bulk discount offer.', 'merchant' ),
1051 ),
1052
1053 array(
1054 'id' => 'button_text',
1055 'type' => 'text',
1056 'title' => esc_html__( 'Button text', 'merchant' ),
1057 'default' => esc_html__( 'Add To Cart', 'merchant' ),
1058 ),
1059 ),
1060 ),
1061 ),
1062 ),
1063 ),
1064 'default' => array(
1065 array(
1066 'layout' => 'offer-details',
1067 'min_quantity' => 2,
1068 'discount' => 10,
1069 'discount_type' => 'fixed_discount',
1070 ),
1071 ),
1072 ),
1073 ),
1074 ),
1075 array(
1076 'title' => esc_html__( 'General', 'merchant' ),
1077 'module' => Merchant_Volume_Discounts::MODULE_ID,
1078 'fields' => array(
1079 array(
1080 'id' => 'max_checkout_offers',
1081 'type' => 'number',
1082 'title' => __( 'Max offers on checkout page', 'merchant' ),
1083 'desc' => __( 'Set the maximum offers can be displayed on the checkout page.', 'merchant' ),
1084 'default' => 3,
1085 ),
1086
1087 array(
1088 'id' => 'offers_display_style',
1089 'type' => 'radio',
1090 'title' => esc_html__( 'Discount Display Style', 'merchant' ),
1091 'options' => array(
1092 'standard' => esc_html__( 'Standard Boxes', 'merchant' ),
1093 'radio' => esc_html__( 'Tiered Radio Select', 'merchant' ),
1094 ),
1095 'default' => 'standard',
1096 ),
1097 ),
1098 ),
1099 array(
1100 'module' => Merchant_Volume_Discounts::MODULE_ID,
1101 'title' => esc_html__( 'Use shortcode', 'merchant' ),
1102 'fields' => array(
1103 array(
1104 'id' => 'use_shortcode',
1105 'type' => 'switcher',
1106 'title' => __( 'Use shortcode', 'merchant' ),
1107 'default' => 0,
1108 ),
1109 array(
1110 'type' => 'info',
1111 'id' => 'shortcode_info',
1112 'content' => esc_html__( 'If you are using a page builder or a theme that supports shortcodes, then you can output the module using the shortcode above. This might be useful if, for example, you find that you want to control the position of the module output more precisely than with the module settings. Note that the shortcodes can only be used on single product pages.',
1113 'merchant' ),
1114 ),
1115 array(
1116 'id' => 'shortcode_text',
1117 'type' => 'text_readonly',
1118 'title' => esc_html__( 'Shortcode text', 'merchant' ),
1119 'default' => '[merchant_module_' . str_replace( '-', '_', Merchant_Volume_Discounts::MODULE_ID ) . ']',
1120 'condition' => array( 'use_shortcode', '==', '1' ),
1121 ),
1122 ),
1123 ),
1124 );
1125