Route::findUrl()   C
last analyzed

Complexity

Conditions 8
Paths 14

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 16
nc 14
nop 4
dl 0
loc 29
rs 5.3846
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of Jitamin.
5
 *
6
 * Copyright (C) Jitamin Team
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Jitamin\Foundation\Http;
13
14
use Jitamin\Foundation\Base;
15
16
/**
17
 * Route Handler.
18
 */
19
class Route extends Base
20
{
21
    /**
22
     * Flag that enable the routing table.
23
     *
24
     * @var bool
25
     */
26
    private $activated = false;
27
28
    /**
29
     * Store routes for path lookup.
30
     *
31
     * @var array
32
     */
33
    private $paths = [];
34
35
    /**
36
     * Store routes for url lookup.
37
     *
38
     * @var array
39
     */
40
    private $urls = [];
41
42
    /**
43
     * Enable routing table.
44
     *
45
     * @return Route
46
     */
47
    public function enable()
48
    {
49
        $this->activated = true;
50
51
        return $this;
52
    }
53
54
    /**
55
     * Add route.
56
     *
57
     * @param string $path
58
     * @param string $controller
59
     * @param string $action
60
     * @param string $plugin
61
     *
62
     * @return Route
63
     */
64
    public function addRoute($path, $controller, $action, $plugin = '')
65
    {
66
        if ($this->activated) {
67
            $path = ltrim($path, '/');
68
            $items = explode('/', $path);
69
            $params = $this->findParams($path);
70
71
            $this->paths[] = [
72
                'items'      => $items,
73
                'count'      => count($items),
74
                'controller' => $controller,
75
                'action'     => $action,
76
                'plugin'     => $plugin,
77
            ];
78
79
            $this->urls[$plugin][$controller][$action][] = [
80
                'path'   => $path,
81
                'params' => $params,
82
                'count'  => count($params),
83
            ];
84
        }
85
86
        return $this;
87
    }
88
89
    /**
90
     * Find a route according to the given path.
91
     *
92
     * @param string $path
93
     *
94
     * @return array
95
     */
96
    public function findRoute($path)
97
    {
98
        $items = explode('/', ltrim($path, '/'));
99
        $count = count($items);
100
        foreach ($this->paths as $route) {
101
            if ($count === $route['count']) {
102
                $params = [];
103
104
                for ($i = 0; $i < $count; $i++) {
105
                    if ($route['items'][$i][0] === '{') {
106
                        $params[str_replace(['{', '}'], '', $route['items'][$i])] = $items[$i];
107
                    } elseif ($route['items'][$i] !== $items[$i]) {
108
                        break;
109
                    }
110
                }
111
                if ($i === $count) {
112
                    $this->request->setParams($params);
0 ignored issues
show
Documentation introduced by
The property request does not exist on object<Jitamin\Foundation\Http\Route>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
113
114
                    return [
115
                        'controller' => $route['controller'],
116
                        'action'     => $route['action'],
117
                        'plugin'     => $route['plugin'],
118
                    ];
119
                }
120
            }
121
        }
122
123
        return [
124
                'controller' => Router::DEFAULT_CONTROLLER,
125
                'action'     => Router::DEFAULT_METHOD,
126
                'plugin'     => '',
127
            ];
128
    }
129
130
    /**
131
     * Find route url.
132
     *
133
     * @param string $controller
134
     * @param string $action
135
     * @param array  $params
136
     * @param string $plugin
137
     *
138
     * @return string
139
     */
140
    public function findUrl($controller, $action, array $params = [], $plugin = '')
141
    {
142
        if ($plugin === '' && isset($params['plugin'])) {
143
            $plugin = $params['plugin'];
144
            unset($params['plugin']);
145
        }
146
147
        if (!isset($this->urls[$plugin][$controller][$action])) {
148
            return '';
149
        }
150
151
        foreach ($this->urls[$plugin][$controller][$action] as $route) {
152
            if (array_diff_key($params, $route['params']) === []) {
153
                $url = $route['path'];
154
                $i = 0;
155
156
                foreach ($params as $variable => $value) {
157
                    $url = str_replace('{'.$variable.'}', $value, $url);
158
                    $i++;
159
                }
160
161
                if ($i === $route['count']) {
162
                    return $url;
163
                }
164
            }
165
        }
166
167
        return '';
168
    }
169
170
    /**
171
     * Load route data from cache.
172
     *
173
     * @param array $routes
174
     */
175
    public function loadCacheData($routes)
176
    {
177
        $this->urls = $routes['urls'];
178
        $this->paths = $routes['paths'];
179
    }
180
181
    /**
182
     * Get route data.
183
     *
184
     * @return array
185
     */
186
    public function getRouteData()
187
    {
188
        return [
189
            'urls'  => $this->urls,
190
            'paths' => $this->paths,
191
        ];
192
    }
193
194
    /**
195
     * Find url params.
196
     *
197
     * @param array $items
0 ignored issues
show
Bug introduced by
There is no parameter named $items. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
198
     *
199
     * @return array
200
     */
201
    public function findParams($path)
202
    {
203
        preg_match_all('/\{(.*?)\}/', $path, $matches);
204
205
        return array_fill_keys($matches[1], true);
206
    }
207
}
208