ImageFilterData   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 202
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 62
c 7
b 0
f 0
dl 0
loc 202
rs 9.0399
wmc 42

22 Methods

Rating   Name   Duplication   Size   Complexity  
A hasEndDate() 0 3 1
A overrideEndDateFromUrlParam() 0 4 2
A overrideLocationFromUrlParam() 0 4 2
A setLocation() 0 3 2
A getLocation() 0 3 1
A hasRating() 0 3 1
A __construct() 0 7 1
A getRating() 0 3 1
A hasStartDate() 0 3 1
A getRatingComparison() 0 3 1
A setStartDate() 0 6 2
A setRating() 0 3 1
A dateFromUrlParam() 0 21 6
A getStartDate() 0 6 2
A setEndDate() 0 6 2
A hasLocation() 0 3 1
A overrideStartDateFromUrlParam() 0 4 2
A getDateForUrlParam() 0 6 2
A getEndDate() 0 6 2
A setRatingComparison() 0 3 1
A getAsUrlParams() 0 8 4
A overrideRatingFromUrlParam() 0 7 4

How to fix   Complexity   

Complex Class

Complex classes like ImageFilterData often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ImageFilterData, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Form;
4
5
use Carbon\Carbon;
6
use Carbon\CarbonImmutable;
7
use Carbon\CarbonInterface;
8
use DateTimeImmutable;
9
use DateTimeInterface;
10
use Exception;
11
use Carbon\Exceptions\InvalidFormatException;
12
use Doctrine\Common\Cache\Psr6\InvalidArgument;
13
use InvalidArgumentException;
14
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
15
use Symfony\Component\Validator\Constraints as Assert;
16
17
class ImageFilterData
18
{
19
    /**
20
     * @var ?CarbonImmutable
21
     *
22
     * @Assert\Range(
23
     *  min = "Jan 1 1900",
24
     *  max = "now + 10 years"
25
     * )
26
     */
27
    private $startDate;
28
29
    /**
30
     * @var ?CarbonImmutable
31
     *
32
     * @Assert\Range(
33
     *  min = "Jan 1 1900",
34
     *  max = "now + 10 years"
35
     * )
36
     */
37
    private $endDate;
38
39
    /**
40
     * @var ?int
41
     *
42
     * @Assert\Range(
43
     *  min = 0,
44
     *  max = 5
45
     * )
46
     *
47
     */
48
    private $rating;
49
50
    /**
51
     * @var string
52
     *
53
     * @Assert\Regex(
54
     *  pattern = "/eq|lte|gte/"
55
     * )
56
     *
57
     */
58
    private $ratingComparison;
59
60
    /** @var ?string */
61
    private $location;
62
63
    public function __construct(
64
        DateTimeInterface $startDate = null,
65
        DateTimeInterface $endDate = null
66
    ) {
67
        $this->startDate = new CarbonImmutable($startDate);
68
        $this->endDate = new CarbonImmutable($endDate);
69
        $this->ratingComparison = 'eq';
70
    }
71
72
    public function setStartDate(?DateTimeInterface $startDate): void
73
    {
74
        if ($startDate === null) {
75
            $this->startDate = null;
76
        } else {
77
            $this->startDate = new CarbonImmutable($startDate);
78
        }
79
    }
80
    public function overrideStartDateFromUrlParam(?string $startDate): void
81
    {
82
        if (!empty($startDate)) {
83
            $this->startDate = $this->dateFromUrlParam($startDate);
84
        }
85
    }
86
    public function getStartDate(): ?DateTimeInterface
87
    {
88
        if ($this->startDate === null) {
89
            return null;
90
        }
91
        return $this->startDate->toDateTimeImmutable();
92
    }
93
    public function hasStartDate(): bool
94
    {
95
        return $this->startDate !== null;
96
    }
97
    public function setEndDate(?DateTimeInterface $endDate): void
98
    {
99
        if ($endDate === null) {
100
            $this->endDate = null;
101
        }
102
        $this->endDate = new CarbonImmutable($endDate);
103
    }
104
    public function overrideEndDateFromUrlParam(?string $endDate): void
105
    {
106
        if (!empty($endDate)) {
107
            $this->endDate = $this->dateFromUrlParam($endDate);
108
        }
109
    }
110
    public function getEndDate(): ?DateTimeImmutable
111
    {
112
        if ($this->endDate === null) {
113
            return null;
114
        }
115
        return $this->endDate->toDateTimeImmutable();
116
    }
117
    public function hasEndDate(): bool
118
    {
119
        return $this->endDate !== null;
120
    }
121
    public function setRating(?int $rating): void
122
    {
123
        $this->rating = $rating;
124
    }
125
    /**
126
     * @throws InvalidArgumentException
127
     */
128
    public function overrideRatingFromUrlParam(?string $rating): void
129
    {
130
        if (!empty($rating)) {
131
            if (intval($rating) >= 0 && intval($rating) <= 5) {
132
                $this->rating = intval($rating);
133
            } else {
134
                throw new InvalidArgumentException('Invalid rating override in URL parameter');
135
            }
136
        }
137
    }
138
    public function getRating(): ?int
139
    {
140
        return $this->rating;
141
    }
142
    public function hasRating(): bool
143
    {
144
        return $this->rating !== null;
145
    }
146
    public function setRatingComparison(string $ratingComparison): void
147
    {
148
        $this->ratingComparison = $ratingComparison;
149
    }
150
    public function getRatingComparison(): string
151
    {
152
        return $this->ratingComparison;
153
    }
154
    public function setLocation(?string $location): void
155
    {
156
        $this->location = $location === "" ? null : $location;
157
    }
158
    public function overrideLocationFromUrlParam(?string $location): void
159
    {
160
        if (!empty($location)) {
161
            $this->location = $location;
162
        }
163
    }
164
    public function getLocation(): ?string
165
    {
166
        return $this->location;
167
    }
168
    public function hasLocation(): bool
169
    {
170
        return $this->location !== null;
171
    }
172
    private function getDateForUrlParam(?CarbonImmutable $d): string
173
    {
174
        if ($d === null) {
175
            return '';
176
        }
177
        return $d->isoFormat('YYYY-MM-DD');
178
    }
179
    /**
180
     * Gets all filter parameters in a format suitable for passing to Symfony's
181
     * route generator.
182
     *
183
     * @return array<string>
184
     */
185
    public function getAsUrlParams(): array
186
    {
187
        return [
188
            'startDate' => $this->getDateForUrlParam($this->startDate),
189
            'endDate' => $this->getDateForUrlParam($this->endDate),
190
            'rating' => $this->rating === null ? '' : (string) $this->rating,
191
            'ratingComparison' => $this->ratingComparison === null ? '' : $this->ratingComparison,
192
            'location' => $this->location === null ? '' : $this->location
193
        ];
194
    }
195
    /**
196
     * @throws InvalidArgumentException
197
     */
198
    private function dateFromUrlParam(?string $param): ?CarbonImmutable
199
    {
200
        if ($param === null || $param === "") {
201
            return null;
202
        }
203
        // These inputs are as-yet unsanitised, so:
204
        $result = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
205
        try {
206
            $result = CarbonImmutable::parse($param);
207
            if ($result->year < 1900 || $result->year > 9999) {
208
                // Improbable dates could cause problems if used in DB queries.
209
                $result = null;
210
            }
211
        } catch (Exception $e) {
212
            // I don't care what happened personally; we'll just not bother
213
            // overriding our existing dates. However, whatever called us
214
            // might want to log this, as someone may be probing the app for
215
            // insecure points.
216
            throw new InvalidArgument('Invalid date URL parameter', 0, $e);
217
        }
218
        return $result;
219
    }
220
}
221