Completed
Push — master ( 4da3a0...4ef8bc )
by Matt
09:23
created

Image   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 455
Duplicated Lines 0 %

Importance

Changes 6
Bugs 0 Features 1
Metric Value
eloc 91
c 6
b 0
f 1
dl 0
loc 455
rs 8.64
wmc 47

44 Methods

Rating   Name   Duplication   Size   Complexity  
A setName() 0 5 1
A setSizeInBytes() 0 5 1
A getCapturedAt() 0 3 1
A setDimensions() 0 5 1
A setUpdatedAt() 0 4 1
A setTitle() 0 5 1
A getTitle() 0 3 1
A getSizeInBytes() 0 3 1
A getName() 0 3 1
A getWander() 0 3 1
A setImageFile() 0 8 2
A setRating() 0 5 1
A getMimeType() 0 3 1
A getDescription() 0 3 1
A setKeywords() 0 5 1
A setLatlng() 0 5 1
A setCapturedAt() 0 5 1
A getRating() 0 3 1
A __construct() 0 2 1
A setMimeType() 0 5 1
A getId() 0 3 1
A getUpdatedAt() 0 3 1
A setWander() 0 4 1
A getLatlng() 0 3 1
A getImageFile() 0 3 1
A getKeywords() 0 3 1
A getOriginalName() 0 3 1
A getDimensions() 0 3 1
A setDescription() 0 5 1
A setOriginalName() 0 5 1
A getLocation() 0 3 1
A setImageShowUri() 0 2 1
A getMediumImageUri() 0 2 1
A updateWanderToForceElasticReindex() 0 15 2
A setAutoTags() 0 5 1
A setMarkerImageUri() 0 2 1
A getAutoTagsCount() 0 5 2
A getImageUri() 0 2 1
A setMediumImageUri() 0 2 1
A setImageUri() 0 2 1
A getMarkerImageUri() 0 2 1
A setLocation() 0 5 1
A getAutoTags() 0 3 1
A getImageShowUri() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like Image 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 Image, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Entity;
4
5
use ApiPlatform\Core\Annotation\ApiFilter;
6
use ApiPlatform\Core\Annotation\ApiResource;
7
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\ExistsFilter;
8
use App\EventListener\ImageCalculatedFieldSetterListener;
9
use App\EventListener\WanderUploadListener;
10
use App\Repository\ImageRepository;
11
use Doctrine\Common\Collections\ArrayCollection;
12
use Doctrine\Common\Collections\Collection;
13
use Doctrine\ORM\Mapping as ORM;
14
use Symfony\Component\HttpFoundation\File\File;
15
use Vich\UploaderBundle\Mapping\Annotation as Vich;
16
use Symfony\Component\Validator\Constraints as Assert;
17
use Symfony\Component\Serializer\Annotation\Groups;
18
use Symfony\Component\Serializer\Annotation\Ignore;
19
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
20
use Doctrine\ORM\Event\LifecycleEventArgs;
21
22
/**
23
 * @ApiResource(
24
 *  collectionOperations={"get"={"normalization_context"={"groups"="image:list"}}},
25
 *  itemOperations={"get"={"normalization_context"={"groups"="image:item"}}},
26
 *  order={"capturedAt"="ASC"},
27
 *  paginationEnabled=false
28
 * )
29
 *
30
 * @ApiFilter(SearchFilter::class, properties={"wanders": "exact"})
31
 * @ApiFilter(ExistsFilter::class, properties={"latlng"})
32
 *
33
 * @ORM\Entity(repositoryClass=ImageRepository::class)
34
 *
35
 * @ORM\EntityListeners({
36
 *     ImageCalculatedFieldSetterListener::class
37
 * })
38
 *
39
 * @ORM\HasLifecycleCallbacks()
40
 *
41
 * This is just to control the stuff that goes back from our one controller
42
 * action that returns a JSON response, ImageController::upload
43
 *
44
 * @Vich\Uploadable
45
 */
