PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.74
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.74
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 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / helpers / Theme_Builder / Conditions.php

Conditions.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.74, at includes/helpers/Theme_Builder/Conditions.php

236 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Theme Builder conditions evaluator.
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons\Theme_Builder;
9
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 /**
15 * Evaluates stored Theme Builder display conditions.
16 */
17 class Conditions
18 {
19 /**
20 * Decode and normalize saved conditions data.
21 *
22 * @param string|array<mixed> $raw Raw meta value.
23 *
24 * @return array<string,mixed>
25 */
26 public static function normalize($raw): array
27 {
28 if (is_array($raw)) {
29 return $raw;
30 }
31
32 if (is_string($raw) && !empty($raw)) {
33 $decoded = json_decode($raw, true);
34 if (is_array($decoded)) {
35 return $decoded;
36 }
37 }
38
39 return ['groups' => []];
40 }
41
42 /**
43 * Check whether a conditions set requires Pro.
44 *
45 * @param array<string,mixed> $conditions Conditions payload.
46 *
47 * @return bool
48 */
49 public static function is_pro_only(array $conditions): bool
50 {
51 $groups = $conditions['groups'] ?? [];
52 if (empty($groups)) {
53 return false;
54 }
55
56 foreach ($groups as $group) {
57 $rules = $group['rules'] ?? [];
58 foreach ($rules as $rule) {
59 $target = $rule['target'] ?? '';
60 $values = is_array($rule['value'] ?? null) ? ($rule['value'] ?? []) : [];
61
62 if (!in_array($target, self::get_free_targets(), true)) {
63 return true;
64 }
65
66 if ('post_type' === $target && array_diff($values, ['post', 'page'])) {
67 return true;
68 }
69
70 if (in_array($target, ['post_id', 'term', 'author', 'front_page', 'blog_page'], true)) {
71 return true;
72 }
73 }
74 }
75
76 return false;
77 }
78
79 /**
80 * Evaluate conditions against current context.
81 *
82 * @param array<string,mixed> $conditions Conditions payload.
83 * @param array<string,mixed> $context Request context.
84 *
85 * @return bool
86 */
87 public static function evaluate(array $conditions, array $context): bool
88 {
89 $groups = $conditions['groups'] ?? [];
90 if (empty($groups)) {
91 return true;
92 }
93
94 foreach ($groups as $group) {
95 if (self::evaluate_group($group, $context)) {
96 return true;
97 }
98 }
99
100 return false;
101 }
102
103 /**
104 * Get free-condition targets.
105 *
106 * @return array<int,string>
107 */
108 private static function get_free_targets(): array
109 {
110 return ['post_type', 'search', '404'];
111 }
112
113 /**
114 * Evaluate a single group with relation.
115 *
116 * @param array<string,mixed> $group Conditions group.
117 * @param array<string,mixed> $context Request context.
118 *
119 * @return bool
120 */
121 private static function evaluate_group(array $group, array $context): bool
122 {
123 $relation = strtoupper($group['relation'] ?? 'AND');
124 $rules = $group['rules'] ?? [];
125
126 if (empty($rules)) {
127 return true;
128 }
129
130 $results = [];
131
132 foreach ($rules as $rule) {
133 $match = self::match_rule($rule, $context);
134 $type = $rule['type'] ?? 'include';
135
136 if ('exclude' === $type) {
137 $results[] = !$match;
138 } else {
139 $results[] = $match;
140 }
141 }
142
143 if ('OR' === $relation) {
144 return in_array(true, $results, true);
145 }
146
147 return !in_array(false, $results, true);
148 }
149
150 /**
151 * Evaluate a single rule.
152 *
153 * @param array<string,mixed> $rule Rule data.
154 * @param array<string,mixed> $context Request context.
155 *
156 * @return bool
157 */
158 private static function match_rule(array $rule, array $context): bool
159 {
160 $target = $rule['target'] ?? '';
161 $values = $rule['value'] ?? [];
162 $operator = $rule['operator'] ?? 'in';
163
164 if (!is_array($values)) {
165 $values = [$values];
166 }
167
168 switch ($target) {
169 case 'post_type':
170 return self::match_in((array) ($context['post_type'] ?? null), $values, $operator);
171 case 'post_id':
172 return self::match_in([(int) ($context['post_id'] ?? 0)], array_map('intval', $values), $operator);
173 case 'term':
174 $term_id = (int) ($context['term_id'] ?? 0);
175 $taxonomy = $context['taxonomy'] ?? '';
176 $filtered = array_filter($values, static function ($item) use ($taxonomy) {
177 if (is_array($item) && isset($item['taxonomy'], $item['id'])) {
178 return $taxonomy === ($item['taxonomy'] ?? '');
179 }
180 return true;
181 });
182 $term_values = array_map(static function ($item) {
183 if (is_array($item) && isset($item['id'])) {
184 return (int) $item['id'];
185 }
186 return (int) $item;
187 }, $filtered);
188 return self::match_in([$term_id], $term_values, $operator);
189 case 'author':
190 return self::match_in([(int) ($context['author_id'] ?? 0)], array_map('intval', $values), $operator);
191 case 'front_page':
192 return !empty($context['is_front_page']);
193 case 'blog_page':
194 return !empty($context['is_blog_page']);
195 case 'search':
196 return 'search' === ($context['type'] ?? '');
197 case '404':
198 return 'not_found' === ($context['type'] ?? '');
199 default:
200 return false;
201 }
202 }
203
204 /**
205 * Match values with operator.
206 *
207 * @param array<int|string> $current Current context values.
208 * @param array<int|string> $allowed Allowed values.
209 * @param string $operator Operator string.
210 *
211 * @return bool
212 */
213 private static function match_in(array $current, array $allowed, string $operator): bool
214 {
215 $operator = strtolower($operator ?: 'in');
216 $current = array_filter($current, static fn($value) => null !== $value && '' !== $value);
217 $allowed = array_filter($allowed, static fn($value) => null !== $value && '' !== $value);
218
219 if (empty($allowed)) {
220 return false;
221 }
222
223 $intersection = array_intersect($current, $allowed);
224
225 if ('not_in' === $operator) {
226 return empty($intersection);
227 }
228
229 return !empty($intersection);
230 }
231 }
232
233
234
235
236