<?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;
-use Fig\Http\Message\RequestMethodInterface;
+namespace PHPRouter;
class Route
{
/**
* Accepted HTTP methods for this route.
+ *
* @var string[]
*/
- private $methods = array(
- RequestMethodInterface::METHOD_GET,
- RequestMethodInterface::METHOD_POST,
- RequestMethodInterface::METHOD_PUT,
- RequestMethodInterface::METHOD_DELETE,
- );
+ private $methods;
/**
* Target for this route, can be anything.
private $parameters = array();
/**
- * Set named parameters to target method
- * @example [ [0] => [ ["link_id"] => "12312" ] ]
- * @var bool
+ * @var null|string
*/
- private $parametersByName;
+ private $action;
/**
* @var array
private $config;
/**
- * @param $resource
- * @param array $config
+ * @var null|string
*/
- public function __construct($resource, array $config)
+ private $class;
+
+ /**
+ * @param string $pathInfo
+ * @param array $config
+ */
+ public function __construct($pathInfo, array $config)
{
- $this->url = $resource;
- $this->config = $config;
- $this->methods = isset($config['methods']) ? (array) $config['methods'] : array();
- $this->target = isset($config['target']) ? $config['target'] : null;
- $this->name = isset($config['name']) ? $config['name'] : null;
+ $this->url = $pathInfo;
+ $this->config = $config;
+ $this->methods = isset($config['methods']) ? (array)$config['methods'] : array();
+ $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 = isset ($this->config['_controller']) ? explode('::', $this->config['_controller']) : array();
+ $this->class = isset($action[0]) ? $action[0] : null;
+ $this->action = isset($action[1]) ? $action[1] : null;
}
public function getUrl()
$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()
{
- return preg_replace_callback('/(:\w+)/', array(&$this, 'substituteFilter'), $this->url);
+ $url = preg_quote($this->url);
+
+ return preg_replace_callback('/(\\\\(:\w+))/', array(&$this, 'substituteFilter'), $url);
}
private function substituteFilter($matches)
{
- if (isset($matches[1], $this->filters[$matches[1]])) {
- return $this->filters[$matches[1]];
+ if (isset($matches[1], $this->filters[$matches[2]])) {
+ return $this->filters[$matches[2]];
}
return '([\w-%]+)';
$this->parameters = $parameters;
}
- public function dispatch()
+ public function getValidController()
+ {
+ $class = $this->class;
+ $method = $this->action;
+
+ if (!class_exists($class)) {
+ return null;
+ }
+
+ if (empty($method) || trim($method) === '') {
+ $method = "__invoke";
+ }
+
+ try {
+ $classRexl = new \ReflectionClass($class);
+ } catch (\ReflectionException $ex) {
+ return null;
+ }
+
+ try {
+ $methRexl = $classRexl->getMethod($method);
+ } catch (\ReflectionException $ex) {
+ return null;
+ }
+
+ // use only public methods
+ // to avoid calling inherited protected methods
+ if(!$methRexl->isPublic()) {
+ return null;
+ }
+
+ return $this->config['_controller'];
+ }
+
+ /**
+ * sort parameters according the the method's arguments
+ *
+ * @return array
+ *
+ * @throws \ReflectionException
+ */
+ private function sortParameters()
{
- $action = explode('::', $this->config['_controller']);
+ $class = $this->class;
+ $method = $this->action;
+ $parameters = $this->parameters;
+ $arguments = array();
- if ($this->parametersByName) {
- $this->parameters = array($this->parameters);
+ if (empty($method) || trim($method) === '') {
+ $method = "__invoke";
}
- $this->action = !empty($action[1]) && trim($action[1]) !== '' ? $action[1] : null;
+ $rexl = new \ReflectionMethod($class, $method);
- if (!is_null($this->action)) {
- $instance = new $action[0];
- call_user_func_array(array($instance, $this->action), $this->parameters);
+ 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);
+ }
+
+ private function canBeEchoed($var)
+ {
+ return method_exists($var, '__toString') || (is_scalar($var) && !is_null($var));
+ }
+
+ public function dispatch($instance = null)
+ {
+ is_null($instance) and $instance = new $this->class();
+
+ $param = $this->sortParameters();
+
+ ob_start();
+
+ if (empty($this->action) || trim($this->action) === '') {
+ // __invoke on a class
+ $result = call_user_func_array($instance, $param);
} else {
- $instance = new $action[0]($this->parameters);
+ $result = call_user_func_array(array($instance, $this->action), $param);
+ }
+
+ if ($this->canBeEchoed($result)) {
+ echo $result;
}
+
+ $buffer = ob_get_clean();
+
+ return $buffer;
}
public function getAction()
{
return $this->action;
}
+
+ public function getClass()
+ {
+ return $this->class;
+ }
}