From 556fdb4a25872f02f5bcb58e77249bdca41224b5 Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 09:12:14 -0600 Subject: [PATCH 1/7] First pass at else --- src/Illuminate/Routing/Route.php | 23 +++++++++++++++++++++++ src/Illuminate/Routing/Router.php | 15 ++++++++++++--- tests/Routing/RoutingRouteTest.php | 22 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Routing/Route.php b/src/Illuminate/Routing/Route.php index 37ba1aaa4236..bfa7a549d1d4 100755 --- a/src/Illuminate/Routing/Route.php +++ b/src/Illuminate/Routing/Route.php @@ -933,6 +933,29 @@ public function setAction(array $action) return $this; } + /** + * Get the value of the else redirect. + * + * @return \Illuminate\Http\RedirectResponse|null + */ + public function getElse() + { + return $this->action['else'] ?? null; + } + + /** + * Add or change the else redirect. + * + * @param \Illuminate\Http\RedirectResponse $else + * @return $this + */ + public function else($else) + { + $this->action['else'] = $else; + + return $this; + } + /** * Get all middleware, including the ones from the controller. * diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index f1b61dc74dcf..376bb35e6801 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -12,6 +12,7 @@ use Illuminate\Contracts\Support\Jsonable; use Illuminate\Contracts\Support\Responsable; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; @@ -665,9 +666,17 @@ protected function runRoute(Request $request, Route $route) $this->events->dispatch(new RouteMatched($route, $request)); - return $this->prepareResponse($request, - $this->runRouteWithinStack($route, $request) - ); + try { + return $this->prepareResponse($request, + $this->runRouteWithinStack($route, $request) + ); + } catch (ModelNotFoundException $exception) { + if($route->getElse()) { + return $route->getElse(); + } + + throw $exception; + } } /** diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index 9a9f76e8123f..dd7c4c92fe36 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -15,6 +15,7 @@ use Illuminate\Events\Dispatcher; use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Routing\Controller; @@ -1671,6 +1672,27 @@ public function testImplicitBindingsWithOptionalParameterWithExistingKeyInUri() $this->assertSame('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); } + public function testImplicitBindingsWithMissingModelHandledByElse() + { + $redirect = new RedirectResponse('/', 302); + + $router = $this->getRouter(); + $router->get('foo/{bar}', [ + 'middleware' => SubstituteBindings::class, + 'uses' => function (RouteModelBindingNullStub $bar = null) { + $this->assertInstanceOf(RouteModelBindingNullStub::class, $bar); + + return $bar->first(); + }, + ])->else($redirect); + + $request = Request::create('foo/taylor', 'GET'); + + $response = $router->dispatch($request); + $this->assertTrue($response->isRedirect('/')); + $this->assertEquals(302, $response->getStatusCode()); + } + public function testImplicitBindingsWithOptionalParameterWithNoKeyInUri() { $router = $this->getRouter(); From e5f217135464a7de2b11d6e11ca7e5940678ecf9 Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 09:32:30 -0600 Subject: [PATCH 2/7] Fix styling issue --- src/Illuminate/Routing/Router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index 376bb35e6801..c46f2c9e5e05 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -671,7 +671,7 @@ protected function runRoute(Request $request, Route $route) $this->runRouteWithinStack($route, $request) ); } catch (ModelNotFoundException $exception) { - if($route->getElse()) { + if ($route->getElse()) { return $route->getElse(); } From 14b8f794fca23575fbfb076c44eecaad1b9979c3 Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 10:22:26 -0600 Subject: [PATCH 3/7] Update method name to "missing", accepts callbcak --- src/Illuminate/Routing/Route.php | 16 ++++++++-------- src/Illuminate/Routing/Router.php | 4 ++-- tests/Routing/RoutingRouteTest.php | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Illuminate/Routing/Route.php b/src/Illuminate/Routing/Route.php index bfa7a549d1d4..00323d6b417a 100755 --- a/src/Illuminate/Routing/Route.php +++ b/src/Illuminate/Routing/Route.php @@ -934,24 +934,24 @@ public function setAction(array $action) } /** - * Get the value of the else redirect. + * Get the value of the missing redirect. * - * @return \Illuminate\Http\RedirectResponse|null + * @return \Closure|null */ - public function getElse() + public function getMissing() { - return $this->action['else'] ?? null; + return $this->action['missing'] ?? null; } /** - * Add or change the else redirect. + * Add or change the missing redirect. * - * @param \Illuminate\Http\RedirectResponse $else + * @param \Closure $missing * @return $this */ - public function else($else) + public function missing($missing) { - $this->action['else'] = $else; + $this->action['missing'] = $missing; return $this; } diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index c46f2c9e5e05..4c25592a988c 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -671,8 +671,8 @@ protected function runRoute(Request $request, Route $route) $this->runRouteWithinStack($route, $request) ); } catch (ModelNotFoundException $exception) { - if ($route->getElse()) { - return $route->getElse(); + if ($route->getMissing()) { + return $route->getMissing()($request); } throw $exception; diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index dd7c4c92fe36..851d57c472d8 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -1672,10 +1672,8 @@ public function testImplicitBindingsWithOptionalParameterWithExistingKeyInUri() $this->assertSame('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); } - public function testImplicitBindingsWithMissingModelHandledByElse() + public function testImplicitBindingsWithMissingModelHandledByMissing() { - $redirect = new RedirectResponse('/', 302); - $router = $this->getRouter(); $router->get('foo/{bar}', [ 'middleware' => SubstituteBindings::class, @@ -1684,7 +1682,9 @@ public function testImplicitBindingsWithMissingModelHandledByElse() return $bar->first(); }, - ])->else($redirect); + ])->missing(function() { + return new RedirectResponse('/', 302); + }); $request = Request::create('foo/taylor', 'GET'); From 2ff9969e7d659742dbf62d7fc88f07386056d517 Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 10:23:17 -0600 Subject: [PATCH 4/7] Update styling --- tests/Routing/RoutingRouteTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index 851d57c472d8..a0d4548dc06e 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -1682,7 +1682,7 @@ public function testImplicitBindingsWithMissingModelHandledByMissing() return $bar->first(); }, - ])->missing(function() { + ])->missing(function () { return new RedirectResponse('/', 302); }); From 055b880b14dfcb1ad8fa9a018c3818394e33890b Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 16:34:19 -0600 Subject: [PATCH 5/7] Update middleware instead of Router --- .../Routing/Middleware/SubstituteBindings.php | 13 +++++++++++-- src/Illuminate/Routing/Route.php | 11 ++++++++++- src/Illuminate/Routing/Router.php | 14 +++----------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Illuminate/Routing/Middleware/SubstituteBindings.php b/src/Illuminate/Routing/Middleware/SubstituteBindings.php index 57adde76e915..2ce0eb05ca07 100644 --- a/src/Illuminate/Routing/Middleware/SubstituteBindings.php +++ b/src/Illuminate/Routing/Middleware/SubstituteBindings.php @@ -4,6 +4,7 @@ use Closure; use Illuminate\Contracts\Routing\Registrar; +use Illuminate\Database\Eloquent\ModelNotFoundException; class SubstituteBindings { @@ -34,9 +35,17 @@ public function __construct(Registrar $router) */ public function handle($request, Closure $next) { - $this->router->substituteBindings($route = $request->route()); + try { + $this->router->substituteBindings($route = $request->route()); - $this->router->substituteImplicitBindings($route); + $this->router->substituteImplicitBindings($route); + } catch (ModelNotFoundException $exception) { + if($route->getMissing()) { + return $route->getMissing()($request); + } + + throw $exception; + } return $next($request); } diff --git a/src/Illuminate/Routing/Route.php b/src/Illuminate/Routing/Route.php index 00323d6b417a..5e4da85ad673 100755 --- a/src/Illuminate/Routing/Route.php +++ b/src/Illuminate/Routing/Route.php @@ -940,7 +940,12 @@ public function setAction(array $action) */ public function getMissing() { - return $this->action['missing'] ?? null; + $missing = $this->action['missing'] ?? null; + + return is_string($missing) && + Str::startsWith($missing, 'C:32:"Opis\\Closure\\SerializableClosure') + ? unserialize($missing) + : $missing; } /** @@ -1194,6 +1199,10 @@ public function prepareForSerialization() // throw new LogicException("Unable to prepare route [{$this->uri}] for serialization. Uses Closure."); } + if (isset($this->action['missing']) && $this->action['missing'] instanceof Closure) { + $this->action['missing'] = serialize(new SerializableClosure($this->action['missing'])); + } + $this->compileRoute(); unset($this->router, $this->container); diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index 4c25592a988c..a22bc971dee6 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -666,17 +666,9 @@ protected function runRoute(Request $request, Route $route) $this->events->dispatch(new RouteMatched($route, $request)); - try { - return $this->prepareResponse($request, - $this->runRouteWithinStack($route, $request) - ); - } catch (ModelNotFoundException $exception) { - if ($route->getMissing()) { - return $route->getMissing()($request); - } - - throw $exception; - } + return $this->prepareResponse($request, + $this->runRouteWithinStack($route, $request) + ); } /** From a7c1bc22549c4450a6c41c638a37eb54261a573c Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 16:37:51 -0600 Subject: [PATCH 6/7] Fix style issue --- src/Illuminate/Routing/Middleware/SubstituteBindings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Routing/Middleware/SubstituteBindings.php b/src/Illuminate/Routing/Middleware/SubstituteBindings.php index 2ce0eb05ca07..d5f49ea91d9c 100644 --- a/src/Illuminate/Routing/Middleware/SubstituteBindings.php +++ b/src/Illuminate/Routing/Middleware/SubstituteBindings.php @@ -40,7 +40,7 @@ public function handle($request, Closure $next) $this->router->substituteImplicitBindings($route); } catch (ModelNotFoundException $exception) { - if($route->getMissing()) { + if ($route->getMissing()) { return $route->getMissing()($request); } From 8bbd689146c5ac472d93e173ba0f1f3e165ba426 Mon Sep 17 00:00:00 2001 From: Adam Campbell Date: Mon, 25 Jan 2021 16:40:06 -0600 Subject: [PATCH 7/7] Update Router.php --- src/Illuminate/Routing/Router.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index a22bc971dee6..f1b61dc74dcf 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -12,7 +12,6 @@ use Illuminate\Contracts\Support\Jsonable; use Illuminate\Contracts\Support\Responsable; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\Response;