From 1320f7b34b0313c1b164cb0edb59bdde3f3ffce2 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Apr 2023 01:52:38 +0200 Subject: [PATCH 01/20] feat: routing v2 --- Dockerfile | 2 +- docker-compose.yml | 1 + src/App.php | 172 +++++------------------------------ src/Route.php | 178 +++---------------------------------- src/Router.php | 133 +++++++++++++++++++++++++++ tests/AppTest.php | 96 +------------------- tests/RouteTest.php | 45 ---------- tests/RouterTest.php | 83 +++++++++++++++++ tests/e2e/ResponseTest.php | 6 ++ tests/e2e/server.php | 16 ++-- 10 files changed, 274 insertions(+), 458 deletions(-) create mode 100644 src/Router.php create mode 100644 tests/RouterTest.php diff --git a/Dockerfile b/Dockerfile index c9ae2094..53fecf42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ RUN \ apk add --no-cache --virtual .deps \ - supervisor php$PHP_VERSION php$PHP_VERSION-fpm nginx bash + supervisor php$PHP_VERSION php$PHP_VERSION-fpm php$PHP_VERSION-mbstring nginx bash # Nginx Configuration (with self-signed ssl certificates) diff --git a/docker-compose.yml b/docker-compose.yml index 55ad1dfc..849fa5ec 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,4 +6,5 @@ services: ports: - "9020:80" volumes: + - ./src:/usr/share/nginx/html/src - ./tests:/usr/share/nginx/html/tests \ No newline at end of file diff --git a/src/App.php b/src/App.php index 244a0f47..fa438046 100755 --- a/src/App.php +++ b/src/App.php @@ -30,19 +30,6 @@ class App const MODE_TYPE_PRODUCTION = 'production'; - /** - * Routes - * - * @var array - */ - protected static array $routes = [ - self::REQUEST_METHOD_GET => [], - self::REQUEST_METHOD_POST => [], - self::REQUEST_METHOD_PUT => [], - self::REQUEST_METHOD_PATCH => [], - self::REQUEST_METHOD_DELETE => [], - ]; - /** * @var array */ @@ -98,13 +85,6 @@ class App */ protected static array $options = []; - /** - * Is Sorted? - * - * @var bool - */ - protected static bool $sorted = false; - /** * Route * @@ -122,15 +102,6 @@ class App */ protected static ?Route $wildcardRoute = null; - /** - * Matches - * - * Parameters matched from URL regex - * - * @var array - */ - protected array $matches = []; - /** * App * @@ -231,6 +202,7 @@ public static function init(): Hook { $hook = new Hook(); $hook->groups(['*']); + self::$init[] = $hook; return $hook; @@ -247,6 +219,7 @@ public static function shutdown(): Hook { $hook = new Hook(); $hook->groups(['*']); + self::$shutdown[] = $hook; return $hook; @@ -263,6 +236,7 @@ public static function options(): Hook { $hook = new Hook(); $hook->groups(['*']); + self::$options[] = $hook; return $hook; @@ -279,6 +253,7 @@ public static function error(): Hook { $hook = new Hook(); $hook->groups(['*']); + self::$errors[] = $hook; return $hook; @@ -338,9 +313,9 @@ public function getResource(string $name, bool $fresh = false): mixed return $this; } - if (! \array_key_exists($name, $this->resources) || $fresh || self::$resourcesCallbacks[$name]['reset']) { - if (! \array_key_exists($name, self::$resourcesCallbacks)) { - throw new Exception('Failed to find resource: "'.$name.'"'); + if (!\array_key_exists($name, $this->resources) || $fresh || self::$resourcesCallbacks[$name]['reset']) { + if (!\array_key_exists($name, self::$resourcesCallbacks)) { + throw new Exception('Failed to find resource: "' . $name . '"'); } $this->resources[$name] = \call_user_func_array( @@ -428,7 +403,7 @@ public static function isStage(): bool */ public static function getRoutes(): array { - return self::$routes; + return Router::getRoutes(); } /** @@ -446,7 +421,7 @@ public function getRoute(): ?Route * * @param Route $route */ - public function setRoute(Route $route): static + public function setRoute(Route $route): self { $this->route = $route; @@ -464,14 +439,9 @@ public function setRoute(Route $route): static */ public static function addRoute(string $method, string $url): Route { - if (! array_key_exists($method, self::$routes)) { - throw new Exception('Invalid Request Method'); - } $route = new Route($method, $url); - self::$routes[$method][$url] = $route; - - self::$sorted = false; + Router::addRoute($route); return $route; } @@ -487,7 +457,7 @@ public static function addRoute(string $method, string $url): Route */ public function match(Request $request, bool $fresh = false): ?Route { - if (null !== $this->route && ! $fresh) { + if (null !== $this->route && !$fresh) { return $this->route; } @@ -495,36 +465,7 @@ public function match(Request $request, bool $fresh = false): ?Route $method = $request->getMethod(); $method = (self::REQUEST_METHOD_HEAD == $method) ? self::REQUEST_METHOD_GET : $method; - if (! isset(self::$routes[$method])) { - self::$routes[$method] = []; - } - - foreach (self::$routes[$method] as $routeUrl => $route) { - /** @var Route $route */ - - // convert urls like '/users/:uid/posts/:pid' to regular expression - $regex = '@'.\preg_replace('@:[^/]+@', '([^/]+)', $routeUrl).'@'; - - // Check if the current request matches the expression - if (! \preg_match($regex, $url, $this->matches)) { - continue; - } - - \array_shift($this->matches); - $this->route = $route; - - if (isset($route->getAliases()[$routeUrl])) { - $this->route->setAliasPath($routeUrl); - } else { - $this->route->setAliasPath(null); - } - - break; - } - - if (! empty($this->route) && ('/' === $this->route->getPath()) && ($url != $this->route->getPath())) { - return null; - } + $this->route = Router::match($method, $url); return $this->route; } @@ -537,25 +478,15 @@ public function match(Request $request, bool $fresh = false): ?Route */ public function execute(Route $route, Request $request): static { - $keys = []; $arguments = []; $groups = $route->getGroups(); + $pathValues = $route->getPathValues($request); - // Extract keys from URL - $url = $route->getIsAlias() ? $route->getAliasPath() : $route->getPath(); - $keyRegex = '@^'.\preg_replace('@:[^/]+@', ':([^/]+)', $url).'$@'; - \preg_match($keyRegex, $url, $keys); - - // Remove the first key and value ( corresponding to full regex match ) - \array_shift($keys); - - // combine keys and values to one array - $values = \array_combine($keys, $this->matches); try { if ($route->getHook()) { foreach (self::$init as $hook) { // Global init hooks if (in_array('*', $hook->getGroups())) { - $arguments = $this->getArguments($hook, $values, $request->getParams()); + $arguments = $this->getArguments($hook, $pathValues, $request->getParams()); \call_user_func_array($hook->getAction(), $arguments); } } @@ -564,13 +495,13 @@ public function execute(Route $route, Request $request): static foreach ($groups as $group) { foreach (self::$init as $hook) { // Group init hooks if (in_array($group, $hook->getGroups())) { - $arguments = $this->getArguments($hook, $values, $request->getParams()); + $arguments = $this->getArguments($hook, $pathValues, $request->getParams()); \call_user_func_array($hook->getAction(), $arguments); } } } - $arguments = $this->getArguments($route, $values, $request->getParams()); + $arguments = $this->getArguments($route, $pathValues, $request->getParams()); // Call the callback with the matched positions as params if ($route->getIsActive()) { @@ -581,9 +512,8 @@ public function execute(Route $route, Request $request): static foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks - /** @var Hook $hook */ if (in_array($group, $hook->getGroups())) { - $arguments = $this->getArguments($hook, $values, $request->getParams()); + $arguments = $this->getArguments($hook, $pathValues, $request->getParams()); \call_user_func_array($hook->getAction(), $arguments); } } @@ -591,9 +521,8 @@ public function execute(Route $route, Request $request): static if ($route->getHook()) { foreach (self::$shutdown as $hook) { // Group shutdown hooks - /** @var Hook $hook */ if (in_array('*', $hook->getGroups())) { - $arguments = $this->getArguments($hook, $values, $request->getParams()); + $arguments = $this->getArguments($hook, $pathValues, $request->getParams()); \call_user_func_array($hook->getAction(), $arguments); } } @@ -603,26 +532,24 @@ public function execute(Route $route, Request $request): static foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks - /** @var Hook $error */ if (in_array($group, $error->getGroups())) { try { - $arguments = $this->getArguments($error, $values, $request->getParams()); + $arguments = $this->getArguments($error, $pathValues, $request->getParams()); \call_user_func_array($error->getAction(), $arguments); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: '.$e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } } } } foreach (self::$errors as $error) { // Global error hooks - /** @var Hook $error */ if (in_array('*', $error->getGroups())) { try { - $arguments = $this->getArguments($error, $values, $request->getParams()); + $arguments = $this->getArguments($error, $pathValues, $request->getParams()); \call_user_func_array($error->getAction(), $arguments); } catch (\Throwable $e) { - throw new Exception('Error handler had an error: '.$e->getMessage(), 500, $e); + throw new Exception('Error handler had an error: ' . $e->getMessage(), 500, $e); } } } @@ -652,13 +579,6 @@ protected function getArguments(Hook $hook, array $values, array $requestParams) $arg = $existsInRequest ? $requestParams[$key] : $param['default']; $value = $existsInValues ? $values[$key] : $arg; - if ($hook instanceof Route) { - if ($hook->getIsAlias() && isset($hook->getAliasParams($hook->getAliasPath())[$key])) { - $value = $hook->getAliasParams($hook->getAliasPath())[$key]; - $paramExists = true; - } - } - if (!$param['skipValidation']) { if (!$paramExists && !$param['optional']) { throw new Exception('Param "' . $key . '" is not optional.', 400); @@ -702,40 +622,6 @@ public function run(Request $request, Response $response): static return $response; }); - /* - * Re-order array - * - * For route to work with similar links where one is shorter than other - * but both might match given pattern - */ - if (! self::$sorted) { - foreach (self::$routes as $method => $list) { //adding route alias in $routes - foreach ($list as $key => $route) { - /** @var Route $route */ - foreach (array_keys($route->getAliases()) as $path) { - self::$routes[$method][$path] = $route; - } - } - } - foreach (self::$routes as $method => $list) { - \uksort(self::$routes[$method], function (string $a, string $b) { - return \strlen($b) - \strlen($a); - }); - - \uksort(self::$routes[$method], function (string $a, string $b) { - $result = \count(\explode('/', $b)) - \count(\explode('/', $a)); - - if ($result === 0) { - return \substr_count($a, ':') - \substr_count($b, ':'); - } - - return $result; - }); - } - - self::$sorted = true; - } - $method = $request->getMethod(); $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; @@ -757,7 +643,6 @@ public function run(Request $request, Response $response): static try { foreach ($groups as $group) { foreach (self::$options as $option) { // Group options hooks - /** @var Hook $option */ if (in_array($group, $option->getGroups())) { \call_user_func_array($option->getAction(), $this->getArguments($option, [], $request->getParams())); } @@ -765,14 +650,12 @@ public function run(Request $request, Response $response): static } foreach (self::$options as $option) { // Global options hooks - /** @var Hook $option */ if (in_array('*', $option->getGroups())) { \call_user_func_array($option->getAction(), $this->getArguments($option, [], $request->getParams())); } } } catch (\Throwable $e) { foreach (self::$errors as $error) { // Global error hooks - /** @var Hook $error */ if (in_array('*', $error->getGroups())) { self::setResource('error', function () use ($e) { return $e; @@ -825,7 +708,7 @@ protected function validate(string $key, array $param, mixed $value): void } if (!$validator->isValid($value)) { - throw new Exception('Invalid '.$key.': '.$validator->getDescription(), 400); + throw new Exception('Invalid ' . $key . ': ' . $validator->getDescription(), 400); } } @@ -840,13 +723,6 @@ public static function reset(): void self::$init = []; self::$shutdown = []; self::$options = []; - self::$sorted = false; - self::$routes = [ - self::REQUEST_METHOD_GET => [], - self::REQUEST_METHOD_POST => [], - self::REQUEST_METHOD_PUT => [], - self::REQUEST_METHOD_PATCH => [], - self::REQUEST_METHOD_DELETE => [], - ]; + Router::reset(); } } diff --git a/src/Route.php b/src/Route.php index cf6ba482..fb684d51 100755 --- a/src/Route.php +++ b/src/Route.php @@ -25,62 +25,20 @@ class Route extends Hook */ protected string $path = ''; - /** - * Alias path - * - * @var null|string - */ - protected ?string $aliasPath = null; - - /** - * Array of aliases where key is the path and value is an array of params - * - * @var array - */ - protected array $aliases = []; - - /** - * Is Alias Route? - * - * @var bool - */ - protected bool $isAlias = false; - - /** - * @var int - */ - public static int $counter = 0; - - /** - * @var int - */ - protected int $order; - - /** - * @var bool - */ protected bool $isActive = true; - /** - * @param string $method - * @param string $path - */ + protected array $pathParams = []; + public function __construct(string $method, string $path) { - self::$counter++; - $this->path($path); $this->method = $method; - $this->order = self::$counter; $this->action = function (): void { }; } /** * Add path - * - * @param string $path - * @return static */ public function path(string $path): static { @@ -89,48 +47,18 @@ public function path(string $path): static return $this; } - /** - * Add alias - * - * @param string $path - * @param array $params - * @return static - */ - public function alias(string $path, array $params = []): static - { - $this->aliases[$path] = $params; - - return $this; - } - + //TODO: remove /** * Set isActive - * - * @param bool $isActive - * @return void */ public function setIsActive(bool $isActive): void { $this->isActive = $isActive; } - /** - * Set isAlias - * - * @param bool $isAlias - * @return void - */ - public function setIsAlias(bool $isAlias): void - { - $this->isAlias = $isAlias; - } - /** * Set hook status * When set false, hooks for this route will be skipped. - * - * @param bool $hook - * @return static */ public function hook(bool $hook = true): static { @@ -141,8 +69,6 @@ public function hook(bool $hook = true): static /** * When set to false the route will be skipped - * - * @return bool */ public function getIsActive(): bool { @@ -151,8 +77,6 @@ public function getIsActive(): bool /** * Get HTTP Method - * - * @return string */ public function getMethod(): string { @@ -161,8 +85,6 @@ public function getMethod(): string /** * Get path - * - * @return string */ public function getPath(): string { @@ -170,99 +92,27 @@ public function getPath(): string } /** - * Get Aliases - * - * Returns an array where the keys are paths and values are params - * - * @return array + * Get hook status */ - public function getAliases(): array + public function getHook(): bool { - return $this->aliases; + return $this->hook; } - /** - * Get Alias path - * - * For backwards compatibility, returns the first alias path - * - * @return string - */ - public function getAliasPath(): string + public function setPathParam(string $key, int $index): void { - if ($this->aliasPath !== null) { - return $this->aliasPath; - } - - $paths = array_keys($this->aliases); - if (count($paths) === 0) { - return ''; - } - - return $paths[0]; + $this->pathParams[$key] = $index; } - /** - * Set Alias path - * - * For backwards compatibility, returns the first alias path - * - * @return void - */ - public function setAliasPath(?string $path): void + public function getPathValues(Request $request): array { - $this->aliasPath = $path; - $this->setIsAlias($path !== null); - } + $pathParams = []; + $parts = explode('/', ltrim($request->getURI(), '/')); - /** - * Get Alias Params - * - * For backwards compatibility, returns the first alias params if no path passed - * - * @return array - */ - public function getAliasParams(string $path = null): array - { - if ($path === null) { - $params = array_values($this->aliases); - if (count($params) === 0) { - return []; - } - - return $params[0]; + foreach ($this->pathParams as $key => $index) { + $pathParams[$key] = $parts[$index]; } - return $this->aliases[$path]; - } - - /** - * Get is Alias - * - * @return bool - */ - public function getIsAlias(): bool - { - return $this->isAlias; - } - - /** - * Get Route Order ID - * - * @return int - */ - public function getOrder(): int - { - return $this->order; - } - - /** - * Get hook status - * - * @return bool - */ - public function getHook(): bool - { - return $this->hook; + return $pathParams; } } diff --git a/src/Router.php b/src/Router.php new file mode 100644 index 00000000..fffc31f8 --- /dev/null +++ b/src/Router.php @@ -0,0 +1,133 @@ + + */ + protected static array $routes = [ + App::REQUEST_METHOD_GET => [], + App::REQUEST_METHOD_POST => [], + App::REQUEST_METHOD_PUT => [], + App::REQUEST_METHOD_PATCH => [], + App::REQUEST_METHOD_DELETE => [], + ]; + + /** + * Contains the positions of all params in the paths of all registered Routes. + * + * @var array + */ + protected static array $params = []; + + public static function getRoutes(): array + { + return self::$routes; + } + + public static function addRoute(Route $route): void + { + [$path, $params] = self::preparePath($route->getPath()); + + if (! array_key_exists($route->getMethod(), self::$routes)) { + throw new Exception("Method ({$route->getMethod()}) not supported."); + } + + if (array_key_exists($path, self::$routes[$route->getMethod()])) { + throw new Exception("Route for ({$route->getMethod()}:{$path}) already registered."); + } + + foreach ($params as $key => $index) { + $route->setPathParam($key, $index); + } + + self::$routes[$route->getMethod()][$path] = $route; + } + + public static function match(string $method, string $path): Route|null + { + if (! array_key_exists($method, self::$routes)) { + return null; + } + + $parts = array_values(array_filter(explode('/', $path))); + $length = count($parts) - 1; + $filteredParams = array_filter(self::$params, fn ($i) => $i <= $length); + + foreach (self::combinations($filteredParams) as $sample) { + $sample = array_filter($sample, fn (int $i) => $i <= $length); + $match = implode( + '/', + array_replace( + $parts, + array_fill_keys($sample, self::PLACEHOLDER_TOKEN) + ) + ); + + if (array_key_exists($match, self::$routes[$method])) { + return self::$routes[$method][$match]; + } + } + + return null; + } + + public static function reset(): void + { + self::$params = []; + self::$routes = [ + App::REQUEST_METHOD_GET => [], + App::REQUEST_METHOD_POST => [], + App::REQUEST_METHOD_PUT => [], + App::REQUEST_METHOD_PATCH => [], + App::REQUEST_METHOD_DELETE => [], + ]; + } + + protected static function combinations(array $set): iterable + { + yield []; + + $results = [[]]; + + foreach ($set as $element) { + foreach ($results as $combination) { + $ret = array_merge([$element], $combination); + $results[] = $ret; + + yield $ret; + } + } + } + + protected static function preparePath(string $path): array + { + $parts = array_values(array_filter(explode('/', $path))); + $prepare = ''; + $params = []; + + foreach ($parts as $key => $part) { + if ($key !== 0) { + $prepare .= '/'; + } + + if (str_starts_with($part, ':')) { + $prepare .= self::PLACEHOLDER_TOKEN; + $params[ltrim($part, ':')] = $key; + if (! in_array($key, self::$params)) { + self::$params[] = $key; + } + } else { + $prepare .= $part; + } + } + + return [$prepare, $params]; + } +} diff --git a/tests/AppTest.php b/tests/AppTest.php index 79bc9b91..a74fbf41 100755 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -114,19 +114,6 @@ public function testCanGetResources(): void $this->assertEquals('x-def-y-def-'.$resource, $result); } - public function testCanAddRoute(): void - { - $getRoute = App::addRoute(App::REQUEST_METHOD_GET, '/addroute'); - $postRoute = App::addRoute(App::REQUEST_METHOD_POST, '/addroute'); - - $routes = App::getRoutes(); - $this->assertEquals($getRoute, $routes[App::REQUEST_METHOD_GET]['/addroute']); - $this->assertEquals($postRoute, $routes[App::REQUEST_METHOD_POST]['/addroute']); - - $this->expectExceptionMessage('Invalid Request Method'); - App::addRoute('REST', '/addroute'); - } - public function testCanExecuteRoute(): void { App::setResource('rand', fn () => rand()); @@ -143,7 +130,6 @@ public function testCanExecuteRoute(): void $route = new Route('GET', '/path'); $route - ->alias('/path1', ['x' => 'x-def-1', 'y' => 'y-def-1']) ->param('x', 'x-def', new Text(200), 'x param', true) ->param('y', 'y-def', new Text(200), 'y param', true) ->action(function ($x, $y) { @@ -155,17 +141,6 @@ public function testCanExecuteRoute(): void $result = \ob_get_contents(); \ob_end_clean(); - // test alias with param override - $route->setIsAlias(true); - - \ob_start(); - $this->app->execute($route, new Request()); - $result1 = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals('x-def-y-def', $result); - $this->assertEquals('x-def-1-y-def-1', $result1); - // With Params $route = new Route('GET', '/path'); @@ -498,75 +473,6 @@ public function testCanRunRequest(): void $this->assertStringNotContainsString('HELLO', $result); } - public function testCanRunAliasEndpoint(): void - { - // Test head requests - App::get('/storage/buckets/:bucketId/files/:fileId') - ->alias('/storage/files/:fileId', [ - 'bucketId' => 'default', - ]) - ->param('bucketId', 'bucketid', new Text(100), 'My id', false) - ->param('fileId', 'fileId', new Text(100), 'My id', false) - ->inject('response') - ->action(function ($bucketId, $fileId, $response) { - $response->send('HELLO'); - }); - - $_SERVER['REQUEST_METHOD'] = 'HEAD'; - $_SERVER['REQUEST_URI'] = '/storage/files/myfileid'; - - // Test Alias - \ob_start(); - $this->app->run(new Request(), new Response()); - $result1 = \ob_get_contents(); - \ob_end_clean(); - - $this->assertStringNotContainsString('HELLO', $result1); - } - - public function providerAliases(): array - { - return [ - '/real/:param1' => ['/real/p1', 'p1'], - '/alias' => ['/alias', 'default'], - '/another/:param1' => ['/another/a', 'a'], - '/param2' => ['/param2', 'param2'], - ]; - } - - /** - * @dataProvider providerAliases - */ - public function testMultipleAliases(string $path, string $expected): void - { - App::get('/real/:param1') - ->alias('/alias', [ - 'param1' => 'default', - ]) - ->alias('/another/:param1') - ->alias('/param2', [ - 'param1' => 'param2', - ]) - ->param('param1', '', new Text(100), 'a param', false) - ->inject('response') - ->action(function ($param1, $response) { - echo $param1; - }); - - $routes = App::getRoutes(); - $this->assertContains('/real/:param1', array_keys($routes[App::REQUEST_METHOD_GET])); - - $_SERVER['REQUEST_METHOD'] = 'GET'; - - $_SERVER['REQUEST_URI'] = $path; - \ob_start(); - $this->app->run(new Request(), new Response()); - $result = \ob_get_contents(); - \ob_end_clean(); - - $this->assertEquals($expected, $result); - } - public function testWildcardRoute(): void { $method = $_SERVER['REQUEST_METHOD'] ?? null; @@ -591,4 +497,4 @@ public function testWildcardRoute(): void $this->assertEquals('HELLO', $result); } -} \ No newline at end of file +} diff --git a/tests/RouteTest.php b/tests/RouteTest.php index 4f2e5741..968de9cf 100755 --- a/tests/RouteTest.php +++ b/tests/RouteTest.php @@ -28,51 +28,6 @@ public function testCanGetAndSetPath() $this->assertEquals('/path', $this->route->getPath()); } - public function testCanSetAndGetAlias() - { - $this->assertEquals('', $this->route->getAliasPath()); - $this->assertEquals([], $this->route->getAliasParams()); - - $params = [ - 'pathId' => 'hello', - ]; - $this->route->alias('/path1', $params); - - $this->assertEquals('/path1', $this->route->getAliasPath()); - $this->assertEquals($params, $this->route->getAliasParams()); - } - - public function testCanSetAndGetAliases() - { - $this->assertEquals('', $this->route->getAliasPath()); - $this->assertEquals([], $this->route->getAliasParams()); - - $path1Params = [ - 'pathId' => 'hello', - ]; - $this->route->alias('/path1', $path1Params); - - $path2Params = [ - 'anotherPathId' => 'world', - ]; - $this->route->alias('/path2', $path2Params); - - $aliases = $this->route->getAliases(); - - $this->assertEquals( - [ - '/path1' => $path1Params, - '/path2' => $path2Params, - ], - $aliases - ); - - $this->assertEquals('/path1', $this->route->getAliasPath()); - $this->assertEquals($path1Params, $this->route->getAliasParams()); - $this->assertEquals($path1Params, $this->route->getAliasParams('/path1')); - $this->assertEquals($path2Params, $this->route->getAliasParams('/path2')); - } - public function testCanSetAndGetDescription() { $this->assertEquals('', $this->route->getDesc()); diff --git a/tests/RouterTest.php b/tests/RouterTest.php new file mode 100644 index 00000000..b78e4d1f --- /dev/null +++ b/tests/RouterTest.php @@ -0,0 +1,83 @@ +assertEquals($routeIndex, Router::match(App::REQUEST_METHOD_GET, '/')); + $this->assertEquals($routeAbout, Router::match(App::REQUEST_METHOD_GET, '/about')); + $this->assertEquals($routeAboutMe, Router::match(App::REQUEST_METHOD_GET, '/about/me')); + } + + public function testCanMatchUrlWithPlaceholder(): void + { + $routeBlog = new Route(App::REQUEST_METHOD_GET, '/blog'); + $routeBlogAuthors = new Route(App::REQUEST_METHOD_GET, '/blog/authors'); + $routeBlogAuthorsComments = new Route(App::REQUEST_METHOD_GET, '/blog/authors/comments'); + $routeBlogPost = new Route(App::REQUEST_METHOD_GET, '/blog/:post'); + $routeBlogPostComments = new Route(App::REQUEST_METHOD_GET, '/blog/:post/comments'); + $routeBlogPostCommentsSingle = new Route(App::REQUEST_METHOD_GET, '/blog/:post/comments/:comment'); + + Router::addRoute($routeBlog); + Router::addRoute($routeBlogAuthors); + Router::addRoute($routeBlogAuthorsComments); + Router::addRoute($routeBlogPost); + Router::addRoute($routeBlogPostComments); + Router::addRoute($routeBlogPostCommentsSingle); + + $this->assertEquals($routeBlog, Router::match(App::REQUEST_METHOD_GET, '/blog')); + $this->assertEquals($routeBlogAuthors, Router::match(App::REQUEST_METHOD_GET, '/blog/authors')); + $this->assertEquals($routeBlogAuthorsComments, Router::match(App::REQUEST_METHOD_GET, '/blog/authors/comments')); + $this->assertEquals($routeBlogPost, Router::match(App::REQUEST_METHOD_GET, '/blog/:post')); + $this->assertEquals($routeBlogPostComments, Router::match(App::REQUEST_METHOD_GET, '/blog/:post/comments')); + $this->assertEquals($routeBlogPostCommentsSingle, Router::match(App::REQUEST_METHOD_GET, '/blog/:post/comments/:comment')); + } + + public function testCanMatchHttpMethod(): void + { + $routeGET = new Route(App::REQUEST_METHOD_GET, '/'); + $routePOST = new Route(App::REQUEST_METHOD_POST, '/'); + + Router::addRoute($routeGET); + Router::addRoute($routePOST); + + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/')); + $this->assertEquals($routePOST, Router::match(App::REQUEST_METHOD_POST, '/')); + + $this->assertNotEquals($routeGET, Router::match(App::REQUEST_METHOD_POST, '/')); + $this->assertNotEquals($routePOST, Router::match(App::REQUEST_METHOD_GET, '/')); + } + + public function testCannotFindUnknownRouteByPath(): void + { + $this->assertNull(Router::match(App::REQUEST_METHOD_GET, '/404')); + } + + public function testCannotFindUnknownRouteByMethod(): void + { + $route = new Route(App::REQUEST_METHOD_GET, '/404'); + + Router::addRoute($route); + + $this->assertEquals($route, Router::match(App::REQUEST_METHOD_GET, '/404')); + + $this->assertNull(Router::match(App::REQUEST_METHOD_POST, '/404')); + } +} diff --git a/tests/e2e/ResponseTest.php b/tests/e2e/ResponseTest.php index 081b25ef..ce639ae7 100644 --- a/tests/e2e/ResponseTest.php +++ b/tests/e2e/ResponseTest.php @@ -28,6 +28,12 @@ public function testResponse() $this->assertEquals('Hello World!', $response['body']); } + public function testResponseValue() + { + $response = $this->client->call(Client::METHOD_GET, '/value/123'); + $this->assertEquals('123', $response['body']); + } + public function testChunkResponse() { $response = $this->client->call(Client::METHOD_GET, '/chunked'); diff --git a/tests/e2e/server.php b/tests/e2e/server.php index 64db8d56..8dec4fa8 100644 --- a/tests/e2e/server.php +++ b/tests/e2e/server.php @@ -5,6 +5,7 @@ use Utopia\App; use Utopia\Request; use Utopia\Response; +use Utopia\Validator\Text; ini_set('memory_limit', '512M'); ini_set('display_errors', 1); @@ -14,14 +15,20 @@ App::get('/') ->inject('response') - ->action(function ($response) { + ->action(function (Response $response) { $response->send('Hello World!'); }); +App::get('/value/:value') + ->param('value', '', new Text(64)) + ->inject('response') + ->action(function (string $value, Response $response) { + $response->send($value); + }); + App::get('/chunked') ->inject('response') - ->action(function ($response) { - /** @var Utopia/Response $response */ + ->action(function (Response $response) { foreach (['Hello ', 'World!'] as $key => $word) { $response->chunk($word, $key == 1); } @@ -29,8 +36,7 @@ App::get('/redirect') ->inject('response') - ->action(function ($response) { - /** @var Utopia/Response $response */ + ->action(function (Response $response) { $response->redirect('/'); }); From 9c55fb465ce45421bd34690a757f0e5fc4a3d530 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Apr 2023 14:16:36 +0200 Subject: [PATCH 02/20] fix: remove isactive --- composer.json | 2 +- src/App.php | 12 ++++---- src/Route.php | 54 ++++++++++++++++++++--------------- src/Router.php | 69 +++++++++++++++++++++++++++++++++++---------- tests/RouteTest.php | 11 -------- 5 files changed, 92 insertions(+), 56 deletions(-) diff --git a/composer.json b/composer.json index bc8a9a2d..b079409a 100755 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ }, "scripts": { "lint": "./vendor/bin/pint --test", - "format": "./vendor/bin/pint" + "format": "./vendor/bin/pint --preset psr12" }, "require": { "php": ">=8.0.0" diff --git a/src/App.php b/src/App.php index fa438046..2fed8caa 100755 --- a/src/App.php +++ b/src/App.php @@ -503,12 +503,8 @@ public function execute(Route $route, Request $request): static $arguments = $this->getArguments($route, $pathValues, $request->getParams()); - // Call the callback with the matched positions as params - if ($route->getIsActive()) { - \call_user_func_array($route->getAction(), $arguments); - } - - $route->setIsActive(true); + // Call the action callback with the matched positions as params + \call_user_func_array($route->getAction(), $arguments); foreach ($groups as $group) { foreach (self::$shutdown as $hook) { // Group shutdown hooks @@ -714,15 +710,17 @@ protected function validate(string $key, array $param, mixed $value): void /** * Reset all the static variables + * + * @return void */ public static function reset(): void { + Router::reset(); self::$resourcesCallbacks = []; self::$mode = ''; self::$errors = []; self::$init = []; self::$shutdown = []; self::$options = []; - Router::reset(); } } diff --git a/src/Route.php b/src/Route.php index fb684d51..29875b8b 100755 --- a/src/Route.php +++ b/src/Route.php @@ -25,8 +25,11 @@ class Route extends Hook */ protected string $path = ''; - protected bool $isActive = true; - + /** + * Path params. + * + * @var array + */ protected array $pathParams = []; public function __construct(string $method, string $path) @@ -39,44 +42,34 @@ public function __construct(string $method, string $path) /** * Add path + * + * @param string $path + * @return self */ - public function path(string $path): static + public function path(string $path): self { $this->path = $path; return $this; } - //TODO: remove /** - * Set isActive - */ - public function setIsActive(bool $isActive): void - { - $this->isActive = $isActive; - } - - /** - * Set hook status * When set false, hooks for this route will be skipped. + * + * @param bool $hook + * @return self */ - public function hook(bool $hook = true): static + public function hook(bool $hook = true): self { $this->hook = $hook; return $this; } - /** - * When set to false the route will be skipped - */ - public function getIsActive(): bool - { - return $this->isActive; - } - /** * Get HTTP Method + * + * @return string */ public function getMethod(): string { @@ -85,6 +78,8 @@ public function getMethod(): string /** * Get path + * + * @return string */ public function getPath(): string { @@ -93,17 +88,32 @@ public function getPath(): string /** * Get hook status + * + * @return bool */ public function getHook(): bool { return $this->hook; } + /** + * Set path param. + * + * @param string $key + * @param int $index + * @return void + */ public function setPathParam(string $key, int $index): void { $this->pathParams[$key] = $index; } + /** + * Get path params. + * + * @param \Utopia\Request $request + * @return array + */ public function getPathValues(Request $request): array { $pathParams = []; diff --git a/src/Router.php b/src/Router.php index fffc31f8..3ffc26dd 100644 --- a/src/Router.php +++ b/src/Router.php @@ -6,6 +6,9 @@ class Router { + /** + * Placeholder token for params in paths. + */ public const PLACEHOLDER_TOKEN = ':::'; /** @@ -26,16 +29,28 @@ class Router */ protected static array $params = []; + /** + * Get all registered routes. + * + * @return array + */ public static function getRoutes(): array { return self::$routes; } + /** + * Add route to router. + * + * @param \Utopia\Route $route + * @return void + * @throws \Exception + */ public static function addRoute(Route $route): void { [$path, $params] = self::preparePath($route->getPath()); - if (! array_key_exists($route->getMethod(), self::$routes)) { + if (!array_key_exists($route->getMethod(), self::$routes)) { throw new Exception("Method ({$route->getMethod()}) not supported."); } @@ -50,9 +65,16 @@ public static function addRoute(Route $route): void self::$routes[$route->getMethod()][$path] = $route; } + /** + * Match route against the method and path. + * + * @param string $method + * @param string $path + * @return \Utopia\Route|null + */ public static function match(string $method, string $path): Route|null { - if (! array_key_exists($method, self::$routes)) { + if (!array_key_exists($method, self::$routes)) { return null; } @@ -78,18 +100,12 @@ public static function match(string $method, string $path): Route|null return null; } - public static function reset(): void - { - self::$params = []; - self::$routes = [ - App::REQUEST_METHOD_GET => [], - App::REQUEST_METHOD_POST => [], - App::REQUEST_METHOD_PUT => [], - App::REQUEST_METHOD_PATCH => [], - App::REQUEST_METHOD_DELETE => [], - ]; - } - + /** + * Get all combinations of the given set. + * + * @param array $set + * @return iterable + */ protected static function combinations(array $set): iterable { yield []; @@ -106,6 +122,12 @@ protected static function combinations(array $set): iterable } } + /** + * Prepare path for matching + * + * @param string $path + * @return array + */ protected static function preparePath(string $path): array { $parts = array_values(array_filter(explode('/', $path))); @@ -120,7 +142,7 @@ protected static function preparePath(string $path): array if (str_starts_with($part, ':')) { $prepare .= self::PLACEHOLDER_TOKEN; $params[ltrim($part, ':')] = $key; - if (! in_array($key, self::$params)) { + if (!in_array($key, self::$params)) { self::$params[] = $key; } } else { @@ -130,4 +152,21 @@ protected static function preparePath(string $path): array return [$prepare, $params]; } + + /** + * Reset router + * + * @return void + */ + public static function reset(): void + { + self::$params = []; + self::$routes = [ + App::REQUEST_METHOD_GET => [], + App::REQUEST_METHOD_POST => [], + App::REQUEST_METHOD_PUT => [], + App::REQUEST_METHOD_PATCH => [], + App::REQUEST_METHOD_DELETE => [], + ]; + } } diff --git a/tests/RouteTest.php b/tests/RouteTest.php index 968de9cf..cbdea1c3 100755 --- a/tests/RouteTest.php +++ b/tests/RouteTest.php @@ -100,17 +100,6 @@ public function testCanSetAndGetHooks() $this->assertFalse($this->route->getHook()); } - public function testCanSetAndGetIsActive() - { - $this->assertTrue($this->route->getIsActive()); - $this->route->setIsActive(true); - $this->assertTrue($this->route->getIsActive()); - $this->route->setIsActive(false); - $this->assertFalse($this->route->getIsActive()); - $this->route->setIsActive(true); - $this->assertTrue($this->route->getIsActive()); - } - public function tearDown(): void { $this->route = null; From a75201523f197c01438d014541131a8ad90b4780 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Apr 2023 14:16:42 +0200 Subject: [PATCH 03/20] chore: remove gitlab ci --- .gitlab-ci.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 14df38c0..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This file is a template, and might need editing before it works on your project. -# Select image from https://hub.docker.com/_/php/ -image: php:7.1.1 - -# Select what we should cache between builds -cache: - paths: - - vendor/ - -before_script: -- apt-get update -yqq -- apt-get install -yqq git -# Install PHP extensions -- docker-php-ext-install mbstring json opcache -# Install & enable Xdebug for code coverage reports -- pecl install xdebug -- docker-php-ext-enable xdebug -# Install and run Composer -- curl -sS https://getcomposer.org/installer | php -- php composer.phar install - -# Run our tests -# If Xdebug was installed you can generate a coverage report and see code coverage metrics. -test: - script: - - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never \ No newline at end of file From f644da8967beb962c78db92092ce05daa2d0e968 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 11 Apr 2023 14:37:31 +0200 Subject: [PATCH 04/20] fix: add back aliases --- src/Route.php | 33 +++++++++++++++++++++++++++++++++ src/Router.php | 5 +++++ tests/RouterTest.php | 12 ++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/Route.php b/src/Route.php index 29875b8b..c978dff8 100755 --- a/src/Route.php +++ b/src/Route.php @@ -18,6 +18,13 @@ class Route extends Hook */ protected bool $hook = true; + /** + * Array of aliases. + * + * @var array + */ + protected array $aliases = []; + /** * Path * @@ -53,6 +60,22 @@ public function path(string $path): self return $this; } + /** + * Add alias + * + * @param string $path + * @param array $params + * @return self + */ + public function alias(string $path): self + { + if (!in_array($path, $this->aliases)) { + $this->aliases[] = $path; + } + + return $this; + } + /** * When set false, hooks for this route will be skipped. * @@ -86,6 +109,16 @@ public function getPath(): string return $this->path; } + /** + * Get Aliases + * + * @return array + */ + public function getAliases(): array + { + return $this->aliases; + } + /** * Get hook status * diff --git a/src/Router.php b/src/Router.php index 408bb4d3..c0d56456 100644 --- a/src/Router.php +++ b/src/Router.php @@ -63,6 +63,11 @@ public static function addRoute(Route $route): void } self::$routes[$route->getMethod()][$path] = $route; + + foreach ($route->getAliases() as $alias) { + [$alias] = self::preparePath($alias); + self::$routes[$route->getMethod()][$alias] = $route; + } } /** diff --git a/tests/RouterTest.php b/tests/RouterTest.php index b78e4d1f..5f26103a 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -65,6 +65,18 @@ public function testCanMatchHttpMethod(): void $this->assertNotEquals($routePOST, Router::match(App::REQUEST_METHOD_GET, '/')); } + public function testCanMatchAlias(): void + { + $routeGET = new Route(App::REQUEST_METHOD_GET, '/target'); + $routeGET->alias('/alias')->alias('/alias2'); + + Router::addRoute($routeGET); + + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/target')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/alias')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/alias2')); + } + public function testCannotFindUnknownRouteByPath(): void { $this->assertNull(Router::match(App::REQUEST_METHOD_GET, '/404')); From f13872859b446a7a662ab8b20402a5f6df7552e7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 11 Apr 2023 15:12:53 +0200 Subject: [PATCH 05/20] fix stan --- src/Route.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Route.php b/src/Route.php index c978dff8..06277b97 100755 --- a/src/Route.php +++ b/src/Route.php @@ -64,7 +64,6 @@ public function path(string $path): self * Add alias * * @param string $path - * @param array $params * @return self */ public function alias(string $path): self @@ -149,13 +148,15 @@ public function setPathParam(string $key, int $index): void */ public function getPathValues(Request $request): array { - $pathParams = []; + $pathValues = []; $parts = explode('/', ltrim($request->getURI(), '/')); foreach ($this->pathParams as $key => $index) { - $pathParams[$key] = $parts[$index]; + if (array_key_exists($index, $parts)) { + $pathValues[$key] = $parts[$index]; + } } - return $pathParams; + return $pathValues; } } From 130e44afc9c62aeb31255ec66583152999701f13 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 12 Apr 2023 15:17:58 +0200 Subject: [PATCH 06/20] fix: migrate to gh actions --- .github/workflows/lint.yml | 22 ++++++++++++++++++++++ .github/workflows/testl.yml | 25 +++++++++++++++++++++++++ .travis.yml | 36 ------------------------------------ composer.json | 1 - psalm.xml | 15 --------------- 5 files changed, 47 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/testl.yml delete mode 100644 .travis.yml delete mode 100644 psalm.xml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..bcb85b66 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,22 @@ +name: "Linter" + +on: [pull_request] +jobs: + lint: + name: Linter + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + + - name: Install dependencies + run: composer install --prefer-dist + + - name: Run Linter + run: composer lint \ No newline at end of file diff --git a/.github/workflows/testl.yml b/.github/workflows/testl.yml new file mode 100644 index 00000000..cc41aa6f --- /dev/null +++ b/.github/workflows/testl.yml @@ -0,0 +1,25 @@ +name: "Tests" + +on: [pull_request] +jobs: + lint: + name: Tests + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + + - name: Setup Docker + run: docker-compose up -d --build + + - name: Wait for Server to be ready + run: sleep 10 + + - name: Run Tests + run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ef34aadb..00000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -dist: focal - -arch: - - amd64 - -os: linux - -language: shell - -notifications: - email: - - team@appwrite.io - -services: - - docker - -before_install: - - curl -fsSL https://get.docker.com | sh - - echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json - - mkdir -p $HOME/.docker - - echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json - - sudo service docker start - - > - if [ ! -z "${DOCKERHUB_PULL_USERNAME:-}" ]; then - echo "${DOCKERHUB_PULL_PASSWORD}" | docker login --username "${DOCKERHUB_PULL_USERNAME}" --password-stdin - fi - - docker --version - -install: - - docker-compose up -d - - sleep 10 - -script: - - docker ps -a - - docker-compose exec web vendor/bin/phpunit --configuration phpunit.xml - - docker-compose exec web vendor/bin/psalm --show-info=true diff --git a/composer.json b/composer.json index 3fb769b5..b9b923ba 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,6 @@ }, "require-dev": { "phpunit/phpunit": "^9.5.25", - "vimeo/psalm": "4.27.0", "laravel/pint": "^1.2", "phpstan/phpstan": "1.9.x-dev" } diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index 30258a70..00000000 --- a/psalm.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - From 6dc5bd305a6875989af48cb65c4689420d23debf Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 12 Apr 2023 15:19:19 +0200 Subject: [PATCH 07/20] fix: remove psalm from dockerfile --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 53fecf42..ad0fb57b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,7 +38,6 @@ COPY ./tests/docker/start /usr/local/bin/start COPY ./src /usr/share/nginx/html/src COPY ./tests /usr/share/nginx/html/tests COPY ./phpunit.xml /usr/share/nginx/html/phpunit.xml -COPY ./psalm.xml /usr/share/nginx/html/psalm.xml COPY --from=step0 /usr/local/src/vendor /usr/share/nginx/html/vendor # Supervisord Conf From 0d67d992ed6043cdc8b28ab0540ed66b2d1f06e3 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 12 Apr 2023 15:25:49 +0200 Subject: [PATCH 08/20] fix: phpstan errors --- tests/e2e/server.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/e2e/server.php b/tests/e2e/server.php index 8dec4fa8..d269f8e0 100644 --- a/tests/e2e/server.php +++ b/tests/e2e/server.php @@ -7,10 +7,10 @@ use Utopia\Response; use Utopia\Validator\Text; -ini_set('memory_limit', '512M'); -ini_set('display_errors', 1); -ini_set('display_startup_errors', 1); -ini_set('display_socket_timeout', -1); +ini_set('memory_limit', '1024M'); +ini_set('display_errors', '1'); +ini_set('display_startup_errors', '1'); +ini_set('display_socket_timeout', '-1'); error_reporting(E_ALL); App::get('/') From da814441cf528b804364660e579ecc24f21d9791 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 11:57:31 +0200 Subject: [PATCH 09/20] add: phpbench regression tests --- .github/workflows/{testl.yml => test.yml} | 5 +- Dockerfile | 1 + composer.json | 21 +- composer.lock | 2953 +++++++++------------ phpbench.json | 6 + phpstan.neon | 5 + tests/RouterBench.php | 58 + tests/RouterTest.php | 14 +- tests/e2e/ResponseTest.php | 6 + tests/e2e/server.php | 6 + 10 files changed, 1397 insertions(+), 1678 deletions(-) rename .github/workflows/{testl.yml => test.yml} (82%) create mode 100644 phpbench.json create mode 100644 phpstan.neon create mode 100644 tests/RouterBench.php diff --git a/.github/workflows/testl.yml b/.github/workflows/test.yml similarity index 82% rename from .github/workflows/testl.yml rename to .github/workflows/test.yml index cc41aa6f..09777f59 100644 --- a/.github/workflows/testl.yml +++ b/.github/workflows/test.yml @@ -22,4 +22,7 @@ jobs: run: sleep 10 - name: Run Tests - run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml \ No newline at end of file + run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml + + - name: Run Benchmarks + run: docker compose exec web vendor/bin/phpbench run \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index ad0fb57b..54c948a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,6 +38,7 @@ COPY ./tests/docker/start /usr/local/bin/start COPY ./src /usr/share/nginx/html/src COPY ./tests /usr/share/nginx/html/tests COPY ./phpunit.xml /usr/share/nginx/html/phpunit.xml +COPY ./phpbench.json /usr/share/nginx/html/phpbench.json COPY --from=step0 /usr/local/src/vendor /usr/share/nginx/html/vendor # Supervisord Conf diff --git a/composer.json b/composer.json index b9b923ba..fe84d0d0 100644 --- a/composer.json +++ b/composer.json @@ -2,16 +2,24 @@ "name": "utopia-php/framework", "description": "A simple, light and advanced PHP framework", "type": "library", - "keywords": ["php","framework", "upf"], + "keywords": [ + "php", + "framework", + "upf" + ], "license": "MIT", "minimum-stability": "stable", "autoload": { - "psr-4": {"Utopia\\": "src/"} + "psr-4": { + "Utopia\\": "src/" + } }, "scripts": { - "lint": "./vendor/bin/pint --test", - "format": "./vendor/bin/pint", - "check": "./vendor/bin/phpstan analyse -l 5 src tests" + "lint": "vendor/bin/pint --test", + "format": "vendor/bin/pint", + "check": "vendor/bin/phpstan analyse -c phpstan.neon", + "test": "vendor/bin/phpunit --configuration phpunit.xml", + "bench": "vendor/bin/phpbench run --report=benchmark" }, "require": { "php": ">=8.0" @@ -19,6 +27,7 @@ "require-dev": { "phpunit/phpunit": "^9.5.25", "laravel/pint": "^1.2", - "phpstan/phpstan": "1.9.x-dev" + "phpstan/phpstan": "^1.10", + "phpbench/phpbench": "^1.2" } } diff --git a/composer.lock b/composer.lock index 8acbb111..812fe97b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,48 +4,44 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f89715e407bde4aecfdff0a0961815de", + "content-hash": "d41ea47cadd897ad4053410229874733", "packages": [], "packages-dev": [ { - "name": "amphp/amp", - "version": "v2.6.2", + "name": "doctrine/annotations", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" + "url": "https://github.com/doctrine/annotations.git", + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", "shasum": "" }, "require": { - "php": ">=7.1" + "doctrine/lexer": "^2 || ^3", + "ext-tokenizer": "*", + "php": "^7.2 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" + "doctrine/cache": "^2.0", + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^5.4 || ^6", + "vimeo/psalm": "^4.10" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" }, + "type": "library", "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], "psr-4": { - "Amp\\": "lib" + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", @@ -54,161 +50,113 @@ ], "authors": [ { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" }, { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" }, { - "name": "Niklas Keller", - "email": "me@kelunik.com" + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" + "annotations", + "docblock", + "parser" ], "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/2.0.1" }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" + "time": "2023-02-02T22:02:53+00:00" }, { - "name": "amphp/byte-stream", - "version": "v1.8.1", + "name": "doctrine/deprecations", + "version": "v1.0.0", "source": { "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", "shasum": "" }, "require": { - "amphp/amp": "^2", - "php": ">=7.1" + "php": "^7.1|^8.0" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, + "type": "library", "autoload": { - "files": [ - "lib/functions.php" - ], "psr-4": { - "Amp\\ByteStream\\": "lib" + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" + "time": "2022-05-02T15:47:09+00:00" }, { - "name": "composer/package-versions-deprecated", - "version": "1.11.99.5", + "name": "doctrine/instantiator", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/composer/package-versions-deprecated.git", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", - "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "composer-plugin-api": "^1.1.0 || ^2.0", - "php": "^7 || ^8" - }, - "replace": { - "ocramius/package-versions": "1.11.99" + "php": "^7.1 || ^8.0" }, "require-dev": { - "composer/composer": "^1.9.3 || ^2.0@dev", - "ext-zip": "^1.13", - "phpunit/phpunit": "^6.5 || ^7" - }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "1.x-dev" - } + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, + "type": "library", "autoload": { "psr-4": { - "PackageVersions\\": "src/PackageVersions" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -218,65 +166,65 @@ "authors": [ { "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], "support": { - "issues": "https://github.com/composer/package-versions-deprecated/issues", - "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { - "url": "https://packagist.com", + "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { - "url": "https://github.com/composer", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", "type": "tidelift" } ], - "time": "2022-01-17T14:14:24+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { - "name": "composer/pcre", - "version": "3.1.0", + "name": "doctrine/lexer", + "version": "2.1.0", "source": { "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0" + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" }, "require-dev": { + "doctrine/coding-standard": "^9 || ^10", "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Composer\\Pcre\\": "src" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -285,68 +233,86 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" + "annotations", + "docblock", + "lexer", + "parser", + "php" ], "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" }, "funding": [ { - "url": "https://packagist.com", + "url": "https://www.doctrine-project.org/sponsorship.html", "type": "custom" }, { - "url": "https://github.com/composer", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", "type": "tidelift" } ], - "time": "2022-11-17T09:50:14+00:00" + "time": "2022-12-14T08:49:07+00:00" }, { - "name": "composer/semver", - "version": "3.3.2", + "name": "laravel/pint", + "version": "v1.5.0", "source": { "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + "url": "https://github.com/laravel/pint.git", + "reference": "e0a8cef58b74662f27355be9cdea0e726bbac362" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "url": "https://api.github.com/repos/laravel/pint/zipball/e0a8cef58b74662f27355be9cdea0e726bbac362", + "reference": "e0a8cef58b74662f27355be9cdea0e726bbac362", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } + "friendsofphp/php-cs-fixer": "^3.14.4", + "illuminate/view": "^9.51.0", + "laravel-zero/framework": "^9.2.0", + "mockery/mockery": "^1.5.1", + "nunomaduro/larastan": "^2.4.0", + "nunomaduro/termwind": "^1.15.1", + "pestphp/pest": "^1.22.4" }, + "bin": [ + "builds/pint" + ], + "type": "project", "autoload": { "psr-4": { - "Composer\\Semver\\": "src" + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" } }, "notification-url": "https://packagist.org/downloads/", @@ -355,405 +321,418 @@ ], "authors": [ { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", "keywords": [ - "semantic", - "semver", - "validation", - "versioning" + "format", + "formatter", + "lint", + "linter", + "php" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-04-01T19:23:25+00:00" + "time": "2023-02-14T16:31:02+00:00" }, { - "name": "composer/xdebug-handler", - "version": "3.0.3", + "name": "myclabs/deep-copy", + "version": "1.11.1", "source": { "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "Composer\\XdebugHandler\\": "src" + "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", + "description": "Create deep copies (clones) of your objects", "keywords": [ - "Xdebug", - "performance" + "clone", + "copy", + "duplicate", + "object", + "object graph" ], "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], - "time": "2022-02-25T21:32:43+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", + "name": "nikic/php-parser", + "version": "v4.15.4", "source": { "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", "shasum": "" }, "require": { - "php": ">=5.3.2" + "ext-tokenizer": "*", + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, "autoload": { "psr-4": { - "XdgBaseDir\\": "src/" + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" ], - "description": "implementation of xdg base directory specification for php", "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" }, - "time": "2019-12-04T15:06:13+00:00" + "time": "2023-03-05T19:49:14+00:00" }, { - "name": "doctrine/deprecations", - "version": "v1.0.0", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "php": "^7.1|^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.5.0", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "time": "2022-12-30T00:15:36+00:00" + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", + "name": "phpbench/container", + "version": "2.2.1", "source": { "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + "url": "https://github.com/phpbench/container.git", + "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", + "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", "shasum": "" }, "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + "psr/container": "^1.0|^2.0", + "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" + "friendsofphp/php-cs-fixer": "^2.16", + "phpstan/phpstan": "^0.12.52", + "phpunit/phpunit": "^8" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, "autoload": { "psr-4": { - "AdvancedJsonRpc\\": "lib/" + "PhpBench\\DependencyInjection\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "ISC" + "MIT" ], "authors": [ { - "name": "Felix Becker", - "email": "felix.b@outlook.com" + "name": "Daniel Leech", + "email": "daniel@dantleech.com" } ], - "description": "A more advanced JSONRPC implementation", + "description": "Simple, configurable, service container.", "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + "issues": "https://github.com/phpbench/container/issues", + "source": "https://github.com/phpbench/container/tree/2.2.1" }, - "time": "2021-06-11T22:34:44+00:00" + "time": "2022-01-25T10:17:35+00:00" }, { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", + "name": "phpbench/dom", + "version": "0.3.3", "source": { "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + "url": "https://github.com/phpbench/dom.git", + "reference": "786a96db538d0def931f5b19225233ec42ec7a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "url": "https://api.github.com/repos/phpbench/dom/zipball/786a96db538d0def931f5b19225233ec42ec7a72", + "reference": "786a96db538d0def931f5b19225233ec42ec7a72", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-dom": "*", + "php": "^7.3||^8.0" }, "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" + "friendsofphp/php-cs-fixer": "^3.14", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.0||^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "LanguageServerProtocol\\": "src/" + "PhpBench\\Dom\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "ISC" + "MIT" ], "authors": [ { - "name": "Felix Becker", - "email": "felix.b@outlook.com" + "name": "Daniel Leech", + "email": "daniel@dantleech.com" } ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], + "description": "DOM wrapper to simplify working with the PHP DOM implementation", "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + "issues": "https://github.com/phpbench/dom/issues", + "source": "https://github.com/phpbench/dom/tree/0.3.3" }, - "time": "2022-03-02T22:36:06+00:00" + "time": "2023-03-06T23:46:57+00:00" }, { - "name": "laravel/pint", - "version": "v1.5.0", + "name": "phpbench/phpbench", + "version": "1.2.10", "source": { "type": "git", - "url": "https://github.com/laravel/pint.git", - "reference": "e0a8cef58b74662f27355be9cdea0e726bbac362" + "url": "https://github.com/phpbench/phpbench.git", + "reference": "95206f92479674599a75e02b74b9933e2d9883aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/e0a8cef58b74662f27355be9cdea0e726bbac362", - "reference": "e0a8cef58b74662f27355be9cdea0e726bbac362", + "url": "https://api.github.com/repos/phpbench/phpbench/zipball/95206f92479674599a75e02b74b9933e2d9883aa", + "reference": "95206f92479674599a75e02b74b9933e2d9883aa", "shasum": "" }, "require": { + "doctrine/annotations": "^1.13 || ^2.0", + "ext-dom": "*", "ext-json": "*", - "ext-mbstring": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", "ext-tokenizer": "*", - "ext-xml": "*", - "php": "^8.0" + "php": "^7.4 || ^8.0", + "phpbench/container": "^2.1", + "phpbench/dom": "~0.3.3", + "psr/log": "^1.1 || ^2.0 || ^3.0", + "seld/jsonlint": "^1.1", + "symfony/console": "^4.2 || ^5.0 || ^6.0", + "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", + "symfony/finder": "^4.2 || ^5.0 || ^6.0", + "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", + "symfony/process": "^4.2 || ^5.0 || ^6.0", + "webmozart/glob": "^4.6" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.14.4", - "illuminate/view": "^9.51.0", - "laravel-zero/framework": "^9.2.0", - "mockery/mockery": "^1.5.1", - "nunomaduro/larastan": "^2.4.0", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^1.22.4" + "dantleech/invoke": "^2.0", + "friendsofphp/php-cs-fixer": "^3.0", + "jangregor/phpstan-prophecy": "^1.0", + "phpspec/prophecy": "^1.12", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.0", + "symfony/error-handler": "^5.2 || ^6.0", + "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" + }, + "suggest": { + "ext-xdebug": "For Xdebug profiling extension." }, "bin": [ - "builds/pint" + "bin/phpbench" ], - "type": "project", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, "autoload": { + "files": [ + "lib/Report/Func/functions.php" + ], "psr-4": { - "App\\": "app/", - "Database\\Seeders\\": "database/seeders/", - "Database\\Factories\\": "database/factories/" + "PhpBench\\": "lib/", + "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -762,170 +741,131 @@ ], "authors": [ { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" + "name": "Daniel Leech", + "email": "daniel@dantleech.com" } ], - "description": "An opinionated code formatter for PHP.", - "homepage": "https://laravel.com", - "keywords": [ - "format", - "formatter", - "lint", - "linter", - "php" - ], + "description": "PHP Benchmarking Framework", "support": { - "issues": "https://github.com/laravel/pint/issues", - "source": "https://github.com/laravel/pint" + "issues": "https://github.com/phpbench/phpbench/issues", + "source": "https://github.com/phpbench/phpbench/tree/1.2.10" }, - "time": "2023-02-14T16:31:02+00:00" + "funding": [ + { + "url": "https://github.com/dantleech", + "type": "github" + } + ], + "time": "2023-03-24T08:52:55+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.11.1", + "name": "phpstan/phpstan", + "version": "1.10.14", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + "url": "https://github.com/phpstan/phpstan.git", + "reference": "d232901b09e67538e5c86a724be841bea5768a7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d232901b09e67538e5c86a724be841bea5768a7c", + "reference": "d232901b09e67538e5c86a724be841bea5768a7c", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.2|^8.0" }, "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + "phpstan/phpstan-shim": "*" }, + "bin": [ + "phpstan", + "phpstan.phar" + ], "type": "library", "autoload": { "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "dev", + "static analysis" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.2.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" } ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" - }, - "time": "2023-04-09T17:37:40+00:00" + "time": "2023-04-19T13:47:27+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.15.4", + "name": "phpunit/php-code-coverage", + "version": "9.2.26", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "9.2-dev" } }, "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -933,98 +873,54 @@ ], "authors": [ { - "name": "Nikita Popov" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "A PHP parser written in PHP", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "parser", - "php" + "coverage", + "testing", + "xunit" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" - }, - "time": "2023-03-05T19:49:14+00:00" - }, - { - "name": "openlss/lib-array2xml", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nullivex/lib-array2xml.git", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "type": "library", - "autoload": { - "psr-0": { - "LSS": "" - } + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Bryan Tong", - "email": "bryan@nullivex.com", - "homepage": "https://www.nullivex.com" - }, + "funding": [ { - "name": "Tony Butler", - "email": "spudz76@gmail.com", - "homepage": "https://www.nullivex.com" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Array2XML conversion library credit to lalit.org", - "homepage": "https://www.nullivex.com", - "keywords": [ - "array", - "array conversion", - "xml", - "xml conversion" - ], - "support": { - "issues": "https://github.com/nullivex/lib-array2xml/issues", - "source": "https://github.com/nullivex/lib-array2xml/tree/master" - }, - "time": "2019-03-29T20:06:56+00:00" + "time": "2023-03-06T12:58:08+00:00" }, { - "name": "phar-io/manifest", - "version": "2.0.3", + "name": "phpunit/php-file-iterator", + "version": "3.0.6", "source": { "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1037,395 +933,271 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", - "role": "Developer" + "role": "lead" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-2.x": "2.x-dev" + "dev-master": "3.1-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "process" ], "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" }, - "time": "2020-06-27T09:03:43+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", + "name": "phpunit/php-text-template", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" + "php": ">=7.3" }, "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" }, - "time": "2021-10-19T17:43:47+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { - "name": "phpdocumentor/type-resolver", - "version": "1.7.1", + "name": "phpunit/php-timer", + "version": "5.0.3", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "php": ">=7.3" }, "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1" - }, - "time": "2023-03-27T19:02:04+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.18.1", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/22dcdfd725ddf99583bfe398fc624ad6c5004a0f", - "reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.18.1" - }, - "time": "2023-04-07T11:51:11+00:00" - }, - { - "name": "phpstan/phpstan", - "version": "1.9.x-dev", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "6c0217aa2b146c3e28474e8be3e87188fac55dac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6c0217aa2b146c3e28474e8be3e87188fac55dac", - "reference": "6c0217aa2b146c3e28474e8be3e87188fac55dac", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0" - }, - "conflict": { - "phpstan/phpstan-shim": "*" - }, - "bin": [ - "phpstan", - "phpstan.phar" - ], - "type": "library", - "autoload": { - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPStan - PHP Static Analysis Tool", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "dev", - "static analysis" + "timer" ], "support": { - "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.9.x" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" }, "funding": [ { - "url": "https://github.com/ondrejmirtes", - "type": "github" - }, - { - "url": "https://github.com/phpstan", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" } ], - "time": "2023-02-18T15:01:46+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "name": "phpunit/phpunit", + "version": "9.6.7", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", + "reference": "c993f0d3b0489ffc42ee2fe0bd645af1538a63b2", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", + "ext-json": "*", "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", + "ext-soap": "To be able to generate mocks based on WSDL files", "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-master": "9.6-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -1441,160 +1213,198 @@ "role": "lead" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "coverage", + "phpunit", "testing", "xunit" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.7" }, "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-04-14T08:58:40+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "name": "psr/cache", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\Cache\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "Common interface for caching libraries", "keywords": [ - "filesystem", - "iterator" + "cache", + "psr", + "psr-6" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "source": "https://github.com/php-fig/cache/tree/3.0.0" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2021-02-03T23:26:27+00:00" }, { - "name": "phpunit/php-invoker", - "version": "3.1.1", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" + "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\Container\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "process" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "funding": [ + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "url": "https://github.com/sebastianbergmann", - "type": "github" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "time": "2020-09-28T05:58:55+00:00" + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" }, { - "name": "phpunit/php-text-template", - "version": "2.0.4", + "name": "sebastian/cli-parser", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { @@ -1606,7 +1416,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -1625,14 +1435,11 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" }, "funding": [ { @@ -1640,20 +1447,20 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2020-09-28T06:08:49+00:00" }, { - "name": "phpunit/php-timer", - "version": "5.0.3", + "name": "sebastian/code-unit", + "version": "1.0.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { @@ -1665,7 +1472,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -1684,83 +1491,47 @@ "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "b65d59a059d3004a040c16a82e07bbdf6cfdd115" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b65d59a059d3004a040c16a82e07bbdf6cfdd115", - "reference": "b65d59a059d3004a040c16a82e07bbdf6cfdd115", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -1772,165 +1543,179 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.6" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" }, "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" } ], - "time": "2023-03-27T11:43:46+00:00" + "time": "2020-09-28T05:30:19+00:00" }, { - "name": "psr/container", - "version": "2.0.2", + "name": "sebastian/comparator", + "version": "4.0.8", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "comparator", + "compare", + "equality" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" }, - "time": "2021-11-05T16:47:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "psr/log", - "version": "3.0.0", + "name": "sebastian/complexity", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { - "php": ">=8.0.0" + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" }, - "time": "2021-07-14T16:46:02+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" }, { - "name": "sebastian/cli-parser", - "version": "1.0.1", + "name": "sebastian/diff", + "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1945,15 +1730,24 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" }, "funding": [ { @@ -1961,20 +1755,20 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2020-10-26T13:10:38+00:00" }, { - "name": "sebastian/code-unit", - "version": "1.0.8", + "name": "sebastian/environment", + "version": "5.1.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -1983,10 +1777,13 @@ "require-dev": { "phpunit/phpunit": "^9.3" }, + "suggest": { + "ext-posix": "*" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -2001,15 +1798,19 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -2017,32 +1818,34 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "name": "sebastian/exporter", + "version": "4.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2058,13 +1861,33 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" }, "funding": [ { @@ -2072,34 +1895,38 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { - "name": "sebastian/comparator", - "version": "4.0.8", + "name": "sebastian/global-state", + "version": "5.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { + "ext-dom": "*", "phpunit/phpunit": "^9.3" }, + "suggest": { + "ext-uopz": "*" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2115,30 +1942,16 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ - "comparator", - "compare", - "equality" + "global state" ], "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" }, "funding": [ { @@ -2146,24 +1959,24 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2022-02-14T08:28:10+00:00" }, { - "name": "sebastian/complexity", - "version": "2.0.2", + "name": "sebastian/lines-of-code", + "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", + "nikic/php-parser": "^4.6", "php": ">=7.3" }, "require-dev": { @@ -2172,7 +1985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -2191,11 +2004,11 @@ "role": "lead" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" }, "funding": [ { @@ -2203,28 +2016,29 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2020-11-28T06:42:11+00:00" }, { - "name": "sebastian/diff", + "name": "sebastian/object-enumerator", "version": "4.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2245,23 +2059,13 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, "funding": [ { @@ -2269,20 +2073,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2020-10-26T13:12:34+00:00" }, { - "name": "sebastian/environment", - "version": "5.1.5", + "name": "sebastian/object-reflector", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { @@ -2291,13 +2095,10 @@ "require-dev": { "phpunit/phpunit": "^9.3" }, - "suggest": { - "ext-posix": "*" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2315,16 +2116,11 @@ "email": "sebastian@phpunit.de" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, "funding": [ { @@ -2332,28 +2128,26 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2020-10-26T13:14:26+00:00" }, { - "name": "sebastian/exporter", + "name": "sebastian/recursion-context", "version": "4.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "php": ">=7.3" }, "require-dev": { - "ext-mbstring": "*", "phpunit/phpunit": "^9.3" }, "type": "library", @@ -2380,28 +2174,16 @@ "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -2409,38 +2191,32 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { - "name": "sebastian/global-state", - "version": "5.0.5", + "name": "sebastian/resource-operations", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=7.3" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2455,17 +2231,14 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" + "email": "sebastian@phpunit.de" + } ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" }, "funding": [ { @@ -2473,33 +2246,32 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2020-09-28T06:45:17+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "1.0.3", + "name": "sebastian/type", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -2518,11 +2290,11 @@ "role": "lead" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -2530,34 +2302,29 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "4.0.4", + "name": "sebastian/version", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2572,14 +2339,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, "funding": [ { @@ -2587,339 +2355,380 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2020-09-28T06:39:44+00:00" }, { - "name": "sebastian/object-reflector", - "version": "2.0.4", + "name": "seld/jsonlint", + "version": "1.9.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "url": "https://github.com/Seldaek/jsonlint.git", + "reference": "4211420d25eba80712bff236a98960ef68b866b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", + "reference": "4211420d25eba80712bff236a98960ef68b866b7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": "^5.3 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpstan/phpstan": "^1.5", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" }, + "bin": [ + "bin/jsonlint" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Seld\\JsonLint\\": "src/Seld/JsonLint/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "JSON Linter", + "keywords": [ + "json", + "linter", + "parser", + "validator" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "issues": "https://github.com/Seldaek/jsonlint/issues", + "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/Seldaek", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", + "type": "tidelift" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2022-04-01T13:37:23+00:00" }, { - "name": "sebastian/recursion-context", - "version": "4.0.5", + "name": "symfony/console", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "url": "https://github.com/symfony/console.git", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/symfony/console/tree/v6.0.19" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { - "name": "sebastian/resource-operations", - "version": "3.0.3", + "name": "symfony/deprecation-contracts", + "version": "v3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" + "php": ">=8.0.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "classmap": [ - "src/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2022-01-02T09:55:41+00:00" }, { - "name": "sebastian/type", - "version": "3.2.1", + "name": "symfony/filesystem", + "version": "v6.0.19", "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/3d49eec03fda1f0fc19b7349fbbe55ebc1004214", + "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" + "php": ">=8.0.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/symfony/filesystem/tree/v6.0.19" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-01-20T17:44:14+00:00" }, { - "name": "sebastian/version", - "version": "3.0.2", + "name": "symfony/finder", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "url": "https://github.com/symfony/finder.git", + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/symfony/finder/zipball/5cc9cac6586fc0c28cd173780ca696e419fefa11", + "reference": "5cc9cac6586fc0c28cd173780ca696e419fefa11", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.0.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/symfony/finder/tree/v6.0.19" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-01-20T17:44:14+00:00" }, { - "name": "symfony/console", + "name": "symfony/options-resolver", "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + "url": "https://github.com/symfony/options-resolver.git", + "reference": "6a180d1c45e0d9797470ca9eb46215692de00fa3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/6a180d1c45e0d9797470ca9eb46215692de00fa3", + "reference": "6a180d1c45e0d9797470ca9eb46215692de00fa3", "shasum": "" }, "require": { "php": ">=8.0.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/deprecation-contracts": "^2.1|^3" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" + "Symfony\\Component\\OptionsResolver\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -2939,16 +2748,15 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Eases the creation of beautiful and testable command line interfaces", + "description": "Provides an improved replacement for the array_replace PHP function", "homepage": "https://symfony.com", "keywords": [ - "cli", - "command line", - "console", - "terminal" + "config", + "configuration", + "options" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.19" + "source": "https://github.com/symfony/options-resolver/tree/v6.0.19" }, "funding": [ { @@ -3297,41 +3105,29 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "name": "symfony/process", + "version": "v6.0.19", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "url": "https://github.com/symfony/process.git", + "reference": "2114fd60f26a296cc403a7939ab91478475a33d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/process/zipball/2114fd60f26a296cc403a7939ab91478475a33d4", + "reference": "2114fd60f26a296cc403a7939ab91478475a33d4", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.0.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Component\\Process\\": "" }, - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3340,28 +3136,18 @@ ], "authors": [ { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/process/tree/v6.0.19" }, "funding": [ { @@ -3377,7 +3163,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-01T08:36:10+00:00" }, { "name": "symfony/service-contracts", @@ -3597,201 +3383,35 @@ "time": "2021-07-28T10:34:58+00:00" }, { - "name": "vimeo/psalm", - "version": "4.27.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "faf106e717c37b8c81721845dba9de3d8deed8ff" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/faf106e717c37b8c81721845dba9de3d8deed8ff", - "reference": "faf106e717c37b8c81721845dba9de3d8deed8ff", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer/package-versions-deprecated": "^1.8.0", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.0.3", - "felixfbecker/language-server-protocol": "^1.5", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.13", - "openlss/lib-array2xml": "^1.0", - "php": "^7.1|^8", - "sebastian/diff": "^3.0 || ^4.0", - "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", - "symfony/polyfill-php80": "^1.25", - "webmozart/path-util": "^2.3" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.2", - "brianium/paratest": "^4.0||^6.0", - "ext-curl": "*", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpdocumentor/reflection-docblock": "^5", - "phpmyadmin/sql-parser": "5.1.0||dev-master", - "phpspec/prophecy": ">=1.9.0", - "phpunit/phpunit": "^9.0", - "psalm/plugin-phpunit": "^0.16", - "slevomat/coding-standard": "^7.0", - "squizlabs/php_codesniffer": "^3.5", - "symfony/process": "^4.3 || ^5.0 || ^6.0", - "weirdan/prophecy-shim": "^1.0 || ^2.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "files": [ - "src/functions.php", - "src/spl_object_id.php" - ], - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/4.27.0" - }, - "time": "2022-08-31T13:47:09+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - }, - { - "name": "webmozart/path-util", - "version": "2.3.0", + "name": "webmozart/glob", + "version": "4.6.0", "source": { "type": "git", - "url": "https://github.com/webmozart/path-util.git", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + "url": "https://github.com/webmozarts/glob.git", + "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", - "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655", + "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655", "shasum": "" }, "require": { - "php": ">=5.3.3", - "webmozart/assert": "~1.0" + "php": "^7.3 || ^8.0.0" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^9.5", + "symfony/filesystem": "^5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "4.1-dev" } }, "autoload": { "psr-4": { - "Webmozart\\PathUtil\\": "src/" + "Webmozart\\Glob\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3804,20 +3424,17 @@ "email": "bschussek@gmail.com" } ], - "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", + "description": "A PHP implementation of Ant's glob.", "support": { - "issues": "https://github.com/webmozart/path-util/issues", - "source": "https://github.com/webmozart/path-util/tree/2.3.0" + "issues": "https://github.com/webmozarts/glob/issues", + "source": "https://github.com/webmozarts/glob/tree/4.6.0" }, - "abandoned": "symfony/filesystem", - "time": "2015-12-17T08:42:14+00:00" + "time": "2022-05-24T19:45:58+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "phpstan/phpstan": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/phpbench.json b/phpbench.json new file mode 100644 index 00000000..adc40d12 --- /dev/null +++ b/phpbench.json @@ -0,0 +1,6 @@ +{ + "$schema":"vendor/phpbench/phpbench/phpbench.schema.json", + "runner.bootstrap": "vendor/autoload.php", + "runner.path": "tests", + "runner.file_pattern": "*Bench.php" +} \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 00000000..a76a8329 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 5 + paths: + - src + - tests \ No newline at end of file diff --git a/tests/RouterBench.php b/tests/RouterBench.php new file mode 100644 index 00000000..b0564c08 --- /dev/null +++ b/tests/RouterBench.php @@ -0,0 +1,58 @@ + '/blog', + 'nested' => '/blog/authors', + 'single param' => '/blog/lorem-ipsum', + 'single param with nested' => '/blog/lorem-ipsum/comments', + 'multiple params' => '/blog/lorem-ipsum/comments/1337', + 'long' => '/blog/lorem/ipsum/dolor/sit/amet/consectetur/adipiscing/elit/Quisque/dolor/nisi/gravida/non/malesuada/eget/tincidunt/vitae/eros/Donec/hendrerit/mollis/purus/non/efficitur/augue/efficitur/sed/Praesent/a/tempus/felis/et/elementum/lorem/Vestibulum/ante/ipsum/primis/in/faucibus/orci/luctus/et/ultrices/posuere/cubilia/curae/Ut/luctus/ultrices/ligula/vulputate/malesuada/magna/pellentesque/eget/Mauris/at/sodales/orci/Mauris/efficitur/volutpat/est/in/faucibus/Donec/non/eleifend/nibh/Nunc/cursus/ornare/sollicitudin/Nullam/pellentesque/placerat/justo/ac/eleifend/tortor/imperdiet/quis/Nullam/tincidunt/non/justo/ut/pulvinar/Suspendisse/laoreet/tempus/nulla/eu/aliquet/Proin/metus/erat/facilisis/in/euismod/sit/amet/mollis/ac/nisi/Nulla/facilisi' + ] as $name => $route) { + yield $name => ['route' => $route]; + } + } + + #[BeforeMethods("setUpRouter")] + #[AfterMethods("tearDown")] + #[Iterations(50)] + #[Assert('mode(variant.time.avg) < 0.025 ms')] + #[ParamProviders('provideRoutesToMatch')] + public function benchRouter(array $data): void + { + Router::match(App::REQUEST_METHOD_GET, $data['route']); + } +} diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 5f26103a..ab243b9e 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -45,9 +45,9 @@ public function testCanMatchUrlWithPlaceholder(): void $this->assertEquals($routeBlog, Router::match(App::REQUEST_METHOD_GET, '/blog')); $this->assertEquals($routeBlogAuthors, Router::match(App::REQUEST_METHOD_GET, '/blog/authors')); $this->assertEquals($routeBlogAuthorsComments, Router::match(App::REQUEST_METHOD_GET, '/blog/authors/comments')); - $this->assertEquals($routeBlogPost, Router::match(App::REQUEST_METHOD_GET, '/blog/:post')); - $this->assertEquals($routeBlogPostComments, Router::match(App::REQUEST_METHOD_GET, '/blog/:post/comments')); - $this->assertEquals($routeBlogPostCommentsSingle, Router::match(App::REQUEST_METHOD_GET, '/blog/:post/comments/:comment')); + $this->assertEquals($routeBlogPost, Router::match(App::REQUEST_METHOD_GET, '/blog/test')); + $this->assertEquals($routeBlogPostComments, Router::match(App::REQUEST_METHOD_GET, '/blog/test/comments')); + $this->assertEquals($routeBlogPostCommentsSingle, Router::match(App::REQUEST_METHOD_GET, '/blog/test/comments/:comment')); } public function testCanMatchHttpMethod(): void @@ -77,6 +77,14 @@ public function testCanMatchAlias(): void $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/alias2')); } + public function testCanMatchFilename(): void + { + $routeGET = new Route(App::REQUEST_METHOD_GET, '/robots.txt'); + + Router::addRoute($routeGET); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/robots.txt')); + } + public function testCannotFindUnknownRouteByPath(): void { $this->assertNull(Router::match(App::REQUEST_METHOD_GET, '/404')); diff --git a/tests/e2e/ResponseTest.php b/tests/e2e/ResponseTest.php index 5b5a74bf..878cc23f 100644 --- a/tests/e2e/ResponseTest.php +++ b/tests/e2e/ResponseTest.php @@ -37,4 +37,10 @@ public function testRedirect() $response = $this->client->call(Client::METHOD_GET, '/redirect'); $this->assertEquals('Hello World!', $response['body']); } + + public function testFile() + { + $response = $this->client->call(Client::METHOD_GET, '/humans.txt'); + $this->assertEquals(204, $response['headers']['status-code']); + } } diff --git a/tests/e2e/server.php b/tests/e2e/server.php index d269f8e0..cef864ee 100644 --- a/tests/e2e/server.php +++ b/tests/e2e/server.php @@ -40,6 +40,12 @@ $response->redirect('/'); }); +App::get('/humans.txt') + ->inject('response') + ->action(function (Response $response) { + $response->noContent(); + }); + $request = new Request(); $response = new Response(); From 900f60f8120448669e6a4bdcf064d4b356b507ea Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 11:59:57 +0200 Subject: [PATCH 10/20] tests: adapt time for regression --- tests/RouterBench.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/RouterBench.php b/tests/RouterBench.php index b0564c08..9bc665e1 100644 --- a/tests/RouterBench.php +++ b/tests/RouterBench.php @@ -49,7 +49,7 @@ public function provideRoutesToMatch(): iterable #[BeforeMethods("setUpRouter")] #[AfterMethods("tearDown")] #[Iterations(50)] - #[Assert('mode(variant.time.avg) < 0.025 ms')] + #[Assert('mode(variant.time.avg) < 0.1 ms')] #[ParamProviders('provideRoutesToMatch')] public function benchRouter(array $data): void { From 7878fcd934b2267c07c9e2b9fc49fadbfacf8b20 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 12:04:58 +0200 Subject: [PATCH 11/20] ci. fix bench output --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09777f59..5d52ec5a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,4 +25,4 @@ jobs: run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml - name: Run Benchmarks - run: docker compose exec web vendor/bin/phpbench run \ No newline at end of file + run: docker compose exec web vendor/bin/phpbench run --progress=plain \ No newline at end of file From 1f9dddc0ef545f33be25806facb9e5e6c814bf93 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 12:10:54 +0200 Subject: [PATCH 12/20] ci: move bench tests into single file --- .github/workflows/bench.yml | 22 ++++++++++++++++++++++ .github/workflows/test.yml | 5 +---- 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/bench.yml diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 00000000..3098877a --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,22 @@ +name: "Benchmarks" + +on: [pull_request] +jobs: + lint: + name: Benchmarks + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + + - name: Install dependencies + run: composer install --prefer-dist + + - name: Run Benchmarks + run: composer bench -- --progress=plain \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5d52ec5a..cc41aa6f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,4 @@ jobs: run: sleep 10 - name: Run Tests - run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml - - - name: Run Benchmarks - run: docker compose exec web vendor/bin/phpbench run --progress=plain \ No newline at end of file + run: docker compose exec web vendor/bin/phpunit --configuration phpunit.xml \ No newline at end of file From 28769b8d9a5edeb8826b3eed33622a8e6172a29f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 12:11:56 +0200 Subject: [PATCH 13/20] ci: remove plain progress --- .github/workflows/bench.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 3098877a..0a397e7b 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -19,4 +19,4 @@ jobs: run: composer install --prefer-dist - name: Run Benchmarks - run: composer bench -- --progress=plain \ No newline at end of file + run: composer bench \ No newline at end of file From 0563443b2a92f9240ad9c88f9d57f62af28f2a71 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 27 Apr 2023 12:13:03 +0200 Subject: [PATCH 14/20] revert: last commit --- .github/workflows/bench.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 0a397e7b..3098877a 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -19,4 +19,4 @@ jobs: run: composer install --prefer-dist - name: Run Benchmarks - run: composer bench \ No newline at end of file + run: composer bench -- --progress=plain \ No newline at end of file From efce8b43a2732e89ec4c9c1861b1ed15b8ec2a39 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 4 May 2023 12:43:01 +0200 Subject: [PATCH 15/20] fix: quotes --- tests/RouterBench.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/RouterBench.php b/tests/RouterBench.php index 9bc665e1..466506d6 100644 --- a/tests/RouterBench.php +++ b/tests/RouterBench.php @@ -46,8 +46,8 @@ public function provideRoutesToMatch(): iterable } } - #[BeforeMethods("setUpRouter")] - #[AfterMethods("tearDown")] + #[BeforeMethods('setUpRouter')] + #[AfterMethods('tearDown')] #[Iterations(50)] #[Assert('mode(variant.time.avg) < 0.1 ms')] #[ParamProviders('provideRoutesToMatch')] From a86c1e4dfd4a0ccad34917cc7c807bcceb3b3d4e Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 31 May 2023 12:33:54 +0200 Subject: [PATCH 16/20] feat: add wildcard support --- src/Router.php | 10 ++++++++++ tests/RouterTest.php | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Router.php b/src/Router.php index c0d56456..8748c253 100644 --- a/src/Router.php +++ b/src/Router.php @@ -10,6 +10,7 @@ class Router * Placeholder token for params in paths. */ public const PLACEHOLDER_TOKEN = ':::'; + public const WILDCARD_TOKEN = '*'; /** * @var array @@ -102,6 +103,15 @@ public static function match(string $method, string $path): Route|null } } + foreach ($parts as $part) { + $current ??= ''; + $match = $current . self::WILDCARD_TOKEN; + if (array_key_exists($match, self::$routes[$method])) { + return self::$routes[$method][$match]; + } + $current = $current . "{$part}/"; + } + return null; } diff --git a/tests/RouterTest.php b/tests/RouterTest.php index ab243b9e..bee2f1d3 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -50,6 +50,23 @@ public function testCanMatchUrlWithPlaceholder(): void $this->assertEquals($routeBlogPostCommentsSingle, Router::match(App::REQUEST_METHOD_GET, '/blog/test/comments/:comment')); } + public function testCanMatchUrlWithWildcard(): void + { + $routeIndex = new Route('GET', '/'); + $routeAbout = new Route('GET', '/about'); + $routeAboutWildcard = new Route('GET', '/about/*'); + + Router::addRoute($routeIndex); + Router::addRoute($routeAbout); + Router::addRoute($routeAboutWildcard); + + $this->assertEquals($routeIndex, Router::match('GET', '/')); + $this->assertEquals($routeAbout, Router::match('GET', '/about')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/you')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me/myself/i')); + } + public function testCanMatchHttpMethod(): void { $routeGET = new Route(App::REQUEST_METHOD_GET, '/'); From fa7ba33715333dd7a7435e9c461a95933f98047a Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 31 May 2023 12:34:38 +0200 Subject: [PATCH 17/20] chore: fix linter --- tests/RouterTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/RouterTest.php b/tests/RouterTest.php index bee2f1d3..072d7693 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -61,10 +61,10 @@ public function testCanMatchUrlWithWildcard(): void Router::addRoute($routeAboutWildcard); $this->assertEquals($routeIndex, Router::match('GET', '/')); - $this->assertEquals($routeAbout, Router::match('GET', '/about')); - $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me')); - $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/you')); - $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me/myself/i')); + $this->assertEquals($routeAbout, Router::match('GET', '/about')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/you')); + $this->assertEquals($routeAboutWildcard, Router::match('GET', '/about/me/myself/i')); } public function testCanMatchHttpMethod(): void From 7ad40ec70bf0714629efd3128806e40b6c9fe6ee Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 18 Jul 2023 14:29:24 +0200 Subject: [PATCH 18/20] fix: wildcard --- src/Router.php | 14 ++++++++++++-- tests/RouterTest.php | 27 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Router.php b/src/Router.php index 8748c253..ac481f55 100644 --- a/src/Router.php +++ b/src/Router.php @@ -103,13 +103,23 @@ public static function match(string $method, string $path): Route|null } } + /** + * Match root wildcard. + */ + $match = self::WILDCARD_TOKEN; + if (array_key_exists($match, self::$routes[$method])) { + return self::$routes[$method][$match]; + } + + /** + * Match wildcard for path segments. + */ foreach ($parts as $part) { - $current ??= ''; + $current = ($current ?? '') . "{$part}/"; $match = $current . self::WILDCARD_TOKEN; if (array_key_exists($match, self::$routes[$method])) { return self::$routes[$method][$match]; } - $current = $current . "{$part}/"; } return null; diff --git a/tests/RouterTest.php b/tests/RouterTest.php index 072d7693..fcaa93c2 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -85,7 +85,9 @@ public function testCanMatchHttpMethod(): void public function testCanMatchAlias(): void { $routeGET = new Route(App::REQUEST_METHOD_GET, '/target'); - $routeGET->alias('/alias')->alias('/alias2'); + $routeGET + ->alias('/alias') + ->alias('/alias2'); Router::addRoute($routeGET); @@ -94,6 +96,29 @@ public function testCanMatchAlias(): void $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/alias2')); } + public function testCanMatchMix(): void + { + $routeGET = new Route(App::REQUEST_METHOD_GET, '/'); + $routeGET + ->alias('/console/*') + ->alias('/auth/*') + ->alias('/invite') + ->alias('/login') + ->alias('/recover') + ->alias('/register/*'); + + Router::addRoute($routeGET); + + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/console')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/invite')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/login')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/recover')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/console/lorem/ipsum/dolor')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/auth/lorem/ipsum')); + $this->assertEquals($routeGET, Router::match(App::REQUEST_METHOD_GET, '/register/lorem/ipsum')); + } + public function testCanMatchFilename(): void { $routeGET = new Route(App::REQUEST_METHOD_GET, '/robots.txt'); From da3e397615963edee9b359b71d4da558a171d763 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 18 Jul 2023 14:50:03 +0200 Subject: [PATCH 19/20] fix: add alias later --- src/Route.php | 21 +-------------------- src/Router.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Route.php b/src/Route.php index 06277b97..5936cbbc 100755 --- a/src/Route.php +++ b/src/Route.php @@ -18,13 +18,6 @@ class Route extends Hook */ protected bool $hook = true; - /** - * Array of aliases. - * - * @var array - */ - protected array $aliases = []; - /** * Path * @@ -68,9 +61,7 @@ public function path(string $path): self */ public function alias(string $path): self { - if (!in_array($path, $this->aliases)) { - $this->aliases[] = $path; - } + Router::addRouteAlias($path, $this); return $this; } @@ -108,16 +99,6 @@ public function getPath(): string return $this->path; } - /** - * Get Aliases - * - * @return array - */ - public function getAliases(): array - { - return $this->aliases; - } - /** * Get hook status * diff --git a/src/Router.php b/src/Router.php index ac481f55..85459a9b 100644 --- a/src/Router.php +++ b/src/Router.php @@ -71,6 +71,24 @@ public static function addRoute(Route $route): void } } + /** + * Add route to router. + * + * @param \Utopia\Route $route + * @return void + * @throws \Exception + */ + public static function addRouteAlias(string $path, Route $route): void + { + [$alias] = self::preparePath($path); + + if (array_key_exists($alias, self::$routes[$route->getMethod()])) { + throw new Exception("Route for ({$route->getMethod()}:{$alias}) already registered."); + } + + self::$routes[$route->getMethod()][$alias] = $route; + } + /** * Match route against the method and path. * From 557afb898f9cab0331513e567564db4e987f4e0f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 18 Jul 2023 14:50:36 +0200 Subject: [PATCH 20/20] fix: unused alias loop --- src/Router.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Router.php b/src/Router.php index 85459a9b..b8820711 100644 --- a/src/Router.php +++ b/src/Router.php @@ -64,11 +64,6 @@ public static function addRoute(Route $route): void } self::$routes[$route->getMethod()][$path] = $route; - - foreach ($route->getAliases() as $alias) { - [$alias] = self::preparePath($alias); - self::$routes[$route->getMethod()][$alias] = $route; - } } /**