Passed
Pull Request — master (#86)
by
unknown
02:57
created

RangeParser::parse()   C

Complexity

Conditions 13
Paths 34

Size

Total Lines 35
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 14.5763

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 25
c 1
b 0
f 0
nc 34
nop 1
dl 0
loc 35
ccs 15
cts 19
cp 0.7895
crap 14.5763
rs 6.6166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Db\Pgsql;
6
7
use DateInterval;
8
use DateTime;
9
use InvalidArgumentException;
10
use RuntimeException;
11
use function preg_match;
12
13
final class RangeParser
14
{
15
    private const RANGES = [
16
        Schema::TYPE_INT_4_RANGE,
17
        Schema::TYPE_INT_8_RANGE,
18
        Schema::TYPE_NUM_RANGE,
19
        Schema::TYPE_TS_RANGE,
20
        Schema::TYPE_TS_TZ_RANGE,
21
        Schema::TYPE_DATE_RANGE,
22
    ];
23
24
    private ?string $type = null;
25
26 4
    public function __construct(?string $type = null)
27
    {
28 4
        if ($type !== null) {
29 3
            if (self::isAllowedType($type)) {
30 3
                $this->type = $type;
31
            } else {
32
                throw new InvalidArgumentException('Unsupported range type "' . $type . '"');
33
            }
34
        }
35 4
    }
36
37 4
    public function parse(?string $value): ?array
38
    {
39 4
        if ($value === null) {
40 1
            return null;
41
        }
42
43 4
        if (!preg_match('/^(\[|\()([^,]*),([^\)\]]*)(\)|\])$/', $value, $matches)) {
44
            throw new InvalidArgumentException();
45
        }
46
47 4
        $lower = $matches[2] ? trim($matches[2], '"') : null;
48 4
        $upper = $matches[3] ? trim($matches[3], '"') : null;
49 4
        $includeLower = $matches[1] === '[';
50 4
        $includeUpper = $matches[4] === ']';
51
52 4
        if ($lower === null && $upper === null) {
53 1
            return [null, null];
54
        }
55
56 4
        $type = $this->type ?? self::parseType($lower, $upper);
57
58 4
        switch ($type) {
59
            case Schema::TYPE_INT_4_RANGE:
60
            case Schema::TYPE_INT_8_RANGE:
61 2
                return self::parseIntRange($lower, $upper, $includeLower, $includeUpper);
62
            case Schema::TYPE_NUM_RANGE:
63 2
                return self::parseNumRange($lower, $upper, $includeLower, $includeUpper);
64
            case Schema::TYPE_DATE_RANGE:
65 1
                return self::parseDateRange($lower, $upper, $includeLower, $includeUpper);
66
            case Schema::TYPE_TS_RANGE:
67
                return self::parseTsRange($lower, $upper, $includeLower, $includeUpper);
68
            case Schema::TYPE_TS_TZ_RANGE:
69
                return self::parseTsTzRange($lower, $upper, $includeLower, $includeUpper);
70
            default:
71
                throw new RuntimeException();
72
        }
73
    }
74
75 2
    private static function parseIntRange(?string $lower, ?string $upper, bool $includeLower, bool $includeUpper): array
76
    {
77 2
        $min = $lower === null ? null : (int) $lower;
78 2
        $max = $upper === null ? null : (int) $upper;
79
80 2
        if ($min !== null && $includeLower === false) {
81 2
            $min += 1;
82
        }
83
84 2
        if ($max !== null && $includeUpper === false) {
85 2
            $max -= 1;
86
        }
87
88 2
        return [$min, $max];
89
    }
90
91 2
    private static function parseNumRange(?string $lower, ?string $upper, bool $includeLower, bool $includeUpper): array
0 ignored issues
show
Unused Code introduced by
The parameter $includeUpper is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

91
    private static function parseNumRange(?string $lower, ?string $upper, bool $includeLower, /** @scrutinizer ignore-unused */ bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $includeLower is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

91
    private static function parseNumRange(?string $lower, ?string $upper, /** @scrutinizer ignore-unused */ bool $includeLower, bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
92
    {
93 2
        $min = $lower === null ? null : (float) $lower;
94 2
        $max = $upper === null ? null : (float) $upper;
95
96 2
        return [$min, $max];
97
    }
98
99 1
    private static function parseDateRange(?string $lower, ?string $upper, bool $includeLower, bool $includeUpper): array
100
    {
101 1
        $interval = new DateInterval('P1D');
102 1
        $min = $lower ? DateTime::createFromFormat('Y-m-d', $lower) : null;
103 1
        $max = $upper ? DateTime::createFromFormat('Y-m-d', $upper) : null;
104
105 1
        if ($min && $includeLower === false) {
106 1
            $min->add($interval);
107
        }
108
109 1
        if ($max && $includeUpper === false) {
110
            $max->sub($interval);
111
        }
112
113 1
        return [$min, $max];
114
    }
115
116
    private static function parseTsRange(?string $lower, ?string $upper, bool $includeLower, bool $includeUpper): array
0 ignored issues
show
Unused Code introduced by
The parameter $includeUpper is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
    private static function parseTsRange(?string $lower, ?string $upper, bool $includeLower, /** @scrutinizer ignore-unused */ bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $includeLower is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

116
    private static function parseTsRange(?string $lower, ?string $upper, /** @scrutinizer ignore-unused */ bool $includeLower, bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
117
    {
118
        $min = $lower ? DateTime::createFromFormat('Y-m-d H:i:s', $lower) : null;
119
        $max = $upper ? DateTime::createFromFormat('Y-m-d H:i:s', $upper) : null;
120
121
        return [$min, $max];
122
    }
123
124
    private static function parseTsTzRange(?string $lower, ?string $upper, bool $includeLower, bool $includeUpper): array
0 ignored issues
show
Unused Code introduced by
The parameter $includeLower is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

124
    private static function parseTsTzRange(?string $lower, ?string $upper, /** @scrutinizer ignore-unused */ bool $includeLower, bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $includeUpper is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

124
    private static function parseTsTzRange(?string $lower, ?string $upper, bool $includeLower, /** @scrutinizer ignore-unused */ bool $includeUpper): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
125
    {
126
        $min = $lower ? DateTime::createFromFormat('Y-m-d H:i:sP', $lower) : null;
127
        $max = $upper ? DateTime::createFromFormat('Y-m-d H:i:sP', $upper) : null;
128
129
        return [$min, $max];
130
    }
131
132 35
    public static function isAllowedType(string $type): bool
133
    {
134 35
        return in_array($type, self::RANGES, true);
135
    }
136
137
    /**
138
     * Find range type from value format
139
     *
140
     * @param string $lower
141
     * @param string $upper
142
     *
143
     * @return string|null
144
     */
145 1
    private static function parseType(?string $lower, ?string $upper): ?string
146
    {
147 1
        if ($lower !== null && $upper !== null) {
148 1
            if (filter_var($lower, FILTER_VALIDATE_INT) && filter_var($upper, FILTER_VALIDATE_INT)) {
149 1
                return Schema::TYPE_INT_4_RANGE;
150
            }
151
152 1
            if (filter_var($lower, FILTER_VALIDATE_FLOAT) && filter_var($upper, FILTER_VALIDATE_FLOAT)) {
153 1
                return Schema::TYPE_NUM_RANGE;
154
            }
155
        }
156
157
        $value = $lower ?? $upper;
158
159
        if (filter_var($value, FILTER_VALIDATE_INT)) {
160
            return Schema::TYPE_INT_4_RANGE;
161
        }
162
163
164
        if (filter_var($value, FILTER_VALIDATE_FLOAT)) {
165
            return Schema::TYPE_NUM_RANGE;
166
        }
167
168
        if (DateTime::createFromFormat('Y-m-d', $value)) {
169
            return Schema::TYPE_DATE_RANGE;
170
        }
171
172
        if (DateTime::createFromFormat('Y-m-d H:i:s', $value)) {
173
            return Schema::TYPE_TS_RANGE;
174
        }
175
176
        if (DateTime::createFromFormat('Y-m-d H:i:sP', $value)) {
177
            return Schema::TYPE_TS_TZ_RANGE;
178
        }
179
180
        return null;
181
    }
182
}
183