Completed
Push — master ( f172d4...76e139 )
by devosc
02:14
created

src/Route/Definition/Tokens.php (1 issue)

Labels

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 *
4
 */
5
6
namespace Mvc5\Route\Definition;
7
8
use Mvc5\Exception;
9
10
/**
11
 * Portions copyright (c) 2013 Ben Scholzen 'DASPRiD'. (http://github.com/DASPRiD/Dash)
12
 * under the Simplified BSD License (http://opensource.org/licenses/BSD-2-Clause).
13
 *
14
 * Match types are based on https://github.com/klein/klein.php
15
 *
16
 * Variable regular expression is based on https://github.com/nikic/FastRoute
17
 */
18
trait Tokens
19
{
20
    /**
21
     * @var array
22
     */
23
    protected $expressions = [
24
        'a' => '[a-zA-Z0-9]++',
25
        'i' => '[0-9]++',
26
        'n' => '[a-zA-Z][a-zA-Z0-9]++',
27
        's' => '[a-zA-Z0-9_-]++',
28
        '*' => '.++',
29
        '*$' => '[a-zA-Z0-9/]+[a-zA-Z0-9]$'
30
    ];
31
32
    /**
33
     * @param $name
34
     * @param $constraint
35
     * @param array $constraints
36
     * @return mixed|string
37
     */
38 9
    protected function constraint($name, $constraint, array $constraints)
39
    {
40 9
        return $constraint ? $constraint : (isset($constraints[$name]) ? $constraints[$name] : '[^/]+');
41
    }
42
43
    /**
44
     * @param string $expr
45
     * @return mixed|string
46
     */
47 9
    protected function expression($expr)
48
    {
49 9
        return ':' === $expr[0] && isset($this->expressions[$n = substr($expr, 1)]) ? $this->expressions[$n] : $expr;
0 ignored issues
show
The variable $n does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
50
    }
51
52
    /**
53
     * @param string $route
54
     * @param array $constraints
55
     * @return array
56
     * @throws \RuntimeException
57
     */
58 44
    protected function tokens($route, array $constraints = [])
59
    {
60 44
        $currentPos = 0;
61 44
        $length     = strlen($route);
62 44
        $level      = 0;
63 44
        $token      = '(\G(?P<literal>[^{}\[\]]*)(?P<token>[{}\[\]]|$))';
64 44
        $tokens     = [];
65 44
        $variable   = '(\G\s*(?P<name>[a-zA-Z0-9_]++)?\s*(?(1):)?\s*(?P<constraint>[^{}]*(?:\{(?-1)\}[^{}]*)*)?)';
66
67 44
        while($currentPos < $length) {
68 44
            preg_match($token, $route, $match, 0, $currentPos);
69
70 44
            $currentPos += strlen($match[0]);
71
72 44
            '' !== $match['literal'] && $tokens[] = ['literal', $match['literal']];
73
74 44
            if ('{' === $match['token']) {
75 9
                preg_match($variable, $route, $match, 0, $currentPos);
76
77 9
                $currentPos += strlen($match[0]);
78
79 9
                $tokens[] = [
80 9
                    'param', $match['name'], $this->expression(
81 9
                        $this->constraint($match['name'], $match['constraint'], $constraints)
82
                    )
83
                ];
84
85 9
                continue;
86
            }
87
88 44
            if ('[' === $match['token']) {
89 4
                $tokens[] = ['optional-start'];
90 4
                $level++;
91 4
                continue;
92
            }
93
94 44
            if (']' === $match['token']) {
95 4
                $tokens[] = ['optional-end'];
96
97 4
                (--$level < 0) && Exception::runtime('Found closing bracket without matching opening bracket');
98
99 3
                continue;
100
            }
101
        }
102
103 43
        ($level > 0) && Exception::runtime('Found unbalanced brackets');
104
105 42
        return $tokens;
106
    }
107
}
108