diff --git a/src/App.php b/src/App.php index 41c620be..05b7c8a2 100755 --- a/src/App.php +++ b/src/App.php @@ -298,54 +298,6 @@ public static function setMode(string $value): void self::$mode = $value; } - /** - * If a resource has been created return it, otherwise create it and then return it - * - * @param string $name - * @param bool $fresh - * @return mixed - * - * @throws Exception - */ - public function getResource(string $name, bool $fresh = false): mixed - { - if ($name === 'utopia') { - 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 . '"'); - } - - $this->resources[$name] = \call_user_func_array( - self::$resourcesCallbacks[$name]['callback'], - $this->getResources(self::$resourcesCallbacks[$name]['injections']) - ); - } - - self::$resourcesCallbacks[$name]['reset'] = false; - - return $this->resources[$name]; - } - - /** - * Get Resources By List - * - * @param array $list - * @return array - */ - public function getResources(array $list): array - { - $resources = []; - - foreach ($list as $name) { - $resources[$name] = $this->getResource($name); - } - - return $resources; - } - /** * Set a new resource callback * @@ -528,7 +480,7 @@ public function execute(Transaction $transaction, Route $route, Request $request } } catch (\Throwable $e) { self::setResource('error', fn () => $e); - $transaction->setResource('error', fn () => $e); + $transaction->setResource('error', fn () => $e); foreach ($groups as $group) { foreach (self::$errors as $error) { // Group error hooks @@ -600,16 +552,7 @@ protected function getArguments(Transaction $transaction, Hook $hook, array $val return $arguments; } - /** - * Run - * - * This is the place to initialize any pre routing logic. - * This is where you might want to parse the application current URL by any desired logic - * - * @param Request $request - * @param Response $response - */ - public function run(Request $request, Response $response): static + public function createTransaction(Request $request, Response $response) { $transaction = new Transaction(); @@ -635,6 +578,26 @@ public function run(Request $request, Response $response): static return $route; }); + $transaction->setResource('transaction', function () use ($transaction) { + return $transaction; + }); + + return $transaction; + } + + /** + * Run + * + * This is the place to initialize any pre routing logic. + * This is where you might want to parse the application current URL by any desired logic + * + * @param Request $request + * @param Response $response + */ + public function run(Request $request, Response $response): static + { + $transaction = $this->createTransaction($request, $response); + $method = $request->getMethod(); $route = $this->match($request); $groups = ($route instanceof Route) ? $route->getGroups() : []; diff --git a/src/Transaction.php b/src/Transaction.php old mode 100644 new mode 100755 index cc152098..5198a9cb --- a/src/Transaction.php +++ b/src/Transaction.php @@ -6,11 +6,13 @@ class Transaction { protected string $id; protected array $resourcesCallbacks; + protected array $resources; public function __construct() { $this->id = $this->unique(); $this->resourcesCallbacks = []; + $this->resources = []; } public function setResource(string $name, callable $callback, array $injections = []): void @@ -18,16 +20,24 @@ public function setResource(string $name, callable $callback, array $injections $this->resourcesCallbacks[$name] = ['callback' => $callback, 'injections' => $injections]; } - public function getResource(string $name): mixed + public function getResource(string $name, bool $fresh = false): mixed { - if (! \array_key_exists($name, $this->resourcesCallbacks)) { - throw new Exception('Failed to find resource: "'.$name.'"'); + if ($name === 'transaction') { + return $this; } - return \call_user_func_array( - $this->resourcesCallbacks[$name]['callback'], - $this->getResources($this->resourcesCallbacks[$name]['injections']) - ); + if (!\array_key_exists($name, $this->resources) || $fresh) { + if (!\array_key_exists($name, $this->resourcesCallbacks)) { + throw new Exception('Failed to find resource: "' . $name . '"'); + } + + $this->resources[$name] = \call_user_func_array( + $this->resourcesCallbacks[$name]['callback'], + $this->getResources($this->resourcesCallbacks[$name]['injections']) + ); + } + + return $this->resources[$name]; } public function getResources(array $list): array @@ -46,10 +56,10 @@ protected static function unique(int $padding = 7): string $uniqid = \uniqid(); if ($padding > 0) { - $bytes = \random_bytes(\ceil($padding / 2)); // one byte expands to two chars + $bytes = \random_bytes((int) \ceil($padding / 2)); // one byte expands to two chars $uniqid .= \substr(\bin2hex($bytes), 0, $padding); } return $uniqid; } -} \ No newline at end of file +} diff --git a/tests/AppTest.php b/tests/AppTest.php index 5f08054a..fecf24b1 100755 --- a/tests/AppTest.php +++ b/tests/AppTest.php @@ -83,17 +83,21 @@ public function testCanGetResources(): void App::setResource('first', fn ($second) => "first-{$second}", ['second']); App::setResource('second', fn () => 'second'); - $second = $this->app->getResource('second'); - $first = $this->app->getResource('first'); + $request = new Request(); + $response = new Response(); + $transaction = $this->app->createTransaction($request, $response); + + $second = $transaction->getResource('second'); + $first = $transaction->getResource('first'); $this->assertEquals('second', $second); $this->assertEquals('first-second', $first); - $resource = $this->app->getResource('rand'); + $resource = $transaction->getResource('rand'); $this->assertNotEmpty($resource); - $this->assertEquals($resource, $this->app->getResource('rand')); - $this->assertEquals($resource, $this->app->getResource('rand')); - $this->assertEquals($resource, $this->app->getResource('rand')); + $this->assertEquals($resource, $transaction->getResource('rand')); + $this->assertEquals($resource, $transaction->getResource('rand')); + $this->assertEquals($resource, $transaction->getResource('rand')); // Default Params $route = new Route('GET', '/path'); @@ -107,7 +111,7 @@ public function testCanGetResources(): void }); \ob_start(); - $this->app->execute($route, new Request(), new Response()); + $this->app->execute($transaction, $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -117,7 +121,12 @@ public function testCanGetResources(): void public function testCanExecuteRoute(): void { App::setResource('rand', fn () => rand()); - $resource = $this->app->getResource('rand'); + + $request = new Request(); + $response = new Response(); + $transaction = $this->app->createTransaction($request, $response); + + $resource = $transaction->getResource('rand'); $this->app ->error() @@ -137,7 +146,7 @@ public function testCanExecuteRoute(): void }); \ob_start(); - $this->app->execute($route, new Request(), new Response()); + $this->app->execute($transaction, $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -161,7 +170,9 @@ public function testCanExecuteRoute(): void \ob_start(); $request = new UtopiaRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y', 'z' => 'param-z']); - $this->app->execute($route, $request, new Response()); + $response = new Response(); + $transaction->setResource('request', fn () => $request); + $this->app->execute($transaction, $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -181,7 +192,8 @@ public function testCanExecuteRoute(): void \ob_start(); $request = new UtopiaRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->app->execute($route, $request, new Response()); + $response = new Response(); + $this->app->execute($this->app->createTransaction($request, $response), $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -253,7 +265,8 @@ public function testCanExecuteRoute(): void \ob_start(); $request = new UtopiaRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->app->execute($route, $request, new Response()); + $transaction->setResource('request', fn () => $request); + $this->app->execute($transaction, $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -262,7 +275,8 @@ public function testCanExecuteRoute(): void \ob_start(); $request = new UtopiaRequestTest(); $request::_setParams(['x' => 'param-x', 'y' => 'param-y']); - $this->app->execute($homepage, $request, new Response()); + $transaction->setResource('request', fn () => $request); + $this->app->execute($transaction, $homepage, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -292,7 +306,9 @@ public function testCanAddAndExecuteHooks() }); \ob_start(); - $this->app->execute($route, new Request(), new Response()); + $request = new Request(); + $response = new Response(); + $this->app->execute($this->app->createTransaction($request, $response), $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -308,7 +324,9 @@ public function testCanAddAndExecuteHooks() }); \ob_start(); - $this->app->execute($route, new Request(), new Response()); + $request = new Request(); + $response = new Response(); + $this->app->execute($this->app->createTransaction($request, $response), $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -346,7 +364,9 @@ public function testCanHookThrowExceptions() }); \ob_start(); - $this->app->execute($route, new Request(), new Response()); + $request = new Request(); + $response = new Response(); + $this->app->execute($this->app->createTransaction($request, $response), $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -354,7 +374,9 @@ public function testCanHookThrowExceptions() \ob_start(); $_GET['y'] = 'y-def'; - $this->app->execute($route, new Request(), new Response()); + $request = new Request(); + $response = new Response(); + $this->app->execute($this->app->createTransaction($request, $response), $route, $request, $response); $result = \ob_get_contents(); \ob_end_clean(); @@ -519,9 +541,10 @@ public function testWildcardRoute(): void App::init() ->inject('request') ->inject('response') - ->action(function (Request $request, Response $response) { - $route = $this->app->getRoute(); - App::setResource('myRoute', fn () => $route); + ->inject('route') + ->inject('transaction') + ->action(function (Request $request, Response $response, Route $route, Transaction $transaction) { + $transaction->setResource('myRoute', fn () => $route); if ($request->getURI() === '/init_response') { $response->send('THIS IS RESPONSE FROM INIT!');