summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold Daniels <arnold@jasny.net>2016-11-29 16:53:49 +0100
committerGitHub <noreply@github.com>2016-11-29 16:53:49 +0100
commit8db24c7d9e173bb8a126dfde4889f3316d892d66 (patch)
treeab215c24bea919013537d67a193ab27f73309c79
parent85b270a15e378d2e1862d0e797b9ec44a6925bed (diff)
parent8f42e1e3a34b1b7eab9892a9d4a40efe524eba42 (diff)
downloadrouter-8db24c7d9e173bb8a126dfde4889f3316d892d66.zip
router-8db24c7d9e173bb8a126dfde4889f3316d892d66.tar.gz
router-8db24c7d9e173bb8a126dfde4889f3316d892d66.tar.bz2
Merge pull request #15 from jasny/controller-runner-notfound
Let the controller runner return a not found response
-rw-r--r--src/Router/Runner/Controller.php25
-rw-r--r--tests/Router/Runner/ControllerTest.php63
-rw-r--r--tests/support/TestHelpers.php19
3 files changed, 81 insertions, 26 deletions
diff --git a/src/Router/Runner/Controller.php b/src/Router/Runner/Controller.php
index 7985029..3d5e569 100644
--- a/src/Router/Runner/Controller.php
+++ b/src/Router/Runner/Controller.php
@@ -12,6 +12,25 @@ use Psr\Http\Message\ResponseInterface;
class Controller extends Runner
{
/**
+ * Return with a 404 not found response
+ *
+ * @param ServerRequestInterface $request
+ * @param ResponseInterface $response
+ * @return ResponseInterface
+ */
+ protected function notFound(ServerRequestInterface $request, ResponseInterface $response)
+ {
+ $finalResponse = $response
+ ->withProtocolVersion($request->getProtocolVersion())
+ ->withStatus(404)
+ ->withHeader('Content-Type', 'text/plain');
+
+ $finalResponse->getBody()->write("Not found");
+
+ return $finalResponse;
+ }
+
+ /**
* Get class name from controller name
*
* @param string $name
@@ -49,11 +68,13 @@ class Controller extends Runner
$class = $this->getClass($name);
if (!class_exists($class)) {
- throw new \RuntimeException("Can not route to controller '$class': class not exists");
+ trigger_error("Can't route to controller '$class': class not exists", E_USER_NOTICE);
+ return $this->notFound($request, $response);
}
if (!method_exists($class, '__invoke')) {
- throw new \RuntimeException("Can not route to controller '$class': class does not have '__invoke' method");
+ trigger_error("Can't route to controller '$class': class does not have '__invoke' method", E_USER_NOTICE);
+ return $this->notFound($request, $response);
}
$controller = $this->instantiate($class);
diff --git a/tests/Router/Runner/ControllerTest.php b/tests/Router/Runner/ControllerTest.php
index c1b1801..5bbbeca 100644
--- a/tests/Router/Runner/ControllerTest.php
+++ b/tests/Router/Runner/ControllerTest.php
@@ -6,6 +6,7 @@ use Jasny\Router\Route;
use Jasny\Router\Runner;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
use Jasny\Router\TestHelpers;
@@ -39,44 +40,58 @@ class ControllerTest extends \PHPUnit_Framework_TestCase
$this->assertSame($finalResponse, $result);
}
- /**
- * @expectedException RuntimeException
- * @expectedExceptionMessage Can not route to controller 'DoesNotExistsController': class not exists
- */
- public function testInvalidClass()
+ public function invalidProvider()
{
- $request = $this->createMock(ServerRequestInterface::class);
- $response = $this->createMock(ResponseInterface::class);
+ $runnerNotExists = $this->createPartialMock(Runner\Controller::class, ['instantiate']);
+ $runnerNotExists->expects($this->never())->method('instantiate');
- $route = $this->createMock(Route::class);
- $route->controller = 'does-not-exists';
-
- $request->expects($this->once())->method('getAttribute')->with('route')->willReturn($route);
+ $runnerNotCallable = $this->createPartialMock(Runner\Controller::class, ['instantiate', 'getClass']);
+ $runnerNotCallable->expects($this->once())->method('getClass')->with('foo-bar-zoo')->willReturn('stdClass');
+ $runnerNotCallable->expects($this->never())->method('instantiate');
- $runner = $this->getMockBuilder(Runner\Controller::class)->setMethods(['instantiate'])->getMock();
- $runner->expects($this->never())->method('instantiate');
-
- $runner($request, $response);
+ return [
+ [
+ $runnerNotExists,
+ "Can't route to controller 'FooBarZooController': class not exists"
+ ],
+ [
+ $runnerNotCallable,
+ "Can't route to controller 'stdClass': class does not have '__invoke' method"
+ ]
+ ];
}
/**
- * @expectedException RuntimeException
- * @expectedExceptionMessage Can not route to controller 'stdClass': class does not have '__invoke' method
+ * @dataProvider invalidProvider
+ *
+ * @param Runner $runner
+ * @param string $message
*/
- public function testInvokeNotCallable()
+ public function testInvokeInvalid(Runner $runner, $message)
{
$request = $this->createMock(ServerRequestInterface::class);
+ $request->method('getProtocolVersion')->willReturn('1.1');
+
+ $body = $this->createMock(StreamInterface::class);
+ $body->expects($this->once())->method('write')->with('Not found');
+
+ $notFound = $this->createMock(ResponseInterface::class);
+ $notFound->expects($this->once())->method('getBody')->willReturn($body);
+
$response = $this->createMock(ResponseInterface::class);
+ $response->expects($this->once())->method('withProtocolVersion')->with('1.1')->willReturnSelf();
+ $response->expects($this->once())->method('withStatus')->with(404)->willReturnSelf();
+ $response->expects($this->once())->method('withHeader')->with('Content-Type', 'text/plain')
+ ->willReturn($notFound);
$route = $this->createMock(Route::class);
- $route->controller = 'foo';
+ $route->controller = 'foo-bar-zoo';
$request->expects($this->once())->method('getAttribute')->with('route')->willReturn($route);
- $runner = $this->getMockBuilder(Runner\Controller::class)->setMethods(['instantiate', 'getClass'])->getMock();
- $runner->expects($this->once())->method('getClass')->with('foo')->willReturn('stdClass');
- $runner->expects($this->never())->method('instantiate');
-
- $runner($request, $response);
+ $result = @$runner($request, $response);
+
+ $this->assertSame($notFound, $result);
+ $this->assertLastError(E_USER_NOTICE, $message);
}
}
diff --git a/tests/support/TestHelpers.php b/tests/support/TestHelpers.php
index e4fdff7..3781851 100644
--- a/tests/support/TestHelpers.php
+++ b/tests/support/TestHelpers.php
@@ -27,4 +27,23 @@ trait TestHelpers
return $callback;
}
+
+ /**
+ * Assert a non-fatal error
+ *
+ * @param int $type
+ * @param string $message
+ */
+ protected function assertLastError($type, $message)
+ {
+ $error = error_get_last();
+
+ $expect = compact('type', 'message');
+
+ if (is_array($error)) {
+ $error = array_intersect_key($error, $expect);
+ }
+
+ $this->assertEquals($expect, $error);
+ }
}