PluginProbe
404 Solution / 4.3.0
404 Solution v4.3.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 / view / View_RedirectConditions.php

View_RedirectConditions.php in 404 Solution 4.3.0, at includes/view/View_RedirectConditions.php

163 lines 7.0 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 class ABJ_404_Solution_View_RedirectConditions extends ABJ_404_Solution_ViewComponent {
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 * HTML is loaded from includes/html/redirectConditions*.html templates.
16 *
17 * @return void
18 */
19 public function echoRedirectConditionsSection(): void {
20 $redirectId = 0;
21 if (isset($_GET['id']) && is_scalar($_GET['id']) && $this->f->regexMatch('[0-9]+', (string)$_GET['id'])) {
22 $redirectId = absint($_GET['id']);
23 } elseif (isset($_POST['id']) && is_scalar($_POST['id']) && $this->f->regexMatch('[0-9]+', (string)$_POST['id'])) {
24 $redirectId = absint($_POST['id']);
25 }
26
27 $existingConditions = ($redirectId > 0) ? $this->redirectsRepository->getRedirectConditions($redirectId) : [];
28
29 $openTpl = $this->loadTemplate('redirectConditionsSectionOpen.html');
30 echo strtr($openTpl, [
31 '{section_label}' => esc_html__('Conditions (optional)', '404-solution'),
32 '{section_help}' => esc_html__('This redirect only fires when all conditions are met. Leave empty to always redirect.', '404-solution'),
33 ]);
34
35 foreach ($existingConditions as $i => $cond) {
36 $this->echoConditionRow($i, $cond);
37 }
38
39 $closeTpl = $this->loadTemplate('redirectConditionsSectionClose.html');
40 echo strtr($closeTpl, [
41 '{add_label}' => esc_html__('+ Add Condition', '404-solution'),
42 ]);
43
44 // Hidden template row (display:none) cloned by JS.
45 echo $this->loadTemplate('redirectConditionsRowTemplateOpen.html');
46 $this->echoConditionRow('__IDX__', []);
47 echo $this->loadTemplate('redirectConditionsRowTemplateClose.html');
48
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 public 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 $logicOptions = $this->buildOptions([
69 'AND' => __('AND', '404-solution'),
70 'OR' => __('OR', '404-solution'),
71 ], $logic);
72
73 $typeOptions = $this->buildOptions([
74 'login_status' => __('Login Status', '404-solution'),
75 'user_role' => __('User Role', '404-solution'),
76 'referrer' => __('Referrer URL', '404-solution'),
77 'user_agent' => __('User Agent', '404-solution'),
78 'ip_range' => __('IP Range (CIDR)', '404-solution'),
79 'http_header' => __('HTTP Header', '404-solution'),
80 ], $type);
81
82 $operatorOptions = $this->buildOptions([
83 'equals' => __('equals', '404-solution'),
84 'not_equals' => __('not equals', '404-solution'),
85 'contains' => __('contains', '404-solution'),
86 'not_contains' => __('does not contain', '404-solution'),
87 'regex' => __('matches regex', '404-solution'),
88 ], $operator);
89
90 $rowTpl = $this->loadTemplate('redirectConditionRow.html');
91 echo strtr($rowTpl, [
92 '{index}' => esc_attr((string)$index),
93 '{name_prefix}' => esc_attr($namePrefix),
94 '{logic_aria}' => esc_attr__('Logic', '404-solution'),
95 '{logic_options}' => $logicOptions,
96 '{type_aria}' => esc_attr__('Condition type', '404-solution'),
97 // allow-em-dash: preserving translated placeholder label.
98 '{type_placeholder}' => esc_html__('— Select type —', '404-solution'),
99 '{type_options}' => $typeOptions,
100 '{operator_aria}' => esc_attr__('Operator', '404-solution'),
101 '{operator_options}' => $operatorOptions,
102 '{value}' => esc_attr($value),
103 '{value_placeholder}' => esc_attr__('Value', '404-solution'),
104 '{value_aria}' => esc_attr__('Condition value', '404-solution'),
105 '{sort_order}' => esc_attr((string)$sortOrder),
106 '{remove_aria}' => esc_attr__('Remove condition', '404-solution'),
107 '{remove_label}' => esc_html__('Remove', '404-solution'),
108 ]);
109 }
110
111 /**
112 * Build the inner <option> markup for a <select>.
113 *
114 * @param array<string, string> $options value => translated label map.
115 * @param string $selected Currently selected value.
116 * @return string Concatenated <option> HTML.
117 */
118 private function buildOptions(array $options, string $selected): string {
119 $tpl = $this->loadTemplate('redirectConditionOption.html');
120 $out = '';
121 foreach ($options as $val => $label) {
122 $out .= strtr($tpl, [
123 '{value}' => esc_attr((string)$val),
124 '{selected}' => ((string)$val === $selected) ? ' selected' : '',
125 '{label}' => esc_html((string)$label),
126 ]);
127 }
128 return $out;
129 }
130
131 /**
132 * Output inline JavaScript that manages dynamic condition rows.
133 *
134 * @return void
135 */
136 public function echoConditionsJavaScript(): void {
137 $redirectId = 0;
138 if (isset($_GET['id']) && is_scalar($_GET['id']) && ctype_digit((string)$_GET['id'])) {
139 $redirectId = (int)$_GET['id'];
140 } elseif (isset($_POST['id']) && is_scalar($_POST['id']) && ctype_digit((string)$_POST['id'])) {
141 $redirectId = (int)$_POST['id'];
142 }
143 $initialIndex = ($redirectId > 0) ? max(1, count($this->redirectsRepository->getRedirectConditions($redirectId))) : 1;
144
145 $tpl = $this->loadTemplate('redirectConditionsScript.html');
146 echo strtr($tpl, [
147 '{initial_index}' => (string)(int)$initialIndex,
148 ]);
149 }
150
151 /**
152 * Read an HTML template from includes/html/.
153 *
154 * @param string $filename Template filename relative to includes/html/.
155 * @return string Template contents.
156 */
157 private function loadTemplate(string $filename): string {
158 return ABJ_404_Solution_FileSystemService::readFileContents(
159 dirname(__DIR__) . '/html/' . $filename
160 );
161 }
162 }
163