Completed
Pull Request — master (#3)
by Бабичев
02:07
created

Path   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 83.33%

Importance

Changes 0
Metric Value
wmc 11
dl 0
loc 141
ccs 40
cts 48
cp 0.8333
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A hinge() 0 7 1
A getPattern() 0 14 2
A getRegex() 0 3 1
A getValue() 0 3 1
A regexAttribute() 0 3 1
A processing() 0 22 3
A quote() 0 11 1
1
<?php
2
3
namespace Bavix\Router;
4
5
use Bavix\Exceptions\Runtime;
6
7
class Path
8
{
9
10
    /**
11
     * default regexp
12
     */
13
    protected const DEFAULT_REGEX = '[\w-]+';
14
15
    /**
16
     * @var string
17
     */
18
    protected $pattern;
19
20
    /**
21
     * @var string
22
     */
23
    protected $value;
24
25
    /**
26
     * @var array
27
     */
28
    protected $regex;
29
30
    /**
31
     * Path constructor.
32
     *
33
     * @param string $value
34
     * @param array  $regex
35
     */
36 4
    public function __construct(string $value, array $regex = [])
37
    {
38 4
        $this->value = $value;
39 4
        $this->regex = $regex;
40 4
        $this->processing();
41 4
    }
42
43
    /**
44
     * @param string $value
45
     *
46
     * @return string
47
     */
48 3
    protected function quote(string $value): string
49
    {
50 3
        $path = \preg_quote($value, '()');
51 3
        $path = \strtr($path, [
52 3
            '\\(' => '(',
53
            '\\)' => ')',
54
            '\\<' => '<',
55
            '\\>' => '>',
56
        ]);
57
58 3
        return \str_replace(')', ')?', $path);
59
    }
60
61
    /**
62
     * @param string $name
63
     *
64
     * @return string
65
     */
66 3
    protected function regexAttribute(string $name): string
67
    {
68 3
        return $this->regex[$name] ?? self::DEFAULT_REGEX;
69
    }
70
71
    /**
72
     * @return string
73
     */
74 3
    public function getPattern(): string
75
    {
76 3
        if (!$this->pattern) {
77 3
            $this->pattern = \preg_replace_callback(
78 3
                '~\<(?<key>' . self::DEFAULT_REGEX . '+)\>~',
79 3
                function ($matches) {
80 3
                    return '(?<' . $matches['key'] . '>' .
81 3
                        $this->regexAttribute($matches['key']) .
82 3
                        ')';
83 3
                },
84 3
                $this->quote($this->value)
85
            );
86
        }
87 3
        return $this->pattern;
88
    }
89
90
    /**
91
     * @return string
92
     */
93
    public function getValue(): string
94
    {
95
        return $this->value;
96
    }
97
98
    /**
99
     * @return array
100
     */
101
    public function getRegex(): array
102
    {
103
        return $this->regex;
104
    }
105
106
    /**
107
     * @param self $parent
108
     */
109 2
    public function hinge(self $parent): void
110
    {
111 2
        $this->pattern = null;
112 2
        $this->value   = $parent->value . $this->value;
113 2
        $this->regex   = \array_merge(
114 2
            $parent->regex,
115 2
            $this->regex
116
        );
117 2
    }
118
119
    /**
120
     * processing:
121
     *  path: '/(<lang:\w+>)' -> '/(<lang>)'
122
     *  re: [] -> ['lang' => '\w+']
123
     *
124
     *  if attr exists -> throws
125
     */
126 4
    protected function processing(): void
127
    {
128 4
        $this->value = \preg_replace_callback(
129 4
            '~\<(?<key>' . self::DEFAULT_REGEX . '+):(?<value>.+?)>~',
130 4
            function (array $matches) {
131
132 2
                if (!empty($this->regex[$matches['key']])) {
133
                    throw new Runtime(\sprintf(
134
                        'duplicate in registry key `%s` for path `%s`',
135
                        $matches['key'],
136
                        $this->value
137
                    ));
138
                }
139
140 2
                if (!empty($matches['value']))
141
                {
142 2
                    $this->regex[$matches['key']] = $matches['value'];
143
                }
144
145 2
                return '<' . $matches['key'] . '>';
146 4
            },
147 4
            $this->value
148
        );
149 4
    }
150
151
}
152