RegExp   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 130
rs 10
c 0
b 0
f 0
wmc 17
lcom 1
cbo 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A isGlobal() 0 4 1
A __toString() 0 4 1
A wrapInDelimiters() 0 7 2
A hasDelimiters() 0 15 4
A isValidDelimiter() 0 4 1
A fromString() 0 14 2
A of() 0 9 2
A matchAll() 0 13 2
A test() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Baethon\Phln;
6
7
use Baethon\Phln\Phln as P;
8
9
final class RegExp
10
{
11
    /**
12
     * @var string
13
     */
14
    private $pattern;
15
16
    /**
17
     * @var string
18
     */
19
    private $modifiers;
20
21
    /**
22
     * @var bool
23
     */
24
    private $global = false;
25
26
    public function __construct(string $pattern, string $modifiers = '')
27
    {
28
        $this->pattern = $this->wrapInDelimiters($pattern);
29
        $this->modifiers = str_replace('g', '', $modifiers);
30
        $this->global = (false !== strstr($modifiers, 'g'));
31
    }
32
33
    public function isGlobal(): bool
34
    {
35
        return $this->global;
36
    }
37
38
    public function __toString(): string
39
    {
40
        return $this->pattern . $this->modifiers;
41
    }
42
43
    private function wrapInDelimiters(string $pattern): string
44
    {
45
        return $this->hasDelimiters($pattern) ? $pattern : sprintf(
46
            '/%s/',
47
            preg_quote($pattern, '/')
48
        );
49
    }
50
51
    /**
52
     * Checks if pattern has valid delimiter
53
     *
54
     * @param string $pattern
55
     * @return bool
56
     * @see https://secure.php.net/manual/en/regexp.reference.delimiters.php
57
     */
58
    private function hasDelimiters(string $pattern): bool
59
    {
60
        if (mb_strlen($pattern) < 2) {
61
            return false;
62
        }
63
64
        $start = substr($pattern, 0, 1);
65
        $end = substr($pattern, -1);
66
67
        if ($start !== $end) {
68
            return false;
69
        }
70
71
        return static::isValidDelimiter($start) && static::isValidDelimiter($end);
0 ignored issues
show
Comprehensibility introduced by
Since Baethon\Phln\RegExp is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
72
    }
73
74
    private static function isValidDelimiter(string $char): bool
75
    {
76
        return (bool) preg_match('/^[^a-z0-9\s]$/', $char);
77
    }
78
79
    /**
80
     * Creates RegExp instance based on passed regular expression.
81
     *
82
     * @param string $regexp
83
     * @return RegExp
84
     * @example
85
     *      RegExp::fromString('/foo/gi'); // -> new RegExp('/foo/', 'gi');
86
     */
87
    public static function fromString(string $regexp): RegExp
88
    {
89
        $start = substr($regexp, 0, 1);
90
91
        if (false === static::isValidDelimiter($start)) {
0 ignored issues
show
Comprehensibility introduced by
Since Baethon\Phln\RegExp is declared final, using late-static binding will have no effect. You might want to replace static with self instead.

Late static binding only has effect in subclasses. A final class cannot be extended anymore so late static binding cannot occurr. Consider replacing static:: with self::.

To learn more about late static binding, please refer to the PHP core documentation.

Loading history...
92
            return new static($regexp);
93
        }
94
95
        $endPosition = strrpos($regexp, $start);
96
        $pattern = substr($regexp, 0, $endPosition + 1);
97
        $modifiers = substr($regexp, $endPosition + 1);
98
99
        return new static($pattern, $modifiers);
100
    }
101
102
    /**
103
     * @param string|RegExp $regexp
104
     * @return RegExp
105
     */
106
    public static function of($regexp): RegExp
107
    {
108
        if ($regexp instanceof static) {
109
            return $regexp;
110
        }
111
112
        /** @var string $regexp */
113
        return static::fromString($regexp);
114
    }
115
116
    /**
117
     * @param string $test
118
     * @return string[]
119
     */
120
    public function matchAll(string $test): array
121
    {
122
        $matches = [];
123
        preg_match_all((string) $this, $test, $matches, PREG_SET_ORDER);
124
125
        $slice = function ($list) {
126
            return count($list) > 1
127
                ? array_slice($list, 1)
128
                : $list;
129
        };
130
131
        return P::flatMap($slice, $matches);
132
    }
133
134
    public function test(string $string): bool
135
    {
136
        return (bool) preg_match((string) $this, $string);
137
    }
138
}
139