Completed
Push — master ( 6c498f...bcf6d3 )
by
unknown
17s queued 14s
created

Event::applyEventUpdatedFromUDB2()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace CultuurNet\UDB3\Event;
4
5
use Broadway\EventSourcing\EventSourcedAggregateRoot;
6
use CultuurNet\Geocoding\Coordinate\Coordinates;
7
use CultuurNet\UDB3\BookingInfo;
8
use CultuurNet\UDB3\Calendar;
9
use CultuurNet\UDB3\CalendarInterface;
10
use CultuurNet\UDB3\Cdb\EventItemFactory;
11
use CultuurNet\UDB3\Cdb\UpdateableWithCdbXmlInterface;
12
use CultuurNet\UDB3\ContactPoint;
13
use CultuurNet\UDB3\Description;
14
use CultuurNet\UDB3\Event\Events\AudienceUpdated;
15
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated;
16
use CultuurNet\UDB3\Event\Events\CalendarUpdated;
17
use CultuurNet\UDB3\Event\Events\Concluded;
18
use CultuurNet\UDB3\Event\Events\ContactPointUpdated;
19
use CultuurNet\UDB3\Event\Events\DescriptionTranslated;
20
use CultuurNet\UDB3\Event\Events\DescriptionUpdated;
21
use CultuurNet\UDB3\Event\Events\EventCdbXMLInterface;
22
use CultuurNet\UDB3\Event\Events\EventCopied;
23
use CultuurNet\UDB3\Event\Events\EventCreated;
24
use CultuurNet\UDB3\Event\Events\EventDeleted;
25
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
26
use CultuurNet\UDB3\Event\Events\EventUpdatedFromUDB2;
27
use CultuurNet\UDB3\Event\Events\FacilitiesUpdated;
28
use CultuurNet\UDB3\Event\Events\GeoCoordinatesUpdated;
29
use CultuurNet\UDB3\Event\Events\ImageAdded;
30
use CultuurNet\UDB3\Event\Events\ImageRemoved;
31
use CultuurNet\UDB3\Event\Events\Image\ImagesImportedFromUDB2;
32
use CultuurNet\UDB3\Event\Events\Image\ImagesUpdatedFromUDB2;
33
use CultuurNet\UDB3\Event\Events\ImageUpdated;
34
use CultuurNet\UDB3\Event\Events\LabelAdded;
35
use CultuurNet\UDB3\Event\Events\LabelRemoved;
36
use CultuurNet\UDB3\Event\Events\LabelsImported;
37
use CultuurNet\UDB3\Event\Events\LocationUpdated;
38
use CultuurNet\UDB3\Event\Events\MainImageSelected;
39
use CultuurNet\UDB3\Event\Events\MajorInfoUpdated;
40
use CultuurNet\UDB3\Event\Events\Moderation\Approved;
41
use CultuurNet\UDB3\Event\Events\Moderation\FlaggedAsDuplicate;
42
use CultuurNet\UDB3\Event\Events\Moderation\FlaggedAsInappropriate;
43
use CultuurNet\UDB3\Event\Events\Moderation\Published;
44
use CultuurNet\UDB3\Event\Events\Moderation\Rejected;
45
use CultuurNet\UDB3\Event\Events\OrganizerDeleted;
46
use CultuurNet\UDB3\Event\Events\OrganizerUpdated;
47
use CultuurNet\UDB3\Event\Events\PriceInfoUpdated;
48
use CultuurNet\UDB3\Event\Events\ThemeUpdated;
49
use CultuurNet\UDB3\Event\Events\TitleTranslated;
50
use CultuurNet\UDB3\Event\Events\TitleUpdated;
51
use CultuurNet\UDB3\Event\Events\TypeUpdated;
52
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeDeleted;
53
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeUpdated;
54
use CultuurNet\UDB3\Event\ValueObjects\Audience;
55
use CultuurNet\UDB3\Event\ValueObjects\AudienceType;
56
use CultuurNet\UDB3\Label;
57
use CultuurNet\UDB3\LabelCollection;
58
use CultuurNet\UDB3\Language;
59
use CultuurNet\UDB3\Event\ValueObjects\LocationId;
60
use CultuurNet\UDB3\Media\ImageCollection;
61
use CultuurNet\UDB3\Media\Image;
62
use CultuurNet\UDB3\Model\ValueObject\Taxonomy\Label\Labels;
63
use CultuurNet\UDB3\Offer\AgeRange;
64
use CultuurNet\UDB3\Offer\Offer;
65
use CultuurNet\UDB3\Offer\WorkflowStatus;
66
use CultuurNet\UDB3\PriceInfo\PriceInfo;
67
use CultuurNet\UDB3\Theme;
68
use CultuurNet\UDB3\Title;
69
use ValueObjects\Identity\UUID;
70
use ValueObjects\Person\Age;
71
use ValueObjects\StringLiteral\StringLiteral;
72
73
class Event extends Offer implements UpdateableWithCdbXmlInterface
74
{
75
    /**
76
     * @var string
77
     */
78
    protected $eventId;
79
80
    /**
81
     * @var Audience
82
     */
83
    private $audience;
84
85
    /**
86
     * @var LocationId
87
     */
88
    private $locationId;
89
90
    /**
91
     * @var boolean
92
     */
93
    private $concluded = false;
94
95
    public function __construct()
96
    {
97
        parent::__construct();
98
    }
99
100
    /**
101
     * Factory method to create a new event.
102
     *
103
     * @param $eventId
104
     * @param Language $mainLanguage
105
     * @param Title $title
106
     * @param EventType $eventType
107
     * @param LocationId $location
108
     * @param CalendarInterface $calendar
109
     * @param Theme|null $theme
110
     * @param \DateTimeImmutable|null $publicationDate
111
     * @return Event
112
     */
113
    public static function create(
114
        $eventId,
115
        Language $mainLanguage,
116
        Title $title,
117
        EventType $eventType,
118
        LocationId $location,
119
        CalendarInterface $calendar,
120
        Theme $theme = null,
121
        \DateTimeImmutable $publicationDate = null
122
    ) {
123
        $event = new self();
124
125
        $event->apply(
126
            new EventCreated(
127
                $eventId,
128
                $mainLanguage,
129
                $title,
130
                $eventType,
131
                $location,
132
                $calendar,
133
                $theme,
134
                $publicationDate
135
            )
136
        );
137
138
        if ($location->isDummyPlaceForEducation()) {
139
            // Bookable education events should get education as their audience type. We record this explicitly so we
140
            // don't have to handle this edge case in every read model projector.
141
            $event->apply(
142
                new AudienceUpdated($eventId, new Audience(AudienceType::EDUCATION()))
143
            );
144
        }
145
146
        return $event;
147
    }
148
149
    /**
150
     * @param string $newEventId
151
     * @param CalendarInterface $calendar
152
     *
153
     * @return Event
154
     */
155
    public function copy($newEventId, CalendarInterface $calendar)
156
    {
157
        if ($this->hasUncommittedEvents()) {
158
            throw new \RuntimeException('I refuse to copy, there are uncommitted events present.');
159
        }
160
161
        // The copied event will have a playhead of the original event + 1
162
        $copy = clone $this;
163
164
        $copy->apply(
165
            new EventCopied(
166
                $newEventId,
167
                $this->eventId,
168
                $calendar
169
            )
170
        );
171
172
        return $copy;
173
    }
174
175
    /**
176
     * @param string $eventId
177
     * @param string $cdbXml
178
     * @param string $cdbXmlNamespaceUri
179
     * @return Event
180
     */
181
    public static function importFromUDB2(
182
        $eventId,
183
        $cdbXml,
184
        $cdbXmlNamespaceUri
185
    ) {
186
        $event = new self();
187
        $event->apply(
188
            new EventImportedFromUDB2(
189
                $eventId,
190
                $cdbXml,
191
                $cdbXmlNamespaceUri
192
            )
193
        );
194
195
        return $event;
196
    }
197
198
    /**
199
     * {@inheritdoc}
200
     */
201
    public function getAggregateRootId()
202
    {
203
        return $this->eventId;
204
    }
205
206
    protected function applyEventCreated(EventCreated $eventCreated)
207
    {
208
        $this->eventId = $eventCreated->getEventId();
209
        $this->titles[$eventCreated->getMainLanguage()->getCode()] = $eventCreated->getTitle();
210
        $this->calendar = $eventCreated->getCalendar();
211
        $this->audience = new Audience(AudienceType::EVERYONE());
212
        $this->contactPoint = new ContactPoint();
213
        $this->bookingInfo = new BookingInfo();
214
        $this->typeId = $eventCreated->getEventType()->getId();
215
        $this->themeId = $eventCreated->getTheme() ? $eventCreated->getTheme()->getId() : null;
216
        $this->locationId = $eventCreated->getLocation();
217
        $this->mainLanguage = $eventCreated->getMainLanguage();
218
        $this->workflowStatus = WorkflowStatus::DRAFT();
219
    }
220
221
    /**
222
     * @param EventCopied $eventCopied
223
     */
224
    protected function applyEventCopied(EventCopied $eventCopied)
225
    {
226
        $this->eventId = $eventCopied->getItemId();
227
        $this->workflowStatus = WorkflowStatus::DRAFT();
228
        $this->labels = new LabelCollection();
229
    }
230
231
    protected function applyEventImportedFromUDB2(
232
        EventImportedFromUDB2 $eventImported
233
    ) {
234
        $this->eventId = $eventImported->getEventId();
235
        // When importing from UDB2 the default main language is always 'nl'.
236
        $this->mainLanguage = new Language('nl');
237
        $this->setUDB2Data($eventImported);
238
    }
239
240
    /**
241
     * @param EventUpdatedFromUDB2 $eventUpdated
242
     */
243
    protected function applyEventUpdatedFromUDB2(
244
        EventUpdatedFromUDB2 $eventUpdated
245
    ) {
246
        // Note: when updating from UDB2 never change the main language.
247
        $this->setUDB2Data($eventUpdated);
248
    }
249
250
    protected function applyEventDeleted(EventDeleted $event): void
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

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

Loading history...
251
    {
252
        $this->isDeleted = true;
253
    }
254
255
    /**
256
     * @param EventCdbXMLInterface $eventCdbXML
257
     */
258
    protected function setUDB2Data(
259
        EventCdbXMLInterface $eventCdbXML
260
    ) {
261
        $udb2Event = EventItemFactory::createEventFromCdbXml(
262
            $eventCdbXML->getCdbXmlNamespaceUri(),
263
            $eventCdbXML->getCdbXml()
264
        );
265
266
        // Just clear the facilities.
267
        $this->facilities = [];
268
269
        // Just clear the location id after an import or update.
270
        $this->locationId = null;
271
272
        // Just clear the contact point.
273
        $this->contactPoint = null;
274
275
        // Just clear the calendar.
276
        $this->calendar = null;
277
278
        // Correctly set the age range to avoid issues with deleting age range.
279
        // after an update from UDB2.
280
        $this->typicalAgeRange = new AgeRange(
281
            $udb2Event->getAgeFrom() ? new Age($udb2Event->getAgeFrom()) : null,
282
            $udb2Event->getAgeTo() ? new Age($udb2Event->getAgeTo()) : null
283
        );
284
285
        // Just clear the booking info.
286
        $this->bookingInfo = null;
287
288
        // Just clear the price info.
289
        $this->priceInfo = null;
290
291
        $this->importWorkflowStatus($udb2Event);
292
        $this->labels = LabelCollection::fromKeywords($udb2Event->getKeywords(true));
293
    }
294
295
    /**
296
     * Update the major info.
297
     *
298
     * @param Title $title
299
     * @param EventType $eventType
300
     * @param LocationId $location
301
     * @param CalendarInterface $calendar
302
     * @param Theme|null $theme
303
     */
304
    public function updateMajorInfo(
305
        Title $title,
306
        EventType $eventType,
307
        LocationId $location,
308
        CalendarInterface $calendar,
309
        Theme $theme = null
310
    ) {
311
        $this->apply(new MajorInfoUpdated($this->eventId, $title, $eventType, $location, $calendar, $theme));
312
    }
313
314
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
315
    {
316
        $this->locationId = $majorInfoUpdated->getLocation();
317
    }
318
319
    /**
320
     * @param LocationId $locationId
321
     */
322
    public function updateLocation(LocationId $locationId)
323
    {
324
        if (!is_null($this->locationId) && $this->locationId->sameValueAs($locationId)) {
325
            return;
326
        }
327
328
        $this->apply(new LocationUpdated($this->eventId, $locationId));
329
330
        if ($locationId->isDummyPlaceForEducation()) {
331
            // Bookable education events should get education as their audience type. We record this explicitly so we
332
            // don't have to handle this edge case in every read model projector.
333
            $this->apply(
334
                new AudienceUpdated($this->eventId, new Audience(AudienceType::EDUCATION()))
335
            );
336
        }
337
    }
338
339
    /**
340
     * @param LocationUpdated $locationUpdated
341
     */
342
    public function applyLocationUpdated(LocationUpdated $locationUpdated)
343
    {
344
        $this->locationId = $locationUpdated->getLocationId();
345
    }
346
347
    public function updateAudience(
348
        Audience $audience
349
    ): void {
350
        $audienceType = $audience->getAudienceType();
351
        if ($this->locationId &&
352
            $this->locationId->isDummyPlaceForEducation() &&
353
            !$audienceType->sameValueAs(AudienceType::EDUCATION())
354
        ) {
355
            throw IncompatibleAudienceType::forEvent($this->eventId, $audienceType);
356
        }
357
358
        if (is_null($this->audience) || !$this->audience->equals($audience)) {
359
            $this->apply(new AudienceUpdated(
360
                $this->eventId,
361
                $audience
362
            ));
363
        }
364
    }
365
366
    /**
367
     * @param AudienceUpdated $audienceUpdated
368
     */
369
    public function applyAudienceUpdated(AudienceUpdated $audienceUpdated)
370
    {
371
        $this->audience= $audienceUpdated->getAudience();
372
    }
373
374
    /**
375
     * @inheritDoc
376
     * @return ImagesImportedFromUDB2
377
     */
378
    protected function createImagesImportedFromUDB2(ImageCollection $images)
379
    {
380
        return new ImagesImportedFromUDB2($this->eventId, $images);
381
    }
382
383
    /**
384
     * @inheritDoc
385
     * @return ImagesUpdatedFromUDB2
386
     */
387
    protected function createImagesUpdatedFromUDB2(ImageCollection $images)
388
    {
389
        return new ImagesUpdatedFromUDB2($this->eventId, $images);
390
    }
391
392
    /**
393
     * @inheritdoc
394
     */
395
    public function updateWithCdbXml($cdbXml, $cdbXmlNamespaceUri)
396
    {
397
        $this->apply(
398
            new EventUpdatedFromUDB2(
399
                $this->eventId,
400
                $cdbXml,
401
                $cdbXmlNamespaceUri
402
            )
403
        );
404
    }
405
406
    /**
407
     * @param Label $label
408
     * @return LabelAdded
409
     */
410
    protected function createLabelAddedEvent(Label $label)
411
    {
412
        return new LabelAdded($this->eventId, $label);
413
    }
414
415
    /**
416
     * @param Label $label
417
     * @return LabelRemoved
418
     */
419
    protected function createLabelRemovedEvent(Label $label)
420
    {
421
        return new LabelRemoved($this->eventId, $label);
422
    }
423
424
    /**
425
     * @inheritdoc
426
     */
427
    protected function createLabelsImportedEvent(Labels $labels)
428
    {
429
        return new LabelsImported($this->eventId, $labels);
430
    }
431
432
    /**
433
     * @param Image $image
434
     * @return ImageAdded
435
     */
436
    protected function createImageAddedEvent(Image $image)
437
    {
438
        return new ImageAdded($this->eventId, $image);
439
    }
440
441
    /**
442
     * @param Image $image
443
     * @return ImageRemoved
444
     */
445
    protected function createImageRemovedEvent(Image $image)
446
    {
447
        return new ImageRemoved($this->eventId, $image);
448
    }
449
450
    /**
451
     * @param UUID $mediaObjectId
452
     * @param StringLiteral $description
453
     * @param StringLiteral $copyrightHolder
454
     * @return ImageUpdated
455
     */
456
    protected function createImageUpdatedEvent(
457
        UUID $mediaObjectId,
458
        StringLiteral $description,
459
        StringLiteral $copyrightHolder
460
    ) {
461
        return new ImageUpdated(
462
            $this->eventId,
463
            $mediaObjectId,
464
            $description,
465
            $copyrightHolder
466
        );
467
    }
468
469
    /**
470
     * @param Image $image
471
     * @return MainImageSelected
472
     */
473
    protected function createMainImageSelectedEvent(Image $image)
474
    {
475
        return new MainImageSelected($this->eventId, $image);
476
    }
477
478
    /**
479
     * @inheritdoc
480
     */
481
    protected function createTitleTranslatedEvent(Language $language, Title $title)
482
    {
483
        return new TitleTranslated($this->eventId, $language, $title);
484
    }
485
486
    /**
487
     * @param Title $title
488
     * @return TitleUpdated
489
     */
490
    protected function createTitleUpdatedEvent(Title $title)
491
    {
492
        return new TitleUpdated($this->eventId, $title);
493
    }
494
495
    /**
496
     * @inheritdoc
497
     */
498
    protected function createDescriptionTranslatedEvent(Language $language, Description $description)
499
    {
500
        return new DescriptionTranslated($this->eventId, $language, $description);
501
    }
502
503
    /**
504
     * @inheritdoc
505
     */
506
    protected function createDescriptionUpdatedEvent(Description $description)
507
    {
508
        return new DescriptionUpdated($this->eventId, $description);
509
    }
510
511
    /**
512
     * @inheritdoc
513
     */
514
    protected function createCalendarUpdatedEvent(Calendar $calendar)
515
    {
516
        return new CalendarUpdated($this->eventId, $calendar);
517
    }
518
519
    /**
520
     * @param AgeRange $typicalAgeRange
521
     * @return TypicalAgeRangeUpdated
522
     */
523
    protected function createTypicalAgeRangeUpdatedEvent($typicalAgeRange)
524
    {
525
        return new TypicalAgeRangeUpdated($this->eventId, $typicalAgeRange);
526
    }
527
528
    /**
529
     * @return TypicalAgeRangeDeleted
530
     */
531
    protected function createTypicalAgeRangeDeletedEvent()
532
    {
533
        return new TypicalAgeRangeDeleted($this->eventId);
534
    }
535
536
    /**
537
     * @param string $organizerId
538
     * @return OrganizerUpdated
539
     */
540
    protected function createOrganizerUpdatedEvent($organizerId)
541
    {
542
        return new OrganizerUpdated($this->eventId, $organizerId);
543
    }
544
545
    /**
546
     * @param string $organizerId
547
     * @return OrganizerDeleted
548
     */
549
    protected function createOrganizerDeletedEvent($organizerId)
550
    {
551
        return new OrganizerDeleted($this->eventId, $organizerId);
552
    }
553
554
    /**
555
     * @param ContactPoint $contactPoint
556
     * @return ContactPointUpdated
557
     */
558
    protected function createContactPointUpdatedEvent(ContactPoint $contactPoint)
559
    {
560
        return new ContactPointUpdated($this->eventId, $contactPoint);
561
    }
562
563
    /**
564
     * @inheritdoc
565
     */
566
    protected function createGeoCoordinatesUpdatedEvent(Coordinates $coordinates)
567
    {
568
        return new GeoCoordinatesUpdated($this->eventId, $coordinates);
569
    }
570
571
    /**
572
     * @param BookingInfo $bookingInfo
573
     * @return BookingInfoUpdated
574
     */
575
    protected function createBookingInfoUpdatedEvent(BookingInfo $bookingInfo)
576
    {
577
        return new BookingInfoUpdated($this->eventId, $bookingInfo);
578
    }
579
580
    /**
581
     * @param PriceInfo $priceInfo
582
     * @return PriceInfoUpdated
583
     */
584
    protected function createPriceInfoUpdatedEvent(PriceInfo $priceInfo)
585
    {
586
        return new PriceInfoUpdated($this->eventId, $priceInfo);
587
    }
588
589
    /**
590
     * @return EventDeleted
591
     */
592
    protected function createOfferDeletedEvent()
593
    {
594
        return new EventDeleted($this->eventId);
595
    }
596
597
    /**
598
     * @inheritdoc
599
     */
600
    protected function createPublishedEvent(\DateTimeInterface $publicationDate)
601
    {
602
        return new Published($this->eventId, $publicationDate);
603
    }
604
605
    /**
606
     * @inheritdoc
607
     */
608
    protected function createApprovedEvent()
609
    {
610
        return new Approved($this->eventId);
611
    }
612
613
    /**
614
     * @inheritdoc
615
     */
616
    protected function createRejectedEvent(StringLiteral $reason)
617
    {
618
        return new Rejected($this->eventId, $reason);
619
    }
620
621
    /**
622
     * @inheritDoc
623
     */
624
    protected function createFlaggedAsDuplicate()
625
    {
626
        return new FlaggedAsDuplicate($this->eventId);
627
    }
628
629
    /**
630
     * @inheritDoc
631
     */
632
    protected function createFlaggedAsInappropriate()
633
    {
634
        return new FlaggedAsInappropriate($this->eventId);
635
    }
636
637
    /**
638
     * @inheritdoc
639
     */
640
    protected function createTypeUpdatedEvent(EventType $type)
641
    {
642
        return new TypeUpdated($this->eventId, $type);
643
    }
644
645
    /**
646
     * @inheritdoc
647
     */
648
    protected function createThemeUpdatedEvent(Theme $theme)
649
    {
650
        return new ThemeUpdated($this->eventId, $theme);
651
    }
652
653
    /**
654
     * @inheritdoc
655
     */
656
    protected function createFacilitiesUpdatedEvent(array $facilities)
657
    {
658
        return new FacilitiesUpdated($this->eventId, $facilities);
659
    }
660
661
    /**
662
     * Use reflection to get check if the aggregate has uncommitted events.
663
     * @return bool
664
     */
665
    private function hasUncommittedEvents()
666
    {
667
        $reflector = new \ReflectionClass(EventSourcedAggregateRoot::class);
668
        $property = $reflector->getProperty('uncommittedEvents');
669
670
        $property->setAccessible(true);
671
        $uncommittedEvents = $property->getValue($this);
672
673
        return !empty($uncommittedEvents);
674
    }
675
676
    public function conclude()
677
    {
678
        if (!$this->concluded) {
679
            $this->apply(new Concluded($this->eventId));
680
        }
681
    }
682
683
    /**
684
     * @param Concluded $concluded
685
     */
686
    protected function applyConcluded(Concluded $concluded)
0 ignored issues
show
Unused Code introduced by
The parameter $concluded is not used and could be removed.

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

Loading history...
687
    {
688
        $this->concluded = true;
689
    }
690
}
691