PluginProbe
404 Solution / 4.2.0
404 Solution v4.2.0
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / ViewTrait_RedirectConditions.php

ViewTrait_RedirectConditions.php in 404 Solution 4.2.0, at includes/ViewTrait_RedirectConditions.php

176 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 trait ViewTrait_RedirectConditions {
8
9 /**
10 * Render the Conditions section on the Edit Redirect page.
11 *
12 * Reads the current redirect ID from GET/POST so existing conditions can
13 * be pre-populated. New redirects (id = 0) render an empty container.
14 *
15 * @return void
16 */
17 private function echoRedirectConditionsSection(): void {
18 $redirectId = 0;
19 if (isset($_GET['id']) && $this->f->regexMatch('[0-9]+', (string)$_GET['id'])) {
20 $redirectId = absint($_GET['id']);
21 } elseif (isset($_POST['id']) && $this->f->regexMatch('[0-9]+', (string)$_POST['id'])) {
22 $redirectId = absint($_POST['id']);
23 }
24
25 $existingConditions = ($redirectId > 0) ? $this->redirectsRepository->getRedirectConditions($redirectId) : [];
26
27 echo '<div class="abj404-form-group abj404-conditions-section">';
28 echo '<h4>' . esc_html__('Conditions (optional)', '404-solution') . '</h4>';
29 echo '<p class="abj404-form-help">' . esc_html__('This redirect only fires when all conditions are met. Leave empty to always redirect.', '404-solution') . '</p>';
30
31 echo '<div id="abj404-conditions-container">';
32 foreach ($existingConditions as $i => $cond) {
33 $this->echoConditionRow($i, $cond);
34 }
35 echo '</div>';
36
37 echo '<button type="button" onclick="abj404AddConditionRow()" class="button abj404-btn-add-condition">'
38 . esc_html__('+ Add Condition', '404-solution')
39 . '</button>';
40
41 echo '</div>';
42
43 // Hidden template row (display:none) cloned by JS.
44 echo '<script type="text/template" id="abj404-condition-row-template">';
45 $this->echoConditionRow('__IDX__', []);
46 echo '</script>';
47
48 // Inline JS for dynamic condition rows.
49 $this->echoConditionsJavaScript();
50 }
51
52 /**
53 * Render a single condition row.
54 *
55 * @param int|string $index Row index (used in field names).
56 * @param array<string, mixed> $cond Existing condition data (empty = defaults).
57 * @return void
58 */
59 private function echoConditionRow($index, array $cond): void {
60 $logic = isset($cond['logic']) && is_string($cond['logic']) ? $cond['logic'] : 'AND';
61 $type = isset($cond['condition_type']) && is_string($cond['condition_type']) ? $cond['condition_type'] : '';
62 $operator = isset($cond['operator']) && is_string($cond['operator']) ? $cond['operator'] : 'equals';
63 $value = isset($cond['value']) && is_string($cond['value']) ? $cond['value'] : '';
64 $sortOrder = isset($cond['sort_order']) && is_scalar($cond['sort_order']) ? (int)$cond['sort_order'] : (int)$index;
65
66 $namePrefix = 'conditions[' . $index . ']';
67
68 echo '<div class="abj404-condition-row" data-index="' . esc_attr((string)$index) . '">';
69
70 // Logic (AND / OR) — shown only on rows after the first.
71 echo '<select name="' . esc_attr($namePrefix . '[logic]') . '" class="abj404-condition-logic" aria-label="' . esc_attr__('Logic', '404-solution') . '">';
72 foreach (['AND' => __('AND', '404-solution'), 'OR' => __('OR', '404-solution')] as $logicVal => $logicLabel) {
73 $sel = ($logic === $logicVal) ? ' selected' : '';
74 echo '<option value="' . esc_attr($logicVal) . '"' . $sel . '>' . esc_html($logicLabel) . '</option>';
75 }
76 echo '</select>';
77
78 // Condition type.
79 $typeOptions = [
80 'login_status' => __('Login Status', '404-solution'),
81 'user_role' => __('User Role', '404-solution'),
82 'referrer' => __('Referrer URL', '404-solution'),
83 'user_agent' => __('User Agent', '404-solution'),
84 'ip_range' => __('IP Range (CIDR)', '404-solution'),
85 'http_header' => __('HTTP Header', '404-solution'),
86 ];
87 echo '<select name="' . esc_attr($namePrefix . '[condition_type]') . '" class="abj404-condition-type" aria-label="' . esc_attr__('Condition type', '404-solution') . '">';
88 echo '<option value="">' . esc_html__('— Select type —', '404-solution') . '</option>';
89 foreach ($typeOptions as $typeVal => $typeLabel) {
90 $sel = ($type === $typeVal) ? ' selected' : '';
91 echo '<option value="' . esc_attr($typeVal) . '"' . $sel . '>' . esc_html($typeLabel) . '</option>';
92 }
93 echo '</select>';
94
95 // Operator.
96 $operatorOptions = [
97 'equals' => __('equals', '404-solution'),
98 'not_equals' => __('not equals', '404-solution'),
99 'contains' => __('contains', '404-solution'),
100 'not_contains' => __('does not contain', '404-solution'),
101 'regex' => __('matches regex', '404-solution'),
102 ];
103 echo '<select name="' . esc_attr($namePrefix . '[operator]') . '" class="abj404-condition-operator" aria-label="' . esc_attr__('Operator', '404-solution') . '">';
104 foreach ($operatorOptions as $opVal => $opLabel) {
105 $sel = ($operator === $opVal) ? ' selected' : '';
106 echo '<option value="' . esc_attr($opVal) . '"' . $sel . '>' . esc_html($opLabel) . '</option>';
107 }
108 echo '</select>';
109
110 // Value input.
111 echo '<input type="text" name="' . esc_attr($namePrefix . '[value]') . '" class="abj404-condition-value abj404-form-input" value="' . esc_attr($value) . '" placeholder="' . esc_attr__('Value', '404-solution') . '" aria-label="' . esc_attr__('Condition value', '404-solution') . '">';
112
113 // Sort order (hidden).
114 echo '<input type="hidden" name="' . esc_attr($namePrefix . '[sort_order]') . '" class="abj404-condition-sort-order" value="' . esc_attr((string)$sortOrder) . '">';
115
116 // Remove button.
117 echo '<button type="button" class="button abj404-remove-condition" onclick="abj404RemoveConditionRow(this)" aria-label="' . esc_attr__('Remove condition', '404-solution') . '">'
118 . esc_html__('Remove', '404-solution')
119 . '</button>';
120
121 echo '</div>';
122 }
123
124 /**
125 * Output inline JavaScript that manages dynamic condition rows.
126 *
127 * @return void
128 */
129 private function echoConditionsJavaScript(): void {
130 $redirectId = 0;
131 if (isset($_GET['id']) && is_scalar($_GET['id']) && ctype_digit((string)$_GET['id'])) {
132 $redirectId = (int)$_GET['id'];
133 } elseif (isset($_POST['id']) && is_scalar($_POST['id']) && ctype_digit((string)$_POST['id'])) {
134 $redirectId = (int)$_POST['id'];
135 }
136 $initialIndex = ($redirectId > 0) ? max(1, count($this->redirectsRepository->getRedirectConditions($redirectId))) : 1;
137
138 echo '<script type="text/javascript">' . "\n";
139 echo '(function() {' . "\n";
140 echo ' var abj404ConditionIndex = ' . (int)$initialIndex . ';' . "\n";
141 echo "\n";
142 echo ' window.abj404AddConditionRow = function() {' . "\n";
143 echo ' var template = document.getElementById(\'abj404-condition-row-template\');' . "\n";
144 echo ' if (!template) { return; }' . "\n";
145 echo ' var html = template.innerHTML.replace(/__IDX__/g, String(abj404ConditionIndex));' . "\n";
146 echo ' var container = document.getElementById(\'abj404-conditions-container\');' . "\n";
147 echo ' if (!container) { return; }' . "\n";
148 echo ' var div = document.createElement(\'div\');' . "\n";
149 echo ' div.innerHTML = html;' . "\n";
150 echo ' while (div.firstChild) {' . "\n";
151 echo ' container.appendChild(div.firstChild);' . "\n";
152 echo ' }' . "\n";
153 echo ' abj404UpdateConditionSortOrders();' . "\n";
154 echo ' abj404ConditionIndex++;' . "\n";
155 echo ' };' . "\n";
156 echo "\n";
157 echo ' window.abj404RemoveConditionRow = function(btn) {' . "\n";
158 echo ' var row = btn.closest(\'.abj404-condition-row\');' . "\n";
159 echo ' if (row) {' . "\n";
160 echo ' row.parentNode.removeChild(row);' . "\n";
161 echo ' abj404UpdateConditionSortOrders();' . "\n";
162 echo ' }' . "\n";
163 echo ' };' . "\n";
164 echo "\n";
165 echo ' function abj404UpdateConditionSortOrders() {' . "\n";
166 echo ' var rows = document.querySelectorAll(\'#abj404-conditions-container .abj404-condition-row\');' . "\n";
167 echo ' for (var i = 0; i < rows.length; i++) {' . "\n";
168 echo ' var so = rows[i].querySelector(\'.abj404-condition-sort-order\');' . "\n";
169 echo ' if (so) { so.value = String(i); }' . "\n";
170 echo ' }' . "\n";
171 echo ' }' . "\n";
172 echo '}());' . "\n";
173 echo '</script>' . "\n";
174 }
175 }
176