generate($length, $alphabet)->serialize(); } function parseDateFromQuery(array $query, string $dateName): ?Chronos { return normalizeOptionalDate(empty($query[$dateName] ?? null) ? null : Chronos::parse($query[$dateName])); } function parseDateRangeFromQuery(array $query, string $startDateName, string $endDateName): DateRange { $startDate = parseDateFromQuery($query, $startDateName); $endDate = parseDateFromQuery($query, $endDateName); return buildDateRange($startDate, $endDate); } /** * @return ($date is null ? null : Chronos) */ function normalizeOptionalDate(string|DateTimeInterface|Chronos|null $date): ?Chronos { $parsedDate = match (true) { $date === null || $date instanceof Chronos => $date, $date instanceof DateTimeInterface => Chronos::instance($date), default => Chronos::parse($date), }; return $parsedDate?->setTimezone(date_default_timezone_get()); } function normalizeDate(string|DateTimeInterface|Chronos $date): Chronos { return normalizeOptionalDate($date); } function getOptionalIntFromInputFilter(InputFilter $inputFilter, string $fieldName): ?int { $value = $inputFilter->getValue($fieldName); return $value !== null ? (int) $value : null; } function getOptionalBoolFromInputFilter(InputFilter $inputFilter, string $fieldName): ?bool { $value = $inputFilter->getValue($fieldName); return $value !== null ? (bool) $value : null; } function getNonEmptyOptionalValueFromInputFilter(InputFilter $inputFilter, string $fieldName): mixed { $value = $inputFilter->getValue($fieldName); return empty($value) ? null : $value; } function arrayToString(array $array, int $indentSize = 4): string { $indent = str_repeat(' ', $indentSize); $names = array_keys($array); $index = 0; return array_reduce($names, static function (string $acc, string $name) use (&$index, $indent, $array) { $index++; $messages = $array[$name]; return $acc . sprintf( "%s%s'%s' => %s", $index === 1 ? '' : "\n", $indent, $name, is_array($messages) ? print_r($messages, true) : $messages, ); }, ''); } function isCrawler(string $userAgent): bool { static $detector; if ($detector === null) { $detector = new CrawlerDetect(); } return $detector->isCrawler($userAgent); } function determineTableName(string $tableName, array $emConfig = []): string { $schema = $emConfig['connection']['schema'] ?? null; // $tablePrefix = $emConfig['connection']['table_prefix'] ?? null; // TODO if ($schema === null) { return $tableName; } return sprintf('%s.%s', $schema, $tableName); } function fieldWithUtf8Charset(FieldBuilder $field, array $emConfig, string $collation = 'unicode_ci'): FieldBuilder { return match ($emConfig['connection']['driver'] ?? null) { 'pdo_mysql' => $field->option('charset', 'utf8mb4') ->option('collation', 'utf8mb4_' . $collation), default => $field, }; } function camelCaseToHumanFriendly(string $value): string { static $filter; if ($filter === null) { $filter = new CamelCaseToSeparator(' '); } return ucfirst($filter->filter($value)); } function camelCaseToSnakeCase(string $value): string { static $filter; if ($filter === null) { $filter = new CamelCaseToUnderscore(); } return strtolower($filter->filter($value)); } function toProblemDetailsType(string $errorCode): string { return sprintf('https://shlink.io/api/error/%s', $errorCode); } /** * @param class-string $enum * @return string[] */ function enumValues(string $enum): array { static $cache; if ($cache === null) { $cache = []; } return $cache[$enum] ?? ( $cache[$enum] = array_map(static fn (BackedEnum $type) => (string) $type->value, $enum::cases()) ); } function contains(mixed $value, array $array): bool { return in_array($value, $array, strict: true); } /** * @param array[] $multiArray * @return array */ function flatten(array $multiArray): array { return array_reduce( $multiArray, static fn (array $carry, array $value) => [...$carry, ...$value], initial: [], ); } /** * Checks if a callback returns true for at least one item in a collection. * @param callable(mixed $value, string|number $key): bool $callback */ function some(iterable $collection, callable $callback): bool { foreach ($collection as $key => $value) { if ($callback($value, $key)) { return true; } } return false; } /** * Checks if a callback returns true for all item in a collection. * @param callable(mixed $value, string|number $key): bool $callback */ function every(iterable $collection, callable $callback): bool { foreach ($collection as $key => $value) { if (! $callback($value, $key)) { return false; } } return true; }