f->regexMatch('[0-9]+', (string)$getId)) { $redirectId = absint($getId); } elseif (is_scalar($postId) && $this->f->regexMatch('[0-9]+', (string)$postId)) { $redirectId = absint($postId); } $existingConditions = ($redirectId > 0) ? $this->redirectsRepository->getRedirectConditions($redirectId) : []; $openTpl = $this->loadTemplate('redirectConditionsSectionOpen.html'); echo strtr($openTpl, [ '{section_label}' => esc_html__('Conditions (optional)', '404-solution'), '{section_help}' => esc_html__('This redirect only fires when all conditions are met. Leave empty to always redirect.', '404-solution'), ]); foreach ($existingConditions as $i => $cond) { $this->echoConditionRow($i, $cond); } $closeTpl = $this->loadTemplate('redirectConditionsSectionClose.html'); echo strtr($closeTpl, [ '{add_label}' => esc_html__('+ Add Condition', '404-solution'), ]); // Hidden template row (display:none) cloned by JS. echo $this->loadTemplate('redirectConditionsRowTemplateOpen.html'); $this->echoConditionRow('__IDX__', []); echo $this->loadTemplate('redirectConditionsRowTemplateClose.html'); $this->echoConditionsJavaScript(); } /** * Render a single condition row. * * @param int|string $index Row index (used in field names). * @param array $cond Existing condition data (empty = defaults). * @return void */ public function echoConditionRow($index, array $cond): void { $logic = isset($cond['logic']) && is_string($cond['logic']) ? $cond['logic'] : 'AND'; $type = isset($cond['condition_type']) && is_string($cond['condition_type']) ? $cond['condition_type'] : ''; $operator = isset($cond['operator']) && is_string($cond['operator']) ? $cond['operator'] : 'equals'; $value = isset($cond['value']) && is_string($cond['value']) ? $cond['value'] : ''; $sortOrder = isset($cond['sort_order']) && is_scalar($cond['sort_order']) ? (int)$cond['sort_order'] : (int)$index; $namePrefix = 'conditions[' . $index . ']'; $logicOptions = $this->buildOptions([ 'AND' => __('AND', '404-solution'), 'OR' => __('OR', '404-solution'), ], $logic); $typeOptions = $this->buildOptions([ 'login_status' => __('Login Status', '404-solution'), 'user_role' => __('User Role', '404-solution'), 'referrer' => __('Referrer URL', '404-solution'), 'user_agent' => __('User Agent', '404-solution'), 'ip_range' => __('IP Range (CIDR)', '404-solution'), 'http_header' => __('HTTP Header', '404-solution'), ], $type); $operatorOptions = $this->buildOptions([ 'equals' => __('equals', '404-solution'), 'not_equals' => __('not equals', '404-solution'), 'contains' => __('contains', '404-solution'), 'not_contains' => __('does not contain', '404-solution'), 'regex' => __('matches regex', '404-solution'), ], $operator); $rowTpl = $this->loadTemplate('redirectConditionRow.html'); echo strtr($rowTpl, [ '{index}' => esc_attr((string)$index), '{name_prefix}' => esc_attr($namePrefix), '{logic_aria}' => esc_attr__('Logic', '404-solution'), '{logic_options}' => $logicOptions, '{type_aria}' => esc_attr__('Condition type', '404-solution'), // allow-em-dash: preserving translated placeholder label. '{type_placeholder}' => esc_html__('— Select type —', '404-solution'), '{type_options}' => $typeOptions, '{operator_aria}' => esc_attr__('Operator', '404-solution'), '{operator_options}' => $operatorOptions, '{value}' => esc_attr($value), '{value_placeholder}' => esc_attr__('Value', '404-solution'), '{value_aria}' => esc_attr__('Condition value', '404-solution'), '{sort_order}' => esc_attr((string)$sortOrder), '{remove_aria}' => esc_attr__('Remove condition', '404-solution'), '{remove_label}' => esc_html__('Remove', '404-solution'), ]); } /** * Build the inner