- SELECT * nahrazen explicitnimi sloupci ve 22 PHP souborech (69+ vyskytu) - users-handlers.php: password_hash explicitne vyloucen z dotazu - Overdue detekce presunuta do invoices.php routeru (1x pred dispatch misto 3x v handlerech) - Validator.php: validacni helper s pravidly required, string, int, email, in, numeric - PaginationHelper: PHPStan typy opraveny Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
140 lines
4.2 KiB
PHP
140 lines
4.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Validacni helper pro API vstupy.
|
|
*
|
|
* Pouziti:
|
|
* $v = new Validator($input);
|
|
* $v->required('name')->string('name', 1, 255);
|
|
* $v->required('email')->email('email');
|
|
* $v->int('amount', 0, 1000000);
|
|
* $v->in('status', ['active', 'inactive']);
|
|
* if ($v->fails()) errorResponse($v->firstError());
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
class Validator
|
|
{
|
|
/** @var array<string, mixed> */
|
|
private array $data;
|
|
|
|
/** @var array<string, string> */
|
|
private array $errors = [];
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public function __construct(array $data)
|
|
{
|
|
$this->data = $data;
|
|
}
|
|
|
|
public function required(string $field, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
$this->errors[$field] = ($label ?: $field) . ' je povinné pole';
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function string(string $field, int $min = 0, int $max = 0, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
return $this;
|
|
}
|
|
if (!is_string($value)) {
|
|
$this->errors[$field] = ($label ?: $field) . ' musí být text';
|
|
return $this;
|
|
}
|
|
$len = mb_strlen($value);
|
|
if ($min > 0 && $len < $min) {
|
|
$this->errors[$field] = ($label ?: $field) . " musí mít alespoň {$min} znaků";
|
|
} elseif ($max > 0 && $len > $max) {
|
|
$this->errors[$field] = ($label ?: $field) . " nesmí překročit {$max} znaků";
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function int(string $field, ?int $min = null, ?int $max = null, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
return $this;
|
|
}
|
|
if (!is_numeric($value)) {
|
|
$this->errors[$field] = ($label ?: $field) . ' musí být číslo';
|
|
return $this;
|
|
}
|
|
$intVal = (int) $value;
|
|
if ($min !== null && $intVal < $min) {
|
|
$this->errors[$field] = ($label ?: $field) . " musí být alespoň {$min}";
|
|
} elseif ($max !== null && $intVal > $max) {
|
|
$this->errors[$field] = ($label ?: $field) . " nesmí překročit {$max}";
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function email(string $field, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
return $this;
|
|
}
|
|
if (!is_string($value) || !filter_var($value, FILTER_VALIDATE_EMAIL)) {
|
|
$this->errors[$field] = ($label ?: $field) . ' musí být platný e-mail';
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $allowed
|
|
*/
|
|
public function in(string $field, array $allowed, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
return $this;
|
|
}
|
|
if (!in_array($value, $allowed, true)) {
|
|
$this->errors[$field] = ($label ?: $field) . ' má neplatnou hodnotu';
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function numeric(string $field, ?float $min = null, ?float $max = null, string $label = ''): self
|
|
{
|
|
$value = $this->data[$field] ?? null;
|
|
if ($value === null || $value === '') {
|
|
return $this;
|
|
}
|
|
if (!is_numeric($value)) {
|
|
$this->errors[$field] = ($label ?: $field) . ' musí být číslo';
|
|
return $this;
|
|
}
|
|
$numVal = (float) $value;
|
|
if ($min !== null && $numVal < $min) {
|
|
$this->errors[$field] = ($label ?: $field) . " musí být alespoň {$min}";
|
|
} elseif ($max !== null && $numVal > $max) {
|
|
$this->errors[$field] = ($label ?: $field) . " nesmí překročit {$max}";
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function fails(): bool
|
|
{
|
|
return count($this->errors) > 0;
|
|
}
|
|
|
|
public function firstError(): string
|
|
{
|
|
return reset($this->errors) ?: '';
|
|
}
|
|
|
|
/** @return array<string, string> */
|
|
public function errors(): array
|
|
{
|
|
return $this->errors;
|
|
}
|
|
}
|