PluginProbe
PostNL for WooCommerce / 4.4.1
PostNL for WooCommerce v4.4.1
5.9.12 5.9.11 5.9.10 5.9.9 5.9.8 5.9.7 5.9.6 trunk 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 3.1.4 3.1.5 3.1.6 3.1.7 4.0.0 4.0.1 4.0.2 4.3.2 4.3.3 4.4.0 4.4.1 All 72 releases
woo-postnl / includes / entities / settings-field-arguments.php

settings-field-arguments.php in PostNL for WooCommerce 4.4.1, at includes/entities/settings-field-arguments.php

533 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPO\WC\PostNL\Entity;
4
5 use MyParcelNL\Sdk\src\Support\Arr;
6 use WCPN_Settings_Data;
7
8 defined('ABSPATH') or exit;
9
10 if (class_exists('\\WPO\\WC\\PostNL\\Entity\\SettingsFieldArguments')) {
11 return;
12 }
13
14 class SettingsFieldArguments
15 {
16 private const CONDITION_DEFAULTS = [
17 "type" => "show",
18 "set_value" => null,
19 ];
20
21 public const IGNORED_ARGUMENTS = [
22 "callback",
23 "condition",
24 "default",
25 "id",
26 "label",
27 "loop",
28 "name",
29 "type",
30 ];
31
32 public const ALTERNATIVE_IGNORED_ARGUMENTS = [
33 "callback",
34 "condition",
35 "default",
36 "type",
37 ];
38
39 public const ALLOWED_ARGUMENTS = [
40 "append",
41 "autocomplete",
42 "autofocus",
43 "class",
44 "custom_attributes",
45 "description",
46 "help_text",
47 "id",
48 "input_class",
49 "label",
50 "label_class",
51 "maxlength",
52 "options",
53 "placeholder",
54 "priority",
55 "required",
56 "return",
57 "type",
58 "validate",
59 ];
60
61 /**
62 * @var array
63 */
64 private $input;
65
66 /**
67 * @var string
68 */
69 private $prefix;
70
71 /**
72 * @var string
73 */
74 private $type;
75
76 /**
77 * @var mixed
78 */
79 private $name;
80
81 /**
82 * @var mixed
83 */
84 private $id;
85
86 /**
87 * @var array
88 */
89 private $arguments = [];
90
91 /**
92 * @var array
93 */
94 private $defaults = [
95 "type" => "text",
96 "class" => [],
97 "input_class" => [],
98 "label_class" => [],
99 ];
100
101 /**
102 * @var string|null
103 */
104 private $description;
105
106 /**
107 * @var mixed
108 */
109 private $value;
110
111 /**
112 * @var string
113 */
114 private $default;
115
116 /**
117 * @var string
118 */
119 private $suffix;
120
121 /**
122 * SettingsFieldArguments constructor.
123 *
124 * @param array $args - The setting's arguments.
125 * @param string $prefix - Optional prefix for name and conditions.
126 * @param string $suffix - Optional suffix for name and conditions.
127 *
128 * @throws \Exception
129 */
130 public function __construct(array $args, string $prefix = '' , string $suffix = '')
131 {
132 $this->input = $args;
133 $this->prefix = $prefix;
134 $this->suffix = $suffix;
135
136 $this->name = $this->wrap($this->getInputArgument("name"));
137 $this->id = $this->getInputArgument("id") ?? $this->name;
138 $this->description = $this->getInputArgument("description");
139
140 $this->setClass();
141 $this->setType();
142 $this->setDefault();
143 $this->setConditions();
144
145 $this->setArguments($this->input);
146 }
147
148 private function setType(): void
149 {
150 $type = $this->getInputArgument("type");
151
152 switch ($type) {
153 case "number":
154 $this->addArgument("min", 0);
155 $this->addArgument("step", 1);
156 break;
157 case "currency":
158 $type = "number";
159 $this->addArgument("step", 0.01);
160 $this->addArgument("placeholder", "0,00");
161 break;
162 case "toggle":
163 $type = "select";
164
165 $this->addArgument("data-type", "toggle");
166 $this->addArgument(
167 "options",
168 [
169 "1" => __("Enabled", "woocommerce-postnl"),
170 "0" => __("Disabled", "woocommerce-postnl"),
171 ]
172 );
173 break;
174 case "select":
175 $this->addArgument("options", $this->getInputArgument("options") ?? []);
176 break;
177 }
178
179 $this->type = $type;
180 }
181
182 private function setClass(): void
183 {
184 $arr = [
185 "class" => $this->getInputArgument("class"),
186 "input_class" => $this->getInputArgument("input_class"),
187 "label_class" => $this->getInputArgument("label_class"),
188 ];
189
190 foreach ($arr as $class => $value) {
191 if ($value) {
192 $this->addArgument($class, is_array($value) ? $value : [$value]);
193 }
194 }
195 }
196
197 /**
198 * If the setting has conditions set up the attributes so the JS can use them. Supports strings, arrays of
199 * strings and associative arrays.
200 */
201 private function setConditions(): void
202 {
203 $conditionArgument = $this->getInputArgument("condition");
204 $conditions = [];
205
206 if (! $conditionArgument) {
207 return;
208 }
209
210 if (!is_array($conditionArgument) || Arr::isAssoc($conditionArgument)) {
211 $conditions[] = $conditionArgument;
212 } else {
213 $conditions = $conditionArgument;
214 }
215
216 $conditionData = array_map([$this, "createCondition"], $conditions);
217 $conditionData = $this->mergeConditions($conditionData);
218
219 $this->addArgument("data-conditions", $conditionData);
220 }
221
222 /**
223 * @param string $name
224 *
225 * @return mixed|null
226 */
227 public function getInputArgument(string $name)
228 {
229 return $this->input[$name] ?? $this->defaults[$name] ?? null;
230 }
231
232 /**
233 * @param string $name
234 *
235 * @return mixed
236 */
237 public function getArgument(string $name)
238 {
239 return $this->arguments[$name] ?? null;
240 }
241
242 /**
243 * Return the arguments formatted for woocommerce_form_field()
244 *
245 * @param bool $ignore
246 *
247 * @return array
248 * @see \woocommerce_form_field
249 */
250 public function getArguments(bool $ignore = true): array
251 {
252 $arguments = [
253 "id" => $this->id,
254 "type" => $this->type,
255 ];
256
257 foreach ($this->arguments as $arg => $value) {
258 $ignoredArguments = $ignore ? self::IGNORED_ARGUMENTS : self::ALTERNATIVE_IGNORED_ARGUMENTS;
259
260 if (in_array($arg, $ignoredArguments)) {
261 continue;
262 }
263
264 if (in_array($arg, self::ALLOWED_ARGUMENTS)) {
265 if (array_key_exists($arg, $arguments)) {
266 $arguments[$arg] = array_replace_recursive(
267 $arguments[$arg],
268 $value
269 );
270 } else {
271 $arguments[$arg] = $value;
272 }
273 } else {
274 if (! isset($arguments["custom_attributes"])) {
275 $arguments["custom_attributes"] = [];
276 }
277
278 if (is_array($value)) {
279 $value = htmlspecialchars(json_encode($value));
280 }
281
282 $arguments["custom_attributes"][$arg] = $value;
283 }
284 }
285
286 return $arguments;
287 }
288
289 /**
290 * Get the custom attributes as a string for use in HTML.
291 *
292 * @return string
293 */
294 public function getCustomAttributesAsString(): string
295 {
296 $attributes = [];
297
298 foreach ($this->getCustomAttributes() ?? [] as $att => $value) {
299 $attributes[] = "$att=\"$value\"";
300 }
301
302 return implode(" ", $attributes);
303 }
304
305 /**
306 * @return array
307 */
308 public function getCustomAttributes(): array
309 {
310 $arguments = $this->getArguments();
311 return $arguments['custom_attributes'] ?? [];
312 }
313
314 /**
315 * Add an argument by key => value.
316 *
317 * @param string $key
318 * @param $value
319 */
320 private function addArgument(string $key, $value): void
321 {
322 $this->setArguments([$key => $value]);
323 }
324
325 /**
326 * @param array $args
327 */
328 private function setArguments(array $args): void
329 {
330 foreach ($args as $arg => $value) {
331 $this->arguments[$arg] = $value;
332 }
333 }
334
335 /**
336 * Set default arguments based on the type.
337 */
338 private function setDefault(): void
339 {
340 if (isset($this->input["default"])) {
341 $this->default = $this->input["default"];
342 return;
343 }
344
345 if (isset($this->input["type"]) && $this->input["type"] === "toggle") {
346 $this->default = "0";
347 return;
348 }
349
350 switch ($this->type) {
351 case "number":
352 $this->default = 0;
353 break;
354 case "text":
355 case "textarea":
356 $this->default = "";
357 break;
358 case "select":
359 // Set first option as default value.
360 if ($this->arguments["options"]) {
361 $this->default = Arr::first($this->arguments["options"]);
362 } else {
363 $this->addArgument("options", []);
364 }
365 break;
366 }
367 }
368
369 /**
370 * @return string
371 */
372 public function getType(): string
373 {
374 return $this->type;
375 }
376
377 /**
378 * @return mixed
379 */
380 public function getName()
381 {
382 return $this->name;
383 }
384
385 /**
386 * @return mixed
387 */
388 public function getId()
389 {
390 return $this->id;
391 }
392
393 /**
394 * @return array
395 */
396 public function getDefaults(): array
397 {
398 return $this->defaults;
399 }
400
401 /**
402 * @return string
403 */
404 public function getDescription(): ?string
405 {
406 return $this->description;
407 }
408
409 /**
410 * @return mixed
411 */
412 public function getValue()
413 {
414 return $this->value;
415 }
416
417 /**
418 * @return mixed
419 */
420 public function getDefault()
421 {
422 return $this->default;
423 }
424
425 /**
426 * @param string $id
427 */
428 public function setId(string $id): void
429 {
430 $this->id = $id;
431 }
432
433 /**
434 * @param mixed $name
435 */
436 public function setName($name): void
437 {
438 $this->name = $name;
439 }
440
441 /**
442 * @param $value
443 */
444 public function setValue($value): void
445 {
446 $this->value = $value;
447 }
448
449 /**
450 * @param string|array $condition
451 *
452 * @return array
453 */
454 private function createCondition($condition): array
455 {
456 if (is_array($condition)) {
457 $parentName = $this->wrap($condition['parent_name']);
458 $parentValue = $condition['parent_value'] ?? WCPN_Settings_Data::ENABLED;
459
460 $condition['parents'] = [
461 $parentName => $parentValue,
462 ];
463
464 unset($condition['parent_name']);
465 unset($condition['parent_value']);
466
467 $newCondition = array_replace_recursive(
468 self::CONDITION_DEFAULTS,
469 $condition
470 );
471 } else {
472 $parentName = $this->wrap($condition);
473 $newCondition = array_merge(
474 self::CONDITION_DEFAULTS,
475 [
476 "parents" => [
477 $parentName => WCPN_Settings_Data::ENABLED,
478 ],
479 ]
480 );
481 }
482
483 return $newCondition;
484 }
485
486 /**
487 * @param string|null $text
488 *
489 * @return string
490 */
491 private function wrap(?string $text): ?string
492 {
493 if (! $text) {
494 return null;
495 }
496
497 return $this->prefix . $text . $this->suffix;
498 }
499
500 /**
501 * Merge multiple matching conditions (if their `type` and `set_value` are the same) into one condition, combining
502 * all `parents` properties.
503 *
504 * @param array $conditionData
505 *
506 * @return array
507 */
508 private function mergeConditions(array $conditionData): array
509 {
510 $mergedConditions = [];
511
512 foreach ($conditionData as $condition) {
513 foreach ($mergedConditions as $key => $mergedCondition) {
514 $typeMatches = $mergedCondition['type'] === $condition['type'];
515
516 if ($typeMatches) {
517 $mergedConditions[$key]['parents'] = array_merge(
518 $mergedCondition['parents'],
519 $condition['parents']
520 );
521
522 // Continue the outer loop as well
523 continue 2;
524 }
525 }
526
527 $mergedConditions[] = $condition;
528 }
529
530 return $mergedConditions;
531 }
532 }
533