Completed
Pull Request — master (#39)
by Tim
35:20
created

ActionMapping   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 273
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 273
c 0
b 0
f 0
wmc 25
lcom 1
cbo 0
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
C compile() 0 51 7
B match() 0 24 4
A getPath() 0 4 1
C applyDefaults() 0 32 7
A getCompiledRegex() 0 4 1
A setControllerName() 0 4 1
A getControllerName() 0 4 1
A setMethodName() 0 4 1
A getMethodName() 0 4 1
A getRequestParameters() 0 4 1
1
<?php
2
3
/**
4
 * AppserverIo\Routlt\ActionMapping
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2014 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      http://github.com/appserver-io/routlt
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Routlt;
22
23
/**
24
 * Tokenize implementation using a regex to parse a route.
25
 *
26
 * @author    Tim Wagner <[email protected]>
27
 * @copyright 2014 TechDivision GmbH <[email protected]>
28
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
29
 * @link      http://github.com/appserver-io/routlt
30
 * @link      http://www.appserver.io
31
 */
32
class ActionMapping implements ActionMappingInterface
33
{
34
35
    /**
36
     * The template for to create the compiled regex from.
37
     *
38
     * @var string
39
     */
40
    protected $regexTemplate = '/^%s$/';
41
42
    /**
43
     * The path with the controller/method name.
44
     *
45
     * @var string
46
     */
47
    protected $path;
48
49
    /**
50
     * The uncompiled expression.
51
     *
52
     * @var string
53
     */
54
    protected $expression;
55
56
    /**
57
     * The compiled regex, used to extract the variables from the route.
58
     *
59
     * @var string
60
     */
61
    protected $compiledRegex;
62
63
    /**
64
     * The controller name, extracted from the route.
65
     *
66
     * @var string
67
     */
68
    protected $controllerName;
69
70
    /**
71
     * The method name, extracted from the route.
72
     *
73
     * @var string
74
     */
75
    protected $methodName;
76
77
   /**
78
    * The array containing the declared placeholders.
79
    *
80
    * @var array
81
    */
82
    protected $vars = array();
83
84
    /**
85
     * The array with the default values for the placeholders.
86
     *
87
     * @var array
88
     */
89
    protected $defaults = array();
90
91
    /**
92
     * The request parameters, extracted from the route.
93
     *
94
     * @var array
95
     */
96
    protected $requestParameters = array();
97
98
    /**
99
     * Compiles the passed route expression into a valid regex.
100
     *
101
     * @param string $expression   The expression to use
102
     * @param array  $requirements The requirements for the expression
103
     * @param array  $defaults     The default values for the found variables
104
     *
105
     * @return void
106
     */
107
    public function compile($expression, array $requirements = array(), array $defaults = array())
108
    {
109
110
        // intialize the expression
111
        $this->expression = $expression;
112
        $this->defaults = $defaults;
113
114
        // the element number of the FIRST variable
115
        $pathLength = null;
116
117
        // extract the variables from the expression, also store their position
118
        $elements = explode('/', ltrim($expression, '/'));
119
        foreach ($elements as $key => $element) {
120
            // query whether or not we found a variable
121
            if (strpos($element, ':') === 0) {
122
                // add the variable and store with the position as key
123
                $this->vars[$key] = ltrim($element, ':');
124
                // we store the position of the FIRST variable
125
                if ($pathLength == null) {
126
                    $pathLength = $key;
127
                }
128
            }
129
        }
130
131
        // query whether or not we found variables
132
        if ($pathLength) {
133
            // if yes, cut of the array at that position
134
            $elements = array_slice($elements, 0, $pathLength);
135
        }
136
137
        // the path ends where the variables begin or
138
        $this->path = sprintf('/%s', implode('/', $elements));
139
140
        // initialize the string that has to be compiled
141
        $toCompile = $this->expression;
142
143
        // try to compile the regex group expression for each variable
144
        foreach ($this->vars as $var) {
145
            // by default the sequence to use is .*
146
            $sequence = '.*';
147
            // check if a sequence for the variable has been passed
148
            if (isset($requirements[$var])) {
149
                $sequence = $requirements[$var];
150
            }
151
            // replace the placeholder with the regex group expression
152
            $toCompile = str_replace(sprintf(':%s', $var), sprintf('(?<%s>%s)', $var, $sequence), $toCompile);
153
        }
154
155
        // initialize the member with the compiled regex
156
        $this->compiledRegex = sprintf($this->regexTemplate, addcslashes($toCompile, '/'));
157
    }
158
159
    /**
160
     * Tokenizes the passed route by using the tokenizers expression.
161
     *
162
     * @param string $route The route to be parsed
163
     *
164
     * @return boolean TRUE if the passed route matches the expression, else FALSE
165
     */
166
    public function match($route)
167
    {
168
169
        // initialize the array for the variable matches
170
        $matches = array();
171
172
        // execute the regex and extract the variables
173
        $result = preg_match($this->getCompiledRegex(), $this->applyDefaults($route), $matches);
174
175
        // append the variable values to the request parameters
176
        foreach ($this->vars as $var) {
177
            if (isset($matches[$var])) {
178
                $this->requestParameters[$var] = $matches[$var];
179
            }
180
        }
181
182
        // return TRUE if the compiled regex matched
183
        if ($result === 1) {
184
            return true;
185
        }
186
187
        // else we return FALSE
188
        return false;
189
    }
190
191
    /**
192
     * Return's the path with the controller/method name.
193
     *
194
     * @return string The path with the controller/method name
195
     */
196
    protected function getPath()
197
    {
198
        return $this->path;
199
    }
200
201
    /**
202
     * If necessary, this method applies the default values to the passed route.
203
     *
204
     * @param string $route The route to apply the default values to
205
     *
206
     * @return string The route with the default values applied
207
     */
208
    protected function applyDefaults($route)
209
    {
210
211
        // query whether or not the route matches
212
        if (preg_match(sprintf('/%s/', addcslashes($this->path, '/')), $route)) {
213
            // initialize the array for the appended variables
214
            $vars = array();
215
216
            // try to extract the appended variables
217
            $varString = ltrim(str_replace($this->path, '', $route), '/');
218
            if (empty($varString) === false) {
219
                $vars = explode('/', $varString);
220
            }
221
222
            // iterate over all variables
223
            foreach ($this->vars as $key => $var) {
224
                // query whether or not, we've a default value and the variable has NOT been set
225
                if (isset($this->defaults[$var]) && !isset($vars[$key])) {
226
                    $vars[$key] = $this->defaults[$var];
227
                }
228
            }
229
230
            // if we've found vars, append them to the path
231
            if (sizeof($vars) > 0) {
232
                $route = sprintf('%s/%s', $this->path, implode('/', $vars));
233
            }
234
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
235
        }
236
237
        // return the route with the defaults applied
238
        return $route;
239
    }
240
241
    /**
242
     * Return's the regex build from the expression.
243
     *
244
     * @return string The regex
245
     */
246
    public function getCompiledRegex()
247
    {
248
        return $this->compiledRegex;
249
    }
250
251
    /**
252
     * Initializes the action mapping with the passed controller name.
253
     *
254
     * @param string $controllerName The controller name found in the route
255
     *
256
     * @return void
257
     */
258
    public function setControllerName($controllerName)
259
    {
260
        $this->controllerName = $controllerName;
261
    }
262
263
    /**
264
     * Return's the controller name found in the route.
265
     *
266
     * @return string The controller name
267
     */
268
    public function getControllerName()
269
    {
270
        return $this->controllerName;
271
    }
272
273
    /**
274
     * Initializes the action mapping with the passed method name.
275
     *
276
     * @param string $methodName The method name found in the route
277
     *
278
     * @return void
279
     */
280
    public function setMethodName($methodName)
281
    {
282
        $this->methodName = $methodName;
283
    }
284
285
    /**
286
     * Return's the method name found in the route.
287
     *
288
     * @return string The method name
289
     */
290
    public function getMethodName()
291
    {
292
        return $this->methodName;
293
    }
294
295
    /**
296
     * Return's the extracted request parameters found in the route.
297
     *
298
     * @return array The extracted request parameters
299
     */
300
    public function getRequestParameters()
301
    {
302
        return $this->requestParameters;
303
    }
304
}
305