summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Router/Runner/Controller.php14
-rw-r--r--tests/Router/Runner/ControllerTest.php140
2 files changed, 153 insertions, 1 deletions
diff --git a/src/Router/Runner/Controller.php b/src/Router/Runner/Controller.php
index ed8c060..0969c21 100644
--- a/src/Router/Runner/Controller.php
+++ b/src/Router/Runner/Controller.php
@@ -14,7 +14,7 @@ use Psr\Http\Message\ResponseInterface;
class Controller extends Runner
{
/**
- * Route to a file
+ * Route to a controller
*
* @param RequestInterface $request
* @param ResponseInterface $response
@@ -22,6 +22,18 @@ class Controller extends Runner
*/
public function run(RequestInterface $request, ResponseInterface $response)
{
+ $class = !empty($this->route->controller) ? $this->route->controller : null;
+ if (!class_exists($class)) {
+ throw new \RuntimeException("Can not route to controller '$class': class not exists");
+ }
+
+ if (!method_exists($class, '__invoke')) {
+ throw new \RuntimeException("Can not route to controller '$class': class does not have '__invoke' method");
+ }
+
+ $controller = new $class($this->route);
+
+ return $controller($request, $response);
}
}
diff --git a/tests/Router/Runner/ControllerTest.php b/tests/Router/Runner/ControllerTest.php
new file mode 100644
index 0000000..abf4246
--- /dev/null
+++ b/tests/Router/Runner/ControllerTest.php
@@ -0,0 +1,140 @@
+<?php
+
+use Jasny\Router\Route;
+use Jasny\Router\Runner\Controller;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
+class ControllerTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * Tmp scripts
+ * @var array
+ **/
+ public static $files = [];
+
+ /**
+ * Test creating Controller runner
+ *
+ * @dataProvider phpScriptProvider
+ * @param Route $route
+ * @param boolean $positive
+ */
+ public function testPhpScript($route, $positive)
+ {
+ $runner = new Controller($route);
+ $this->assertEquals($route, $runner->getRoute(), "Route was not set correctly");
+
+ $request = $this->createMock(RequestInterface::class);
+ $response = $this->createMock(ResponseInterface::class);
+
+ if (!$positive) $this->expectException(\RuntimeException::class);
+ $result = $runner->run($request, $response);
+
+ $this->assertEquals($request, $result['request'], "Request object was not passed correctly to result");
+ $this->assertEquals($response, $result['response'], "Response object was not passed correctly to result");
+ }
+
+ /**
+ * Provide data for testing 'create' method
+ */
+ public function phpScriptProvider()
+ {
+ foreach (['noInvoke', 'withInvoke'] as $type) {
+ list($class, $path) = static::createTmpScript($type);
+ static::$files[$type] = compact('class', 'path');
+ }
+
+ return [
+ [Route::create(['test' => 'test']), false],
+ [Route::create(['fn' => 'testFunction', 'value' => 'test']), false],
+ [Route::create(['controller' => 'TestController', 'value' => 'test']), false],
+ [Route::create(['controller' => '', 'value' => 'test']), false],
+ [Route::create(['controller' => static::$files['noInvoke']['class'], 'path' => static::$files['noInvoke']['path']]), false],
+ [Route::create(['controller' => static::$files['withInvoke']['class'], 'path' => static::$files['withInvoke']['path']]), true],
+ ];
+ }
+
+ /**
+ * Delete tmp test scripts
+ */
+ public static function tearDownAfterClass()
+ {
+ foreach (static::$files as $path) {
+ unlink($path['path']);
+ }
+ }
+
+ /**
+ * Create single tmp script file for testing
+ *
+ * @param string $type ('returnTrue', 'returnNotTrue')
+ * @return string $path
+ */
+ public static function createTmpScript($type)
+ {
+ $dir = rtrim(sys_get_temp_dir(), '/');
+
+ do {
+ $name = static::getRandomString() . '-test-script.php';
+ $path = $dir . '/' . $name;
+
+ if (!file_exists($path)) break;
+ } while (true);
+
+ if ($type === 'noInvoke') {
+ $class = 'RunnerTestConrtollerInvalid';
+ $content =
+<<<CONTENT
+<?php
+
+class $class {
+ public \$route = null;
+
+ public function __construct(\$route)
+ {
+ \$this->route = \$route;
+ }
+}
+CONTENT;
+ } else {
+ $class = 'RunnerTestConrtoller';
+ $content =
+<<<CONTENT
+<?php
+
+class $class {
+ public \$route = null;
+
+ public function __construct(\$route)
+ {
+ \$this->route = \$route;
+ }
+
+ public function __invoke(Psr\Http\Message\RequestInterface \$request, Psr\Http\Message\ResponseInterface \$response)
+ {
+ return ['request' => \$request, 'response' => \$response];
+ }
+}
+CONTENT;
+ }
+
+ $bytes = file_put_contents($path, $content);
+ static::assertTrue((int)$bytes > 0);
+
+ require_once $path;
+
+ return [$class, $path];
+ }
+
+ /**
+ * Get random string of given length (no more then length of md5 hash)
+ *
+ * @param int $length
+ * @return string
+ */
+ public static function getRandomString($length = 10)
+ {
+ return substr(md5(microtime(true) * mt_rand()), 0, $length);
+ }
+}