$input @return array */ public static function validate(array $input, Settings $settings): array { $subject = trim((string)($input['subject'] ?? '')); if ($subject === '') { throw new InvalidArgumentException('Temat jest wymagany.'); } if (str_contains($subject, "\r") || str_contains($subject, "\n")) { throw new InvalidArgumentException('Temat nie może zawierać nowych linii.'); } if (strlen($subject) > $settings->maxSubjectBytes()) { throw new InvalidArgumentException('Temat jest za długi.'); } $body = str_replace(["\r\n", "\r", "\0"], ["\n", "\n", ''], (string)($input['body'] ?? '')); $body = trim($body); if ($body === '') { throw new InvalidArgumentException('Treść wiadomości jest wymagana.'); } if (strlen($body) > $settings->maxBodyBytes()) { throw new InvalidArgumentException('Treść wiadomości jest za długa.'); } $mode = $settings->scheduleMode(); $tz = new DateTimeZone($settings->timezone()); [$startTs, $startValue] = self::parseScheduleValue((string)($input['start_value'] ?? ''), $mode, $tz, true); [$endTs, $endValue] = self::parseScheduleValue((string)($input['end_value'] ?? ''), $mode, $tz, false); if ($endTs <= $startTs) { throw new InvalidArgumentException('Data zakończenia musi być późniejsza niż data rozpoczęcia.'); } return [ 'subject' => $subject, 'body' => $body, 'schedule_mode' => $mode, 'timezone' => $settings->timezone(), 'start_value' => $startValue, 'end_value' => $endValue, 'start_ts' => $startTs, 'end_ts' => $endTs, 'enabled' => self::truthy($input['enabled'] ?? false), 'dynamic_scope' => $settings->dynamicMailboxScope(), ]; } /** @return array{0:int,1:string} */ private static function parseScheduleValue(string $value, string $mode, DateTimeZone $tz, bool $start): array { $value = trim($value); if ($mode === 'exact_hour') { if (!preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}$/', $value)) { throw new InvalidArgumentException('Nieprawidłowa data lub godzina.'); } $dt = DateTimeImmutable::createFromFormat('!Y-m-d\TH:i', $value, $tz); if (!$dt) { throw new InvalidArgumentException('Nieprawidłowa data lub godzina.'); } return [$dt->getTimestamp(), $value]; } if (!preg_match('/^([0-9]{4}-[0-9]{2}-[0-9]{2})\|(morning|afternoon|evening)$/', $value, $m)) { throw new InvalidArgumentException('Nieprawidłowa data lub pora dnia.'); } $hour = ['morning' => 8, 'afternoon' => 13, 'evening' => 18][$m[2]]; if (!$start && $m[2] === 'evening') { $hour = 23; } $dt = DateTimeImmutable::createFromFormat('!Y-m-d H:i', $m[1] . ' ' . sprintf('%02d:00', $hour), $tz); if (!$dt) { throw new InvalidArgumentException('Nieprawidłowa data lub pora dnia.'); } return [$dt->getTimestamp(), $value]; } private static function truthy(mixed $value): bool { return in_array(strtolower((string)$value), ['1', 'true', 'yes', 'on'], true); } }