Files
hado/core/app/Ingest/EventRules.php

98 lines
3.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Ingest;
use Illuminate\Support\Facades\Validator as ValidatorFactory;
use Illuminate\Validation\ValidationException;
use Illuminate\Validation\Validator;
use InvalidArgumentException;
/**
* Правила одного события в форме upsert-элемента (§5 спеки). Один источник правды
* для клиентов (/api, пачкой) и для manual-событий из инбокса и от агента.
*/
final class EventRules
{
/** @return array<string,list<string>> */
public static function item(): array
{
return [
'due_at' => ['required', 'string'],
'fire_at' => ['required', 'date_format:Y-m-d'],
'after_due' => ['required', 'in:keep,expire'],
'payload' => ['required', 'array'],
'payload.title' => ['required', 'string'],
'payload.subtitle' => ['sometimes', 'nullable', 'string'],
'payload.deep_link' => ['sometimes', 'nullable', 'string', 'max:2048', 'regex:#^(/(?![/\\\\])|https?://)#i'],
'payload.done_label' => ['sometimes', 'nullable', 'string', 'max:64'],
];
}
/**
* Те же правила с префиксом ключа — для пачки `events.*.`.
*
* @return array<string,list<string>>
*/
public static function itemPrefixed(string $prefix): array
{
$rules = [];
foreach (self::item() as $key => $rule) {
$rules[$prefix.$key] = $rule;
}
return $rules;
}
/** @return array<string,string> */
public static function messages(string $prefix = ''): array
{
return [$prefix.'payload.deep_link.regex' => 'deep_link должен быть относительным путём или http(s)-ссылкой'];
}
/**
* Проверки после правил: due_at разбирается, fire_at не позже дня срока.
* Возвращает ошибки как поле => текст; пусто — всё хорошо.
*
* @param array<string,mixed> $item
* @return array<string,string>
*/
public static function check(array $item): array
{
if (! isset($item['due_at'], $item['fire_at']) || ! is_string($item['due_at'])) {
return [];
}
try {
$due = DueAtParser::parse($item['due_at']);
} catch (InvalidArgumentException $e) {
return ['due_at' => $e->getMessage()];
}
// Проверка fire_at <= день срока — по поясу по умолчанию; для fixed это
// приближение, точный день пользователя известен только при upsert.
if ($item['fire_at'] > $due->dayFor(config('hado.default_tz'))) {
return ['fire_at' => 'fire_at не может быть позже дня срока'];
}
return [];
}
/**
* Проверить один элемент целиком.
*
* @param array<string,mixed> $item
*
* @throws ValidationException
*/
public static function validate(array $item): void
{
ValidatorFactory::make($item, self::item(), self::messages())
->after(function (Validator $v) use ($item) {
foreach (self::check($item) as $field => $error) {
if ($v->errors()->missing($field)) {
$v->errors()->add($field, $error);
}
}
})
->validate();
}
}