.gitattributes000064400000000054151360551670007447 0ustar00/tests export-ignore /.github export-ignore LICENSE000064400000002110151360551670005554 0ustar00The MIT License (MIT) Copyright (c) Taylor Otwell Copyright (c) Hyperf Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. composer.json000064400000003701151360551670007300 0ustar00{ "name": "hyperf/utils", "description": "A tools package that could help developer solved the problem quickly.", "license": "MIT", "keywords": [ "php", "swoole", "hyperf", "utils" ], "homepage": "https://hyperf.io", "support": { "docs": "https://hyperf.wiki", "issues": "https://github.com/hyperf/hyperf/issues", "pull-request": "https://github.com/hyperf/hyperf/pulls", "source": "https://github.com/hyperf/hyperf" }, "require": { "php": ">=7.2", "doctrine/inflector": "^2.0", "hyperf/collection": "~3.0.0", "hyperf/context": "~3.0.0", "hyperf/contract": "~3.0.0", "hyperf/coordinator": "~3.0.0", "hyperf/coroutine": "~3.0.0", "hyperf/engine": "^1.2|^2.0", "hyperf/macroable": "~3.0.0", "hyperf/stringable": "~3.0.0" }, "suggest": { "ext-swoole": "Required to use methods related to swoole (>=4.5).", "symfony/var-dumper": "Required to use the dd function (^5.0|^6.0).", "symfony/serializer": "Required to use SymfonyNormalizer (^5.0|^6.0)", "symfony/property-access": "Required to use SymfonyNormalizer (^5.0|^6.0)", "hyperf/di": "Required to use ExceptionNormalizer", "nikic/php-parser": "Required to use PhpParser. (^4.0)", "ramsey/uuid": "Required to use uuid and orderedUuid methods", "symfony/uid": "Required to use ulid method" }, "autoload": { "files": [ "src/Functions.php" ], "psr-4": { "Hyperf\\Utils\\": "src/" } }, "autoload-dev": { "psr-4": { "HyperfTest\\Utils\\": "tests/" } }, "config": { "sort-packages": true }, "extra": { "hyperf": { "config": "Hyperf\\Utils\\ConfigProvider" }, "branch-alias": { "dev-master": "3.0-dev" } } } src/ApplicationContext.php000064400000000647151360551670011674 0ustar00 Backoff::CAP) { throw new InvalidArgumentException( sprintf( 'first backoff interval must be less or equal than %d milliseconds', self::CAP ) ); } $this->currentMs = $firstMs; } /** * Sleep until the next execution. */ public function sleep(): void { if ($this->currentMs === 0) { return; } usleep($this->currentMs * 1000); // update backoff using Decorrelated Jitter // see: https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/ $this->currentMs = rand($this->firstMs, $this->currentMs * 3); if ($this->currentMs > self::CAP) { $this->currentMs = self::CAP; } } /** * Get the next backoff for logging, etc. * @return int next backoff */ public function nextBackoff(): int { return $this->currentMs; } } src/Channel/Caller.php000064400000000630151360551670010626 0ustar00 self::$interval || self::$lastCleared || (self::$lastCleared + self::$interval < $now) ) { self::forceClear($filename); self::$lastCleared = $now; } } public static function forceClear(?string $filename = null): void { if ($filename !== null) { clearstatcache(true, $filename); } else { clearstatcache(); } } public static function getInterval(): int { return self::$interval; } public static function setInterval(int $interval) { self::$interval = $interval; } } src/CodeGen/Package.php000064400000001076151360551670010720 0ustar00 'bool', 'boolean' => 'bool', 'string' => 'string', 'int' => 'int', 'integer' => 'int', 'float' => 'float', 'double' => 'float', 'array' => 'array', 'object' => 'object', 'callable' => 'callable', 'resource' => 'resource', 'mixed' => 'mixed', 'iterable' => 'iterable', ]; protected static ?PhpDocReader $instance = null; private UseStatementParser $parser; /** * @param bool $ignorePhpDocErrors enable or disable throwing errors when PhpDoc errors occur (when parsing annotations) */ public function __construct(private bool $ignorePhpDocErrors = false) { $this->parser = new UseStatementParser(); } public static function getInstance(): PhpDocReader { if (static::$instance) { return static::$instance; } return static::$instance = new static(); } /** * Parse the docblock of the property to get the type (class or primitive type) of the param annotation. * * @throws AnnotationException */ public function getReturnType(ReflectionMethod $method, bool $withoutNamespace = false): array { return $this->readReturnClass($method, true, $withoutNamespace); } /** * Parse the docblock of the property to get the class of the param annotation. * * @throws AnnotationException */ public function getReturnClass(ReflectionMethod $method, bool $withoutNamespace = false): array { return $this->readReturnClass($method, false, $withoutNamespace); } protected function readReturnClass(ReflectionMethod $method, bool $allowPrimitiveTypes, bool $withoutNamespace = false): array { // Use reflection $returnType = $method->getReturnType(); if ($returnType instanceof ReflectionNamedType) { if (! $returnType->isBuiltin() || $allowPrimitiveTypes) { return [($returnType->allowsNull() ? '?' : '') . $returnType->getName()]; } } $docComment = $method->getDocComment(); if (! $docComment) { return ['mixed']; } if (preg_match('/@return\s+([^\s]+)\s+/', $docComment, $matches)) { [, $type] = $matches; } else { return ['mixed']; } $result = []; $class = $method->getDeclaringClass(); $types = explode('|', $type); foreach ($types as $type) { // Ignore primitive types if (isset(self::PRIMITIVE_TYPES[$type])) { if ($allowPrimitiveTypes) { $result[] = self::PRIMITIVE_TYPES[$type]; } continue; } // Ignore types containing special characters ([], <> ...) if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) { continue; } // If the class name is not fully qualified (i.e. doesn't start with a \) if ($type[0] !== '\\' && ! $withoutNamespace) { // Try to resolve the FQN using the class context $resolvedType = $this->tryResolveFqn($type, $class, $method); if (! $resolvedType && ! $this->ignorePhpDocErrors) { throw new AnnotationException(sprintf( 'The @return annotation for parameter "%s" of %s::%s contains a non existent class "%s". ' . 'Did you maybe forget to add a "use" statement for this annotation?', $method, $class->name, $method->name, $type )); } $type = $resolvedType; } if (! $this->ignorePhpDocErrors && ! $withoutNamespace && ! $this->classExists($type)) { throw new AnnotationException(sprintf( 'The @return annotation for parameter "%s" of %s::%s contains a non existent class "%s"', $method, $class->name, $method->name, $type )); } // Remove the leading \ (FQN shouldn't contain it) $result[] = is_string($type) ? ltrim($type, '\\') : null; } return $result; } /** * Attempts to resolve the FQN of the provided $type based on the $class and $member context. * * @return null|string Fully qualified name of the type, or null if it could not be resolved */ protected function tryResolveFqn(string $type, ReflectionClass $class, Reflector $member): ?string { $alias = ($pos = strpos($type, '\\')) === false ? $type : substr($type, 0, $pos); $loweredAlias = strtolower($alias); // Retrieve "use" statements $uses = $this->parser->parseUseStatements($class); if (isset($uses[$loweredAlias])) { // Imported classes if ($pos !== false) { return $uses[$loweredAlias] . substr($type, $pos); } return $uses[$loweredAlias]; } if ($this->classExists($class->getNamespaceName() . '\\' . $type)) { return $class->getNamespaceName() . '\\' . $type; } if (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) { // Class namespace return $uses['__NAMESPACE__'] . '\\' . $type; } if ($this->classExists($type)) { // No namespace return $type; } // If all fail, try resolving through related traits return $this->tryResolveFqnInTraits($type, $class, $member); } /** * Attempts to resolve the FQN of the provided $type based on the $class and $member context, specifically searching * through the traits that are used by the provided $class. * * @return null|string Fully qualified name of the type, or null if it could not be resolved */ protected function tryResolveFqnInTraits(string $type, ReflectionClass $class, Reflector $member): ?string { /** @var ReflectionClass[] $traits */ $traits = []; // Get traits for the class and its parents while ($class) { $traits = array_merge($traits, $class->getTraits()); $class = $class->getParentClass(); } foreach ($traits as $trait) { // Eliminate traits that don't have the property/method/parameter if ($member instanceof ReflectionProperty && ! $trait->hasProperty($member->name)) { continue; } if ($member instanceof ReflectionMethod && ! $trait->hasMethod($member->name)) { continue; } if ($member instanceof ReflectionParameter && ! $trait->hasMethod($member->getDeclaringFunction()->name)) { continue; } // Run the resolver again with the ReflectionClass instance for the trait $resolvedType = $this->tryResolveFqn($type, $trait, $member); if ($resolvedType) { return $resolvedType; } } return null; } protected function classExists(string $class): bool { return class_exists($class) || interface_exists($class); } } src/CodeGen/PhpDocReaderManager.php000064400000001116151360551670013153 0ustar00parser = $parserFactory->create(ParserFactory::ONLY_PHP7); } public static function getInstance(): PhpParser { if (static::$instance) { return static::$instance; } return static::$instance = new static(); } /** * @return null|Node\Stmt[] */ public function getNodesFromReflectionClass(ReflectionClass $reflectionClass): ?array { $code = file_get_contents($reflectionClass->getFileName()); return $this->parser->parse($code); } public function getNodeFromReflectionType(ReflectionType $reflection): Node\ComplexType|Node\Identifier|Node\Name { if ($reflection instanceof ReflectionUnionType) { $unionType = []; foreach ($reflection->getTypes() as $objType) { $type = $objType->getName(); if (! in_array($type, static::TYPES)) { $unionType[] = new Node\Name('\\' . $type); } else { $unionType[] = new Node\Identifier($type); } } return new Node\UnionType($unionType); } return $this->getTypeWithNullableOrNot($reflection); } public function getNodeFromReflectionParameter(ReflectionParameter $parameter): Node\Param { $result = new Node\Param( new Node\Expr\Variable($parameter->getName()) ); if ($parameter->isDefaultValueAvailable()) { $result->default = $this->getExprFromValue($parameter->getDefaultValue()); } if ($parameter->hasType()) { $result->type = $this->getNodeFromReflectionType($parameter->getType()); } if ($parameter->isPassedByReference()) { $result->byRef = true; } if ($parameter->isVariadic()) { $result->variadic = true; } return $result; } public function getExprFromValue($value): Node\Expr { return match (gettype($value)) { 'array' => value(function ($value) { $isList = ! Arr::isAssoc($value); $result = []; foreach ($value as $i => $item) { $key = null; if (! $isList) { $key = is_int($i) ? new Node\Scalar\LNumber($i) : new Node\Scalar\String_($i); } $result[] = new Node\Expr\ArrayItem($this->getExprFromValue($item), $key); } return new Node\Expr\Array_($result, [ 'kind' => Node\Expr\Array_::KIND_SHORT, ]); }, $value), 'string' => new Node\Scalar\String_($value), 'integer' => new Node\Scalar\LNumber($value), 'double' => new Node\Scalar\DNumber($value), 'NULL' => new Node\Expr\ConstFetch(new Node\Name('null')), 'boolean' => new Node\Expr\ConstFetch(new Node\Name($value ? 'true' : 'false')), 'object' => $this->getExprFromObject($value), default => throw new InvalidArgumentException($value . ' is invalid'), }; } /** * @return Node\Stmt\ClassMethod[] */ public function getAllMethodsFromStmts(array $stmts): array { $methods = []; foreach ($stmts as $namespace) { if (! $namespace instanceof Node\Stmt\Namespace_) { continue; } foreach ($namespace->stmts as $class) { if (! $class instanceof Node\Stmt\Class_ && ! $class instanceof Node\Stmt\Interface_) { continue; } foreach ($class->getMethods() as $method) { $methods[] = $method; } } } return $methods; } private function getExprFromObject(object $value) { $ref = new ReflectionClass($value); if (method_exists($ref, 'isEnum') && $ref->isEnum()) { return new Node\Expr\ClassConstFetch( new Node\Name('\\' . $value::class), $value->name ); } return new Node\Expr\New_( new Node\Name\FullyQualified($value::class) ); } private function getTypeWithNullableOrNot(ReflectionType $reflection): Node\ComplexType|Node\Identifier|Node\Name { if (! $reflection instanceof ReflectionNamedType) { throw new ReflectionException('ReflectionType must be ReflectionNamedType.'); } $name = $reflection->getName(); if ($reflection->allowsNull() && $name !== 'mixed') { return new Node\NullableType($this->getTypeFromString($name)); } if (! in_array($name, static::TYPES)) { return new Node\Name('\\' . $name); } return new Node\Identifier($name); } private function getTypeFromString(string $name) { if (! in_array($name, static::TYPES)) { return '\\' . $name; } return $name; } } src/CodeGen/Project.php000064400000003630151360551670010771 0ustar00getAutoloadRules() as $prefix => $prefixPath) { if ($this->isRootNamespace($prefix) || str_starts_with($path, $prefixPath)) { return $prefix . str_replace('/', '\\', substr($path, strlen($prefixPath))); } } throw new RuntimeException("Invalid project path: {$path}"); } public function className(string $path): string { return $this->namespace($path); } public function path(string $name, $extension = '.php'): string { if (Str::endsWith($name, '\\')) { $extension = ''; } foreach ($this->getAutoloadRules() as $prefix => $prefixPath) { if ($this->isRootNamespace($prefix) || str_starts_with($name, $prefix)) { return $prefixPath . str_replace('\\', '/', substr($name, strlen($prefix))) . $extension; } } throw new RuntimeException("Invalid class name: {$name}"); } protected function isRootNamespace(string $namespace): bool { return $namespace === ''; } protected function getAutoloadRules(): array { return data_get(Composer::getJsonContent(), 'autoload.psr-4', []); } } src/Codec/Base62.php000064400000002012151360551670010107 0ustar00 0) { $remain = $number % self::BASE; $chars[] = self::CHARS[$remain]; $number = ($number - $remain) / self::BASE; } return implode('', array_reverse($chars)); } public static function decode(string $data): int { return array_reduce(array_map(function ($character) { return strpos(self::CHARS, $character); }, str_split($data)), function ($result, $remain) { return $result * self::BASE + $remain; }); } } src/Codec/Json.php000064400000002762151360551670010012 0ustar00toArray(); } try { $json = json_encode($data, $flags | JSON_THROW_ON_ERROR, $depth); } catch (Throwable $exception) { throw new InvalidArgumentException($exception->getMessage(), (int) $exception->getCode(), $exception); } return $json; } /** * @throws InvalidArgumentException */ public static function decode(string $json, bool $assoc = true, int $depth = 512, int $flags = 0): mixed { try { $decode = json_decode($json, $assoc, $depth, $flags | JSON_THROW_ON_ERROR); } catch (Throwable $exception) { throw new InvalidArgumentException($exception->getMessage(), (int) $exception->getCode(), $exception); } return $decode; } } src/Codec/Xml.php000064400000003310151360551670007627 0ustar00toArray(); } else { $data = (array) $data; } if ($parentNode === null) { $xml = new SimpleXMLElement('' . "<{$root}>"); } else { $xml = $parentNode; } foreach ($data as $key => $value) { if (is_array($value)) { self::toXml($value, $xml->addChild($key)); } else { if (is_numeric($key)) { $xml->addChild('item' . $key, (string) $value); } else { $xml->addChild($key, (string) $value); } } } return trim($xml->asXML()); } public static function toArray($xml): array { $respObject = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOERROR); if ($respObject === false) { throw new InvalidArgumentException('Syntax error.'); } return json_decode(json_encode($respObject), true); } } src/Collection.php000064400000001031151360551670010143 0ustar00offsetGet('packages') ?? []; $packagesDev = self::$content->offsetGet('packages-dev') ?? []; foreach (array_merge($packages, $packagesDev) as $package) { $packageName = ''; foreach ($package ?? [] as $key => $value) { if ($key === 'name') { $packageName = $value; continue; } switch ($key) { case 'extra': $packageName && self::$extra[$packageName] = $value; break; case 'scripts': $packageName && self::$scripts[$packageName] = $value; break; case 'version': $packageName && self::$versions[$packageName] = $value; break; } } } } return self::$content; } public static function getJsonContent(): Collection { if (! self::$json) { $path = BASE_PATH . '/composer.json'; if (! is_readable($path)) { throw new RuntimeException('composer.json is not readable.'); } self::$json = collect(json_decode(file_get_contents($path), true)); } return self::$json; } public static function discoverLockFile(): string { $path = ''; if (is_readable(BASE_PATH . '/composer.lock')) { $path = BASE_PATH . '/composer.lock'; } return $path; } public static function getMergedExtra(string $key = null) { if (! self::$extra) { self::getLockContent(); } if ($key === null) { return self::$extra; } $extra = []; foreach (self::$extra as $project => $config) { foreach ($config ?? [] as $configKey => $item) { if ($key === $configKey && $item) { foreach ($item as $k => $v) { if (is_array($v)) { $extra[$k] = array_merge($extra[$k] ?? [], $v); } else { $extra[$k][] = $v; } } } } } return $extra; } public static function getLoader(): ClassLoader { if (! self::$classLoader) { self::$classLoader = self::findLoader(); } return self::$classLoader; } public static function setLoader(ClassLoader $classLoader): ClassLoader { self::$classLoader = $classLoader; return $classLoader; } public static function getScripts(): array { return self::$scripts; } public static function getVersions(): array { return self::$versions; } private static function findLoader(): ClassLoader { $loaders = spl_autoload_functions(); foreach ($loaders as $loader) { if (is_array($loader) && $loader[0] instanceof ClassLoader) { return $loader[0]; } } throw new RuntimeException('Composer loader not found.'); } } src/ConfigProvider.php000064400000001320151360551670010771 0ustar00 [ Serializer::class => SerializerFactory::class, NormalizerInterface::class => SimpleNormalizer::class, ], ]; } } src/Contracts/Arrayable.php000064400000000566151360551670011726 0ustar00throwable; } } src/Exception/IPReadFailedException.php000064400000000541151360551670014103 0ustar00isFile($path)) { return $lock ? $this->sharedGet($path) : file_get_contents($path); } throw new FileNotFoundException("File does not exist at path {$path}"); } /** * Get contents of a file with shared access. */ public function sharedGet(string $path): string { return $this->atomic($path, function ($path) { $contents = ''; $handle = fopen($path, 'rb'); if ($handle) { $wouldBlock = false; flock($handle, LOCK_SH | LOCK_NB, $wouldBlock); while ($wouldBlock) { usleep(1000); flock($handle, LOCK_SH | LOCK_NB, $wouldBlock); } try { clearstatcache(true, $path); $contents = fread($handle, $this->size($path) ?: 1); } finally { flock($handle, LOCK_UN); fclose($handle); } } return $contents; }); } /** * Get the returned value of a file. * * @throws \Hyperf\Utils\Filesystem\FileNotFoundException */ public function getRequire(string $path) { if ($this->isFile($path)) { return require $path; } throw new FileNotFoundException("File does not exist at path {$path}"); } /** * Require the given file once. */ public function requireOnce(string $file): void { require_once $file; } /** * Get the MD5 hash of the file at the given path. */ public function hash(string $path): string { return md5_file($path); } /** * Clears file status cache. */ public function clearStatCache(string $path): void { clearstatcache(true, $path); } /** * Write the contents of a file. * * @param resource|string $contents * @return bool|int */ public function put(string $path, $contents, bool $lock = false) { if ($lock) { return $this->atomic($path, function ($path) use ($contents) { $handle = fopen($path, 'w+'); if ($handle) { $wouldBlock = false; flock($handle, LOCK_EX | LOCK_NB, $wouldBlock); while ($wouldBlock) { usleep(1000); flock($handle, LOCK_EX | LOCK_NB, $wouldBlock); } try { fwrite($handle, $contents); } finally { flock($handle, LOCK_UN); fclose($handle); } } }); } return file_put_contents($path, $contents); } /** * Write the contents of a file, replacing it atomically if it already exists. */ public function replace(string $path, string $content) { // If the path already exists and is a symlink, get the real path... clearstatcache(true, $path); $path = realpath($path) ?: $path; $tempPath = tempnam(dirname($path), basename($path)); // Fix permissions of tempPath because `tempnam()` creates it with permissions set to 0600... chmod($tempPath, 0777 - umask()); file_put_contents($tempPath, $content); rename($tempPath, $path); } /** * Prepend to a file. */ public function prepend(string $path, string $data): int { if ($this->exists($path)) { return $this->put($path, $data . $this->get($path)); } return $this->put($path, $data); } /** * Append to a file. */ public function append(string $path, string $data): int { return file_put_contents($path, $data, FILE_APPEND); } /** * Get or set UNIX mode of a file or directory. */ public function chmod(string $path, ?int $mode = null) { if ($mode) { return chmod($path, $mode); } return substr(sprintf('%o', fileperms($path)), -4); } /** * Delete the file at a given path. * * @param array|string $paths */ public function delete($paths): bool { $paths = is_array($paths) ? $paths : func_get_args(); $success = true; foreach ($paths as $path) { try { if (! @unlink($path)) { $success = false; } } catch (ErrorException) { $success = false; } } return $success; } /** * Move a file to a new location. */ public function move(string $path, string $target): bool { return rename($path, $target); } /** * Copy a file to a new location. */ public function copy(string $path, string $target): bool { return copy($path, $target); } /** * Create a hard link to the target file or directory. */ public function link(string $target, string $link): bool { if (! $this->windowsOs()) { return symlink($target, $link); } $mode = $this->isDirectory($target) ? 'J' : 'H'; exec("mklink /{$mode} \"{$link}\" \"{$target}\""); return true; } /** * Extract the file name from a file path. */ public function name(string $path): string { return pathinfo($path, PATHINFO_FILENAME); } /** * Extract the trailing name component from a file path. */ public function basename(string $path): string { return pathinfo($path, PATHINFO_BASENAME); } /** * Extract the parent directory from a file path. */ public function dirname(string $path): string { return pathinfo($path, PATHINFO_DIRNAME); } /** * Extract the file extension from a file path. */ public function extension(string $path): string { return pathinfo($path, PATHINFO_EXTENSION); } /** * Get the file type of a given file. */ public function type(string $path): string { return filetype($path); } /** * Get the mime-type of a given file. * * @return false|string */ public function mimeType(string $path) { return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path); } /** * Get the file size of a given file. */ public function size(string $path): int { return filesize($path); } /** * Get the file's last modification time. */ public function lastModified(string $path): int { return filemtime($path); } /** * Determine if the given path is a directory. */ public function isDirectory(string $directory): bool { return is_dir($directory); } /** * Determine if the given path is readable. */ public function isReadable(string $path): bool { return is_readable($path); } /** * Determine if the given path is writable. */ public function isWritable(string $path): bool { return is_writable($path); } /** * Determine if the given path is a file. */ public function isFile(string $file): bool { return is_file($file); } /** * Find path names matching a given pattern. */ public function glob(string $pattern, int $flags = 0): array { return glob($pattern, $flags); } /** * Get an array of all files in a directory. * * @return \Symfony\Component\Finder\SplFileInfo[] */ public function files(string $directory, bool $hidden = false): array { return iterator_to_array( Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->depth(0)->sortByName(), false ); } /** * Get all of the files from the given directory (recursive). * @return \Symfony\Component\Finder\SplFileInfo[] */ public function allFiles(string $directory, bool $hidden = false): array { return iterator_to_array( Finder::create()->files()->ignoreDotFiles(! $hidden)->in($directory)->sortByName(), false ); } /** * Get all of the directories within a given directory. */ public function directories(string $directory): array { $directories = []; foreach (Finder::create()->in($directory)->directories()->depth(0)->sortByName() as $dir) { $directories[] = $dir->getPathname(); } return $directories; } /** * Create a directory. */ public function makeDirectory(string $path, int $mode = 0755, bool $recursive = false, bool $force = false): bool { if ($force) { return @mkdir($path, $mode, $recursive); } return mkdir($path, $mode, $recursive); } /** * Move a directory. */ public function moveDirectory(string $from, string $to, bool $overwrite = false): bool { if ($overwrite && $this->isDirectory($to) && ! $this->deleteDirectory($to)) { return false; } return @rename($from, $to) === true; } /** * Copy a directory from one location to another. */ public function copyDirectory(string $directory, string $destination, int $options = null): bool { if (! $this->isDirectory($directory)) { return false; } $options = $options ?: FilesystemIterator::SKIP_DOTS; // If the destination directory does not actually exist, we will go ahead and // create it recursively, which just gets the destination prepared to copy // the files over. Once we make the directory we'll proceed the copying. if (! $this->isDirectory($destination)) { $this->makeDirectory($destination, 0777, true); } $items = new FilesystemIterator($directory, $options); foreach ($items as $item) { // As we spin through items, we will check to see if the current file is actually // a directory or a file. When it is actually a directory we will need to call // back into this function recursively to keep copying these nested folders. $target = $destination . DIRECTORY_SEPARATOR . $item->getBasename(); if ($item->isDir()) { $path = $item->getPathname(); if (! $this->copyDirectory($path, $target, $options)) { return false; } } // If the current items is just a regular file, we will just copy this to the new // location and keep looping. If for some reason the copy fails we'll bail out // and return false, so the developer is aware that the copy process failed. else { if (! $this->copy($item->getPathname(), $target)) { return false; } } } return true; } /** * Recursively delete a directory. * * The directory itself may be optionally preserved. */ public function deleteDirectory(string $directory, bool $preserve = false): bool { if (! $this->isDirectory($directory)) { return false; } $items = new FilesystemIterator($directory); foreach ($items as $item) { // If the item is a directory, we can just recurse into the function and // delete that sub-directory otherwise we'll just delete the file and // keep iterating through each file until the directory is cleaned. if ($item->isDir() && ! $item->isLink()) { $this->deleteDirectory($item->getPathname()); } // If the item is just a file, we can go ahead and delete it since we're // just looping through and waxing all of the files in this directory // and calling directories recursively, so we delete the real path. else { $this->delete($item->getPathname()); } } if (! $preserve) { @rmdir($directory); } return true; } /** * Remove all of the directories within a given directory. */ public function deleteDirectories(string $directory): bool { $allDirectories = $this->directories($directory); if (! empty($allDirectories)) { foreach ($allDirectories as $directoryName) { $this->deleteDirectory($directoryName); } return true; } return false; } /** * Empty the specified directory of all files and folders. */ public function cleanDirectory(string $directory): bool { return $this->deleteDirectory($directory, true); } /** * Detect whether it's Windows. */ public function windowsOs(): bool { return stripos(PHP_OS, 'win') === 0; } protected function atomic($path, $callback) { if (Coroutine::inCoroutine()) { try { while (! Locker::lock($path)) { usleep(1000); } return $callback($path); } finally { Locker::unlock($path); } } else { return $callback($path); } } } src/Fluent.php000075500000007517151360551670007327 0ustar00 $value) { $this->attributes[$key] = $value; } } /** * Handle dynamic calls to the fluent instance to set attributes. * * @param string $method * @param array $parameters * @return $this */ public function __call($method, $parameters) { $this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true; return $this; } /** * Dynamically retrieve the value of an attribute. * * @param string $key */ public function __get($key) { return $this->get($key); } /** * Dynamically set the value of an attribute. * * @param string $key * @param mixed $value */ public function __set($key, $value) { $this->offsetSet($key, $value); } /** * Dynamically check if an attribute is set. * * @param string $key * @return bool */ public function __isset($key) { return $this->offsetExists($key); } /** * Dynamically unset an attribute. * * @param string $key */ public function __unset($key) { $this->offsetUnset($key); } public function __toString(): string { return $this->toJson(); } /** * Get an attribute from the fluent instance. * * @param string $key * @param null|mixed $default */ public function get($key, $default = null) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return value($default); } /** * Get the attributes from the fluent instance. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Convert the fluent instance to an array. */ public function toArray(): array { return $this->attributes; } /** * Convert the object into something JSON serializable. */ public function jsonSerialize(): mixed { return $this->toArray(); } /** * Convert the fluent instance to JSON. * * @param int $options * @return string */ public function toJson($options = 0) { return json_encode($this->jsonSerialize(), $options); } /** * Determine if the given offset exists. */ public function offsetExists(mixed $offset): bool { return isset($this->attributes[$offset]); } /** * Get the value for a given offset. */ public function offsetGet(mixed $offset): mixed { return $this->get($offset); } /** * Set the value at the given offset. */ public function offsetSet(mixed $offset, mixed $value): void { $this->attributes[$offset] = $value; } /** * Unset the value at the given offset. */ public function offsetUnset(mixed $offset): void { unset($this->attributes[$offset]); } } src/Functions.php000064400000033734151360551670010037 0ustar00 1 && $value[0] === '"' && $value[$valueLength - 1] === '"') { return substr($value, 1, -1); } return $value; } } if (! function_exists('retry')) { /** * Retry an operation a given number of times. * * @param float|int $times * @param int $sleep millisecond * @throws \Throwable */ function retry($times, callable $callback, int $sleep = 0) { $attempts = 0; $backoff = new Backoff($sleep); beginning: try { return $callback(++$attempts); } catch (\Throwable $e) { if (--$times < 0) { throw $e; } $backoff->sleep(); goto beginning; } } } if (! function_exists('with')) { /** * Return the given value, optionally passed through the given callback. * * @param mixed $value */ function with($value, callable $callback = null) { return is_null($callback) ? $value : $callback($value); } } if (! function_exists('collect')) { /** * Create a collection from the given value. * * @deprecated since 3.1, use \Hyperf\Collection\collect instead. * @param null|mixed $value * @return Collection */ function collect($value = null) { return new Collection($value); } } if (! function_exists('data_fill')) { /** * Fill in data where it's missing. * * @param mixed $target * @param array|string $key * @param mixed $value * * @deprecated since 3.1, use `Hyperf\Collection\data_fill()` instead. */ function data_fill(&$target, $key, $value) { return data_set($target, $key, $value, false); } } if (! function_exists('data_get')) { /** * Get an item from an array or object using "dot" notation. * * @param null|array|int|string $key * @param null|mixed $default * @param mixed $target * * @deprecated since 3.1, use `Hyperf\Collection\data_get()` instead. */ function data_get($target, $key, $default = null) { if (is_null($key)) { return $target; } $key = is_array($key) ? $key : explode('.', is_int($key) ? (string) $key : $key); while (! is_null($segment = array_shift($key))) { if ($segment === '*') { if ($target instanceof Collection) { $target = $target->all(); } elseif (! is_array($target)) { return value($default); } $result = []; foreach ($target as $item) { $result[] = data_get($item, $key); } return in_array('*', $key) ? Arr::collapse($result) : $result; } if (Arr::accessible($target) && Arr::exists($target, $segment)) { $target = $target[$segment]; } elseif (is_object($target) && isset($target->{$segment})) { $target = $target->{$segment}; } else { return value($default); } } return $target; } } if (! function_exists('data_set')) { /** * Set an item on an array or object using dot notation. * * @param mixed $target * @param array|string $key * @param bool $overwrite * @param mixed $value * * @deprecated since 3.1, use `Hyperf\Collection\data_set()` instead. */ function data_set(&$target, $key, $value, $overwrite = true) { $segments = is_array($key) ? $key : explode('.', $key); if (($segment = array_shift($segments)) === '*') { if (! Arr::accessible($target)) { $target = []; } if ($segments) { foreach ($target as &$inner) { data_set($inner, $segments, $value, $overwrite); } } elseif ($overwrite) { foreach ($target as &$inner) { $inner = $value; } } } elseif (Arr::accessible($target)) { if ($segments) { if (! Arr::exists($target, $segment)) { $target[$segment] = []; } data_set($target[$segment], $segments, $value, $overwrite); } elseif ($overwrite || ! Arr::exists($target, $segment)) { $target[$segment] = $value; } } elseif (is_object($target)) { if ($segments) { if (! isset($target->{$segment})) { $target->{$segment} = []; } data_set($target->{$segment}, $segments, $value, $overwrite); } elseif ($overwrite || ! isset($target->{$segment})) { $target->{$segment} = $value; } } else { $target = []; if ($segments) { $target[$segment] = []; data_set($target[$segment], $segments, $value, $overwrite); } elseif ($overwrite) { $target[$segment] = $value; } } return $target; } } if (! function_exists('head')) { /** * Get the first element of an array. Useful for method chaining. * * @param array $array * * @deprecated since 3.1, use `Hyperf\Collection\head()` instead. */ function head($array) { return reset($array); } } if (! function_exists('last')) { /** * Get the last element from an array. * * @param array $array * * @deprecated since 3.1, use `Hyperf\Collection\last()` instead. */ function last($array) { return end($array); } } if (! function_exists('tap')) { /** * Call the given Closure with the given value then return the value. * * @template TValue * * @param null|callable $callback * @param TValue $value * @return TValue * * @deprecated since 3.1, please use `Hyperf\Tappable\tap()` instead. */ function tap($value, $callback = null) { if (is_null($callback)) { return new HigherOrderTapProxy($value); } $callback($value); return $value; } } if (! function_exists('call')) { /** * Call a callback with the arguments. * * @param mixed $callback * @return null|mixed */ function call($callback, array $args = []) { $result = null; if ($callback instanceof \Closure) { $result = $callback(...$args); } elseif (is_object($callback) || (is_string($callback) && function_exists($callback))) { $result = $callback(...$args); } elseif (is_array($callback)) { [$object, $method] = $callback; $result = is_object($object) ? $object->{$method}(...$args) : $object::$method(...$args); } else { $result = call_user_func_array($callback, $args); } return $result; } } if (! function_exists('go')) { /** * @return bool|int * * @deprecated since 3.1, use `Hyperf\Coroutine\go` instead. */ function go(callable $callable) { $id = Coroutine::create($callable); return $id > 0 ? $id : false; } } if (! function_exists('co')) { /** * @return bool|int * * @deprecated since 3.1, use `Hyperf\Coroutine\co` instead. */ function co(callable $callable) { $id = Coroutine::create($callable); return $id > 0 ? $id : false; } } if (! function_exists('defer')) { /** * @deprecated since 3.1, use `Hyperf\Coroutine\defer` instead. */ function defer(callable $callable): void { Coroutine::defer($callable); } } if (! function_exists('class_basename')) { /** * Get the class "basename" of the given object / class. * * @param object|string $class * @return string */ function class_basename($class) { $class = is_object($class) ? get_class($class) : $class; return basename(str_replace('\\', '/', $class)); } } if (! function_exists('trait_uses_recursive')) { /** * Returns all traits used by a trait and its traits. * * @param object|string $trait * @return array */ function trait_uses_recursive($trait) { $traits = class_uses($trait); foreach ($traits as $trait) { $traits += trait_uses_recursive($trait); } return $traits; } } if (! function_exists('class_uses_recursive')) { /** * Returns all traits used by a class, its parent classes and trait of their traits. * * @param object|string $class * @return array */ function class_uses_recursive($class) { if (is_object($class)) { $class = get_class($class); } $results = []; /* @phpstan-ignore-next-line */ foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) { $results += trait_uses_recursive($class); } return array_unique($results); } } if (! function_exists('setter')) { /** * Create a setter string. */ function setter(string $property): string { return 'set' . Str::studly($property); } } if (! function_exists('getter')) { /** * Create a getter string. */ function getter(string $property): string { return 'get' . Str::studly($property); } } if (! function_exists('parallel')) { /** * @param callable[] $callables * @param int $concurrent if $concurrent is equal to 0, that means unlimited * * @deprecated since 3.1, use `Hyperf\Coroutine\parallel` instead. */ function parallel(array $callables, int $concurrent = 0) { $parallel = new Parallel($concurrent); foreach ($callables as $key => $callable) { $parallel->add($callable, $key); } return $parallel->wait(); } } if (! function_exists('make')) { /** * Create an object instance, if the DI container exist in ApplicationContext, * then the object will be created by DI container via `make()` method, if not, * the object will create by `new` keyword. */ function make(string $name, array $parameters = []) { if (ApplicationContext::hasContainer()) { $container = ApplicationContext::getContainer(); if (method_exists($container, 'make')) { return $container->make($name, $parameters); } } $parameters = array_values($parameters); return new $name(...$parameters); } } if (! function_exists('run')) { /** * Run callable in non-coroutine environment, all hook functions by Swoole only available in the callable. * * @param array|callable $callbacks * * @deprecated since 3.1, use `Hyperf\Coroutine\run` instead. */ function run($callbacks, int $flags = SWOOLE_HOOK_ALL): bool { if (Coroutine::inCoroutine()) { throw new RuntimeException('Function \'run\' only execute in non-coroutine environment.'); } \Swoole\Runtime::enableCoroutine($flags); /* @phpstan-ignore-next-line */ $result = \Swoole\Coroutine\run(...(array) $callbacks); \Swoole\Runtime::enableCoroutine(false); return $result; } } if (! function_exists('swoole_hook_flags')) { /** * Return the default swoole hook flags, you can rewrite it by defining `SWOOLE_HOOK_FLAGS`. */ function swoole_hook_flags(): int { return defined('SWOOLE_HOOK_FLAGS') ? SWOOLE_HOOK_FLAGS : SWOOLE_HOOK_ALL; } } if (! function_exists('optional')) { /** * Provide access to optional objects. * * @param mixed $value * @return mixed */ function optional($value = null, callable $callback = null) { if (is_null($callback)) { return new Optional($value); } if (! is_null($value)) { return $callback($value); } return null; } } if (! function_exists('wait')) { /** * @deprecated since 3.1, use `Hyperf\Coroutine\wait` instead. */ function wait(Closure $closure, ?float $timeout = null) { if (ApplicationContext::hasContainer()) { $waiter = ApplicationContext::getContainer()->get(Waiter::class); return $waiter->wait($closure, $timeout); } return (new Waiter())->wait($closure, $timeout); } } // TODO: Removed when deleting `\Hyperf\Utils\Collection`. class_exists(\Hyperf\Utils\Collection::class); src/HigherOrderCollectionProxy.php000064400000002623151360551670013340 0ustar00collection->{$this->method}(function ($value) use ($key) { return is_array($value) ? $value[$key] : $value->{$key}; }); } /** * Proxy a method call onto the collection items. */ public function __call(string $method, array $parameters) { return $this->collection->{$this->method}(function ($value) use ($method, $parameters) { return $value->{$method}(...$parameters); }); } } src/HigherOrderTapProxy.php000064400000001534151360551670011771 0ustar00target->{$method}(...$parameters); return $this->target; } } src/IPReader.php000064400000001171151360551670007510 0ustar00getMessage()); } } } src/InteractsWithTime.php000064400000003346151360551670011472 0ustar00parseDateInterval($delay); return $delay instanceof DateTimeInterface ? max(0, $delay->getTimestamp() - $this->currentTime()) : (int) $delay; } /** * Get the "available at" UNIX timestamp. * * @param DateInterval|DateTimeInterface|int $delay */ protected function availableAt($delay = 0): int { $delay = $this->parseDateInterval($delay); return $delay instanceof DateTimeInterface ? $delay->getTimestamp() : Carbon::now()->addSeconds($delay)->getTimestamp(); } /** * If the given value is an interval, convert it to a DateTime instance. * * @param DateInterval|DateTimeInterface|int $delay * @return DateTimeInterface|int */ protected function parseDateInterval($delay) { if ($delay instanceof DateInterval) { $delay = Carbon::now()->add($delay); } return $delay; } /** * Get the current system time as a UNIX timestamp. */ protected function currentTime(): int { return Carbon::now()->getTimestamp(); } } src/MessageBag.php000064400000020616151360551670010060 0ustar00 $value) { $value = $value instanceof Arrayable ? $value->toArray() : (array) $value; $this->messages[$key] = array_unique($value); } } /** * Convert the message bag to its string representation. */ public function __toString(): string { return $this->toJson(); } /** * Get the keys present in the message bag. */ public function keys(): array { return array_keys($this->messages); } /** * Add a message to the message bag. */ public function add(string $key, string $message): MessageBagContract { if ($this->isUnique($key, $message)) { $this->messages[$key][] = $message; } return $this; } /** * Merge a new array of messages into the message bag. * * @param array|MessageProvider $messages * @return $this */ public function merge($messages) { if ($messages instanceof MessageProvider) { $messages = $messages->getMessageBag()->getMessages(); } $this->messages = array_merge_recursive($this->messages, $messages); return $this; } /** * Determine if messages exist for all the given keys. * * @param null|array|string $key */ public function has($key): bool { if ($this->isEmpty()) { return false; } if (is_null($key)) { return $this->any(); } $keys = is_array($key) ? $key : func_get_args(); foreach ($keys as $key) { if ($this->first($key) === '') { return false; } } return true; } /** * Determine if messages exist for any of the given keys. * * @param array|string $keys */ public function hasAny($keys = []): bool { if ($this->isEmpty()) { return false; } $keys = is_array($keys) ? $keys : func_get_args(); foreach ($keys as $key) { if ($this->has($key)) { return true; } } return false; } /** * Get the first message from the message bag for a given key. * * @param string $key * @param string $format */ public function first($key = null, $format = null): string { $messages = is_null($key) ? $this->all($format) : $this->get($key, $format); $firstMessage = Arr::first($messages, null, ''); return is_array($firstMessage) ? Arr::first($firstMessage) : $firstMessage; } /** * Get all the messages from the message bag for a given key. */ public function get(string $key, ?string $format = null): array { // If the message exists in the message bag, we will transform it and return // the message. Otherwise, we will check if the key is implicit & collect // all the messages that match the given key and output it as an array. if (array_key_exists($key, $this->messages)) { return $this->transform( $this->messages[$key], $this->checkFormat($format), $key ); } if (Str::contains($key, '*')) { return $this->getMessagesForWildcardKey($key, $format); } return []; } /** * Get all the messages for every key in the message bag. */ public function all(?string $format = null): array { $format = $this->checkFormat($format); $all = []; foreach ($this->messages as $key => $messages) { $all = array_merge($all, $this->transform($messages, $format, $key)); } return $all; } /** * Get all the unique messages for every key in the message bag. */ public function unique(?string $format = null): array { return array_unique($this->all($format)); } /** * Get the raw messages in the message bag. */ public function messages(): array { return $this->messages; } /** * Get the raw messages in the message bag. */ public function getMessages(): array { return $this->messages(); } /** * Get the messages for the instance. */ public function getMessageBag(): MessageBagContract { return $this; } /** * Get the default message format. */ public function getFormat(): string { return $this->format; } /** * Set the default message format. */ public function setFormat(string $format = ':message'): self { $this->format = $format; return $this; } /** * Determine if the message bag has any messages. */ public function isEmpty(): bool { return ! $this->any(); } /** * Determine if the message bag has any messages. */ public function isNotEmpty(): bool { return $this->any(); } /** * Determine if the message bag has any messages. */ public function any(): bool { return $this->count() > 0; } /** * Get the number of messages in the message bag. */ public function count(): int { return count($this->messages, COUNT_RECURSIVE) - count($this->messages); } /** * Get the instance as an array. */ public function toArray(): array { return $this->getMessages(); } /** * Convert the object into something JSON serializable. */ public function jsonSerialize(): mixed { return $this->toArray(); } /** * Convert the object to its JSON representation. */ public function toJson(int $options = 0): string { return json_encode($this->jsonSerialize(), $options); } /** * Determine if a key and message combination already exists. */ protected function isUnique(string $key, string $message): bool { $messages = $this->messages; return ! isset($messages[$key]) || ! in_array($message, $messages[$key]); } /** * Get the messages for a wildcard key. */ protected function getMessagesForWildcardKey(string $key, ?string $format): array { return collect($this->messages) ->filter(function ($messages, $messageKey) use ($key) { return Str::is($key, $messageKey); }) ->map(function ($messages, $messageKey) use ($format) { return $this->transform( $messages, $this->checkFormat($format), $messageKey ); })->all(); } /** * Format an array of messages. */ protected function transform(array $messages, string $format, string $messageKey): array { return collect($messages) ->map(function ($message) use ($format, $messageKey) { // We will simply spin through the given messages and transform each one // replacing the :message placeholder with the real message allowing // the messages to be easily formatted to each developer's desires. return str_replace([':message', ':key'], [$message, $messageKey], $format); })->all(); } /** * Get the appropriate format based on the given format. */ protected function checkFormat(?string $format): string { return $format ?: $this->format; } } src/MimeTypeExtensionGuesser.php000064400000107363151360551670013053 0ustar00 'ez', 'application/applixware' => 'aw', 'application/atom+xml' => 'atom', 'application/atomcat+xml' => 'atomcat', 'application/atomsvc+xml' => 'atomsvc', 'application/ccxml+xml' => 'ccxml', 'application/cdmi-capability' => 'cdmia', 'application/cdmi-container' => 'cdmic', 'application/cdmi-domain' => 'cdmid', 'application/cdmi-object' => 'cdmio', 'application/cdmi-queue' => 'cdmiq', 'application/cu-seeme' => 'cu', 'application/davmount+xml' => 'davmount', 'application/docbook+xml' => 'dbk', 'application/dssc+der' => 'dssc', 'application/dssc+xml' => 'xdssc', 'application/ecmascript' => 'ecma', 'application/emma+xml' => 'emma', 'application/epub+zip' => 'epub', 'application/exi' => 'exi', 'application/font-tdpfr' => 'pfr', 'application/gml+xml' => 'gml', 'application/gpx+xml' => 'gpx', 'application/gxf' => 'gxf', 'application/hyperstudio' => 'stk', 'application/inkml+xml' => 'ink', 'application/ipfix' => 'ipfix', 'application/java-archive' => 'jar', 'application/java-serialized-object' => 'ser', 'application/java-vm' => 'class', 'application/javascript' => 'js', 'application/json' => 'json', 'application/jsonml+json' => 'jsonml', 'application/lost+xml' => 'lostxml', 'application/mac-binhex40' => 'hqx', 'application/mac-compactpro' => 'cpt', 'application/mads+xml' => 'mads', 'application/marc' => 'mrc', 'application/marcxml+xml' => 'mrcx', 'application/mathematica' => 'ma', 'application/mathml+xml' => 'mathml', 'application/mbox' => 'mbox', 'application/mediaservercontrol+xml' => 'mscml', 'application/metalink+xml' => 'metalink', 'application/metalink4+xml' => 'meta4', 'application/mets+xml' => 'mets', 'application/mods+xml' => 'mods', 'application/mp21' => 'm21', 'application/mp4' => 'mp4s', 'application/msword' => 'doc', 'application/mxf' => 'mxf', 'application/octet-stream' => 'bin', 'application/oda' => 'oda', 'application/oebps-package+xml' => 'opf', 'application/ogg' => 'ogx', 'application/omdoc+xml' => 'omdoc', 'application/onenote' => 'onetoc', 'application/oxps' => 'oxps', 'application/patch-ops-error+xml' => 'xer', 'application/pdf' => 'pdf', 'application/pgp-encrypted' => 'pgp', 'application/pgp-signature' => 'asc', 'application/pics-rules' => 'prf', 'application/pkcs10' => 'p10', 'application/pkcs7-mime' => 'p7m', 'application/pkcs7-signature' => 'p7s', 'application/pkcs8' => 'p8', 'application/pkix-attr-cert' => 'ac', 'application/pkix-cert' => 'cer', 'application/pkix-crl' => 'crl', 'application/pkix-pkipath' => 'pkipath', 'application/pkixcmp' => 'pki', 'application/pls+xml' => 'pls', 'application/postscript' => 'ai', 'application/prs.cww' => 'cww', 'application/pskc+xml' => 'pskcxml', 'application/rdf+xml' => 'rdf', 'application/reginfo+xml' => 'rif', 'application/relax-ng-compact-syntax' => 'rnc', 'application/resource-lists+xml' => 'rl', 'application/resource-lists-diff+xml' => 'rld', 'application/rls-services+xml' => 'rs', 'application/rpki-ghostbusters' => 'gbr', 'application/rpki-manifest' => 'mft', 'application/rpki-roa' => 'roa', 'application/rsd+xml' => 'rsd', 'application/rss+xml' => 'rss', 'application/rtf' => 'rtf', 'application/sbml+xml' => 'sbml', 'application/scvp-cv-request' => 'scq', 'application/scvp-cv-response' => 'scs', 'application/scvp-vp-request' => 'spq', 'application/scvp-vp-response' => 'spp', 'application/sdp' => 'sdp', 'application/set-payment-initiation' => 'setpay', 'application/set-registration-initiation' => 'setreg', 'application/shf+xml' => 'shf', 'application/smil+xml' => 'smi', 'application/sparql-query' => 'rq', 'application/sparql-results+xml' => 'srx', 'application/srgs' => 'gram', 'application/srgs+xml' => 'grxml', 'application/sru+xml' => 'sru', 'application/ssdl+xml' => 'ssdl', 'application/ssml+xml' => 'ssml', 'application/tei+xml' => 'tei', 'application/thraud+xml' => 'tfi', 'application/timestamped-data' => 'tsd', 'application/vnd.3gpp.pic-bw-large' => 'plb', 'application/vnd.3gpp.pic-bw-small' => 'psb', 'application/vnd.3gpp.pic-bw-var' => 'pvb', 'application/vnd.3gpp2.tcap' => 'tcap', 'application/vnd.3m.post-it-notes' => 'pwn', 'application/vnd.accpac.simply.aso' => 'aso', 'application/vnd.accpac.simply.imp' => 'imp', 'application/vnd.acucobol' => 'acu', 'application/vnd.acucorp' => 'atc', 'application/vnd.adobe.air-application-installer-package+zip' => 'air', 'application/vnd.adobe.formscentral.fcdt' => 'fcdt', 'application/vnd.adobe.fxp' => 'fxp', 'application/vnd.adobe.xdp+xml' => 'xdp', 'application/vnd.adobe.xfdf' => 'xfdf', 'application/vnd.ahead.space' => 'ahead', 'application/vnd.airzip.filesecure.azf' => 'azf', 'application/vnd.airzip.filesecure.azs' => 'azs', 'application/vnd.amazon.ebook' => 'azw', 'application/vnd.americandynamics.acc' => 'acc', 'application/vnd.amiga.ami' => 'ami', 'application/vnd.android.package-archive' => 'apk', 'application/vnd.anser-web-certificate-issue-initiation' => 'cii', 'application/vnd.anser-web-funds-transfer-initiation' => 'fti', 'application/vnd.antix.game-component' => 'atx', 'application/vnd.apple.installer+xml' => 'mpkg', 'application/vnd.apple.mpegurl' => 'm3u8', 'application/vnd.aristanetworks.swi' => 'swi', 'application/vnd.astraea-software.iota' => 'iota', 'application/vnd.audiograph' => 'aep', 'application/vnd.blueice.multipass' => 'mpm', 'application/vnd.bmi' => 'bmi', 'application/vnd.businessobjects' => 'rep', 'application/vnd.chemdraw+xml' => 'cdxml', 'application/vnd.chipnuts.karaoke-mmd' => 'mmd', 'application/vnd.cinderella' => 'cdy', 'application/vnd.claymore' => 'cla', 'application/vnd.cloanto.rp9' => 'rp9', 'application/vnd.clonk.c4group' => 'c4g', 'application/vnd.cluetrust.cartomobile-config' => 'c11amc', 'application/vnd.cluetrust.cartomobile-config-pkg' => 'c11amz', 'application/vnd.commonspace' => 'csp', 'application/vnd.contact.cmsg' => 'cdbcmsg', 'application/vnd.cosmocaller' => 'cmc', 'application/vnd.crick.clicker' => 'clkx', 'application/vnd.crick.clicker.keyboard' => 'clkk', 'application/vnd.crick.clicker.palette' => 'clkp', 'application/vnd.crick.clicker.template' => 'clkt', 'application/vnd.crick.clicker.wordbank' => 'clkw', 'application/vnd.criticaltools.wbs+xml' => 'wbs', 'application/vnd.ctc-posml' => 'pml', 'application/vnd.cups-ppd' => 'ppd', 'application/vnd.curl.car' => 'car', 'application/vnd.curl.pcurl' => 'pcurl', 'application/vnd.dart' => 'dart', 'application/vnd.data-vision.rdz' => 'rdz', 'application/vnd.dece.data' => 'uvf', 'application/vnd.dece.ttml+xml' => 'uvt', 'application/vnd.dece.unspecified' => 'uvx', 'application/vnd.dece.zip' => 'uvz', 'application/vnd.denovo.fcselayout-link' => 'fe_launch', 'application/vnd.dna' => 'dna', 'application/vnd.dolby.mlp' => 'mlp', 'application/vnd.dpgraph' => 'dpg', 'application/vnd.dreamfactory' => 'dfac', 'application/vnd.ds-keypoint' => 'kpxx', 'application/vnd.dvb.ait' => 'ait', 'application/vnd.dvb.service' => 'svc', 'application/vnd.dynageo' => 'geo', 'application/vnd.ecowin.chart' => 'mag', 'application/vnd.enliven' => 'nml', 'application/vnd.epson.esf' => 'esf', 'application/vnd.epson.msf' => 'msf', 'application/vnd.epson.quickanime' => 'qam', 'application/vnd.epson.salt' => 'slt', 'application/vnd.epson.ssf' => 'ssf', 'application/vnd.eszigno3+xml' => 'es3', 'application/vnd.ezpix-album' => 'ez2', 'application/vnd.ezpix-package' => 'ez3', 'application/vnd.fdf' => 'fdf', 'application/vnd.fdsn.mseed' => 'mseed', 'application/vnd.fdsn.seed' => 'seed', 'application/vnd.flographit' => 'gph', 'application/vnd.fluxtime.clip' => 'ftc', 'application/vnd.framemaker' => 'fm', 'application/vnd.frogans.fnc' => 'fnc', 'application/vnd.frogans.ltf' => 'ltf', 'application/vnd.fsc.weblaunch' => 'fsc', 'application/vnd.fujitsu.oasys' => 'oas', 'application/vnd.fujitsu.oasys2' => 'oa2', 'application/vnd.fujitsu.oasys3' => 'oa3', 'application/vnd.fujitsu.oasysgp' => 'fg5', 'application/vnd.fujitsu.oasysprs' => 'bh2', 'application/vnd.fujixerox.ddd' => 'ddd', 'application/vnd.fujixerox.docuworks' => 'xdw', 'application/vnd.fujixerox.docuworks.binder' => 'xbd', 'application/vnd.fuzzysheet' => 'fzs', 'application/vnd.genomatix.tuxedo' => 'txd', 'application/vnd.geogebra.file' => 'ggb', 'application/vnd.geogebra.tool' => 'ggt', 'application/vnd.geometry-explorer' => 'gex', 'application/vnd.geonext' => 'gxt', 'application/vnd.geoplan' => 'g2w', 'application/vnd.geospace' => 'g3w', 'application/vnd.gmx' => 'gmx', 'application/vnd.google-earth.kml+xml' => 'kml', 'application/vnd.google-earth.kmz' => 'kmz', 'application/vnd.grafeq' => 'gqf', 'application/vnd.groove-account' => 'gac', 'application/vnd.groove-help' => 'ghf', 'application/vnd.groove-identity-message' => 'gim', 'application/vnd.groove-injector' => 'grv', 'application/vnd.groove-tool-message' => 'gtm', 'application/vnd.groove-tool-template' => 'tpl', 'application/vnd.groove-vcard' => 'vcg', 'application/vnd.hal+xml' => 'hal', 'application/vnd.handheld-entertainment+xml' => 'zmm', 'application/vnd.hbci' => 'hbci', 'application/vnd.hhe.lesson-player' => 'les', 'application/vnd.hp-hpgl' => 'hpgl', 'application/vnd.hp-hpid' => 'hpid', 'application/vnd.hp-hps' => 'hps', 'application/vnd.hp-jlyt' => 'jlt', 'application/vnd.hp-pcl' => 'pcl', 'application/vnd.hp-pclxl' => 'pclxl', 'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx', 'application/vnd.ibm.minipay' => 'mpy', 'application/vnd.ibm.modcap' => 'afp', 'application/vnd.ibm.rights-management' => 'irm', 'application/vnd.ibm.secure-container' => 'sc', 'application/vnd.iccprofile' => 'icc', 'application/vnd.igloader' => 'igl', 'application/vnd.immervision-ivp' => 'ivp', 'application/vnd.immervision-ivu' => 'ivu', 'application/vnd.insors.igm' => 'igm', 'application/vnd.intercon.formnet' => 'xpw', 'application/vnd.intergeo' => 'i2g', 'application/vnd.intu.qbo' => 'qbo', 'application/vnd.intu.qfx' => 'qfx', 'application/vnd.ipunplugged.rcprofile' => 'rcprofile', 'application/vnd.irepository.package+xml' => 'irp', 'application/vnd.is-xpr' => 'xpr', 'application/vnd.isac.fcs' => 'fcs', 'application/vnd.jam' => 'jam', 'application/vnd.jcp.javame.midlet-rms' => 'rms', 'application/vnd.jisp' => 'jisp', 'application/vnd.joost.joda-archive' => 'joda', 'application/vnd.kahootz' => 'ktz', 'application/vnd.kde.karbon' => 'karbon', 'application/vnd.kde.kchart' => 'chrt', 'application/vnd.kde.kformula' => 'kfo', 'application/vnd.kde.kivio' => 'flw', 'application/vnd.kde.kontour' => 'kon', 'application/vnd.kde.kpresenter' => 'kpr', 'application/vnd.kde.kspread' => 'ksp', 'application/vnd.kde.kword' => 'kwd', 'application/vnd.kenameaapp' => 'htke', 'application/vnd.kidspiration' => 'kia', 'application/vnd.kinar' => 'kne', 'application/vnd.koan' => 'skp', 'application/vnd.kodak-descriptor' => 'sse', 'application/vnd.las.las+xml' => 'lasxml', 'application/vnd.llamagraphics.life-balance.desktop' => 'lbd', 'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe', 'application/vnd.lotus-1-2-3' => '123', 'application/vnd.lotus-approach' => 'apr', 'application/vnd.lotus-freelance' => 'pre', 'application/vnd.lotus-notes' => 'nsf', 'application/vnd.lotus-organizer' => 'org', 'application/vnd.lotus-screencam' => 'scm', 'application/vnd.lotus-wordpro' => 'lwp', 'application/vnd.macports.portpkg' => 'portpkg', 'application/vnd.mcd' => 'mcd', 'application/vnd.medcalcdata' => 'mc1', 'application/vnd.mediastation.cdkey' => 'cdkey', 'application/vnd.mfer' => 'mwf', 'application/vnd.mfmp' => 'mfm', 'application/vnd.micrografx.flo' => 'flo', 'application/vnd.micrografx.igx' => 'igx', 'application/vnd.mif' => 'mif', 'application/vnd.mobius.daf' => 'daf', 'application/vnd.mobius.dis' => 'dis', 'application/vnd.mobius.mbk' => 'mbk', 'application/vnd.mobius.mqy' => 'mqy', 'application/vnd.mobius.msl' => 'msl', 'application/vnd.mobius.plc' => 'plc', 'application/vnd.mobius.txf' => 'txf', 'application/vnd.mophun.application' => 'mpn', 'application/vnd.mophun.certificate' => 'mpc', 'application/vnd.mozilla.xul+xml' => 'xul', 'application/vnd.ms-artgalry' => 'cil', 'application/vnd.ms-cab-compressed' => 'cab', 'application/vnd.ms-excel' => 'xls', 'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam', 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb', 'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm', 'application/vnd.ms-excel.template.macroenabled.12' => 'xltm', 'application/vnd.ms-fontobject' => 'eot', 'application/vnd.ms-htmlhelp' => 'chm', 'application/vnd.ms-ims' => 'ims', 'application/vnd.ms-lrm' => 'lrm', 'application/vnd.ms-officetheme' => 'thmx', 'application/vnd.ms-pki.seccat' => 'cat', 'application/vnd.ms-pki.stl' => 'stl', 'application/vnd.ms-powerpoint' => 'ppt', 'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam', 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm', 'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm', 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm', 'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm', 'application/vnd.ms-project' => 'mpp', 'application/vnd.ms-word.document.macroenabled.12' => 'docm', 'application/vnd.ms-word.template.macroenabled.12' => 'dotm', 'application/vnd.ms-works' => 'wps', 'application/vnd.ms-wpl' => 'wpl', 'application/vnd.ms-xpsdocument' => 'xps', 'application/vnd.mseq' => 'mseq', 'application/vnd.musician' => 'mus', 'application/vnd.muvee.style' => 'msty', 'application/vnd.mynfc' => 'taglet', 'application/vnd.neurolanguage.nlu' => 'nlu', 'application/vnd.nitf' => 'ntf', 'application/vnd.noblenet-directory' => 'nnd', 'application/vnd.noblenet-sealer' => 'nns', 'application/vnd.noblenet-web' => 'nnw', 'application/vnd.nokia.n-gage.data' => 'ngdat', 'application/vnd.nokia.n-gage.symbian.install' => 'n-gage', 'application/vnd.nokia.radio-preset' => 'rpst', 'application/vnd.nokia.radio-presets' => 'rpss', 'application/vnd.novadigm.edm' => 'edm', 'application/vnd.novadigm.edx' => 'edx', 'application/vnd.novadigm.ext' => 'ext', 'application/vnd.oasis.opendocument.chart' => 'odc', 'application/vnd.oasis.opendocument.chart-template' => 'otc', 'application/vnd.oasis.opendocument.database' => 'odb', 'application/vnd.oasis.opendocument.formula' => 'odf', 'application/vnd.oasis.opendocument.formula-template' => 'odft', 'application/vnd.oasis.opendocument.graphics' => 'odg', 'application/vnd.oasis.opendocument.graphics-template' => 'otg', 'application/vnd.oasis.opendocument.image' => 'odi', 'application/vnd.oasis.opendocument.image-template' => 'oti', 'application/vnd.oasis.opendocument.presentation' => 'odp', 'application/vnd.oasis.opendocument.presentation-template' => 'otp', 'application/vnd.oasis.opendocument.spreadsheet' => 'ods', 'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots', 'application/vnd.oasis.opendocument.text' => 'odt', 'application/vnd.oasis.opendocument.text-master' => 'odm', 'application/vnd.oasis.opendocument.text-template' => 'ott', 'application/vnd.oasis.opendocument.text-web' => 'oth', 'application/vnd.olpc-sugar' => 'xo', 'application/vnd.oma.dd2+xml' => 'dd2', 'application/vnd.openofficeorg.extension' => 'oxt', 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx', 'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx', 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx', 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx', 'application/vnd.osgeo.mapguide.package' => 'mgp', 'application/vnd.osgi.dp' => 'dp', 'application/vnd.osgi.subsystem' => 'esa', 'application/vnd.palm' => 'pdb', 'application/vnd.pawaafile' => 'paw', 'application/vnd.pg.format' => 'str', 'application/vnd.pg.osasli' => 'ei6', 'application/vnd.picsel' => 'efif', 'application/vnd.pmi.widget' => 'wg', 'application/vnd.pocketlearn' => 'plf', 'application/vnd.powerbuilder6' => 'pbd', 'application/vnd.previewsystems.box' => 'box', 'application/vnd.proteus.magazine' => 'mgz', 'application/vnd.publishare-delta-tree' => 'qps', 'application/vnd.pvi.ptid1' => 'ptid', 'application/vnd.quark.quarkxpress' => 'qxd', 'application/vnd.realvnc.bed' => 'bed', 'application/vnd.recordare.musicxml' => 'mxl', 'application/vnd.recordare.musicxml+xml' => 'musicxml', 'application/vnd.rig.cryptonote' => 'cryptonote', 'application/vnd.rim.cod' => 'cod', 'application/vnd.rn-realmedia' => 'rm', 'application/vnd.rn-realmedia-vbr' => 'rmvb', 'application/vnd.route66.link66+xml' => 'link66', 'application/vnd.sailingtracker.track' => 'st', 'application/vnd.seemail' => 'see', 'application/vnd.sema' => 'sema', 'application/vnd.semd' => 'semd', 'application/vnd.semf' => 'semf', 'application/vnd.shana.informed.formdata' => 'ifm', 'application/vnd.shana.informed.formtemplate' => 'itp', 'application/vnd.shana.informed.interchange' => 'iif', 'application/vnd.shana.informed.package' => 'ipk', 'application/vnd.simtech-mindmapper' => 'twd', 'application/vnd.smaf' => 'mmf', 'application/vnd.smart.teacher' => 'teacher', 'application/vnd.solent.sdkm+xml' => 'sdkm', 'application/vnd.spotfire.dxp' => 'dxp', 'application/vnd.spotfire.sfs' => 'sfs', 'application/vnd.stardivision.calc' => 'sdc', 'application/vnd.stardivision.draw' => 'sda', 'application/vnd.stardivision.impress' => 'sdd', 'application/vnd.stardivision.math' => 'smf', 'application/vnd.stardivision.writer' => 'sdw', 'application/vnd.stardivision.writer-global' => 'sgl', 'application/vnd.stepmania.package' => 'smzip', 'application/vnd.stepmania.stepchart' => 'sm', 'application/vnd.sun.xml.calc' => 'sxc', 'application/vnd.sun.xml.calc.template' => 'stc', 'application/vnd.sun.xml.draw' => 'sxd', 'application/vnd.sun.xml.draw.template' => 'std', 'application/vnd.sun.xml.impress' => 'sxi', 'application/vnd.sun.xml.impress.template' => 'sti', 'application/vnd.sun.xml.math' => 'sxm', 'application/vnd.sun.xml.writer' => 'sxw', 'application/vnd.sun.xml.writer.global' => 'sxg', 'application/vnd.sun.xml.writer.template' => 'stw', 'application/vnd.sus-calendar' => 'sus', 'application/vnd.svd' => 'svd', 'application/vnd.symbian.install' => 'sis', 'application/vnd.syncml+xml' => 'xsm', 'application/vnd.syncml.dm+wbxml' => 'bdm', 'application/vnd.syncml.dm+xml' => 'xdm', 'application/vnd.tao.intent-module-archive' => 'tao', 'application/vnd.tcpdump.pcap' => 'pcap', 'application/vnd.tmobile-livetv' => 'tmo', 'application/vnd.trid.tpt' => 'tpt', 'application/vnd.triscape.mxs' => 'mxs', 'application/vnd.trueapp' => 'tra', 'application/vnd.ufdl' => 'ufd', 'application/vnd.uiq.theme' => 'utz', 'application/vnd.umajin' => 'umj', 'application/vnd.unity' => 'unityweb', 'application/vnd.uoml+xml' => 'uoml', 'application/vnd.vcx' => 'vcx', 'application/vnd.visio' => 'vsd', 'application/vnd.visionary' => 'vis', 'application/vnd.vsf' => 'vsf', 'application/vnd.wap.wbxml' => 'wbxml', 'application/vnd.wap.wmlc' => 'wmlc', 'application/vnd.wap.wmlscriptc' => 'wmlsc', 'application/vnd.webturbo' => 'wtb', 'application/vnd.wolfram.player' => 'nbp', 'application/vnd.wordperfect' => 'wpd', 'application/vnd.wqd' => 'wqd', 'application/vnd.wt.stf' => 'stf', 'application/vnd.xara' => 'xar', 'application/vnd.xfdl' => 'xfdl', 'application/vnd.yamaha.hv-dic' => 'hvd', 'application/vnd.yamaha.hv-script' => 'hvs', 'application/vnd.yamaha.hv-voice' => 'hvp', 'application/vnd.yamaha.openscoreformat' => 'osf', 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg', 'application/vnd.yamaha.smaf-audio' => 'saf', 'application/vnd.yamaha.smaf-phrase' => 'spf', 'application/vnd.yellowriver-custom-menu' => 'cmp', 'application/vnd.zul' => 'zir', 'application/vnd.zzazz.deck+xml' => 'zaz', 'application/voicexml+xml' => 'vxml', 'application/widget' => 'wgt', 'application/winhlp' => 'hlp', 'application/wsdl+xml' => 'wsdl', 'application/wspolicy+xml' => 'wspolicy', 'application/x-7z-compressed' => '7z', 'application/x-abiword' => 'abw', 'application/x-ace-compressed' => 'ace', 'application/x-apple-diskimage' => 'dmg', 'application/x-authorware-bin' => 'aab', 'application/x-authorware-map' => 'aam', 'application/x-authorware-seg' => 'aas', 'application/x-bcpio' => 'bcpio', 'application/x-bittorrent' => 'torrent', 'application/x-blorb' => 'blb', 'application/x-bzip' => 'bz', 'application/x-bzip2' => 'bz2', 'application/x-cbr' => 'cbr', 'application/x-cdlink' => 'vcd', 'application/x-cfs-compressed' => 'cfs', 'application/x-chat' => 'chat', 'application/x-chess-pgn' => 'pgn', 'application/x-conference' => 'nsc', 'application/x-cpio' => 'cpio', 'application/x-csh' => 'csh', 'application/x-debian-package' => 'deb', 'application/x-dgc-compressed' => 'dgc', 'application/x-director' => 'dir', 'application/x-doom' => 'wad', 'application/x-dtbncx+xml' => 'ncx', 'application/x-dtbook+xml' => 'dtb', 'application/x-dtbresource+xml' => 'res', 'application/x-dvi' => 'dvi', 'application/x-envoy' => 'evy', 'application/x-eva' => 'eva', 'application/x-font-bdf' => 'bdf', 'application/x-font-ghostscript' => 'gsf', 'application/x-font-linux-psf' => 'psf', 'application/x-font-otf' => 'otf', 'application/x-font-pcf' => 'pcf', 'application/x-font-snf' => 'snf', 'application/x-font-ttf' => 'ttf', 'application/x-font-type1' => 'pfa', 'application/x-font-woff' => 'woff', 'application/x-freearc' => 'arc', 'application/x-futuresplash' => 'spl', 'application/x-gca-compressed' => 'gca', 'application/x-glulx' => 'ulx', 'application/x-gnumeric' => 'gnumeric', 'application/x-gramps-xml' => 'gramps', 'application/x-gtar' => 'gtar', 'application/x-hdf' => 'hdf', 'application/x-install-instructions' => 'install', 'application/x-iso9660-image' => 'iso', 'application/x-java-jnlp-file' => 'jnlp', 'application/x-latex' => 'latex', 'application/x-lzh-compressed' => 'lzh', 'application/x-mie' => 'mie', 'application/x-mobipocket-ebook' => 'prc', 'application/x-ms-application' => 'application', 'application/x-ms-shortcut' => 'lnk', 'application/x-ms-wmd' => 'wmd', 'application/x-ms-wmz' => 'wmz', 'application/x-ms-xbap' => 'xbap', 'application/x-msaccess' => 'mdb', 'application/x-msbinder' => 'obd', 'application/x-mscardfile' => 'crd', 'application/x-msclip' => 'clp', 'application/x-msdownload' => 'exe', 'application/x-msmediaview' => 'mvb', 'application/x-msmetafile' => 'wmf', 'application/x-msmoney' => 'mny', 'application/x-mspublisher' => 'pub', 'application/x-msschedule' => 'scd', 'application/x-msterminal' => 'trm', 'application/x-mswrite' => 'wri', 'application/x-netcdf' => 'nc', 'application/x-nzb' => 'nzb', 'application/x-pkcs12' => 'p12', 'application/x-pkcs7-certificates' => 'p7b', 'application/x-pkcs7-certreqresp' => 'p7r', 'application/x-rar-compressed' => 'rar', 'application/x-rar' => 'rar', 'application/x-research-info-systems' => 'ris', 'application/x-sh' => 'sh', 'application/x-shar' => 'shar', 'application/x-shockwave-flash' => 'swf', 'application/x-silverlight-app' => 'xap', 'application/x-sql' => 'sql', 'application/x-stuffit' => 'sit', 'application/x-stuffitx' => 'sitx', 'application/x-subrip' => 'srt', 'application/x-sv4cpio' => 'sv4cpio', 'application/x-sv4crc' => 'sv4crc', 'application/x-t3vm-image' => 't3', 'application/x-tads' => 'gam', 'application/x-tar' => 'tar', 'application/x-tcl' => 'tcl', 'application/x-tex' => 'tex', 'application/x-tex-tfm' => 'tfm', 'application/x-texinfo' => 'texinfo', 'application/x-tgif' => 'obj', 'application/x-ustar' => 'ustar', 'application/x-wais-source' => 'src', 'application/x-x509-ca-cert' => 'der', 'application/x-xfig' => 'fig', 'application/x-xliff+xml' => 'xlf', 'application/x-xpinstall' => 'xpi', 'application/x-xz' => 'xz', 'application/x-zip-compressed' => 'zip', 'application/x-zmachine' => 'z1', 'application/xaml+xml' => 'xaml', 'application/xcap-diff+xml' => 'xdf', 'application/xenc+xml' => 'xenc', 'application/xhtml+xml' => 'xhtml', 'application/xml' => 'xml', 'application/xml-dtd' => 'dtd', 'application/xop+xml' => 'xop', 'application/xproc+xml' => 'xpl', 'application/xslt+xml' => 'xslt', 'application/xspf+xml' => 'xspf', 'application/xv+xml' => 'mxml', 'application/yang' => 'yang', 'application/yin+xml' => 'yin', 'application/zip' => 'zip', 'audio/adpcm' => 'adp', 'audio/basic' => 'au', 'audio/midi' => 'mid', 'audio/mp4' => 'mp4a', 'audio/mpeg' => 'mpga', 'audio/ogg' => 'oga', 'audio/s3m' => 's3m', 'audio/silk' => 'sil', 'audio/vnd.dece.audio' => 'uva', 'audio/vnd.digital-winds' => 'eol', 'audio/vnd.dra' => 'dra', 'audio/vnd.dts' => 'dts', 'audio/vnd.dts.hd' => 'dtshd', 'audio/vnd.lucent.voice' => 'lvp', 'audio/vnd.ms-playready.media.pya' => 'pya', 'audio/vnd.nuera.ecelp4800' => 'ecelp4800', 'audio/vnd.nuera.ecelp7470' => 'ecelp7470', 'audio/vnd.nuera.ecelp9600' => 'ecelp9600', 'audio/vnd.rip' => 'rip', 'audio/webm' => 'weba', 'audio/x-aac' => 'aac', 'audio/x-aiff' => 'aif', 'audio/x-caf' => 'caf', 'audio/x-flac' => 'flac', 'audio/x-matroska' => 'mka', 'audio/x-mpegurl' => 'm3u', 'audio/x-ms-wax' => 'wax', 'audio/x-ms-wma' => 'wma', 'audio/x-pn-realaudio' => 'ram', 'audio/x-pn-realaudio-plugin' => 'rmp', 'audio/x-wav' => 'wav', 'audio/xm' => 'xm', 'chemical/x-cdx' => 'cdx', 'chemical/x-cif' => 'cif', 'chemical/x-cmdf' => 'cmdf', 'chemical/x-cml' => 'cml', 'chemical/x-csml' => 'csml', 'chemical/x-xyz' => 'xyz', 'image/bmp' => 'bmp', 'image/x-ms-bmp' => 'bmp', 'image/cgm' => 'cgm', 'image/g3fax' => 'g3', 'image/gif' => 'gif', 'image/ief' => 'ief', 'image/jpeg' => 'jpg', 'image/pjpeg' => 'jpeg', 'image/ktx' => 'ktx', 'image/png' => 'png', 'image/prs.btif' => 'btif', 'image/sgi' => 'sgi', 'image/svg+xml' => 'svg', 'image/tiff' => 'tiff', 'image/vnd.adobe.photoshop' => 'psd', 'image/vnd.dece.graphic' => 'uvi', 'image/vnd.dvb.subtitle' => 'sub', 'image/vnd.djvu' => 'djvu', 'image/vnd.dwg' => 'dwg', 'image/vnd.dxf' => 'dxf', 'image/vnd.fastbidsheet' => 'fbs', 'image/vnd.fpx' => 'fpx', 'image/vnd.fst' => 'fst', 'image/vnd.fujixerox.edmics-mmr' => 'mmr', 'image/vnd.fujixerox.edmics-rlc' => 'rlc', 'image/vnd.ms-modi' => 'mdi', 'image/vnd.ms-photo' => 'wdp', 'image/vnd.net-fpx' => 'npx', 'image/vnd.wap.wbmp' => 'wbmp', 'image/vnd.xiff' => 'xif', 'image/webp' => 'webp', 'image/x-3ds' => '3ds', 'image/x-cmu-raster' => 'ras', 'image/x-cmx' => 'cmx', 'image/x-freehand' => 'fh', 'image/x-icon' => 'ico', 'image/x-mrsid-image' => 'sid', 'image/x-pcx' => 'pcx', 'image/x-pict' => 'pic', 'image/x-portable-anymap' => 'pnm', 'image/x-portable-bitmap' => 'pbm', 'image/x-portable-graymap' => 'pgm', 'image/x-portable-pixmap' => 'ppm', 'image/x-rgb' => 'rgb', 'image/x-tga' => 'tga', 'image/x-xbitmap' => 'xbm', 'image/x-xpixmap' => 'xpm', 'image/x-xwindowdump' => 'xwd', 'message/rfc822' => 'eml', 'model/iges' => 'igs', 'model/mesh' => 'msh', 'model/vnd.collada+xml' => 'dae', 'model/vnd.dwf' => 'dwf', 'model/vnd.gdl' => 'gdl', 'model/vnd.gtw' => 'gtw', 'model/vnd.mts' => 'mts', 'model/vnd.vtu' => 'vtu', 'model/vrml' => 'wrl', 'model/x3d+binary' => 'x3db', 'model/x3d+vrml' => 'x3dv', 'model/x3d+xml' => 'x3d', 'text/cache-manifest' => 'appcache', 'text/calendar' => 'ics', 'text/css' => 'css', 'text/csv' => 'csv', 'text/html' => 'html', 'text/n3' => 'n3', 'text/plain' => 'txt', 'text/prs.lines.tag' => 'dsc', 'text/richtext' => 'rtx', 'text/rtf' => 'rtf', 'text/sgml' => 'sgml', 'text/tab-separated-values' => 'tsv', 'text/troff' => 't', 'text/turtle' => 'ttl', 'text/uri-list' => 'uri', 'text/vcard' => 'vcard', 'text/vnd.curl' => 'curl', 'text/vnd.curl.dcurl' => 'dcurl', 'text/vnd.curl.scurl' => 'scurl', 'text/vnd.curl.mcurl' => 'mcurl', 'text/vnd.dvb.subtitle' => 'sub', 'text/vnd.fly' => 'fly', 'text/vnd.fmi.flexstor' => 'flx', 'text/vnd.graphviz' => 'gv', 'text/vnd.in3d.3dml' => '3dml', 'text/vnd.in3d.spot' => 'spot', 'text/vnd.sun.j2me.app-descriptor' => 'jad', 'text/vnd.wap.wml' => 'wml', 'text/vnd.wap.wmlscript' => 'wmls', 'text/vtt' => 'vtt', 'text/x-asm' => 's', 'text/x-c' => 'c', 'text/x-fortran' => 'f', 'text/x-pascal' => 'p', 'text/x-java-source' => 'java', 'text/x-opml' => 'opml', 'text/x-nfo' => 'nfo', 'text/x-setext' => 'etx', 'text/x-sfv' => 'sfv', 'text/x-uuencode' => 'uu', 'text/x-vcalendar' => 'vcs', 'text/x-vcard' => 'vcf', 'video/3gpp' => '3gp', 'video/3gpp2' => '3g2', 'video/h261' => 'h261', 'video/h263' => 'h263', 'video/h264' => 'h264', 'video/jpeg' => 'jpgv', 'video/jpm' => 'jpm', 'video/mj2' => 'mj2', 'video/mp4' => 'mp4', 'video/mpeg' => 'mpeg', 'video/ogg' => 'ogv', 'video/quicktime' => 'qt', 'video/vnd.dece.hd' => 'uvh', 'video/vnd.dece.mobile' => 'uvm', 'video/vnd.dece.pd' => 'uvp', 'video/vnd.dece.sd' => 'uvs', 'video/vnd.dece.video' => 'uvv', 'video/vnd.dvb.file' => 'dvb', 'video/vnd.fvt' => 'fvt', 'video/vnd.mpegurl' => 'mxu', 'video/vnd.ms-playready.media.pyv' => 'pyv', 'video/vnd.uvvu.mp4' => 'uvu', 'video/vnd.vivo' => 'viv', 'video/webm' => 'webm', 'video/x-f4v' => 'f4v', 'video/x-fli' => 'fli', 'video/x-flv' => 'flv', 'video/x-m4v' => 'm4v', 'video/x-matroska' => 'mkv', 'video/x-mng' => 'mng', 'video/x-ms-asf' => 'asf', 'video/x-ms-vob' => 'vob', 'video/x-ms-wm' => 'wm', 'video/x-ms-wmv' => 'wmv', 'video/x-ms-wmx' => 'wmx', 'video/x-ms-wvx' => 'wvx', 'video/x-msvideo' => 'avi', 'video/x-sgi-movie' => 'movie', 'video/x-smv' => 'smv', 'x-conference/x-cooltalk' => 'ice', ]; /** * Reversed from $defaultExtensions property in constructor. */ private $defaultMineTypes = []; public function __construct() { $this->defaultMineTypes = array_flip($this->defaultExtensions); } public function guessExtension(string $mimeType): ?string { return $this->defaultExtensions[$mimeType] ?? null; } public function guessMimeType(string $extension): ?string { return $this->defaultMineTypes[$extension] ?? null; } } src/Network.php000064400000002377151360551670007517 0ustar00 $value) { foreach ($value['unicast'] as $item) { if (! isset($item['address'])) { continue; } if (! Str::contains($item['address'], ':') && $item['address'] !== '127.0.0.1') { $ips[$name] = $item['address']; } } } } if (is_array($ips) && ! empty($ips)) { return current($ips); } $name = gethostname(); if ($name === false) { throw new RuntimeException('Can not get the internal IP.'); } return gethostbyname($name); } } src/Optional.php000064400000004727151360551670007654 0ustar00value)) { return $this->value->{$key} ?? null; } return null; } /** * Dynamically check a property exists on the underlying object. * * @param mixed $name * @return bool */ public function __isset($name) { if (is_object($this->value)) { return isset($this->value->{$name}); } return false; } /** * Dynamically pass a method to the underlying object. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { if (static::hasMacro($method)) { return $this->macroCall($method, $parameters); } if (is_object($this->value)) { return $this->value->{$method}(...$parameters); } return null; } /** * Determine if an item exists at an offset. */ public function offsetExists(mixed $offset): bool { return Arr::accessible($this->value) && Arr::exists($this->value, $offset); } /** * Get an item at a given offset. */ public function offsetGet(mixed $offset): mixed { return Arr::get($this->value, $offset); } /** * Set the item at a given offset. */ public function offsetSet(mixed $offset, mixed $value): void { if (Arr::accessible($this->value)) { $this->value[$offset] = $value; } } /** * Unset the item at a given offset. */ public function offsetUnset(mixed $offset): void { if (Arr::accessible($this->value)) { unset($this->value[$offset]); } } } src/Packer/JsonPacker.php000064400000001062151360551670011320 0ustar00passable = $passable; return $this; } /** * Set the array of pipes. * * @param array|mixed $pipes */ public function through($pipes): self { $this->pipes = is_array($pipes) ? $pipes : func_get_args(); return $this; } /** * Set the method to call on the pipes. */ public function via(string $method): self { $this->method = $method; return $this; } /** * Run the pipeline with a final destination callback. */ public function then(Closure $destination) { $pipeline = array_reduce(array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)); return $pipeline($this->passable); } /** * Run the pipeline and return the result. */ public function thenReturn() { return $this->then(fn ($passable) => $passable); } /** * Get the final piece of the Closure onion. */ protected function prepareDestination(Closure $destination): Closure { return static function ($passable) use ($destination) { return $destination($passable); }; } /** * Get a Closure that represents a slice of the application onion. */ protected function carry(): Closure { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { if (is_callable($pipe)) { // If the pipe is an instance of a Closure, we will just call it directly, but // otherwise we'll resolve the pipes out of the container and call it with // the appropriate method and arguments, returning the results back out. return $pipe($passable, $stack); } if (! is_object($pipe)) { [$name, $parameters] = $this->parsePipeString($pipe); // If the pipe is a string we will parse the string and resolve the class out // of the dependency injection container. We can then build a callable and // execute the pipe function giving in the parameters that are required. $pipe = $this->container->get($name); $parameters = array_merge([$passable, $stack], $parameters); } else { // If the pipe is already an object we'll just make a callable and pass it to // the pipe as-is. There is no need to do any extra parsing and formatting // since the object we're given was already a fully instantiated object. $parameters = [$passable, $stack]; } $carry = method_exists($pipe, $this->method) ? $pipe->{$this->method}(...$parameters) : $pipe(...$parameters); return $this->handleCarry($carry); }; }; } /** * Parse full pipe string to get name and parameters. * * @param string $pipe * @return array */ protected function parsePipeString($pipe) { [$name, $parameters] = array_pad(explode(':', $pipe, 2), 2, []); if (is_string($parameters)) { $parameters = explode(',', $parameters); } return [$name, $parameters]; } /** * Handle the value returned from each pipe before passing it to the next. * * @param mixed $carry * @return mixed */ protected function handleCarry($carry) { return $carry; } } src/Pluralizer.php000064400000007172151360551670010215 0ustar00pluralize($value); return static::matchCase($plural, $value); } /** * Get the singular form of an English word. * * @param string $value * @return string */ public static function singular($value) { $singular = static::getInflector()->singularize($value); return static::matchCase($singular, $value); } public static function setInflector(?Inflector $inflector): void { static::$inflector = $inflector; } /** * Get the inflector instance. */ public static function getInflector(): Inflector { if (is_null(static::$inflector)) { static::$inflector = new Inflector( new CachedWordInflector(new RulesetInflector( English\Rules::getSingularRuleset() )), new CachedWordInflector(new RulesetInflector( English\Rules::getPluralRuleset() )) ); } return static::$inflector; } /** * Determine if the given value is uncountable. * * @param string $value * @return bool */ protected static function uncountable($value) { return in_array(strtolower($value), static::$uncountable); } /** * Attempt to match the case on two strings. * * @param string $value * @param string $comparison * @return string */ protected static function matchCase($value, $comparison) { $functions = ['mb_strtolower', 'mb_strtoupper', 'ucfirst', 'ucwords']; foreach ($functions as $function) { if (call_user_func($function, $comparison) === $comparison) { return call_user_func($function, $value); } } return $value; } } src/Reflection/ClassInvoker.php000064400000001622151360551670012553 0ustar00reflection = new ReflectionClass($instance); } public function __get($name) { $property = $this->reflection->getProperty($name); $property->setAccessible(true); return $property->getValue($this->instance); } public function __call($name, $arguments) { $method = $this->reflection->getMethod($name); $method->setAccessible(true); return $method->invokeArgs($this->instance, $arguments); } } src/ResourceGenerator.php000064400000001407151360551670011515 0ustar00container->has(StdoutLoggerInterface::class) && $logger = $this->container->get(StdoutLoggerInterface::class)) { $logger->log($level, (string) $exception); } } return value($default); } } src/Serializer/ExceptionNormalizer.php000064400000006554151360551670014201 0ustar00getInstantiator()->instantiate($type); foreach (['code', 'message', 'file', 'line'] as $attribute) { if (isset($data[$attribute])) { $property = ReflectionManager::reflectProperty($type, $attribute); $property->setAccessible(true); $property->setValue($exception, $data[$attribute]); } } return $exception; } catch (\ReflectionException) { return new RuntimeException(sprintf( 'Bad data %s: %s', $data['class'], $data['message'] ), $data['code']); } catch (\TypeError) { return new RuntimeException(sprintf( 'Uncaught data %s: %s', $data['class'], $data['message'] ), $data['code']); } } return new RuntimeException('Bad data data: ' . json_encode($data)); } public function supportsDenormalization($data, $type, $format = null) { return class_exists($type) && is_a($type, Throwable::class, true); } public function normalize($object, string $format = null, array $context = []) { if ($object instanceof Serializable) { return serialize($object); } /* @var \Throwable $object */ return [ 'message' => $object->getMessage(), 'code' => $object->getCode(), 'file' => $object->getFile(), 'line' => $object->getLine(), ]; } public function supportsNormalization($data, string $format = null) { return $data instanceof Throwable; } public function hasCacheableSupportsMethod(): bool { return get_class($this) === __CLASS__; } protected function getInstantiator(): Instantiator { if ($this->instantiator instanceof Instantiator) { return $this->instantiator; } return $this->instantiator = new Instantiator(); } } src/Serializer/JsonDeNormalizer.php000064400000002020151360551670013405 0ustar00 (int) $data, 'string' => (string) $data, 'float' => (float) $data, 'array' => (array) $data, 'bool' => (bool) $data, 'mixed' => $data, default => $this->from($data, $class), }; } private function from(mixed $data, string $class): mixed { if (method_exists($class, 'jsonDeSerialize')) { return $class::jsonDeSerialize($data); } return $data; } } src/Serializer/ScalarNormalizer.php000064400000003270151360551670013440 0ustar00 (int) $data, 'string' => (string) $data, 'float' => (float) $data, 'bool' => (bool) $data, default => $data, }; } public function supportsDenormalization($data, $type, string $format = null) { return in_array($type, [ 'int', 'string', 'float', 'bool', 'mixed', 'array', // TODO: Symfony\Component\Serializer\Normalizer\ArrayDenormalizer not support array, so it denormalized in ScalarNormalizer. ]); } public function normalize($object, string $format = null, array $context = []) { return $object; } public function supportsNormalization($data, string $format = null) { return is_scalar($data); } } src/Serializer/Serializer.php000064400000030067151360551670012305 0ustar00serialize($obj, 'xml') * $serializer->decode($data, 'xml') * $serializer->denormalize($data, 'Class', 'xml') */ class Serializer implements Normalizer, SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface { private const SCALAR_TYPES = [ 'int' => true, 'bool' => true, 'float' => true, 'string' => true, ]; /** * @var Encoder\ChainEncoder */ protected $encoder; /** * @var Encoder\ChainDecoder */ protected $decoder; private $normalizers = []; private $denormalizerCache = []; private $normalizerCache = []; /** * @param (NormalizerInterface|DenormalizerInterface|mixed)[] $normalizers * @param (EncoderInterface|DecoderInterface|mixed)[] $encoders */ public function __construct(array $normalizers = [], array $encoders = []) { foreach ($normalizers as $normalizer) { if ($normalizer instanceof SerializerAwareInterface) { $normalizer->setSerializer($this); } if ($normalizer instanceof DenormalizerAwareInterface) { $normalizer->setDenormalizer($this); } if ($normalizer instanceof NormalizerAwareInterface) { $normalizer->setNormalizer($this); } if (! ($normalizer instanceof NormalizerInterface || $normalizer instanceof DenormalizerInterface)) { throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($normalizer), NormalizerInterface::class, DenormalizerInterface::class)); } } $this->normalizers = $normalizers; $decoders = []; $realEncoders = []; foreach ($encoders as $encoder) { if ($encoder instanceof SerializerAwareInterface) { $encoder->setSerializer($this); } if ($encoder instanceof DecoderInterface) { $decoders[] = $encoder; } if ($encoder instanceof EncoderInterface) { $realEncoders[] = $encoder; } if (! ($encoder instanceof EncoderInterface || $encoder instanceof DecoderInterface)) { throw new InvalidArgumentException(sprintf('The class "%s" neither implements "%s" nor "%s".', get_debug_type($encoder), EncoderInterface::class, DecoderInterface::class)); } } $this->encoder = new ChainEncoder($realEncoders); $this->decoder = new ChainDecoder($decoders); } final public function serialize($data, string $format, array $context = []): string { if (! $this->supportsEncoding($format, $context)) { throw new NotEncodableValueException(sprintf('Serialization for the format "%s" is not supported.', $format)); } if ($this->encoder->needsNormalization($format, $context)) { $data = $this->normalize($data, $format, $context); } return $this->encode($data, $format, $context); } /** * @phpstan-ignore-next-line * @param mixed $data */ final public function deserialize($data, string $type, string $format, array $context = []): mixed { if (! $this->supportsDecoding($format, $context)) { throw new NotEncodableValueException(sprintf('Deserialization for the format "%s" is not supported.', $format)); } $data = $this->decode($data, $format, $context); return $this->denormalize($data, $type, $format, $context); } public function normalize($object, string $format = null, array $context = []) { // If a normalizer supports the given data, use it if ($normalizer = $this->getNormalizer($object, $format, $context)) { return $normalizer->normalize($object, $format, $context); } if ($object === null || is_scalar($object)) { return $object; } if (is_array($object) || $object instanceof Traversable) { if ($object instanceof Countable && $object->count() === 0) { return $object; } $normalized = []; foreach ($object as $key => $val) { $normalized[$key] = $this->normalize($val, $format, $context); } return $normalized; } if (is_object($object)) { if (! $this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); } throw new NotNormalizableValueException(sprintf('Could not normalize object of type "%s", no supporting normalizer found.', get_debug_type($object))); } throw new NotNormalizableValueException('An unexpected value could not be normalized: ' . (! is_resource($object) ? var_export($object, true) : sprintf('%s resource', get_resource_type($object)))); } /** * @param mixed $data * @throws NotNormalizableValueException */ public function denormalize($data, string $type, string $format = null, array $context = []) { if (isset(self::SCALAR_TYPES[$type])) { if (is_scalar($data)) { switch ($type) { case 'int': return (int) $data; case 'bool': return (bool) $data; case 'float': return (float) $data; case 'string': return (string) $data; } } } if (! $this->normalizers) { throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); } if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) { return $normalizer->denormalize($data, $type, $format, $context); } throw new NotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.', $type)); } public function supportsNormalization($data, string $format = null, array $context = []): bool { return $this->getNormalizer($data, $format, $context) !== null; } public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool { return isset(self::SCALAR_TYPES[$type]) || $this->getDenormalizer($data, $type, $format, $context) !== null; } final public function encode($data, string $format, array $context = []): string { return $this->encoder->encode($data, $format, $context); } final public function decode(string $data, string $format, array $context = []) { return $this->decoder->decode($data, $format, $context); } public function supportsEncoding(string $format, array $context = []): bool { return $this->encoder->supportsEncoding($format, $context); } public function supportsDecoding(string $format, array $context = []): bool { return $this->decoder->supportsDecoding($format, $context); } /** * Returns a matching normalizer. * * @param mixed $data Data to get the serializer for * @param string $format Format name, present to give the option to normalizers to act differently based on formats * @param array $context Options available to the normalizer */ private function getNormalizer($data, ?string $format, array $context): ?NormalizerInterface { $type = is_object($data) ? get_class($data) : 'native-' . gettype($data); if (! isset($this->normalizerCache[$format][$type])) { $this->normalizerCache[$format][$type] = []; foreach ($this->normalizers as $k => $normalizer) { if (! $normalizer instanceof NormalizerInterface) { continue; } if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) { $this->normalizerCache[$format][$type][$k] = false; } elseif ($normalizer->supportsNormalization($data, $format)) { $this->normalizerCache[$format][$type][$k] = true; break; } } } foreach ($this->normalizerCache[$format][$type] as $k => $cached) { $normalizer = $this->normalizers[$k]; if ($cached || $normalizer->supportsNormalization($data, $format, $context)) { return $normalizer; } } return null; } /** * Returns a matching denormalizer. * * @param mixed $data Data to restore * @param string $class The expected class to instantiate * @param string $format Format name, present to give the option to normalizers to act differently based on formats * @param array $context Options available to the denormalizer */ private function getDenormalizer($data, string $class, ?string $format, array $context): ?DenormalizerInterface { if (! isset($this->denormalizerCache[$format][$class])) { $this->denormalizerCache[$format][$class] = []; foreach ($this->normalizers as $k => $normalizer) { if (! $normalizer instanceof DenormalizerInterface) { continue; } if (! $normalizer instanceof CacheableSupportsMethodInterface || ! $normalizer->hasCacheableSupportsMethod()) { $this->denormalizerCache[$format][$class][$k] = false; } elseif ($normalizer->supportsDenormalization(null, $class, $format)) { $this->denormalizerCache[$format][$class][$k] = true; break; } } } foreach ($this->denormalizerCache[$format][$class] as $k => $cached) { $normalizer = $this->normalizers[$k]; if ($cached || $normalizer->supportsDenormalization($data, $class, $format, $context)) { return $normalizer; } } return null; } } src/Serializer/SerializerFactory.php000064400000001452151360551670013631 0ustar00serializer([ new ExceptionNormalizer(), new ObjectNormalizer(), new ArrayDenormalizer(), new ScalarNormalizer(), ]); } } src/Serializer/SimpleNormalizer.php000064400000001407151360551670013464 0ustar00 (int) $data, 'string' => (string) $data, 'float' => (float) $data, 'array' => (array) $data, 'bool' => (bool) $data, default => $data, }; } } src/Serializer/SymfonyNormalizer.php000064400000001335151360551670013677 0ustar00serializer->normalize($object); } public function denormalize($data, string $class) { return $this->serializer->denormalize($data, $class); } } src/Str.php000064400000000572151360551670006631 0ustar00{$method}(...$parameters); } catch (Error|BadMethodCallException $e) { $pattern = '~^Call to undefined method (?P[^:]+)::(?P[^\(]+)\(\)$~'; if (! preg_match($pattern, $e->getMessage(), $matches)) { throw $e; } if ($matches['class'] !== get_class($object) || $matches['method'] !== $method) { throw $e; } static::throwBadMethodCallException($method); } } /** * Throw a bad method call exception for the given method. * @throws BadMethodCallException */ protected static function throwBadMethodCallException(string $method): void { throw new BadMethodCallException(sprintf('Call to undefined method %s::%s()', static::class, $method)); } } src/Traits/StaticInstance.php000064400000001425151360551670012241 0ustar00