46
47
class Image
48
{
49
    /**
50
     * @ORM\Id
51
     * @ORM\GeneratedValue
52
     * @ORM\Column(type="integer")
53
     *
54
     * @Groups({"image:list", "image:item"})
55
     */
56
    private $id;
57
58
    // TODO: We probably don't want this massive field being returned
59
    // as part of any API response, etc.
60
    /**
61
     * @Vich\UploadableField(mapping="image", fileNameProperty="name", size="sizeInBytes",
62
     *  mimeType="mimeType", originalName="originalName", dimensions="dimensions")
63
     *
64
     * @Ignore()
65
     */
66
    private $imageFile;
67
68
    /**
69
     * @ORM\Column(type="string", length=255, nullable=true)
70
     *
71
     * @Groups({"image:list", "image:item"})
72
     */
73
    private $name; // For Vich, not for us. We use Title.
74
75
    /**
76
     * @ORM\Column(type="string", length=255, nullable=true)
77
     *
78
     * @Groups({"image:list", "image:item"})
79
     */
80
    private $title;
81
82
    /**
83
     * @ORM\Column(type="text", nullable=true)
84
     *
85
     * @Groups({"image:list", "image:item"})
86
     */
87
    private $description;
88
89
    /**
90
     * @ORM\Column(type="integer", nullable=true)
91
     *
92
     * @Groups({"image:list", "image:item"})
93
     */
94
    private $sizeInBytes;
95
96
    /**
97
     * @ORM\Column(type="string", length=255, nullable=true)
98
     *
99
     * @Groups({"image:list", "image:item"})
100
     */
101
    private $mimeType;
102
103
    /**
104
     * @ORM\Column(type="string", length=255, nullable=true)
105
     *
106
     * @Groups({"image:list", "image:item"})
107
     */
108
    private $originalName;
109
110
    /**
111
     * @ORM\Column(type="simple_array", nullable=true)
112
     *
113
     * @Groups({"image:list", "image:item"})
114
     */
115
    private $dimensions = [];
116
117
    /**
118
     * @ORM\Column(type="datetime")
119
     *
120
     * @Groups({"image:list", "image:item"})
121
     *
122
     * @var \DateTimeInterface|null
123
     */
124
    private $updatedAt;
125
126
    /**
127
     * @ORM\Column(type="simple_array", nullable=true)
128
     * @Assert\Count(
129
     *      min = 2,
130
     *      max = 2,
131
     *      minMessage = "There must be exactly two numbers in a latitude/longitude pair",
132
     *      maxMessage = "There must be exactly two numbers in a latitude/longitude pair",
133
     *      exactMessage = "Co-ordinates must consist of a latitude, longitude pair."
134
     * )
135
     *
136
     * @Groups({"image:list", "image:item"})
137
     *
138
     */
139
    private $latlng = [];
140
141
    /**
142
     * @ORM\Column(type="array", nullable=true, )
143
     *
144
     * @Groups({"image:list", "image:item"})
145
     */
146
    private $keywords = [];
147
148
    /**
149
     * @ORM\Column(type="datetime", nullable=true)
150
     *
151
     * @Groups({"image:list", "image:item"})
152
     */
153
    private $capturedAt;
154
155
    /**
156
     * @ORM\Column(type="integer", nullable=true)
157
     * @Groups({"image:list", "image:item"})
158
     */
159
    private $rating;
160
161
162
    // TODO: This @Ignore was here from when this was a many-to-many. Do we still
163
    // need it?
164
    /**
165
     * @ORM\ManyToOne(targetEntity=Wander::class, inversedBy="images")
166
     *
167
     * @Ignore()
168
     */
169
    private $wander;
170
171
    public function __construct()
172
    {
173
        // $this->wanders = new ArrayCollection();
174
    }
175
176
    /**
177
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
178
     * of 'UploadedFile' is injected into this setter to trigger the update. If this
179
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
180
     * must be able to accept an instance of 'File' as the bundle will inject one here
181
     * during Doctrine hydration.
182
     *
183
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile|null $imageFile
184
     */
185
    public function setImageFile(?File $imageFile = null): void
186
    {
187
        $this->imageFile = $imageFile;
188
189
        if (null !== $imageFile) {
190
            // It is required that at least one field changes if you are using doctrine
191
            // otherwise the event listeners won't be called and the file is lost
192
            $this->updatedAt = new \DateTimeImmutable();
193
        }
194
    }
195
196
    /**
197
     * @Ignore()
198
     */
199
    public function getImageFile(): ?File
200
    {
201
        return $this->imageFile;
202
    }
203
204
    public function getId(): ?int
205
    {
206
        return $this->id;
207
    }
208
209
    public function getName(): ?string
210
    {
211
        return $this->name;
212
    }
213
214
    public function setName(?string $name): self
215
    {
216
        $this->name = $name;
217
218
        return $this;
219
    }
220
221
    public function getTitle(): ?string
222
    {
223
        return $this->title;
224
    }
225
226
    public function setTitle(?string $title): self
227
    {
228
        $this->title = $title;
229
230
        return $this;
231
    }
232
233
    public function getDescription(): ?string
234
    {
235
        return $this->description;
236
    }
237
238
    public function setDescription(?string $description): self
239
    {
240
        $this->description = $description;
241
242
        return $this;
243
    }
244
245
    public function getSizeInBytes(): ?int
246
    {
247
        return $this->sizeInBytes;
248
    }
249
250
    public function setSizeInBytes(?int $sizeInBytes): self
251
    {
252
        $this->sizeInBytes = $sizeInBytes;
253
254
        return $this;
255
    }
256
257
    public function getMimeType(): ?string
258
    {
259
        return $this->mimeType;
260
    }
261
262
    public function setMimeType(?string $mimeType): self
263
    {
264
        $this->mimeType = $mimeType;
265
266
        return $this;
267
    }
268
269
    public function getOriginalName(): ?string
270
    {
271
        return $this->originalName;
272
    }
273
274
    public function setOriginalName(?string $originalName): self
275
    {
276
        $this->originalName = $originalName;
277
278
        return $this;
279
    }
280
281
    public function getDimensions(): ?array
282
    {
283
        return $this->dimensions;
284
    }
285
286
    public function setDimensions(?array $dimensions): self
287
    {
288
        $this->dimensions = $dimensions;
289
290
        return $this;
291
    }
292
293
    public function getUpdatedAt(): ?\DateTimeInterface
294
    {
295
        return $this->updatedAt;
296
    }
297
298
    public function setUpdatedAt(\DateTimeInterface $updatedAt): self
299
    {
300
        $this->updatedAt = $updatedAt;
301
        return $this;
302
    }
303
304
    public function getLatlng(): ?array
305
    {
306
        return $this->latlng;
307
    }
308
309
    public function setLatlng(?array $latlng): self
310
    {
311
        $this->latlng = $latlng;
312
313
        return $this;
314
    }
315
316
    public function getKeywords(): ?array
317
    {
318
        return $this->keywords;
319
    }
320
321
    public function setKeywords(?array $keywords): self
322
    {
323
        $this->keywords = $keywords;
324
325
        return $this;
326
    }
327
328
    public function getCapturedAt(): ?\DateTimeInterface
329
    {
330
        return $this->capturedAt;
331
    }
332
333
    public function setCapturedAt(\DateTimeInterface $capturedAt): self
334
    {
335
        $this->capturedAt = $capturedAt;
336
337
        return $this;
338
    }
339
340
    // /**
341
    //  * @return Collection|Wander[]
342
    //  */
343
    // public function getWanders(): Collection
344
    // {
345
    //     return $this->wanders;
346
    // }
347
348
    // public function addWander(Wander $wander): self
349
    // {
350
    //     if (!$this->wanders->contains($wander)) {
351
    //         $this->wanders[] = $wander;
352
    //         $wander->addImage($this);
353
    //     }
354
355
    //     return $this;
356
    // }
357
358
    // public function removeWander(Wander $wander): self
359
    // {
360
    //     if ($this->wanders->removeElement($wander)) {
361
    //         $wander->removeImage($this);
362
    //     }
363
364
    //     return $this;
365
    // }
366
367
    public function getWander(): ?Wander
368
    {
369
        return $this->wander;
370
    }
371
372
    public function setWander(?Wander $wander): self
373
    {
374
        $this->wander = $wander;
375
        return $this;
376
    }
377
378
    public function getRating(): ?int
379
    {
380
        return $this->rating;
381
    }
382
383
    public function setRating(?int $rating): self
384
    {
385
        $this->rating = $rating;
386
387
        return $this;
388
    }
389
390
391
    /* Computed (set up by Doctrine postLoad listener) */
392
393
    /**
394
     * @Groups({"image:list", "image:item"})
395
     */
396
    private $imageUri;
397
398
    /**
399
     * @Groups({"image:list", "image:item"})
400
     */
401
    private $markerImageUri;
402
403
    /**
404
     * @Groups({"image:list", "image:item"})
405
     */
406
    private $mediumImageUri;
407
408
    /**
409
     * @Groups({"image:list", "image:item"})
410
     */
411
    private $imageShowUri;
412
413
    /**
414
     * @ORM\Column(type="array", nullable=true)
415
     */
416
    private $auto_tags = [];
417
418
    /**
419
     * @ORM\Column(type="string", length=255, nullable=true)
420
     */
421
    private $location;
422
423
424
    public function setImageUri($imageUri) {
425
        $this->imageUri = $imageUri;
426
    }
427
428
    public function getImageUri(): ?string {
429
        return $this->imageUri;
430
    }
431
432
    public function setMarkerImageUri($markerImageUri) {
433
        $this->markerImageUri = $markerImageUri;
434
    }
435
    public function getMarkerImageUri(): ?string {
436
        return $this->markerImageUri;
437
    }
438
439
    public function setMediumImageUri($mediumImageUri) {
440
        $this->mediumImageUri = $mediumImageUri;
441
    }
442
    public function getMediumImageUri(): ?string {
443
        return $this->mediumImageUri;
444
    }
445
446
    public function setImageShowUri($imageShowUri) {
447
        $this->imageShowUri = $imageShowUri;
448
    }
449
    public function getImageShowUri(): ?string {
450
        return $this->imageShowUri;
451
    }
452
453
    /**
454
     * @ORM\PostUpdate
455
     * @ORM\PostPersist
456
     */
457
    public function updateWanderToForceElasticReindex(LifecycleEventArgs $args): self
458
    {
459
        // TODO: We may need extra code or a different function
460
        // if we're to cover the event of an image being deleted,
461
        // maybe. Test. But for now this is good enough and we can
462
        // re-index manually if need be.
463
        $wander = $this->getWander();
464
        if ($wander === null) {
465
            return $this;
466
        }
467
        $wander->setModifiedAt();
468
        $entityManager = $args->getEntityManager();
469
        $entityManager->persist($wander);
470
        $entityManager->flush();
471
        return $this;
472
    }
473
474
    public function getAutoTags(): ?array
475
    {
476
        return $this->auto_tags;
477
    }
478
479
    public function setAutoTags(?array $auto_tags): self
480
    {
481
        $this->auto_tags = $auto_tags;
482
483
        return $this;
484
    }
485
    public function getAutoTagsCount(): int {
486
        if (is_array($this->auto_tags)) {
0 ignored issues
show
introduced by
The condition is_array($this->auto_tags) is always true.
Loading history...
487
            return count($this->auto_tags);
488
        }
489
        return 0;
490
    }
491
492
    public function getLocation(): ?string
493
    {
494
        return $this->location;
495
    }
496
497
    public function setLocation(?string $location): self
498
    {
499
        $this->location = $location;
500
501
        return $this;
502
    }
503
}
504
505