Completed
Push — master ( 99bf78...d383a6 )
by Jay
02:11
created

Framework::getParametersForMatching()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 7
nc 3
nop 2
crap 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Nano;
5
6
/**
7
 * Class Framework
8
 * @package Nano
9
 */
10
final class Framework
11
{
12
    private $projectNamespace = '\Project';
13
    private $controllerPackage = '\Controller';
14
    private $controllerActionSuffix = 'Action';
15
    private $withParameterMatching = false;
16
17
    /**
18
     * Dispatch the request
19
     * @throws \Exception
20
     * @return mixed
21
     */
22 12
    public function dispatch()
23
    {
24 12
        list($controllerName, $action) = $this->getControllerAndAction();
25 12
        $controller = $this->getControllerFromName($controllerName);
26 9
        $finalAction = $this->getVerbFromRequest() . ucfirst($action) . $this->controllerActionSuffix;
27 9
        if (is_callable(array($controller, $finalAction))) {
28 3
            return call_user_func_array(
29 3
                [$controller, $finalAction],
30 3
                $this->getParametersForMatching($controller, $finalAction)
31
            );
32
        }
33 6
        $finalAction = $action . $this->controllerActionSuffix;
34 6
        if (!is_callable(array($controller, $finalAction))) {
35 1
            throw new \Exception('action ' . $finalAction . ' not found in controller ' . $controllerName);
36
        }
37 5
        return call_user_func_array(
38 5
            [$controller, $finalAction],
39 5
            $this->getParametersForMatching($controller, $finalAction)
40
        );
41
    }
42
43
    /**
44
     * Returns parameters from request matching specified controller and action
45
     * @param object $controller
46
     * @param string $action
47
     * @return array
48
     */
49 8
    private function getParametersForMatching($controller, string $action): array
50
    {
51 8
        $parameters = [];
52 8
        $reflection = new \ReflectionMethod($controller, $action);
53 8
        foreach ($reflection->getParameters() as $param) {
54 2
            if (isset($_REQUEST[$param->name])) {
55 2
                $parameters[$param->name] = $_REQUEST[$param->name];
56
            }
57
        }
58 8
        return $parameters;
59
    }
60
61
    /**
62
     * Return Controller instance from a controller name
63
     * @param string $controllerName
64
     * @return object
65
     * @throws \Exception
66
     */
67 12
    private function getControllerFromName(string $controllerName)
68
    {
69 12
        $controller = $this->projectNamespace . $this->controllerPackage . '\\' . ucfirst($controllerName);
70 12
        if (!class_exists($controller)) {
71 3
            throw new \Exception('controller ' . $controllerName . ' not found');
72
        }
73 9
        return new $controller;
74
    }
75
76
    /**
77
     * Return HTTP Method for request
78
     * @return string
79
     */
80 9
    private function getVerbFromRequest(): string
81
    {
82 9
        return isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'get';
83
    }
84
85
    /**
86
     * Returns Request uri without query string
87
     * @return string
88
     */
89 12
    private function getQuery(): string
90
    {
91 12
        $requestUri = $_SERVER['REQUEST_URI'];
92 12
        $appendUri = strpos($requestUri, '?');
93 12
        return substr($requestUri, 0, $appendUri === false ? strlen($requestUri) : $appendUri);
94
    }
95
96
    /**
97
     * Determine controller and action from Request Uri
98
     * @return array
99
     */
100 12
    private function getControllerAndAction(): array
101
    {
102 12
        $parts = explode('/', preg_replace('~^' . Basepath::get() . '~', '', $this->getQuery()));
103 12
        $action = count($parts) >= 2 ? array_pop($parts) : 'index';
104 12
        $controllerName = isset($parts[0]) && $parts[0] ? implode($parts, '\\') : 'index';
105 12
        return [$controllerName, $action ?: 'index'];
106
    }
107
108
    /**
109
     * Redefine personal namespace
110
     * @param string $namespace
111
     * @return Framework
112
     */
113 6
    public function setNamespace(string $namespace = '\Project'): Framework
114
    {
115 6
        $this->projectNamespace = strlen($namespace) && $namespace{0} != '\\' ? '\\' . $namespace : $namespace;
116 6
        return $this;
117
    }
118
119
    /**
120
     * Redefine controller subpackage
121
     * @param string $controllerPackage
122
     * @return Framework
123
     */
124 7
    public function setControllerPackage(string $controllerPackage = '\Controller'): Framework
125
    {
126 7
        $this->controllerPackage = strlen($controllerPackage) && $controllerPackage{0} != '\\'
127 2
            ? '\\' . $controllerPackage
128 5
            : $controllerPackage;
129 7
        return $this;
130
    }
131
132
    /**
133
     * Redefine controller action suffix
134
     * @param string $suffix
135
     * @return Framework
136
     */
137 5
    public function setControllerActionSuffix(string $suffix = 'Action'): Framework
138
    {
139 5
        $this->controllerActionSuffix = (string)$suffix;
140 5
        return $this;
141
    }
142
143
    /**
144
     * Tells if we should use parameter matching for controllers
145
     * @param bool $active
146
     * @return Framework
147
     */
148 2
    public function setParameterMatching($active = true): Framework
149
    {
150 2
        $this->withParameterMatching = (bool)$active;
151 2
        return $this;
152
    }
153
}
154