errors = []; foreach ($fields as $field) { if ($field->type === FormFieldType::LANG_SECTION) { $this->validateLangSection($data, $field, $languages ?? []); } else { $this->validateField($data, $field); } } return $this->errors; } /** * Waliduje pojedyncze pole */ private function validateField(array $data, FormField $field): void { $value = $data[$field->name] ?? null; // Walidacja wymagalności if ($field->required && $this->isEmpty($value)) { $this->errors[$field->name] = "Pole \"{$field->label}\" jest wymagane."; return; } // Jeśli pole puste i nie jest wymagane - pomijamy dalszą walidację if ($this->isEmpty($value)) { return; } // Walidacja typu switch ($field->type) { case FormFieldType::EMAIL: if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { $this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawnym adresem e-mail."; } break; case FormFieldType::NUMBER: if (!is_numeric($value)) { $this->errors[$field->name] = "Pole \"{$field->label}\" musi być liczbą."; } break; case FormFieldType::DATE: if (!$this->isValidDate($value)) { $this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawną datą (YYYY-MM-DD)."; } break; case FormFieldType::DATETIME: if (!$this->isValidDateTime($value)) { $this->errors[$field->name] = "Pole \"{$field->label}\" musi być poprawną datą i czasem."; } break; } // Walidacja customowa (callback) if (isset($field->attributes['validate_callback']) && is_callable($field->attributes['validate_callback'])) { $result = call_user_func($field->attributes['validate_callback'], $value, $data); if ($result !== true) { $this->errors[$field->name] = is_string($result) ? $result : "Pole \"{$field->label}\" zawiera nieprawidłową wartość."; } } } /** * Waliduje sekcję językową */ private function validateLangSection(array $data, FormField $section, array $languages): void { if ($section->langFields === null) { return; } foreach ($languages as $language) { if (!($language['status'] ?? false)) { continue; } $langId = $language['id']; foreach ($section->langFields as $field) { $fieldName = $field->name; $value = $data[$fieldName][$langId] ?? null; // Walidacja wymagalności if ($field->required && $this->isEmpty($value)) { $errorKey = "{$section->name}_{$fieldName}"; $this->errors[$errorKey][$langId] = "Pole \"{$field->label}\" ({$language['name']}) jest wymagane."; continue; } // Walidacja typu dla pól językowych if (!$this->isEmpty($value)) { switch ($field->type) { case FormFieldType::EMAIL: if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { $errorKey = "{$section->name}_{$fieldName}"; $this->errors[$errorKey][$langId] = "Pole \"{$field->label}\" ({$language['name']}) musi być poprawnym e-mailem."; } break; } } } } } /** * Sprawdza czy wartość jest pusta */ private function isEmpty($value): bool { return $value === null || $value === '' || (is_array($value) && empty($value)); } /** * Sprawdza czy data jest poprawna (YYYY-MM-DD) */ private function isValidDate(string $date): bool { $d = \DateTime::createFromFormat('Y-m-d', $date); return $d && $d->format('Y-m-d') === $date; } /** * Sprawdza czy data i czas są poprawne */ private function isValidDateTime(string $datetime): bool { $d = \DateTime::createFromFormat('Y-m-d H:i:s', $datetime); if ($d && $d->format('Y-m-d H:i:s') === $datetime) { return true; } // Spróbuj bez sekund $d = \DateTime::createFromFormat('Y-m-d H:i', $datetime); return $d && $d->format('Y-m-d H:i') === $datetime; } /** * Sprawdza czy walidacja zakończyła się sukcesem */ public function isValid(): bool { return empty($this->errors); } /** * Zwraca wszystkie błędy */ public function getErrors(): array { return $this->errors; } /** * Zwraca pierwszy błąd */ public function getFirstError(): ?string { if (empty($this->errors)) { return null; } $first = reset($this->errors); if (is_array($first)) { return reset($first); } return $first; } }