Completed
Push — master ( 97ef90...b0c954 )
by Matt
04:54
created

Wander::__toString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
namespace App\Entity;
4
5
use ApiPlatform\Core\Annotation\ApiProperty;
6
use App\Repository\WanderRepository;
7
use ApiPlatform\Core\Annotation\ApiResource;
8
use ApiPlatform\Core\Annotation\ApiSubresource;
9
use DateInterval;
10
use DateTime;
11
use Doctrine\Common\Collections\ArrayCollection;
12
use Doctrine\Common\Collections\Collection;
13
use Symfony\Component\Serializer\Annotation\Groups;
14
use Doctrine\ORM\Mapping as ORM;
15
use App\EventListener\WanderUploadListener;
16
use Carbon\Carbon;
17
use Carbon\CarbonInterval;
18
19
20
/**
21
 * @ORM\Entity(repositoryClass=WanderRepository::class)
22
 *
23
 * @ORM\EntityListeners({
24
 *  WanderUploadListener::class, App\EventListener\WanderDeleteListener::class
25
 * })
26
 *
27
 * @ApiResource(
28
 *  collectionOperations={"get"={"normalization_context"={"groups"="wander:list"}}},
29
 *  itemOperations={"get"={"normalization_context"={"groups"="wander:item"}}},
30
 *  order={"endTime"="ASC"},
31
 *  paginationEnabled=false
32
 * )
33
 * @ORM\HasLifecycleCallbacks()
34
 *
35
 */
