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
← All changes | inc/helpers.php +509 -32 1.10.32.3.2 View file →
@@ -61,8 +61,9 @@
61 61 'stroke' => true,
62 62 'stroke-width' => true,
63 63 'stroke-linejoin' => true,
64 64 'clip-rule' => true,
65 + 'opacity' => true,
65 66 ),
66 67 'polyline' => array(
67 68 'points' => true,
68 69 'fill' => true,
@@ -295,8 +296,71 @@
295 296 }
296 297 }
297 298 }
298 299
300 +
301 + // Include script tag
302 + if ( in_array( 'script', $extra, true ) ) {
303 + $allowed_tags['script'] = array(
304 + 'id' => true,
305 + 'src' => true,
306 + 'type' => true,
307 + 'async' => true,
308 + 'defer' => true,
309 + );
310 + }
311 +
312 + if ( in_array( 'div', $extra, true ) ) {
313 + $tags = array( 'form', 'input', 'select', 'option', 'textarea', 'a', 'div' );
314 +
315 + foreach ( $tags as $tag ) {
316 + $allowed_tags[ $tag ] = array(
317 + 'id' => true,
318 + 'class' => true,
319 + 'style' => true,
320 + 'name' => true,
321 + 'href' => true,
322 + 'target' => true,
323 + 'value' => true,
324 + 'type' => true,
325 + 'placeholder' => true,
326 + 'data' => '*',
327 + 'data-source' => true,
328 + 'data-product_id' => true,
329 + 'data-product_variations' => true,
330 + 'data-attribute_name' => true,
331 + 'data-show_option_none' => true,
332 + 'data-name' => true,
333 + 'data-allowed-types' => true,
334 + 'step' => true,
335 + 'min' => true,
336 + 'max' => true,
337 + 'selected' => true,
338 + 'checked' => true,
339 + 'onchange' => true,
340 + 'autocomplete' => true,
341 + 'required' => true,
342 + 'action' => true,
343 + 'method' => true,
344 + 'enctype' => true,
345 + 'size' => true,
346 + 'role' => true,
347 + 'inputmode' => true,
348 + 'aria-label' => true,
349 + 'multiple' => true,
350 + 'title' => true,
351 + 'data-id' => true,
352 + 'data-product-id' => true,
353 + );
354 +
355 + if ( $tag === 'a' ) {
356 + $allowed_tags[ $tag ]['href'] = true;
357 + $allowed_tags[ $tag ]['title'] = true;
358 + $allowed_tags[ $tag ]['target'] = true;
359 + }
360 + }
361 + }
362 +
299 363 /**
300 364 * Filters the allowed tags.
301 365 *
302 366 * @since 1.2.5
@@ -320,8 +384,49 @@
320 384 }
321 385 }
322 386
323 387 /**
388 + * Sanitize SVG markup.
389 + *
390 + * Uses the existing SVG allowlist from merchant_kses_allowed_tags()
391 + * to preserve SVG elements while stripping unsafe content.
392 + *
393 + * @param mixed $value The raw SVG markup.
394 + *
395 + * @return string The sanitized SVG markup.
396 + *
397 + * @since 2.3.0
398 + */
399 +if ( ! function_exists( 'merchant_sanitize_svg' ) ) {
400 + function merchant_sanitize_svg( $value ) {
401 + return wp_kses( (string) $value, merchant_kses_allowed_tags( array(), false ) );
402 + }
403 +}
404 +
405 +/**
406 + * Format a price for admin preview display.
407 + *
408 + * Uses wc_price() when WooCommerce is available, otherwise falls back to a plain
409 + * currency symbol + number_format string.
410 + *
411 + * @param float $price The price value.
412 + * @param string $currency Currency symbol fallback (used only when WC is unavailable).
413 + *
414 + * @return string Formatted price HTML.
415 + *
416 + * @since 2.2.5
417 + */
418 +if ( ! function_exists( 'merchant_preview_price' ) ) {
419 + function merchant_preview_price( $price, $currency = '$' ) {
420 + if ( function_exists( 'wc_price' ) ) {
421 + return wp_kses( wc_price( $price ), merchant_kses_allowed_tags( array( 'bdi' ) ) );
422 + }
423 +
424 + return esc_html( $currency ) . esc_html( number_format( (float) $price, 2 ) );
425 + }
426 +}
427 +
428 +/**
324 429 * Check if WooCommerce checkout page is being rendered by block.
325 430 * Since WooCommerce 8.3.0 the checkout page is rendered by block.
326 431 *
327 432 * @return bool
@@ -417,8 +522,96 @@
417 522 }
418 523 }
419 524
420 525 /**
526 + * Get every descendant category slug of a given category term.
527 + *
528 + * Uses a single `child_of` term query, so the whole branch is returned in one
529 + * call regardless of how deeply the tree is nested.
530 + *
531 + * @param int $term_id Parent product category term ID.
532 + *
533 + * @return string[] Descendant category slugs. Empty when the term has no children.
534 + */
535 +if ( ! function_exists( 'merchant_get_category_descendant_slugs' ) ) {
536 + function merchant_get_category_descendant_slugs( $term_id ) {
537 + $descendants = get_terms(
538 + array(
539 + 'taxonomy' => 'product_cat',
540 + 'child_of' => (int) $term_id,
541 + 'fields' => 'slugs',
542 + 'hide_empty' => false,
543 + )
544 + );
545 +
546 + if ( is_wp_error( $descendants ) || ! is_array( $descendants ) ) {
547 + return array();
548 + }
549 +
550 + return $descendants;
551 + }
552 +}
553 +
554 +/**
555 + * Expand category slugs to include all of their descendant categories.
556 + *
557 + * Products are only ever assigned to the categories picked for them, so a
558 + * product sitting in "Hoodies" is not matched by a rule targeting its parent
559 + * "Clothing". Expanding the parent into its whole branch makes that match work.
560 + *
561 + * Slugs that do not resolve to a category are passed through untouched, so an
562 + * unknown slug never silently disappears from a rule.
563 + *
564 + * @param string[] $slugs Category slugs to expand.
565 + *
566 + * @return string[] The given slugs plus every descendant slug, de-duplicated.
567 + */
568 +if ( ! function_exists( 'merchant_expand_categories_with_children' ) ) {
569 + function merchant_expand_categories_with_children( $slugs ) {
570 + $slugs = array_filter( array_map( 'strval', (array) $slugs ), 'strlen' );
571 +
572 + if ( empty( $slugs ) ) {
573 + return array();
574 + }
575 +
576 + $expanded = $slugs;
577 +
578 + foreach ( $slugs as $slug ) {
579 + $term = get_term_by( 'slug', $slug, 'product_cat' );
580 +
581 + if ( empty( $term ) || is_wp_error( $term ) ) {
582 + continue;
583 + }
584 +
585 + $expanded = array_merge( $expanded, merchant_get_category_descendant_slugs( $term->term_id ) );
586 + }
587 +
588 + return array_values( array_unique( $expanded ) );
589 + }
590 +}
591 +
592 +/**
593 + * Expand category slugs only when a campaign opted into subcategories.
594 + *
595 + * Call this at the point a campaign's category slugs are read, so matching
596 + * behaviour stays byte-for-byte identical while the toggle is off.
597 + *
598 + * @param string[] $slugs Category slugs from the campaign.
599 + * @param array<string, mixed> $settings Campaign settings holding the toggle.
600 + *
601 + * @return string[] Expanded slugs when the toggle is on, otherwise the input.
602 + */
603 +if ( ! function_exists( 'merchant_maybe_expand_categories' ) ) {
604 + function merchant_maybe_expand_categories( $slugs, $settings ) {
605 + if ( empty( $settings['include_subcategories'] ) ) {
606 + return (array) $slugs;
607 + }
608 +
609 + return merchant_expand_categories_with_children( $slugs );
610 + }
611 +}
612 +
613 +/**
421 614 * Get the product tags.
422 615 */
423 616 if ( ! function_exists( 'merchant_get_product_tags' ) ) {
424 617 function merchant_get_product_tags() {
@@ -610,8 +803,40 @@
610 803 return $date_object->getTimestamp(); // Output the timestamp
611 804 }
612 805 }
613 806
807 +if ( ! function_exists( 'merchant_date_string_to_timestamp' ) ) {
808 + /**
809 + * Convert a date string to a Unix timestamp based on the specified format and timezone.
810 + *
811 + * This function signature matches Merchant Pro for compatibility.
812 + *
813 + * @param string $date The date string to convert.
814 + * @param string|null $timezone_offset The timezone offset or timezone string. Defaults to WordPress timezone.
815 + * @param string $format The format of the date string. Defaults to 'm-d-Y h:i A'.
816 + *
817 + * @return int The timestamp, or 0 on failure.
818 + */
819 + function merchant_date_string_to_timestamp( $date, $timezone_offset = null, $format = 'm-d-Y h:i A' ) {
820 + try {
821 + // If it's already numeric, return it as-is
822 + if ( is_numeric( $date ) ) {
823 + return (int) $date;
824 + }
825 +
826 + // Use WordPress timezone if not specified
827 + $timezone_offset = $timezone_offset ?? wp_timezone_string();
828 +
829 + // Create DateTime object from the specified format and timezone
830 + $date_object = DateTime::createFromFormat( $format, $date, new DateTimeZone( $timezone_offset ) );
831 +
832 + return $date_object ? $date_object->getTimestamp() : 0;
833 + } catch ( Exception $e ) {
834 + return 0;
835 + }
836 + }
837 +}
838 +
614 839 /**
615 840 * Parses a list of product IDs
616 841 * @return array
617 842 */
@@ -637,48 +862,59 @@
637 862 * @return bool
638 863 */
639 864 if ( ! function_exists( 'merchant_is_user_condition_passed' ) ) {
640 865 function merchant_is_user_condition_passed( $args = array() ) {
641 - $passed = false;
866 + $args = is_array( $args ) ? $args : array();
642 867
643 868 $is_logged_in = is_user_logged_in();
644 869 $current_user = $is_logged_in ? wp_get_current_user() : null;
870 + $customer_id = is_object( $current_user ) && isset( $current_user->ID ) ? (int) $current_user->ID : 0;
871 + $user_role = is_object( $current_user ) && isset( $current_user->roles ) && ! empty( $current_user->roles ) ? $current_user->roles[0] : '';
645 872
646 873 $condition = $args['user_condition'] ?? 'all';
647 874
875 + $is_exclusion_enabled = $args['user_exclusion_enabled'] ?? false;
876 + $exclude_users_raw = $args['exclude_users'] ?? array();
877 + $excluded_customers = array_map( 'intval', is_array( $exclude_users_raw ) ? $exclude_users_raw : array() );
878 + $excluded_roles_raw = $args['exclude_roles'] ?? array();
879 + $excluded_roles = is_array( $excluded_roles_raw ) ? $excluded_roles_raw : array();
880 +
648 881 switch ( $condition ) {
649 882 case 'all':
650 883 case '':
651 - $passed = true;
652 - break;
884 + if ( $is_exclusion_enabled ) {
885 + if ( in_array( $customer_id, $excluded_customers, true ) ) {
886 + return false;
887 + }
653 888
889 + if ( $condition === 'all' && in_array( $user_role, $excluded_roles, true ) ) {
890 + return false;
891 + }
892 + }
893 +
894 + return true;
895 +
654 896 case 'logged-in':
655 - if ( $is_logged_in ) {
656 - $passed = true;
657 - }
658 - break;
897 + return $is_logged_in;
659 898
660 899 case 'roles':
661 - $roles = $args['user_condition_roles'] ?? array();
662 - $role = $current_user->roles[0] ?? '';
900 + if ( $is_exclusion_enabled && in_array( $customer_id, $excluded_customers, true ) ) {
901 + return false;
902 + }
663 903
664 - if ( in_array( $role, $roles, true ) ) {
665 - $passed = true;
666 - }
667 - break;
904 + $allowed_roles_raw = $args['user_condition_roles'] ?? array();
905 + $allowed_roles = is_array( $allowed_roles_raw ) ? $allowed_roles_raw : array();
906 + return in_array( $user_role, $allowed_roles, true );
668 907
669 908 case 'customers':
670 - $customers_id = $args['user_condition_users'] ?? array();
671 - $customers_id = array_map( 'intval', $customers_id );
672 - $customer_id = (int) ( $current_user->ID ?? 0 );
909 + case 'users':
910 + $allowed_users_raw = $args['user_condition_users'] ?? array();
911 + $allowed_customers = array_map( 'intval', is_array( $allowed_users_raw ) ? $allowed_users_raw : array() );
912 + return $is_logged_in && in_array( $customer_id, $allowed_customers, true );
673 913
674 - if ( in_array( $customer_id, $customers_id, true ) ) {
675 - $passed = true;
676 - }
677 - break;
914 + default:
915 + return false;
678 916 }
679 -
680 - return $passed;
681 917 }
682 918 }
683 919
684 920 /**
@@ -690,14 +926,19 @@
690 926 * @return bool
691 927 */
692 928 if ( ! function_exists( 'merchant_is_product_excluded' ) ) {
693 929 function merchant_is_product_excluded( $product_id, $args = array() ) {
694 - $display_rule = $args['rules_to_display'] ?? $args['display_rules'] ?? $args['rules_to_apply'] ?? 'products';
930 + if ( empty( $args['exclusion_enabled'] ) ) {
931 + return false;
932 + }
695 933
934 + $display_rule = $args['rules_to_display'] ?? $args['display_rules'] ?? $args['rules_to_apply'] ?? $args['trigger_on'] ?? 'products';
935 +
696 936 $rules = array(
697 937 'all',
698 938 'all_products',
699 939 'categories',
940 + 'category',
700 941 'by_category',
701 942 'tags',
702 943 'by_tags',
703 944 'featured_products',
@@ -706,25 +947,25 @@
706 947 'out_of_stock',
707 948 'pre-order',
708 949 );
709 950
951 + $product = wc_get_product( $product_id );
952 + $_product_id = $product && $product->is_type( 'variation' ) ? $product->get_parent_id() : $product_id;
953 +
710 954 // Exclude products
711 955 if ( in_array( $display_rule, $rules, true ) ) {
712 956 $excluded_product_ids = $args['excluded_products'] ?? array();
713 957 $excluded_product_ids = merchant_parse_product_ids( $excluded_product_ids );
714 958
715 - if ( in_array( (int) $product_id, $excluded_product_ids, true ) ) {
959 + if ( in_array( (int) $product_id, $excluded_product_ids, true ) || in_array( (int) $_product_id, $excluded_product_ids, true ) ) {
716 960 return true;
717 961 }
718 962 }
719 963
720 964 // Exclude categories
721 - if ( in_array( $display_rule, array( 'all', 'all_products' ), true ) ) {
722 - $excluded_categories_slugs = $args['excluded_categories'] ?? array();
965 + if ( in_array( $display_rule, array( 'all', 'all_products', 'categories', 'category', 'by_category' ), true ) ) {
966 + $excluded_categories_slugs = merchant_maybe_expand_categories( $args['excluded_categories'] ?? array(), $args );
723 967
724 - $product = wc_get_product( $product_id );
725 - $_product_id = $product && $product->is_type( 'variation' ) ? $product->get_parent_id() : $product_id;
726 -
727 968 if ( ! empty( $excluded_categories_slugs ) && has_term( $excluded_categories_slugs, 'product_cat', $_product_id ) ) {
728 969 return true;
729 970 }
730 971 }
@@ -729,24 +970,88 @@
729 970 }
730 971 }
731 972
732 973 // Exclude tags
733 - if ( in_array( $display_rule, array( 'all', 'all_products' ), true ) ) {
974 + if ( in_array( $display_rule, array( 'all', 'all_products', 'tags', 'by_tags' ), true ) ) {
734 975 $excluded_tags_slugs = $args['excluded_tags'] ?? array();
735 976
736 - $product = wc_get_product( $product_id );
737 - $_product_id = $product && $product->is_type( 'variation' ) ? $product->get_parent_id() : $product_id;
977 + if ( ! empty( $excluded_tags_slugs ) && has_term( $excluded_tags_slugs, 'product_tag', $_product_id ) ) {
978 + return true;
979 + }
980 + }
738 981
982 + // Exclude brands
983 + if ( in_array( $display_rule, array( 'all', 'all_products', 'brands', 'by_brands' ), true ) ) {
984 + $excluded_brands_slugs = $args['excluded_brands'] ?? array();
985 +
986 + if ( ! empty( $excluded_brands_slugs ) && has_term( $excluded_brands_slugs, 'product_brand', $_product_id ) ) {
987 + return true;
988 + }
989 + }
990 +
991 + // Exclude categories with toggle
992 + if ( ! empty( $args['exclude_categories_toggle'] ) && in_array( $display_rule, array( 'all', 'all_products', 'categories', 'category', 'by_category' ), true ) ) {
993 + $excluded_categories_slugs = merchant_maybe_expand_categories( $args['excluded_categories'] ?? array(), $args );
994 +
995 + if ( ! empty( $excluded_categories_slugs ) && has_term( $excluded_categories_slugs, 'product_cat', $_product_id ) ) {
996 + return true;
997 + }
998 + }
999 +
1000 + // Exclude tags with toggle
1001 + if ( ! empty( $args['exclude_tags_toggle'] ) && in_array( $display_rule, array( 'all', 'all_products', 'tags', 'by_tags' ), true ) ) {
1002 + $excluded_tags_slugs = $args['excluded_tags'] ?? array();
1003 +
739 1004 if ( ! empty( $excluded_tags_slugs ) && has_term( $excluded_tags_slugs, 'product_tag', $_product_id ) ) {
740 1005 return true;
741 1006 }
742 1007 }
743 1008
1009 + // Exclude brands with toggle
1010 + if ( ! empty( $args['exclude_brands_toggle'] ) && in_array( $display_rule, array( 'all', 'all_products', 'brands', 'by_brands' ), true ) ) {
1011 + $excluded_brands_slugs = $args['excluded_brands'] ?? array();
1012 +
1013 + if ( ! empty( $excluded_brands_slugs ) && has_term( $excluded_brands_slugs, 'product_brand', $_product_id ) ) {
1014 + return true;
1015 + }
1016 + }
1017 +
744 1018 return false;
745 1019 }
746 1020 }
747 1021
1022 +/**
1023 + * Check if a product or any of its variations is excluded based on the given offer.
1024 + *
1025 + * This method determines if a product (simple or variable) or any of its variations
1026 + * satisfies the merchant exclusion rules.
1027 + *
1028 + * @param int $product_id The ID of the product to check.
1029 + * @param array $offer The offer data to evaluate against exclusion rules.
1030 + *
1031 + * @return bool True if the product or any of its variations is excluded, false otherwise.
1032 + */
1033 +if ( ! function_exists( 'merchant_is_product_or_variation_excluded' ) ) {
1034 + function merchant_is_product_or_variation_excluded( $product_id, $offer = array() ) {
1035 + $product = wc_get_product( $product_id );
748 1036
1037 + if ( ! $product ) {
1038 + return false;
1039 + }
1040 +
1041 + // Get IDs to check for exclusion
1042 + $product_ids = $product->is_type( 'variable' ) ? $product->get_children() : array( $product_id );
1043 +
1044 + foreach ( $product_ids as $id ) {
1045 + if ( merchant_is_product_excluded( $id, $offer ) ) {
1046 + return true; // Excluded if any ID matches
1047 + }
1048 + }
1049 +
1050 + return false;
1051 + }
1052 +}
1053 +
749 1054 /**
750 1055 * Get the label of the first active payment gateway in WooCommerce.
751 1056 *
752 1057 * @return string|null The label of the first active payment gateway, or null if none are found.
@@ -763,6 +1068,178 @@
763 1068 }
764 1069
765 1070 // Return null if no active gateways are found
766 1071 return null;
1072 + }
1073 +}
1074 +
1075 +/**
1076 + * Get the review count of a product.
1077 + *
1078 + * @param int $product_id The ID of the product to get the review count for.
1079 + *
1080 + * @return int The review count of the product.
1081 + */
1082 +if ( ! function_exists( 'merchant_get_product_reviews_count' ) ) {
1083 + function merchant_get_product_reviews_count( $product_id ) {
1084 + $product = wc_get_product( $product_id );
1085 +
1086 + return $product ? $product->get_review_count() : 0;
1087 + }
1088 +}
1089 +
1090 +if ( ! function_exists( 'merchant_get_modules_campaign_data' ) ) {
1091 + /**
1092 + * Retrieves campaign data for a specific module.
1093 + *
1094 + * This function fetches campaign data based on the provided module ID and processes it
1095 + * into a standardized format. The campaigns are indexed by their `flexible_id` (expected to be a UUID v4)
1096 + * and include details such as ID, title, and status.
1097 + *
1098 + * @param string $module_id The ID of the module for which to retrieve campaign data.
1099 + * Expected values include constants like `Merchant_Buy_X_Get_Y::MODULE_ID`,
1100 + * `Merchant_Pre_Orders::MODULE_ID`, and `Merchant_Product_Labels::MODULE_ID`.
1101 + *
1102 + * @return array An associative array of campaigns, where each key is the `flexible_id` (UUID v4)
1103 + * of the campaign, and the value is an array containing the campaign's `id`, `title`,
1104 + * and `status`.
1105 + * Example:
1106 + * [
1107 + * '550e8400-e29b-41d4-a716-446655440000' => [
1108 + * 'id' => '550e8400-e29b-41d4-a716-446655440000',
1109 + * 'title' => 'Campaign Title',
1110 + * 'status' => 'active',
1111 + * ],
1112 + * 'f47ac10b-58cc-4372-a567-0e02b2c3d479' => [
1113 + * 'id' => 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
1114 + * 'title' => 'Another Campaign',
1115 + * 'status' => 'inactive',
1116 + * ],
1117 + * ]
1118 + */
1119 + function merchant_get_module_campaigns_data( $module_id ) {
1120 + $campaigns = array();
1121 +
1122 + // Determine the key to use based on the module ID
1123 + $key = '';
1124 + if ( Merchant_Buy_X_Get_Y::MODULE_ID === $module_id || Merchant_Pre_Orders::MODULE_ID === $module_id ) {
1125 + $key = 'rules';
1126 + } elseif ( Merchant_Product_Labels::MODULE_ID === $module_id ) {
1127 + $key = 'labels';
1128 + } else {
1129 + $key = 'offers';
1130 + }
1131 +
1132 + // Fetch the module campaigns
1133 + $module_campaigns = Merchant_Admin_Options::get( $module_id, $key, array() );
1134 + if ( empty( $module_campaigns ) ) {
1135 + return $campaigns;
1136 + }
1137 +
1138 + // Process each campaign
1139 + foreach ( $module_campaigns as $campaign ) {
1140 + if ( empty( $campaign['flexible_id'] ) ) {
1141 + continue;
1142 + }
1143 +
1144 + $campaigns[ $campaign['flexible_id'] ] = array(
1145 + 'campaign_key' => $key,
1146 + 'campaign_id' => $campaign['flexible_id'],
1147 + 'campaign_title' => $campaign['offer-title'] ?? $campaign['label-title'] ?? '',
1148 + 'campaign_status' => ( isset( $campaign['campaign_status'] ) && $campaign['campaign_status'] === 'inactive' ) ? 'inactive' : 'active',
1149 + );
1150 + }
1151 +
1152 + return $campaigns;
1153 + }
1154 +}
1155 +
1156 +if ( ! function_exists( 'merchant_get_modules_data' ) ) {
1157 + /**
1158 + * Get the data of all the modules.
1159 + *
1160 + * @return array
1161 + */
1162 + function merchant_get_modules_data() {
1163 + $modules = array();
1164 + $registered_modules = Merchant_Admin_Modules::get_modules();
1165 + foreach ( $registered_modules as $module_category => $module_data ) {
1166 + foreach ( $module_data['modules'] as $module_id => $module ) {
1167 + if ( ! empty( $module ) ) {
1168 + $modules[ $module_id ] = array(
1169 + 'id' => $module_id,
1170 + 'active' => Merchant_Modules::is_module_active( $module_id ),
1171 + 'name' => $module['title'],
1172 + 'desc' => $module['desc'],
1173 + 'category' => $module_category,
1174 + 'pro' => $module['pro'],
1175 + );
1176 +
1177 + $campaigns = merchant_get_module_campaigns_data( $module_id );
1178 +
1179 + if ( ! empty( $campaigns ) ) {
1180 + $modules[ $module_id ]['campaigns'] = $campaigns;
1181 + }
1182 + }
1183 + }
1184 + }
1185 +
1186 + return $modules;
1187 + }
1188 +}
1189 +
1190 +if ( ! function_exists( 'merchant_get_active_modules' ) ) {
1191 + /**
1192 + * Get the active modules.
1193 + *
1194 + * @return array
1195 + */
1196 + function merchant_get_active_modules() {
1197 + $modules = array_keys( merchant_get_modules_data() );
1198 +
1199 + return array_values( array_filter( $modules, static function ( $module_id ) {
1200 + return Merchant_Modules::is_module_active( $module_id );
1201 + } ) );
1202 + }
1203 +}
1204 +
1205 +if ( ! function_exists( 'merchant_get_campaign_data' ) ) {
1206 + /**
1207 + * Get the data of a specific campaign.
1208 + *
1209 + * @param string $campaign_id The ID of the campaign.
1210 + * @param string $module_id The ID of the module.
1211 + *
1212 + * @return array
1213 + */
1214 + function merchant_get_campaign_data( $campaign_id, $module_id ) {
1215 + if ( Merchant_Buy_X_Get_Y::MODULE_ID === $module_id || Merchant_Pre_Orders::MODULE_ID === $module_id ) {
1216 + $key = 'rules';
1217 + } elseif ( Merchant_Product_Labels::MODULE_ID === $module_id ) {
1218 + $key = 'labels';
1219 + } elseif ( 'buy-now' === $module_id ) {
1220 + $key = 'campaigns';
1221 + } else {
1222 + $key = 'offers';
1223 + }
1224 +
1225 + $all_modules = merchant_get_modules_data();
1226 + $module_campaigns = Merchant_Admin_Options::get( $module_id, $key, array() );
1227 + if ( ! empty( $module_campaigns ) ) {
1228 + foreach ( $module_campaigns as $campaign ) {
1229 + if ( isset( $all_modules[ $module_id ], $campaign['flexible_id'] ) && $campaign_id === $campaign['flexible_id'] ) {
1230 + return array(
1231 + 'campaign_id' => $campaign['flexible_id'],
1232 + 'campaign_title' => $campaign['offer-title'] ?? $campaign['label-title'] ?? '',
1233 + 'campaign_status' => $campaign['status'] ?? 'active',
1234 + 'module_id' => $module_id,
1235 + 'module_name' => $all_modules[ $module_id ]['name'],
1236 + 'is_pro' => $all_modules[ $module_id ]['pro'],
1237 + 'is_module_active' => $all_modules[ $module_id ]['active'],
1238 + );
1239 + }
1240 + }
1241 + }
1242 +
1243 + return array();
767 1244 }
768 1245 }