OSDN Git Service

add method reflection and parameter sorting
authorfrostbane <frostbane@programmer.net>
Thu, 28 Nov 2019 03:33:03 +0000 (12:33 +0900)
committerfrostbane <frostbane@programmer.net>
Thu, 28 Nov 2019 04:45:40 +0000 (13:45 +0900)
src/Route.php
tests/Fixtures/SomeController.php
tests/src/PHPRouterTest/RouteTest.php

index bff2403..1dc3880 100755 (executable)
@@ -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();
 
index 2361b3c..3a785c1 100644 (file)
@@ -1,20 +1,5 @@
 <?php
-/**
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the MIT license.
- */
+
 namespace PHPRouter\Test\Fixtures;
 
 final class SomeController
@@ -46,4 +31,9 @@ final class SomeController
     {
         return func_get_args();
     }
+
+    public function parameterSort($id, $group, $user, $page, $tag)
+    {
+        echo implode(",", func_get_args());
+    }
 }
index be2faa3..7af7912 100644 (file)
@@ -21,6 +21,10 @@ class RouteTest extends PHPUnit_Framework_TestCase
                 'methods'     => 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());
+    }
 }