From 0f3accf31847cc1898336369f3ad3d5457faaaf6 Mon Sep 17 00:00:00 2001 From: Rougin Gutib Date: Mon, 25 Dec 2023 02:49:02 +0800 Subject: [PATCH] Add Routing for creating HTTP routes directly to Application --- CHANGELOG.md | 1 + composer.json | 13 ++++- phpunit.xml.dist | 2 +- src/Application.php | 6 ++- src/System.php | 17 ++---- src/System/Routing.php | 99 +++++++++++++++++++++++++++++++++++ tests/Forward/Builder.php | 34 ++++++++++++ tests/Forward/ForwardTest.php | 36 +++++++++++++ 8 files changed, 190 insertions(+), 18 deletions(-) create mode 100644 src/System/Routing.php create mode 100644 tests/Forward/Builder.php create mode 100644 tests/Forward/ForwardTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e7346f..63eabe2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to `Slytherin` will be documented in this file. - Support for all versions of `http-interop/http-middleware` (`0.3`, `0.4`, `0.5`) - `ERRATUM.md` for changes in `README.md` for specified versions - Support versions for PHP `v8.3` +- `Routing` for creating HTTP routes directly in `Application` ### Changed - Third-party packages in `Routing` extends to Slytherin's `Dispatcher`, `Router` diff --git a/composer.json b/composer.json index 696195b4..9c919fb1 100644 --- a/composer.json +++ b/composer.json @@ -21,8 +21,17 @@ }, "require-dev": { - "phpunit/phpunit": "~4.2|~5.7|~6.0|~7.0|~8.0|~9.0", - "sanmai/phpunit-legacy-adapter": "~6.1|~8.0" + "filp/whoops": "~2.0", + "http-interop/http-middleware": "0.4.1", + "league/container": "~4.0", + "nikic/fast-route": "~1.0", + "phpunit/phpunit": "~4.0|~5.0|~6.0|~7.0|~8.0|~9.0", + "phroute/phroute": "~2.0", + "rdlowrey/auryn": "~1.0", + "sanmai/phpunit-legacy-adapter": "~6.0|~8.0", + "twig/twig": "~1.0", + "zendframework/zend-diactoros": "~2.0", + "zendframework/zend-stratigility": "~3.0" }, "autoload": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 78a31719..21e742d8 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,5 @@ - + tests diff --git a/src/Application.php b/src/Application.php index e85d2b47..3e916036 100644 --- a/src/Application.php +++ b/src/Application.php @@ -2,14 +2,16 @@ namespace Rougin\Slytherin; +use Rougin\Slytherin\System\Routing; + /** * Application * - * NOTE: To be removed in v1.0.0. Use "System" instead. + * NOTE: To be removed in v1.0.0. Use "Routing" instead. * * @package Slytherin * @author Rougin Gutib */ -class Application extends System +class Application extends Routing { } diff --git a/src/System.php b/src/System.php index b0f01c07..e6e6fd4b 100644 --- a/src/System.php +++ b/src/System.php @@ -3,7 +3,6 @@ namespace Rougin\Slytherin; use Psr\Http\Message\ServerRequestInterface; -use Rougin\Slytherin\Component\Collection; use Rougin\Slytherin\Container\Container; use Rougin\Slytherin\Container\ContainerInterface; use Rougin\Slytherin\Integration\Configuration; @@ -50,26 +49,18 @@ class System /** * Initializes the application instance. * - * @param mixed|null $container - * @param \Rougin\Slytherin\Integration\Configuration|null $config + * @param \Rougin\Slytherin\Container\ContainerInterface|null $container + * @param \Rougin\Slytherin\Integration\Configuration|null $config */ - public function __construct($container = null, Configuration $config = null) + public function __construct(ContainerInterface $container = null, Configuration $config = null) { if (! $config) $config = new Configuration; $this->config = $config; - if ($container instanceof Collection) - { - $container = $container->getContainer(); - } - if (! $container) $container = new Container; - if ($container instanceof ContainerInterface) - { - $this->container = $container; - } + $this->container = $container; } /** diff --git a/src/System/Routing.php b/src/System/Routing.php new file mode 100644 index 00000000..35270910 --- /dev/null +++ b/src/System/Routing.php @@ -0,0 +1,99 @@ + + */ +class Routing extends System +{ + /** + * @var \Rougin\Slytherin\Routing\RouterInterface|null + */ + protected $router = null; + + /** + * Adds a new raw route. + * + * @param string $method + * @param string $uri + * @param callable|string[]|string $handler + * @param \Rougin\Slytherin\Middleware\MiddlewareInterface[]|string[] $middlewares + * @return self + */ + public function add($method, $uri, $handler, $middlewares = array()) + { + if (is_null($this->router)) + { + $this->router = new Router; + } + + $this->router->add($method, $uri, $handler, $middlewares); + + return $this; + } + + /** + * Emits the headers from response and runs the application. + * + * @return void + */ + public function run() + { + if (is_null($this->router)) + { + parent::run(); return; + } + + // Prepare the HttpIntegration ------------------- + $this->config->set('app.http.cookies', $_COOKIE); + + $this->config->set('app.http.files', $_FILES); + + $this->config->set('app.http.get', (array) $_GET); + + $this->config->set('app.http.post', $_POST); + + $this->config->set('app.http.server', $_SERVER); + + $items = array(new HttpIntegration); + // ----------------------------------------------- + + // Prepare the RoutingIntegration ------------------- + $items[] = new RoutingIntegration; + + $this->integrate($items); + + $this->container->set(System::ROUTER, $this->router); + // -------------------------------------------------- + + parent::run(); return; + } + + /** + * Calls methods from the Router instance. + * + * @param string $method + * @param mixed[] $params + * @return mixed + */ + public function __call($method, $params) + { + array_unshift($params, $method); + + /** @var callable $class */ + $class = array($this, 'add'); + + return call_user_func_array($class, $params); + } +} diff --git a/tests/Forward/Builder.php b/tests/Forward/Builder.php new file mode 100644 index 00000000..b5709d5a --- /dev/null +++ b/tests/Forward/Builder.php @@ -0,0 +1,34 @@ + + */ +class Builder +{ + public function make() + { + $app = new Application; + + $app->get('/', 'Rougin\Slytherin\Fixture\Classes\NewClass@index'); + + return $app; + } + + public function setUrl($method, $uri) + { + $_SERVER['REQUEST_METHOD'] = $method; + + $_SERVER['REQUEST_URI'] = $uri; + + $_SERVER['SERVER_NAME'] = 'localhost'; + + $_SERVER['SERVER_PORT'] = '8000'; + + return $this; + } +} diff --git a/tests/Forward/ForwardTest.php b/tests/Forward/ForwardTest.php new file mode 100644 index 00000000..7b5b2da3 --- /dev/null +++ b/tests/Forward/ForwardTest.php @@ -0,0 +1,36 @@ + + */ +class ForwardTest extends Testcase +{ + /** + * @var \Rougin\Slytherin\Forward\Builder + */ + protected $builder; + + protected function doSetUp() + { + $this->builder = new Builder; + } + + /** + * @runInSeparateProcess + * + * @return void + */ + public function test_get_method() + { + $this->builder->setUrl('GET', '/'); + + $this->expectOutputString('Hello'); + + $this->builder->make()->run(); + } +}