$limit) throw new AppException($label . ' must be ' . $limit . ' characters or fewer.'); if ($singleLine && preg_match('/[\x00-\x1f\x7f]/u', $value)) throw new AppException($label . ' must be a single line.'); return $value; } private static function timestamp(array $input, string $prefix, string $label): string { $date = self::text($input, $prefix . '_date', $label . ' date', 10, true, true); $time = self::text($input, $prefix . '_time', $label . ' time', 5, true, true); $value = $date . ' ' . $time; if (!preg_match('/\A[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\z/', $value)) throw new AppException($label . ' must use a valid YYYY-MM-DD date and HH:MM time.'); $parsed = DateTimeImmutable::createFromFormat('!Y-m-d H:i', $value, new DateTimeZone(Base::TIMEZONE)); $errors = DateTimeImmutable::getLastErrors(); if (!$parsed || ($errors && ($errors['warning_count'] || $errors['error_count'])) || $parsed->format('Y-m-d H:i') !== $value || $date < '1000-01-01') throw new AppException($label . ' date/time is invalid.'); return $value; } public static function alert(array $input): array { $title = self::text($input, 'alert_title', 'Alert title', 100, true, true); $starts = self::timestamp($input, 'alert_starts', 'Start'); $expires = self::timestamp($input, 'alert_expires', 'Expiration'); if ($expires < $starts) throw new AppException('Expiration cannot be before the start.'); return ['title' => $title, 'starts' => $starts, 'expires' => $expires, 'message' => self::text($input, 'alert_message', 'Alert message', 1000)]; } public static function popover(array $input): array { return ['name' => self::text($input, 'popover_name', 'Popover name', 100, true, true), 'title' => self::text($input, 'popover_title', 'Popover title', 100, true, true), 'placeholder' => self::text($input, 'popover_placeholder', 'Popover placeholder', 100, false, true), 'text' => self::text($input, 'popover_text', 'Popover text', 1000)]; } }