From b1d7d841fe7f3537a6c426095aeafcfb3a44f26a Mon Sep 17 00:00:00 2001 From: frostbane Date: Thu, 28 Nov 2019 12:33:03 +0900 Subject: [PATCH 1/1] add method reflection and parameter sorting --- src/Route.php | 77 ++++++++++++++++++++++++++++------- tests/Fixtures/SomeController.php | 22 +++------- tests/src/PHPRouterTest/RouteTest.php | 64 ++++++++++++++++++++++++----- 3 files changed, 122 insertions(+), 41 deletions(-) diff --git a/src/Route.php b/src/Route.php index bff2403..1dc3880 100755 --- a/src/Route.php +++ b/src/Route.php @@ -42,13 +42,6 @@ class Route private $parameters = array(); /** - * Set named parameters to target method - * @example [ [0] => [ ["link_id"] => "12312" ] ] - * @var bool - */ - private $parametersByName; - - /** * @var null|string */ private $action; @@ -75,6 +68,7 @@ class Route $this->target = isset($config['target']) ? $config['target'] : null; $this->name = isset($config['name']) ? $config['name'] : null; $this->parameters = isset($config['parameters']) ? $config['parameters'] : array(); + $this->filters = isset($config['filters']) ? $config['filters'] : array(); $action = explode('::', $this->config['_controller']); $this->class = isset($action[0]) ? $action[0] : null; $this->action = isset($action[1]) ? $action[1] : null; @@ -127,10 +121,14 @@ class Route $this->name = (string)$name; } - public function setFilters(array $filters, $parametersByName = false) + public function setFilters(array $filters) { - $this->filters = $filters; - $this->parametersByName = $parametersByName; + $this->filters = $filters; + } + + public function getFilters() + { + return $this->filters; } public function getRegex() @@ -162,7 +160,7 @@ class Route $class = $this->class; $method = $this->action; - if ( !class_exists($class)) { + if (!class_exists($class)) { return null; } @@ -185,14 +183,63 @@ class Route return $this->config['_controller']; } + /** + * sort parameters according the the method's arguments + * + * @return array + * + * @throws \ReflectionException + */ + private function sortParameters() + { + $class = $this->class; + $method = $this->action; + $parameters = $this->parameters; + $arguments = array(); + + if (empty($method) || trim($method) === '') { + $method = "__invoke"; + } + + $rexl = new \ReflectionMethod($class, $method); + + foreach ($rexl->getParameters() as $methArgs) { + $arg = $methArgs->getName(); + + if (array_key_exists($arg, $parameters)) { + $arguments[$arg] = $parameters[$arg]; + + unset($parameters[$arg]); + } else { + // argument is not in the parameters + $arguments[$arg] = null; + } + } + + if (count($parameters) > 0) { + // fill the unset arguments + foreach ($arguments as $arg => &$v) { + if ($v === null) { + //$key = array_keys($parameters)[0]; + + $v = array_shift($parameters); + } + + if (count($parameters) <= 0) { + break; + } + } + } + + // merge the remaining parameters + return array_merge($arguments, $parameters); + } + public function dispatch($instance = null) { is_null($instance) and $instance = new $this->class(); - // todo figure out what parametersByName is for - $param = $this->parametersByName ? - array($this->parameters) : - $this->parameters; + $param = $this->sortParameters(); ob_start(); diff --git a/tests/Fixtures/SomeController.php b/tests/Fixtures/SomeController.php index 2361b3c..3a785c1 100644 --- a/tests/Fixtures/SomeController.php +++ b/tests/Fixtures/SomeController.php @@ -1,20 +1,5 @@ array( 'GET', ), + 'filters' => array( + ":user" => "([A-Z][a-z]+)", + ":id" => "([1-9]\\d)", + ), ) ); @@ -126,33 +130,36 @@ class RouteTest extends PHPUnit_Framework_TestCase $this->assertEquals($param, $this->routeWithParameters->getParameters()); } - public function testGetRegex() + public function testGetRegexNoFilters() { - $regex = $this->routeWithParameters->getRegex(); + $filters = $this->routeWithParameters->getFilters(); + $regex = $this->routeWithParameters->getRegex(); + $this->assertEmpty($filters); $this->assertEquals("/page/([\\w-%]+)/([\\w-%]+)", $regex); } public function testGetFilterRegex() { $filters = array( - ":user" => "([A-Z][a-z]+)", - ":id" => "([1-9]\\d)", + ":page_id" => "([\\d+])", + ":page_size" => "([1-9]\\d)", ); - $this->routeUsing__invoke->setFilters($filters); - - $regex = $this->routeUsing__invoke->getRegex(); + $this->routeWithParameters->setFilters($filters); - $this->assertEquals("/home/([A-Z][a-z]+)/([1-9]\\d)", $regex); + $this->assertEquals("/page/{$filters[':page_id']}/{$filters[':page_size']}", + $this->routeWithParameters->getRegex()); + $this->assertEquals("/home/([A-Z][a-z]+)/([1-9]\\d)", + $this->routeUsing__invoke->getRegex()); } - public function testDispatch() + public function testDispatch__invoke() { $message = "welcome"; $param = array( - "id" => 1, "user" => "akane", + "id" => 1, ); $this->routeUsing__invoke->setParameters($param); @@ -165,4 +172,41 @@ class RouteTest extends PHPUnit_Framework_TestCase $this->assertEquals("$message {$param['id']}:{$param['user']}", $this->routeUsing__invoke->dispatch($instance)); } + + public function testDispatch() + { + $buffer = $this->routeWithParameters->dispatch(); + + var_dump($buffer); + } + + public function testParameterSorting() + { + $route = new Route( + '/', + array( + '_controller' => '\PHPRouter\Test\Fixtures\SomeController::parameterSort', + 'methods' => array( + 'GET', + ), + ) + ); + + $params = array( + "group_name" => "fi", + "id" => 1, + "page_name" => "profile", + "user" => "akane", + "tag_name" => "m", + "flag" => 2, + "admin" => 0, + ); + + // route is expected to arrange the params according to the function arguments + // and fill the missing ones with the remaining unmatched parameters + $expected = implode(",", array(1, "fi", "akane", "profile", "m", 2, 0)); + + $route->setParameters($params); + $this->assertEquals($expected, $route->dispatch()); + } } -- 2.11.0