36
class Wander
37
{
38
    /**
39
     * @ORM\Id
40
     * @ORM\GeneratedValue
41
     * @ORM\Column(type="integer")
42
     *
43
     * @Groups({"wander:list", "wander:item"})
44
     */
45
    private $id;
46
47
    /**
48
     * @ORM\Column(type="string", length=1024)
49
     *
50
     * @Groups({"wander:list", "wander:item"})
51
     */
52
    private $title;
53
54
    /**
55
     * @ORM\Column(type="datetime")
56
     *
57
     * @Groups({"wander:list", "wander:item"})
58
     */
59
    private $startTime;
60
61
    /**
62
     * @ORM\Column(type="datetime")
63
     *
64
     * @Groups({"wander:list", "wander:item"})
65
     */
66
    private $endTime;
67
68
    /**
69
     * @ORM\Column(type="text", nullable=true)
70
     *
71
     * @Groups({"wander:list", "wander:item"})
72
     */
73
    private $description;
74
75
    /**
76
     * @ORM\Column(type="string", length=255)
77
     *
78
     * @Groups({"wander:list", "wander:item"})
79
     */
80
    private $gpxFilename;
81
82
    /**
83
     * @ORM\OneToMany(targetEntity=Image::class, mappedBy="wander", cascade={"persist"})
84
     *
85
     * @Groups({"wander:list", "wander:item"})
86
     * @ApiSubresource
87
     */
88
    private $images;
89
90
    /**
91
     * @ORM\Column(type="float", nullable=true)
92
     *
93
     * Distance walked, in metres.
94
     *
95
     */
96
    private $distance;
97
98
    /**
99
     * @ORM\Column(type="float", nullable=true)
100
     */
101
    private $avgSpeed;
102
103
    /**
104
     * @ORM\Column(type="float", nullable=true)
105
     */
106
    private $avgPace;
107
108
    /**
109
     * @ORM\Column(type="float", nullable=true)
110
     */
111
    private $minAltitude;
112
113
    /**
114
     * @ORM\Column(type="float", nullable=true)
115
     */
116
    private $maxAltitude;
117
118
    /**
119
     * @ORM\Column(type="float", nullable=true)
120
     */
121
    private $cumulativeElevationGain;
122
123
    /**
124
     * @var string|null
125
     *
126
     * @ApiProperty(iri="http://schema.org/contentUrl")
127
     * @Groups({"wander:list", "wander:item"})
128
     */
129
    public $contentUrl;
130
131
    /**
132
     * @ORM\Column(type="array", nullable=true)
133
     */
134
    private $centroid = [];
135
136
    /**
137
     * @ORM\Column(type="float", nullable=true)
138
     */
139
    private $angleFromHome;
140
141
    public function __construct()
142
    {
143
        $this->images = new ArrayCollection();
144
    }
145
146
    public function getId(): ?int
147
    {
148
        return $this->id;
149
    }
150
151
    public function getTitle(): ?string
152
    {
153
        return $this->title;
154
    }
155
156
    public function setTitle(string $title): self
157
    {
158
        $this->title = $title;
159
160
        return $this;
161
    }
162
163
    public function getStartTime(): ?\DateTimeInterface
164
    {
165
        return $this->startTime;
166
    }
167
168
    public function setStartTime(\DateTimeInterface $startTime): self
169
    {
170
        $this->startTime = $startTime;
171
172
        return $this;
173
    }
174
175
    public function getEndTime(): ?\DateTimeInterface
176
    {
177
        return $this->endTime;
178
    }
179
180
    public function setEndTime(\DateTimeInterface $endTime): self
181
    {
182
        $this->endTime = $endTime;
183
184
        return $this;
185
    }
186
187
    public function getDescription(): ?string
188
    {
189
        return $this->description;
190
    }
191
192
    public function setDescription(?string $description): self
193
    {
194
        $this->description = $description;
195
196
        return $this;
197
    }
198
199
    public function getGpxFilename(): ?string
200
    {
201
        return $this->gpxFilename;
202
    }
203
204
    public function setGpxFilename(string $gpxFilename): self
205
    {
206
        $this->gpxFilename = $gpxFilename;
207
208
        return $this;
209
    }
210
211
    public function isTimeLengthSuspicious()
212
    {
213
        $interval = $this->startTime->diff($this->endTime, true);
214
        return $interval->h > 12;
215
    }
216
217
    /**
218
     * @return Collection|Image[]
219
     */
220
    public function getImages(): Collection
221
    {
222
        return $this->images;
223
    }
224
225
    public function addImage(Image $image): self
226
    {
227
        if (!$this->images->contains($image)) {
228
            $this->images[] = $image;
229
            $image->setWander($this);
230
        }
231
232
        return $this;
233
    }
234
235
    public function removeImage(Image $image): self
236
    {
237
        $image->setWander(null);
238
        $this->images->removeElement($image);
239
240
        return $this;
241
    }
242
243
    /**
244
     * @ORM\PreRemove
245
     */
246
    public function removeAllImages(): self
247
    {
248
        $images = $this->images;
249
        foreach ($images as $image) {
250
            $this->removeImage($image);
251
        }
252
        return $this;
253
    }
254
255
    public function getDistance(): ?float
256
    {
257
        return $this->distance;
258
    }
259
260
    public function setDistance(?float $distance): self
261
    {
262
        $this->distance = $distance;
263
264
        return $this;
265
    }
266
267
    public function getAvgSpeed(): ?float
268
    {
269
        return $this->avgSpeed;
270
    }
271
272
    public function setAvgSpeed(?float $avgSpeed): self
273
    {
274
        $this->avgSpeed = $avgSpeed;
275
276
        return $this;
277
    }
278
279
    public function getAvgPace(): ?float
280
    {
281
        return $this->avgPace;
282
    }
283
284
    public function setAvgPace(?float $avgPace): self
285
    {
286
        $this->avgPace = $avgPace;
287
288
        return $this;
289
    }
290
291
    public function getMinAltitude(): ?float
292
    {
293
        return $this->minAltitude;
294
    }
295
296
    public function setMinAltitude(?float $minAltitude): self
297
    {
298
        $this->minAltitude = $minAltitude;
299
300
        return $this;
301
    }
302
303
    public function getMaxAltitude(): ?float
304
    {
305
        return $this->maxAltitude;
306
    }
307
308
    public function setMaxAltitude(?float $maxAltitude): self
309
    {
310
        $this->maxAltitude = $maxAltitude;
311
312
        return $this;
313
    }
314
315
    public function getCumulativeElevationGain(): ?float
316
    {
317
        return $this->cumulativeElevationGain;
318
    }
319
320
    public function setCumulativeElevationGain(?float $cumulativeElevationGain): self
321
    {
322
        $this->cumulativeElevationGain = $cumulativeElevationGain;
323
324
        return $this;
325
    }
326
327
    // TODO: We probably don't need this any more; I've replaced
328
    // existing uses with our seconds_to_hms Twig filter.
329
    public function getDuration(): ?CarbonInterval
330
    {
331
        if (!isset($this->startTime, $this->endTime)) {
332
            return null;
333
        }
334
335
        $difference = CarbonInterval::instance($this->startTime->diff($this->endTime));
336
        return $difference;
337
    }
338
339
    /**
340
     * @return array<float>
341
     */
342
    public function getCentroid(): ?array
343
    {
344
        return $this->centroid;
345
    }
346
347
    /**
348
     * @param array<float> $centroid
349
     */
350
    public function setCentroid(?array $centroid): self
351
    {
352
        $this->centroid = $centroid;
353
354
        return $this;
355
    }
356
357
    // We could calculate the angle from the Centroid each time, but
358
    // for now I'm just going to store it to save time.
359
    public function getAngleFromHome(): ?float
360
    {
361
        return $this->angleFromHome;
362
    }
363
364
    public function setAngleFromHome(?float $angleFromHome): self
365
    {
366
        $this->angleFromHome = $angleFromHome;
367
368
        return $this;
369
    }
370
371
    // Utilities
372
373
    // TODO: This is more like display code. Perhaps this should be in
374
    // a Twig extension and we should stick to storing the angle in here.
375
376
    /**
377
     * @var array<int, string>
378
     */
379
    private static $compass = [
380
        0 => 'N',
381
        1 => 'NE',
382
        2 => 'NE',
383
        3 => 'E',
384
        4 => 'E',
385
        5 => 'SE',
386
        6 => 'SE',
387
        7 => 'S',
388
        8 => 'S',
389
        9 => 'SW',
390
        10 => 'SW',
391
        11 => 'W',
392
        12 => 'W',
393
        13 => 'NW',
394
        14 => 'NW',
395
        15 => 'N'
396
      ];
397
398
    public function getSector(): ?string
399
    {
400
        if ($this->angleFromHome !== null) {
401
            if ($this->angleFromHome >= 0 && $this->angleFromHome < 360.0) {
402
                return self::$compass[floor($this->angleFromHome / 22.5)];
403
            }
404
        }
405
        return null;
406
    }
407
408
    public function getCentroidAsString(): ?string {
409
        if ($this->centroid !== null) {
410
            return implode(", ", $this->centroid);
411
        }
412
        return null;
413
    }
414
415
    // TODO: Put this in but didn't use it in the end; maybe I don't need it
416
    // as in Twig we can use wander.images.count anyway. Take out?
417
    public function getImageCount(): int
418
    {
419
        // https://stackoverflow.com/a/8511611/300836
420
        return $this->images->count();
421
    }
422
423
    public function __toString():string
424
    {
425
        $result = $this->title ?? '';
426
        if (isset($this->startTime)) {
427
            $result .= ' (' . $this->startTime->format('j M Y') . ')';
428
        }
429
        return $result;
430
    }
431
432
433
}
434