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 / frequently-bought-together / 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/frequently-bought-together/admin/options.php

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