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

Event::create()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 35
rs 9.36
c 0
b 0
f 0
cc 2
nc 2
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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