> */ private $conditions; /** @var int */ private $droppedOverMaximum; /** * @param array> $conditions Sanitized conditions, in submitted order. * @param int $droppedOverMaximum How many valid-looking conditions were cut for arriving past the cap. */ private function __construct(array $conditions, int $droppedOverMaximum) { $this->conditions = $conditions; $this->droppedOverMaximum = $droppedOverMaximum; } /** * Sanitize the conditions[] POST payload into the shape redirectsRepo * accepts. Whitelists condition types and operators; coerces logic to * AND/OR. * * @param array $rawConditions The raw conditions[] array from the request. * @return self */ public static function fromRawConditions(array $rawConditions): self { // Enforce the domain maximum before sanitizing/inserting, rather than // rejecting the entire edit over an oversized payload: the rest of the // save is the admin's real work and is valid. $droppedOverMaximum = max(0, count($rawConditions) - self::MAX_CONDITIONS); if ($droppedOverMaximum > 0) { $rawConditions = array_slice($rawConditions, 0, self::MAX_CONDITIONS); } $sanitizedConditions = []; $allowedConditionTypes = [ 'login_status', 'user_role', 'referrer', 'user_agent', 'ip_range', 'http_header', ]; $allowedOperators = [ 'equals', 'not_equals', 'contains', 'not_contains', 'regex', 'cidr', ]; foreach ($rawConditions as $rawCond) { if (!is_array($rawCond)) { continue; } $condType = isset($rawCond['condition_type']) && is_string($rawCond['condition_type']) ? sanitize_text_field($rawCond['condition_type']) : ''; if (!in_array($condType, $allowedConditionTypes, true)) { continue; } $condLogic = (isset($rawCond['logic']) && is_string($rawCond['logic']) && strtoupper($rawCond['logic']) === 'OR') ? 'OR' : 'AND'; $condOperator = isset($rawCond['operator']) && is_string($rawCond['operator']) ? sanitize_text_field($rawCond['operator']) : 'equals'; if (!in_array($condOperator, $allowedOperators, true)) { $condOperator = 'equals'; } $condValue = isset($rawCond['value']) && is_string($rawCond['value']) ? sanitize_text_field(wp_unslash($rawCond['value'])) : ''; $condSortOrder = isset($rawCond['sort_order']) && is_scalar($rawCond['sort_order']) ? absint($rawCond['sort_order']) : 0; $sanitizedConditions[] = [ 'logic' => $condLogic, 'condition_type' => $condType, 'operator' => $condOperator, 'value' => $condValue, 'sort_order' => $condSortOrder, ]; } return new self($sanitizedConditions, $droppedOverMaximum); } /** @return array> The conditions to save, in submitted order. */ public function conditions(): array { return $this->conditions; } /** @return int How many valid conditions were not kept because they arrived past MAX_CONDITIONS. */ public function droppedOverMaximum(): int { return $this->droppedOverMaximum; } }