diff --git a/LICENSE b/LICENSE index 261eeb9e..b9728b5c 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/composer.json b/composer.json index fc9bb299..49c0b60c 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,6 @@ "Max\\Database\\": "src/database/src", "Max\\Di\\": "src/di/src", "Max\\Event\\": "src/event/src", - "Max\\": "src/framework/src", "Max\\Http\\Server\\": "src/http-server/src", "Max\\Http\\Message\\": "src/http-message/src", "Max\\Routing\\": "src/routing/src", @@ -45,7 +44,6 @@ "max/di": "*", "max/aop": "*", "max/event": "*", - "max/framework": "*", "max/http-message": "*", "max/http-server": "*", "max/log": "*", diff --git a/src/aop/LICENSE b/src/aop/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/aop/LICENSE +++ b/src/aop/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/aop/src/PropertyHandlerVisitor.php b/src/aop/src/PropertyHandlerVisitor.php index 6a9c9a4f..f0ec42fc 100644 --- a/src/aop/src/PropertyHandlerVisitor.php +++ b/src/aop/src/PropertyHandlerVisitor.php @@ -78,9 +78,16 @@ public function leaveNode(Node $node) foreach ($reflectionConstructor->getParameters() as $key => $reflectionParameter) { $type = $reflectionParameter->getType(); if (is_null($type) - || ($type instanceof ReflectionNamedType && $type->isBuiltin()) - || $type instanceof ReflectionUnionType - || $type->getName() === 'Closure') { + || ($type instanceof ReflectionNamedType && ($type->isBuiltin() || $type->getName() === 'Closure')) + ) { + continue; + } + if ($type instanceof ReflectionUnionType) { + $unionType = []; + foreach ($type->getTypes() as $reflectionNamedType) { + $unionType[] = ($reflectionNamedType->isBuiltin() ? '' : '\\') . $reflectionNamedType->getName(); + } + $params[$key]->type = new Name(implode('|', $unionType)); continue; } $allowsNull = $reflectionParameter->allowsNull() ? '?' : ''; @@ -88,7 +95,7 @@ public function leaveNode(Node $node) } } $c = []; - if (! $this->metadata->hasConstructor) { + if (!$this->metadata->hasConstructor) { $constructor = new ClassMethod('__construct', [ 'params' => $params, ]); diff --git a/src/aop/src/Scanner.php b/src/aop/src/Scanner.php index bbe6f424..dc6315d6 100644 --- a/src/aop/src/Scanner.php +++ b/src/aop/src/Scanner.php @@ -53,7 +53,7 @@ public static function init(ScannerConfig $config): void self::$astManager = new AstManager(); self::$classMap = self::findClasses($config->getPaths()); self::$proxyMap = $proxyMap = self::$runtimeDir . 'proxy.php'; - if (!$config->isCache() || !self::$filesystem->exists($proxyMap)) { + if (! $config->isCache() || ! self::$filesystem->exists($proxyMap)) { self::$filesystem->exists($proxyMap) && self::$filesystem->delete($proxyMap); if (($pid = pcntl_fork()) == -1) { throw new Exception('Process fork failed.'); @@ -79,25 +79,6 @@ public static function findClasses(array $dirs): array return $classes; } - public static function scanConfig(string $installedJsonDir): array - { - $installed = json_decode(file_get_contents($installedJsonDir), true); - $installed = $installed['packages'] ?? $installed; - $config = []; - foreach ($installed as $package) { - if (isset($package['extra']['max']['config'])) { - $configProvider = $package['extra']['max']['config']; - $configProvider = new $configProvider(); - if (method_exists($configProvider, '__invoke')) { - if (is_array($configItem = $configProvider())) { - $config = array_merge_recursive($config, $configItem); - } - } - } - } - return $config; - } - public static function addClass(string $class, string $path): void { self::$classMap[$class] = $path; @@ -110,7 +91,7 @@ private static function getProxyMap(array $collectors): array { if (! self::$filesystem->exists(self::$proxyMap)) { $proxyDir = self::$runtimeDir . 'proxy/'; - self::$filesystem->makeDirectory($proxyDir, 0755, true, true); + self::$filesystem->exists($proxyDir) || self::$filesystem->makeDirectory($proxyDir, 0755, true, true); self::$filesystem->cleanDirectory($proxyDir); self::collect($collectors); $collectedClasses = array_unique(array_merge(AspectCollector::getCollectedClasses(), PropertyAnnotationCollector::getCollectedClasses())); diff --git a/src/cache/LICENSE b/src/cache/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/cache/LICENSE +++ b/src/cache/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/cache/publish/cache.php b/src/cache/publish/cache.php index 9974eab4..9726e710 100644 --- a/src/cache/publish/cache.php +++ b/src/cache/publish/cache.php @@ -32,5 +32,9 @@ 'port' => 11211, // 端口 ], ], + 'apcu' => [ + 'driver' => \Max\Cache\Driver\ApcDriver::class, + 'config' => [], + ], ], ]; diff --git a/src/cache/src/Driver/ApcDriver.php b/src/cache/src/Driver/ApcDriver.php index 3ddb7682..3980544c 100644 --- a/src/cache/src/Driver/ApcDriver.php +++ b/src/cache/src/Driver/ApcDriver.php @@ -15,37 +15,37 @@ class ApcDriver extends AbstractDriver { public function has(string $key): bool { - return (bool) apc_exists($key); + return (bool) \apc_exists($key); } public function get(string $key): mixed { - $data = apc_fetch($key, $success); + $data = \apc_fetch($key, $success); return $success === true ? $data : null; } public function set(string $key, mixed $value, ?int $ttl = null): bool { - return (bool) apc_store($key, $value, (int) $ttl); + return (bool) \apc_store($key, $value, (int) $ttl); } public function clear(): bool { - return apc_clear_cache('user'); + return \apc_clear_cache('user'); } public function delete(string $key): bool { - return (bool) apc_delete($key); + return (bool) \apc_delete($key); } public function increment(string $key, int $step = 1): int|bool { - return apc_inc($key, $step); + return \apc_inc($key, $step); } public function decrement(string $key, int $step = 1): int|bool { - return apc_dec($key, $step); + return \apc_dec($key, $step); } } diff --git a/src/config/LICENSE b/src/config/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/config/LICENSE +++ b/src/config/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/config/composer.json b/src/config/composer.json index fcdb7957..9fc66ec7 100644 --- a/src/config/composer.json +++ b/src/config/composer.json @@ -20,10 +20,5 @@ "require": { "php": "^8.0", "max/utils": "^1.0" - }, - "extra": { - "max": { - "config": "Max\\Config\\ConfigProvider" - } } } diff --git a/src/config/src/ConfigProvider.php b/src/config/src/ConfigProvider.php deleted file mode 100644 index 6a81f4c3..00000000 --- a/src/config/src/ConfigProvider.php +++ /dev/null @@ -1,24 +0,0 @@ - [ - 'Max\Config\Contract\ConfigInterface' => 'Max\Config\Repository', - ], - ]; - } -} diff --git a/src/context/LICENSE b/src/context/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/context/LICENSE +++ b/src/context/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/database/LICENSE b/src/database/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/database/LICENSE +++ b/src/database/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/di/LICENSE b/src/di/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/di/LICENSE +++ b/src/di/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/event/LICENSE b/src/event/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/event/LICENSE +++ b/src/event/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/event/composer.json b/src/event/composer.json index 1696ebe0..2369ba17 100644 --- a/src/event/composer.json +++ b/src/event/composer.json @@ -23,10 +23,5 @@ "require": { "php": "^8.0", "psr/event-dispatcher": "^1.0" - }, - "extra": { - "max": { - "config": "Max\\Event\\ConfigProvider" - } } } diff --git a/src/event/src/ConfigProvider.php b/src/event/src/ConfigProvider.php deleted file mode 100644 index 1f3a92f3..00000000 --- a/src/event/src/ConfigProvider.php +++ /dev/null @@ -1,26 +0,0 @@ - [ - 'Psr\EventDispatcher\ListenerProviderInterface' => 'Max\Event\ListenerProvider', - 'Psr\EventDispatcher\EventDispatcherInterface' => 'Max\Event\EventDispatcher', - 'Max\Event\Contract\EventDispatcherInterface' => 'Max\Event\EventDispatcher', - ], - ]; - } -} diff --git a/src/framework/LICENSE b/src/framework/LICENSE deleted file mode 100644 index 261eeb9e..00000000 --- a/src/framework/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/src/framework/README.md b/src/framework/README.md deleted file mode 100644 index e845566c..00000000 --- a/src/framework/README.md +++ /dev/null @@ -1 +0,0 @@ -README diff --git a/src/framework/composer.json b/src/framework/composer.json deleted file mode 100644 index 25d62eb0..00000000 --- a/src/framework/composer.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "max/framework", - "license": "Apache-2.0", - "homepage": "https://github.com/marxphp/framework", - "autoload": { - "psr-4": { - "Max\\": "src/" - } - }, - "authors": [ - { - "name": "chengyao", - "email": "987861463@qq.com" - } - ], - "require": { - "max/http-message": "^1.0", - "symfony/console": "*", - "filp/whoops": "*" - }, - "extra": { - "max": { - "config": "Max\\ConfigProvider" - } - } -} diff --git a/src/framework/src/Cache/Aspect/Cacheable.php b/src/framework/src/Cache/Aspect/Cacheable.php deleted file mode 100644 index 24edc568..00000000 --- a/src/framework/src/Cache/Aspect/Cacheable.php +++ /dev/null @@ -1,47 +0,0 @@ -store()->remember($this->getKey($joinPoint), fn () => $next($joinPoint), $this->ttl); - } - - protected function getKey(JoinPoint $joinPoint): string - { - $key = $this->key ?? ($joinPoint->class . ':' . $joinPoint->method . ':' . serialize(array_filter($joinPoint->parameters->getArrayCopy(), fn ($item) => ! is_object($item)))); - return $this->prefix ? ($this->prefix . ':' . $key) : $key; - } -} diff --git a/src/framework/src/Config/Annotation/Config.php b/src/framework/src/Config/Annotation/Config.php deleted file mode 100644 index 338f07b3..00000000 --- a/src/framework/src/Config/Annotation/Config.php +++ /dev/null @@ -1,56 +0,0 @@ -setAccessible(true); // 兼容PHP8.0 - $reflectionProperty->setValue($object, $this->getConfigValue()); - } catch (\Throwable $throwable) { - throw new PropertyHandleException('Property assign failed. ' . $throwable->getMessage()); - } - } - - /** - * 获取配置值 - * - * @throws ContainerExceptionInterface - * @throws ReflectionException - */ - protected function getConfigValue() - { - return make(ConfigInterface::class)->get($this->key, $this->default); - } -} diff --git a/src/framework/src/ConfigProvider.php b/src/framework/src/ConfigProvider.php deleted file mode 100644 index 6cfbe66b..00000000 --- a/src/framework/src/ConfigProvider.php +++ /dev/null @@ -1,29 +0,0 @@ - [ - 'Max\Console\Command\RouteListCommand', - 'Max\Console\Command\ControllerMakeCommand', - 'Max\Console\Command\MiddlewareMakeCommand', - ], - ]; - } -} diff --git a/src/framework/src/Console/Annotation/Command.php b/src/framework/src/Console/Annotation/Command.php deleted file mode 100644 index b64a1cfa..00000000 --- a/src/framework/src/Console/Annotation/Command.php +++ /dev/null @@ -1,22 +0,0 @@ -setName('make:controller') - ->setDescription('Making controllers.') - ->setDefinition([ - new InputArgument('controller', InputArgument::REQUIRED, 'A controller name such as `user`.'), - new InputOption('rest', 'r', InputOption::VALUE_OPTIONAL, 'Make a restful controller.'), - ]); - } - - /** - * @throws FileNotFoundException - * @return int - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $filesystem = new Filesystem(); - $controller = $input->getArgument('controller'); - $stubFile = $this->stubsPath . ($input->hasOption('rest') ? 'controller_rest.stub' : 'controller.stub'); - [$namespace, $controller] = $this->parse($controller); - $controllerPath = base_path('app/Http/Controller/' . str_replace('\\', '/', $namespace) . '/'); - $controllerFile = $controllerPath . $controller . 'Controller.php'; - if ($filesystem->exists($controllerFile)) { - $output->writeln('[WARN] 控制器已经存在!'); - return 1; - } - $filesystem->exists($controllerPath) || $filesystem->makeDirectory($controllerPath, 0777, true); - $filesystem->put($controllerFile, str_replace(['{{namespace}}', '{{class}}', '{{path}}'], ['App\\Http\\Controller' . $namespace, $controller . 'Controller', strtolower($controller)], $filesystem->get($stubFile))); - $output->writeln("[INFO] 控制器App\\Http\\Controller{$namespace}\\{$controller}Controller创建成功!"); - - return 1; - } - - /** - * @param $input - */ - protected function parse($input): array - { - $array = explode('/', $input); - $class = ucfirst(array_pop($array)); - $namespace = implode('\\', array_map(fn ($value) => ucfirst($value), $array)); - if (! empty($namespace)) { - $namespace = '\\' . $namespace; - } - return [$namespace, $class]; - } -} diff --git a/src/framework/src/Console/Command/MiddlewareMakeCommand.php b/src/framework/src/Console/Command/MiddlewareMakeCommand.php deleted file mode 100644 index a1fbeb95..00000000 --- a/src/framework/src/Console/Command/MiddlewareMakeCommand.php +++ /dev/null @@ -1,70 +0,0 @@ -setName('make:middleware') - ->setDescription('Making middleware.') - ->setDefinition([ - new InputArgument('middleware', InputArgument::REQUIRED, 'A middleware name such as `auth`.'), - new InputOption('suffix', 's', InputOption::VALUE_OPTIONAL, 'File is suffixed when this option is available.'), - ]); - } - - /** - * @throws Exception - * @return int - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $filesystem = new Filesystem(); - $stubFile = $this->stubsPath . 'middleware.stub'; - [$namespace, $middleware] = $this->parse($input->getArgument('middleware')); - $middlewarePath = base_path('app/Http/Middleware/' . str_replace('\\', '/', $namespace) . '/'); - $filesystem->exists($middlewarePath) || $filesystem->makeDirectory($middlewarePath, 0755, true); - $suffix = $input->getOption('suffix') ? 'Middleware' : ''; - $middlewareFile = $middlewarePath . $middleware . $suffix . '.php'; - $filesystem->exists($middlewareFile) && throw new InvalidArgumentException('中间件已经存在!'); - $filesystem->put($middlewareFile, str_replace(['{{namespace}}', '{{class}}'], ['App\\Http\\Middleware' . $namespace, $middleware . $suffix], file_get_contents($stubFile))); - $output->writeln("[DEBU]中间件App\\Http\\Middleware{$namespace}\\{$middleware}创建成功!"); - - return 1; - } - - /** - * @param $input - */ - protected function parse($input): array - { - $array = explode('/', $input); - $class = ucfirst(array_pop($array)); - $namespace = implode('\\', array_map(fn ($value) => ucfirst($value), $array)); - if (! empty($namespace)) { - $namespace = '\\' . $namespace; - } - return [$namespace, $class]; - } -} diff --git a/src/framework/src/Console/Command/RouteListCommand.php b/src/framework/src/Console/Command/RouteListCommand.php deleted file mode 100644 index 7af082d4..00000000 --- a/src/framework/src/Console/Command/RouteListCommand.php +++ /dev/null @@ -1,89 +0,0 @@ -setHeaders(['Methods', 'URI', 'Action', 'Middlewares']); - foreach ($this->getRoutes() as $route) { - $table->addRow([ - implode('|', $route->getMethods()), - $route->getPath(), - $this->formatRouteAction($route), - implode(PHP_EOL, $route->getMiddlewares()), - ]); - } - $table->render(); - return 0; - } - - protected function configure() - { - $this->setName('route:list') - ->setDescription('List the routes'); - } - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundException - * @throws ReflectionException - */ - protected function getRoutes(): Collection - { - $kernel = make(Kernel::class); - $routes = []; - foreach ($kernel->getAllRoutes() as $registeredRoute) { - foreach ($registeredRoute as $route) { - if (! in_array($route, $routes)) { - $routes[] = $route; - } - } - } - return Collection::make($routes)->unique(); - } - - /** - * 格式化action为string. - */ - protected function formatRouteAction(Route $route): string - { - $action = $route->getAction(); - if ($action instanceof Closure) { - return 'Closure'; - } - if (is_array($action)) { - return implode('@', $action); - } - return $action; - } -} diff --git a/src/framework/src/Console/Command/VendorPublishCommand.php b/src/framework/src/Console/Command/VendorPublishCommand.php deleted file mode 100644 index fc328150..00000000 --- a/src/framework/src/Console/Command/VendorPublishCommand.php +++ /dev/null @@ -1,45 +0,0 @@ -setName('vendor:publish') - ->setDescription('Publish publishable packages'); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $path = getcwd(); - $config = Scanner::scanConfig($path . '/vendor/composer/installed.json'); - if (isset($config['publish'])) { - foreach ($config['publish'] as $publish) { - $destination = $publish['destination']; - if (! file_exists($destination)) { - copy($publish['source'], $publish['destination']); - $output->writeln('[DEBUG] Package `' . $publish['name'] . '` config file published.'); - } - } - } - $path .= '/runtime/app/'; - file_exists($path) || mkdir($path); - file_put_contents($path . 'config.php', sprintf("')] - public function show(ServerRequestInterface $request, $id): ResponseInterface - { - } - - #[DeleteMapping(path: '/')] - public function delete(ServerRequestInterface $request, $id): ResponseInterface - { - } - - #[RequestMapping(path: '/', methods: ['PUT', 'PATCH'])] - public function update(ServerRequestInterface $request, $id): ResponseInterface - { - } -} diff --git a/src/framework/src/Console/Command/stubs/middleware.stub b/src/framework/src/Console/Command/stubs/middleware.stub deleted file mode 100644 index 8f395d8f..00000000 --- a/src/framework/src/Console/Command/stubs/middleware.stub +++ /dev/null @@ -1,28 +0,0 @@ -handle($request); - // after - return $response; - } -} diff --git a/src/framework/src/Console/CommandCollector.php b/src/framework/src/Console/CommandCollector.php deleted file mode 100644 index 6f9b4bf9..00000000 --- a/src/framework/src/Console/CommandCollector.php +++ /dev/null @@ -1,40 +0,0 @@ -addListener(make($class)); - } - } -} diff --git a/src/framework/src/Exception/Handler/WhoopsExceptionHandler.php b/src/framework/src/Exception/Handler/WhoopsExceptionHandler.php deleted file mode 100644 index 7733cbb0..00000000 --- a/src/framework/src/Exception/Handler/WhoopsExceptionHandler.php +++ /dev/null @@ -1,87 +0,0 @@ - PrettyPageHandler::class, - 'application/json' => JsonResponseHandler::class, - 'application/xml' => XmlResponseHandler::class, - ]; - - public function handle(Throwable $throwable, ServerRequestInterface $request): ?ResponseInterface - { - $whoops = new Run(); - [$handler, $contentType] = $this->negotiateHandler($request); - - $whoops->pushHandler($handler); - $whoops->allowQuit(false); - ob_start(); - $whoops->{RunInterface::EXCEPTION_HANDLER}($throwable); - $content = ob_get_clean(); - - return new Response(StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR, [HeaderInterface::HEADER_CONTENT_TYPE => $contentType], StandardStream::create((string)$content)); - } - - protected function negotiateHandler(ServerRequestInterface $request): array - { - $accepts = $request->getHeaderLine(HeaderInterface::HEADER_ACCEPT); - foreach (self::$preference as $contentType => $handler) { - if (Str::contains($accepts, $contentType)) { - return [$this->setupHandler(new $handler(), $request), $contentType]; - } - } - return [new PlainTextHandler(), 'text/plain']; - } - - protected function setupHandler($handler, ServerRequestInterface $request) - { - if ($handler instanceof PrettyPageHandler) { - $handler->handleUnconditionally(true); - - if (defined('BASE_PATH')) { - $handler->setApplicationRootPath(BASE_PATH); - } - - $handler->addDataTableCallback('GET Data', [$request, 'getQueryParams']); - $handler->addDataTableCallback('POST Data', [$request, 'getParsedBody']); - $handler->addDataTableCallback('Server/Request Data', [$request, 'getServerParams']); - $handler->addDataTableCallback('Cookies', [$request, 'getCookieParams']); - $handler->addDataTableCallback('Files', [$request, 'getUploadedFiles']); - $handler->addDataTableCallback('Attribute', [$request, 'getAttributes']); - try { - $handler->addDataTableCallback('Session', [$request->session(), 'all']); - } catch (Throwable) { - } - } elseif ($handler instanceof JsonResponseHandler) { - $handler->addTraceToOutput(true); - } - - return $handler; - } -} diff --git a/src/framework/src/Http/Annotation/JsonResponse.php b/src/framework/src/Http/Annotation/JsonResponse.php deleted file mode 100644 index 32bde0e2..00000000 --- a/src/framework/src/Http/Annotation/JsonResponse.php +++ /dev/null @@ -1,29 +0,0 @@ - 'application/json'], $data); - } -} diff --git a/src/framework/src/Http/Server/RouteCollector.php b/src/framework/src/Http/Server/RouteCollector.php deleted file mode 100644 index 20defa34..00000000 --- a/src/framework/src/Http/Server/RouteCollector.php +++ /dev/null @@ -1,58 +0,0 @@ -make(\Max\Routing\RouteCollector::class); - $router = new Router($attribute->prefix, $attribute->patterns, middlewares: $attribute->middlewares, routeCollector: $routeCollector); - self::$router = $router; - self::$class = $class; - } - } - - /** - * @throws NotFoundException - */ - public static function collectMethod(string $class, string $method, object $attribute): void - { - if ($attribute instanceof RequestMapping && self::$class === $class && !is_null(self::$router)) { - self::$router->request($attribute->path, [$class, $method], $attribute->methods)->middleware(...$attribute->middlewares); - } - } -} diff --git a/src/http-message/LICENSE b/src/http-message/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/http-message/LICENSE +++ b/src/http-message/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/http-message/src/UploadedFile.php b/src/http-message/src/UploadedFile.php index 865792d7..8e582964 100644 --- a/src/http-message/src/UploadedFile.php +++ b/src/http-message/src/UploadedFile.php @@ -129,4 +129,9 @@ public function getMimeType(): string } return $this->mimeType = (string)mime_content_type($this->tmpFilename); } + + public function isValid(): bool + { + return $this->error === UPLOAD_ERR_OK; + } } diff --git a/src/http-server/LICENSE b/src/http-server/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/http-server/LICENSE +++ b/src/http-server/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/http-server/src/Middleware/AllowCrossDomain.php b/src/http-server/src/Middleware/AllowCrossDomain.php index 38606085..86034aa6 100644 --- a/src/http-server/src/Middleware/AllowCrossDomain.php +++ b/src/http-server/src/Middleware/AllowCrossDomain.php @@ -40,7 +40,7 @@ class AllowCrossDomain implements MiddlewareInterface 'If-Modified-Since', 'If-None-Match', 'If-Unmodified-Since', - 'X-CSRF-TOKEN', + 'X-Csrf-Token', HeaderInterface::HEADER_X_REQUESTED_WITH, ]; diff --git a/src/macro/LICENSE b/src/macro/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/macro/LICENSE +++ b/src/macro/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/redis/LICENSE b/src/redis/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/redis/LICENSE +++ b/src/redis/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/routing/LICENSE b/src/routing/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/routing/LICENSE +++ b/src/routing/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/session/LICENSE b/src/session/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/session/LICENSE +++ b/src/session/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/swoole/LICENSE b/src/swoole/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/swoole/LICENSE +++ b/src/swoole/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/utils/LICENSE b/src/utils/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/utils/LICENSE +++ b/src/utils/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/utils/src/Contract/ValidatedData.php b/src/utils/src/Contract/ValidatedData.php new file mode 100644 index 00000000..c8a833fc --- /dev/null +++ b/src/utils/src/Contract/ValidatedData.php @@ -0,0 +1,10 @@ + + * @implements ArrayAccess + */ +class Fluent implements Arrayable, ArrayAccess, Jsonable, JsonSerializable +{ + /** + * All of the attributes set on the fluent instance. + * + * @var array + */ + protected $attributes = []; + + /** + * Create a new fluent instance. + * + * @param iterable $attributes + * + * @return void + */ + public function __construct($attributes = []) + { + foreach ($attributes as $key => $value) { + $this->attributes[$key] = $value; + } + } + + /** + * Get an attribute from the fluent instance. + * + * @template TGetDefault + * + * @param TKey $key + * @param TGetDefault|(\Closure(): TGetDefault) $default + * + * @return TValue|TGetDefault + */ + 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. + * + * @return array + */ + public function toArray(): array + { + return $this->attributes; + } + + /** + * Convert the object into something JSON serializable. + * + * @return array + */ + public function jsonSerialize(): array + { + 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. + * + * @param TKey $offset + * + * @return bool + */ + public function offsetExists($offset): bool + { + return isset($this->attributes[$offset]); + } + + /** + * Get the value for a given offset. + * + * @param TKey $offset + * + * @return TValue|null + */ + public function offsetGet($offset): mixed + { + return $this->get($offset); + } + + /** + * Set the value at the given offset. + * + * @param TKey $offset + * @param TValue $value + * + * @return void + */ + public function offsetSet($offset, $value): void + { + $this->attributes[$offset] = $value; + } + + /** + * Unset the value at the given offset. + * + * @param TKey $offset + * + * @return void + */ + public function offsetUnset($offset): void + { + unset($this->attributes[$offset]); + } + + /** + * Handle dynamic calls to the fluent instance to set attributes. + * + * @param TKey $method + * @param array{0: ?TValue} $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 TKey $key + * + * @return TValue|null + */ + public function __get($key) + { + return $this->get($key); + } + + /** + * Dynamically set the value of an attribute. + * + * @param TKey $key + * @param TValue $value + * + * @return void + */ + public function __set($key, $value) + { + $this->offsetSet($key, $value); + } + + /** + * Dynamically check if an attribute is set. + * + * @param TKey $key + * + * @return bool + */ + public function __isset($key) + { + return $this->offsetExists($key); + } + + /** + * Dynamically unset an attribute. + * + * @param TKey $key + * + * @return void + */ + public function __unset($key) + { + $this->offsetUnset($key); + } + + public function __toString(): string + { + return $this->toJson(); + } +} diff --git a/src/utils/src/MessageBag.php b/src/utils/src/MessageBag.php new file mode 100644 index 00000000..918f68c9 --- /dev/null +++ b/src/utils/src/MessageBag.php @@ -0,0 +1,428 @@ + $value) { + $value = $value instanceof Arrayable ? $value->toArray() : (array)$value; + + $this->messages[$key] = array_unique($value); + } + } + + /** + * Get the keys present in the message bag. + * + * @return array + */ + public function keys(): array + { + return array_keys($this->messages); + } + + /** + * Add a message to the message bag. + * + * @param string $key + * @param string $message + * + * @return $this + */ + public function add($key, $message): MessageBag + { + if ($this->isUnique($key, $message)) { + $this->messages[$key][] = $message; + } + + return $this; + } + + /** + * Add a message to the message bag if the given conditional is "true". + * + * @param bool $boolean + * @param string $key + * @param string $message + * + * @return $this + */ + public function addIf($boolean, $key, $message) + { + return $boolean ? $this->add($key, $message) : $this; + } + + /** + * Determine if a key and message combination already exists. + * + * @param string $key + * @param string $message + * + * @return bool + */ + protected function isUnique($key, $message) + { + $messages = (array)$this->messages; + + return !isset($messages[$key]) || !in_array($message, $messages[$key]); + } + + /** + * Merge a new array of messages into the message bag. + * + * @param \Illuminate\Contracts\Support\MessageProvider|array $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 of the given keys. + * + * @param array|string|null $key + * + * @return bool + */ + 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 + * + * @return bool + */ + public function hasAny($keys = []) + { + 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|null $key + * @param string|null $format + * + * @return string + */ + 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 of the messages from the message bag for a given key. + * + * @param string $key + * @param string|null $format + * + * @return array + */ + public function get($key, $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 the messages for a wildcard key. + * + * @param string $key + * @param string|null $format + * + * @return array + */ + protected function getMessagesForWildcardKey($key, $format) + { + 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(); + } + + /** + * Get all of the messages for every key in the message bag. + * + * @param string|null $format + * + * @return array + */ + public function all($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 of the unique messages for every key in the message bag. + * + * @param string|null $format + * + * @return array + */ + public function unique($format = null) + { + return array_unique($this->all($format)); + } + + /** + * Format an array of messages. + * + * @param array $messages + * @param string $format + * @param string $messageKey + * + * @return array + */ + protected function transform($messages, $format, $messageKey) + { + return collect((array)$messages) + ->map(function($message) use ($format, $messageKey) { + // We will simply spin through the given messages and transform each one + // replacing the :message place holder 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. + * + * @param string $format + * + * @return string + */ + protected function checkFormat($format) + { + return $format ?: $this->format; + } + + /** + * Get the raw messages in the message bag. + * + * @return array + */ + public function messages() + { + return $this->messages; + } + + /** + * Get the raw messages in the message bag. + * + * @return array + */ + public function getMessages(): array + { + return $this->messages(); + } + + /** + * Get the messages for the instance. + */ + public function getMessageBag(): MessageBag + { + return $this; + } + + /** + * Get the default message format. + * + * @return string + */ + public function getFormat(): string + { + return $this->format; + } + + /** + * Set the default message format. + * + * @param string $format + */ + public function setFormat($format = ':message') + { + $this->format = $format; + + return $this; + } + + /** + * Determine if the message bag has any messages. + * + * @return bool + */ + public function isEmpty(): bool + { + return !$this->any(); + } + + /** + * Determine if the message bag has any messages. + * + * @return bool + */ + public function isNotEmpty(): bool + { + return $this->any(); + } + + /** + * Determine if the message bag has any messages. + * + * @return bool + */ + public function any() + { + return $this->count() > 0; + } + + /** + * Get the number of messages in the message bag. + * + * @return int + */ + public function count(): int + { + return count($this->messages, COUNT_RECURSIVE) - count($this->messages); + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray() + { + return $this->getMessages(); + } + + /** + * Convert the object into something JSON serializable. + * + * @return array + */ + public function jsonSerialize(): array + { + return $this->toArray(); + } + + /** + * Convert the object to its JSON representation. + * + * @param int $options + * + * @return string + */ + public function toJson($options = 0) + { + return json_encode($this->jsonSerialize(), $options); + } + + /** + * Convert the message bag to its string representation. + * + * @return string + */ + public function __toString(): string + { + return $this->toJson(); + } +} diff --git a/src/utils/src/NamespacedItemResolver.php b/src/utils/src/NamespacedItemResolver.php new file mode 100644 index 00000000..4cdc45f8 --- /dev/null +++ b/src/utils/src/NamespacedItemResolver.php @@ -0,0 +1,112 @@ +parsed[$key])) { + return $this->parsed[$key]; + } + + // If the key does not contain a double colon, it means the key is not in a + // namespace, and is just a regular configuration item. Namespaces are a + // tool for organizing configuration items for things such as modules. + if (! str_contains($key, '::')) { + $segments = explode('.', $key); + + $parsed = $this->parseBasicSegments($segments); + } else { + $parsed = $this->parseNamespacedSegments($key); + } + + // Once we have the parsed array of this key's elements, such as its groups + // and namespace, we will cache each array inside a simple list that has + // the key and the parsed array for quick look-ups for later requests. + return $this->parsed[$key] = $parsed; + } + + /** + * Parse an array of basic segments. + * + * @param array $segments + * @return array + */ + protected function parseBasicSegments(array $segments) + { + // The first segment in a basic array will always be the group, so we can go + // ahead and grab that segment. If there is only one total segment we are + // just pulling an entire group out of the array and not a single item. + $group = $segments[0]; + + // If there is more than one segment in this group, it means we are pulling + // a specific item out of a group and will need to return this item name + // as well as the group so we know which item to pull from the arrays. + $item = count($segments) === 1 + ? null + : implode('.', array_slice($segments, 1)); + + return [null, $group, $item]; + } + + /** + * Parse an array of namespaced segments. + * + * @param string $key + * @return array + */ + protected function parseNamespacedSegments($key) + { + [$namespace, $item] = explode('::', $key); + + // First we'll just explode the first segment to get the namespace and group + // since the item should be in the remaining segments. Once we have these + // two pieces of data we can proceed with parsing out the item's value. + $itemSegments = explode('.', $item); + + $groupAndItem = array_slice( + $this->parseBasicSegments($itemSegments), 1 + ); + + return array_merge([$namespace], $groupAndItem); + } + + /** + * Set the parsed value of a key. + * + * @param string $key + * @param array $parsed + * @return void + */ + public function setParsedKey($key, $parsed) + { + $this->parsed[$key] = $parsed; + } + + /** + * Flush the cache of parsed keys. + * + * @return void + */ + public function flushParsedKeys() + { + $this->parsed = []; + } +} diff --git a/src/utils/src/Str.php b/src/utils/src/Str.php index 6a6a5392..48e76fc1 100644 --- a/src/utils/src/Str.php +++ b/src/utils/src/Str.php @@ -235,7 +235,7 @@ public static function contains($haystack, $needles, $ignoreCase = false) } foreach ((array) $needles as $needle) { - if ($needle !== '' && str_contains($haystack, $needle)) { + if ($needle !== '' && str_contains((string) $haystack, (string) $needle)) { return true; } } diff --git a/src/utils/src/ValidatedInput.php b/src/utils/src/ValidatedInput.php new file mode 100644 index 00000000..286df0a6 --- /dev/null +++ b/src/utils/src/ValidatedInput.php @@ -0,0 +1,226 @@ +input = $input; + } + + /** + * Get a subset containing the provided keys with values from the input data. + * + * @param array|mixed $keys + * + * @return array + */ + public function only($keys) + { + $results = []; + + $input = $this->input; + + $placeholder = new stdClass; + + foreach (is_array($keys) ? $keys : func_get_args() as $key) { + $value = data_get($input, $key, $placeholder); + + if ($value !== $placeholder) { + Arr::set($results, $key, $value); + } + } + + return $results; + } + + /** + * Get all of the input except for a specified array of items. + * + * @param array|mixed $keys + * + * @return array + */ + public function except($keys) + { + $keys = is_array($keys) ? $keys : func_get_args(); + + $results = $this->input; + + Arr::forget($results, $keys); + + return $results; + } + + /** + * Merge the validated input with the given array of additional data. + * + * @param array $items + * + * @return static + */ + public function merge(array $items) + { + return new static(array_merge($this->input, $items)); + } + + /** + * Get the input as a collection. + * + * @return \Illuminate\Support\Collection + */ + public function collect() + { + return new Collection($this->input); + } + + /** + * Get the raw, underlying input array. + * + * @return array + */ + public function all() + { + return $this->input; + } + + /** + * Get the instance as an array. + * + * @return array + */ + public function toArray(): array + { + return $this->all(); + } + + /** + * Dynamically access input data. + * + * @param string $name + * + * @return mixed + */ + public function __get($name) + { + return $this->input[$name]; + } + + /** + * Dynamically set input data. + * + * @param string $name + * @param mixed $value + * + * @return mixed + */ + public function __set($name, $value) + { + $this->input[$name] = $value; + } + + /** + * Determine if an input key is set. + * + * @return bool + */ + public function __isset($name) + { + return isset($this->input[$name]); + } + + /** + * Remove an input key. + * + * @param string $name + * + * @return void + */ + public function __unset($name) + { + unset($this->input[$name]); + } + + /** + * Determine if an item exists at an offset. + * + * @param mixed $key + * + * @return bool + */ + public function offsetExists($key): bool + { + return isset($this->input[$key]); + } + + /** + * Get an item at a given offset. + * + * @param mixed $key + * + * @return mixed + */ + public function offsetGet($key): mixed + { + return $this->input[$key]; + } + + /** + * Set the item at a given offset. + * + * @param mixed $key + * @param mixed $value + * + * @return void + */ + public function offsetSet($key, $value): void + { + if (is_null($key)) { + $this->input[] = $value; + } else { + $this->input[$key] = $value; + } + } + + /** + * Unset the item at a given offset. + * + * @param string $key + * + * @return void + */ + public function offsetUnset($key): void + { + unset($this->input[$key]); + } + + /** + * Get an iterator for the input. + * + * @return \ArrayIterator + */ + public function getIterator(): Traversable + { + return new ArrayIterator($this->input); + } +} diff --git a/src/validator/LICENSE b/src/validator/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/validator/LICENSE +++ b/src/validator/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/var-dumper/LICENSE b/src/var-dumper/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/var-dumper/LICENSE +++ b/src/var-dumper/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/view/LICENSE b/src/view/LICENSE index 261eeb9e..b9728b5c 100644 --- a/src/view/LICENSE +++ b/src/view/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright [2022] [ChengYao <987861463@qq.com>] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.