PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.44
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.44
51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 All 40 releases
king-addons / includes / helpers / Woo_Builder / Context.php

Context.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.44, at includes/helpers/Woo_Builder/Context.php

219 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Woo Builder context helpers.
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons\Woo_Builder;
9
10 use WC_Product;
11
12 if (!defined('ABSPATH')) {
13 exit;
14 }
15
16 /**
17 * Utility helpers for Woo Builder.
18 */
19 class Context
20 {
21 /**
22 * Detect current WooCommerce context.
23 *
24 * Cart, Checkout, and My Account pages may not pass is_woocommerce()
25 * so we check them separately.
26 *
27 * @return string|null
28 */
29 public static function detect_context(): ?string
30 {
31 if (!function_exists('is_woocommerce')) {
32 return null;
33 }
34
35 // Check cart page first (may not pass is_woocommerce())
36 if (function_exists('is_cart') && is_cart()) {
37 return 'cart';
38 }
39
40 // Check checkout page (may not pass is_woocommerce())
41 if (function_exists('is_checkout') && is_checkout() && !is_order_received_page()) {
42 return 'checkout';
43 }
44
45 // Check My Account page (may not pass is_woocommerce())
46 if (function_exists('is_account_page') && is_account_page()) {
47 return 'my_account';
48 }
49
50 // For product and archive pages, is_woocommerce() should be true
51 if (!is_woocommerce()) {
52 return null;
53 }
54
55 if (is_product()) {
56 return 'single_product';
57 }
58
59 if (is_shop() || is_product_category() || is_product_tag() || is_product_taxonomy()) {
60 return 'product_archive';
61 }
62
63 return null;
64 }
65
66 /**
67 * Get current product ID.
68 *
69 * @return int|null
70 */
71 public static function get_product_id(): ?int
72 {
73 global $product, $post;
74
75 if ($product instanceof WC_Product) {
76 return (int) $product->get_id();
77 }
78
79 if (!empty($post->ID) && 'product' === get_post_type($post->ID)) {
80 return (int) $post->ID;
81 }
82
83 return null;
84 }
85
86 /**
87 * Match conditions array against current page context.
88 *
89 * @param string $context Page context.
90 * @param array<string,mixed> $conditions Conditions array.
91 *
92 * @return bool
93 */
94 public static function match_conditions(string $context, array $conditions): bool
95 {
96 if (empty($conditions['rules']) || !is_array($conditions['rules'])) {
97 return true;
98 }
99
100 $product_id = self::get_product_id();
101
102 foreach ($conditions['rules'] as $rule) {
103 $type = $rule['type'] ?? '';
104 $values = is_array($rule['values'] ?? null) ? $rule['values'] : [];
105
106 if (!self::match_rule($context, $type, $values, $product_id)) {
107 return false;
108 }
109 }
110
111 return true;
112 }
113
114 /**
115 * Match a single rule.
116 *
117 * @param string $context Context.
118 * @param string $type Rule type.
119 * @param array $values Rule values.
120 * @param int|null $product_id Product ID.
121 *
122 * @return bool
123 */
124 private static function match_rule(string $context, string $type, array $values, ?int $product_id): bool
125 {
126 switch ($type) {
127 case 'all_products':
128 return 'single_product' === $context;
129 case 'product_in':
130 case 'products':
131 return ('single_product' === $context && $product_id && in_array($product_id, $values, true));
132 case 'product_cat_in':
133 case 'product_categories':
134 if ('single_product' !== $context || !$product_id) {
135 return false;
136 }
137 $terms = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'ids']);
138 return !empty(array_intersect($values, $terms));
139 case 'product_tag_in':
140 case 'product_tags':
141 if ('single_product' !== $context || !$product_id) {
142 return false;
143 }
144 $terms = wp_get_post_terms($product_id, 'product_tag', ['fields' => 'ids']);
145 return !empty(array_intersect($values, $terms));
146 case 'product_type_in':
147 case 'product_types':
148 if ('single_product' !== $context || !$product_id) {
149 return false;
150 }
151 $types = wp_get_object_terms($product_id, 'product_type', ['fields' => 'slugs']);
152 return !empty(array_intersect($values, $types));
153 case 'is_shop':
154 case 'shop':
155 return 'product_archive' === $context && is_shop();
156 case 'product_cat_archive_in':
157 case 'product_cat_archives':
158 if ('product_archive' !== $context) {
159 return false;
160 }
161 if (is_product_category()) {
162 $term = get_queried_object();
163 if (!empty($term->term_id)) {
164 return in_array((int) $term->term_id, $values, true);
165 }
166 }
167 return false;
168 case 'cart':
169 return 'cart' === $context;
170 case 'checkout':
171 return 'checkout' === $context;
172 case 'my_account':
173 return 'my_account' === $context;
174 case 'always':
175 return true;
176 default:
177 return true;
178 }
179 }
180
181 /**
182 * Render an editor-only notice if widget is not in the expected Woo context.
183 *
184 * @param string $expected_context Expected context slug.
185 *
186 * @return bool True when context matches or not in edit mode, false when notice rendered.
187 */
188 public static function maybe_render_context_notice(string $expected_context): bool
189 {
190 if (!class_exists('\Elementor\Plugin') || !\Elementor\Plugin::$instance->editor->is_edit_mode()) {
191 return true;
192 }
193
194 $current = self::detect_context();
195 if ($current === $expected_context) {
196 return true;
197 }
198
199 $labels = [
200 'single_product' => esc_html__('This widget works on Single Product pages.', 'king-addons'),
201 'product_archive' => esc_html__('This widget works on Product Archive pages.', 'king-addons'),
202 'cart' => esc_html__('This widget works on the Cart page.', 'king-addons'),
203 'checkout' => esc_html__('This widget works on the Checkout page.', 'king-addons'),
204 'my_account' => esc_html__('This widget works on My Account pages.', 'king-addons'),
205 ];
206
207 $message = $labels[$expected_context] ?? esc_html__('This widget is only available on WooCommerce pages.', 'king-addons');
208 echo '<div class="king-addons-woo-builder-notice">' . esc_html($message) . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
209 return false;
210 }
211 }
212
213
214
215
216
217
218
219