Completed
Pull Request — master (#342)
by Luc
05:03
created

Offer::applyFacilitiesUpdated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace CultuurNet\UDB3\Offer;
4
5
use Broadway\EventSourcing\EventSourcedAggregateRoot;
6
use CultureFeed_Cdb_Item_Base;
7
use CultuurNet\Geocoding\Coordinate\Coordinates;
8
use CultuurNet\UDB3\BookingInfo;
9
use CultuurNet\UDB3\Calendar;
10
use CultuurNet\UDB3\ContactPoint;
11
use CultuurNet\UDB3\Description;
12
use CultuurNet\UDB3\Event\EventType;
13
use CultuurNet\UDB3\Facility;
14
use CultuurNet\UDB3\Label;
15
use CultuurNet\UDB3\LabelAwareAggregateRoot;
16
use CultuurNet\UDB3\LabelCollection;
17
use CultuurNet\UDB3\Media\Image;
18
use CultuurNet\UDB3\Media\ImageCollection;
19
use CultuurNet\UDB3\Offer\Commands\Image\AbstractUpdateImage;
20
use CultuurNet\UDB3\Language;
21
use CultuurNet\UDB3\Offer\Events\AbstractBookingInfoUpdated;
22
use CultuurNet\UDB3\Offer\Events\AbstractCalendarUpdated;
23
use CultuurNet\UDB3\Offer\Events\AbstractContactPointUpdated;
24
use CultuurNet\UDB3\Offer\Events\AbstractFacilitiesUpdated;
25
use CultuurNet\UDB3\Offer\Events\AbstractGeoCoordinatesUpdated;
26
use CultuurNet\UDB3\Offer\Events\AbstractThemeUpdated;
27
use CultuurNet\UDB3\Offer\Events\AbstractTitleTranslated;
28
use CultuurNet\UDB3\Offer\Events\AbstractTitleUpdated;
29
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionTranslated;
30
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionUpdated;
31
use CultuurNet\UDB3\Offer\Events\AbstractLabelAdded;
32
use CultuurNet\UDB3\Offer\Events\AbstractLabelRemoved;
33
use CultuurNet\UDB3\Offer\Events\AbstractOfferDeleted;
34
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerDeleted;
35
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerUpdated;
36
use CultuurNet\UDB3\Offer\Events\AbstractPriceInfoUpdated;
37
use CultuurNet\UDB3\Offer\Events\AbstractTypeUpdated;
38
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeDeleted;
39
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeUpdated;
40
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageAdded;
41
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageRemoved;
42
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesEvent;
43
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesImportedFromUDB2;
44
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesUpdatedFromUDB2;
45
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageUpdated;
46
use CultuurNet\UDB3\Offer\Events\Image\AbstractMainImageSelected;
47
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractApproved;
48
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsDuplicate;
49
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsInappropriate;
50
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractPublished;
51
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractRejected;
52
use CultuurNet\UDB3\PriceInfo\PriceInfo;
53
use CultuurNet\UDB3\Theme;
54
use CultuurNet\UDB3\Title;
55
use Exception;
56
use ValueObjects\Identity\UUID;
57
use ValueObjects\StringLiteral\StringLiteral;
58
59
abstract class Offer extends EventSourcedAggregateRoot implements LabelAwareAggregateRoot
60
{
61
    const DUPLICATE_REASON = 'duplicate';
62
    const INAPPROPRIATE_REASON = 'inappropriate';
63
64
    /**
65
     * @var LabelCollection
66
     */
67
    protected $labels;
68
69
    /**
70
     * @var ImageCollection
71
     */
72
    protected $images;
73
74
    /**
75
     * @var string
76
     *
77
     * Organizer ids can come from UDB2 which does not strictly use UUIDs.
78
     */
79
    protected $organizerId;
80
81
    /**
82
     * @var WorkflowStatus
83
     */
84
    protected $workflowStatus;
85
86
    /**
87
     * @var StringLiteral|null
88
     */
89
    protected $rejectedReason;
90
91
    /**
92
     * @var PriceInfo
93
     */
94
    protected $priceInfo;
95
96
    /**
97
     * @var StringLiteral[]
98
     */
99
    protected $titles;
100
101
    /**
102
     * @var Description[]
103
     */
104
    protected $descriptions;
105
106
    /**
107
     * @var Language
108
     */
109
    protected $mainLanguage;
110
111
    /**
112
     * @var string;
113
     */
114
    protected $typeId;
115
116
    /**
117
     * @var string;
118
     */
119
    protected $themeId;
120
121
    /**
122
     * @var array
123
     */
124
    protected $facilities;
125
126
    /**
127
     * @var ContactPoint
128
     */
129
    protected $contactPoint;
130
131
    /**
132
     * @var Calendar
133
     */
134
    protected $calendar;
135
136
    /**
137
     * @var AgeRange
138
     */
139
    protected $typicalAgeRange;
140
141
    /**
142
     * Offer constructor.
143
     */
144
    public function __construct()
145
    {
146
        $this->titles = [];
147
        $this->descriptions = [];
148
        $this->labels = new LabelCollection();
149
        $this->images = new ImageCollection();
150
        $this->facilities = [];
151
        $this->contactPoint = null;
152
        $this->calendar = null;
153
        $this->typicalAgeRange = null;
154
    }
155
156
    /**
157
     * @param EventType $type
158
     */
159
    public function updateType(EventType $type)
160
    {
161
        if (!$this->typeId || $this->typeId !== $type->getId()) {
162
            $this->apply($this->createTypeUpdatedEvent($type));
163
        }
164
    }
165
166
    /**
167
     * @param Theme $theme
168
     */
169
    public function updateTheme(Theme $theme)
170
    {
171
        if (!$this->themeId || $this->themeId !== $theme->getId()) {
172
            $this->apply($this->createThemeUpdatedEvent($theme));
173
        }
174
    }
175
176
    /**
177
     * @param array $facilities
178
     */
179
    public function updateFacilities(array $facilities)
180
    {
181
        if (empty($this->facilities) || !$this->sameFacilities($this->facilities, $facilities)) {
182
            $this->apply($this->createFacilitiesUpdatedEvent($facilities));
183
        }
184
    }
185
186
    /**
187
     * @param AbstractFacilitiesUpdated $facilitiesUpdated
188
     */
189
    protected function applyFacilitiesUpdated(AbstractFacilitiesUpdated $facilitiesUpdated)
190
    {
191
        $this->facilities = $facilitiesUpdated->getFacilities();
192
    }
193
194
    /**
195
     * @param array $facilities1
196
     * @param array $facilities2
197
     * @return bool
198
     */
199
    private function sameFacilities($facilities1, $facilities2)
200
    {
201
        if (count($facilities1) !== count($facilities2)) {
202
            return false;
203
        }
204
205
        $sameFacilities = array_uintersect(
206
            $facilities1,
207
            $facilities2,
208
            function (Facility $facility1, Facility $facility2) {
209
                return strcmp($facility1->getId(), $facility2->getId());
210
            }
211
        );
212
213
        return count($sameFacilities) === count($facilities2);
214
    }
215
216
    /**
217
     * Get the id of the main image if one is selected for this offer.
218
     *
219
     * @return UUID|null
220
     */
221
    protected function getMainImageId()
222
    {
223
        $mainImage = $this->images->getMain();
224
        return isset($mainImage) ? $mainImage->getMediaObjectId() : null;
225
    }
226
227
    /**
228
     * @inheritdoc
229
     */
230
    public function addLabel(Label $label)
231
    {
232
        if (!$this->labels->contains($label)) {
233
            $this->apply(
234
                $this->createLabelAddedEvent($label)
235
            );
236
        }
237
    }
238
239
    /**
240
     * @inheritdoc
241
     */
242
    public function removeLabel(Label $label)
243
    {
244
        if ($this->labels->contains($label)) {
245
            $this->apply(
246
                $this->createLabelRemovedEvent($label)
247
            );
248
        }
249
    }
250
251
    /**
252
     * @param Language $language
253
     * @param Title $title
254
     */
255
    public function updateTitle(Language $language, Title $title)
256
    {
257
        if ($this->isTitleChanged($title, $language)) {
258
            if ($language->getCode() !== $this->mainLanguage->getCode()) {
259
                $event = $this->createTitleTranslatedEvent($language, $title);
260
            } else {
261
                $event = $this->createTitleUpdatedEvent($title);
262
            }
263
264
            $this->apply($event);
265
        }
266
    }
267
268
    /**
269
     * @param Description $description
270
     * @param Language $language
271
     */
272
    public function updateDescription(Description $description, Language $language)
273
    {
274
        if ($this->isDescriptionChanged($description, $language)) {
275
            if ($language->getCode() !== $this->mainLanguage->getCode()) {
276
                $event = $this->createDescriptionTranslatedEvent($language, $description);
277
            } else {
278
                $event = $this->createDescriptionUpdatedEvent((string) $description);
279
            }
280
281
            $this->apply($event);
282
        }
283
    }
284
285
    /**
286
     * @param Calendar $calendar
287
     */
288
    public function updateCalendar(Calendar $calendar)
289
    {
290
        if (is_null($this->calendar) || !$this->calendar->sameAs($calendar)) {
291
            $this->apply(
292
                $this->createCalendarUpdatedEvent($calendar)
293
            );
294
        }
295
    }
296
297
    /**
298
     * @param AbstractCalendarUpdated $calendarUpdated
299
     */
300
    protected function applyCalendarUpdated(AbstractCalendarUpdated $calendarUpdated)
301
    {
302
        $this->calendar = $calendarUpdated->getCalendar();
303
    }
304
305
    /**
306
     * @param string $typicalAgeRange
307
     */
308
    public function updateTypicalAgeRange($typicalAgeRange)
309
    {
310
        $typicalAgeRangeUpdatedEvent = $this->createTypicalAgeRangeUpdatedEvent($typicalAgeRange);
311
312
        if (empty($this->typicalAgeRange) || !$this->typicalAgeRange->sameAs($typicalAgeRangeUpdatedEvent->getTypicalAgeRange())) {
313
            $this->apply($typicalAgeRangeUpdatedEvent);
314
        }
315
    }
316
317
    /**
318
     * @param AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated
319
     */
320
    protected function applyTypicalAgeRangeUpdated(AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated)
321
    {
322
        $this->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
323
    }
324
325
    public function deleteTypicalAgeRange()
326
    {
327
        $this->apply(
328
            $this->createTypicalAgeRangeDeletedEvent()
329
        );
330
    }
331
332
    /**
333
     * @param AbstractTypicalAgeRangeDeleted $typicalAgeRangeDeleted
334
     */
335
    protected function applyTypicalAgeRangeDeleted(AbstractTypicalAgeRangeDeleted $typicalAgeRangeDeleted)
0 ignored issues
show
Unused Code introduced by
The parameter $typicalAgeRangeDeleted 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...
336
    {
337
        $this->typicalAgeRange = null;
338
    }
339
340
    /**
341
     * @param string $organizerId
342
     */
343
    public function updateOrganizer($organizerId)
344
    {
345
        if ($this->organizerId !== $organizerId) {
346
            $this->apply(
347
                $this->createOrganizerUpdatedEvent($organizerId)
348
            );
349
        }
350
    }
351
352
    /**
353
     * Delete the given organizer.
354
     *
355
     * @param string $organizerId
356
     */
357
    public function deleteOrganizer($organizerId)
358
    {
359
        if ($this->organizerId === $organizerId) {
360
            $this->apply(
361
                $this->createOrganizerDeletedEvent($organizerId)
362
            );
363
        }
364
    }
365
366
    /**
367
     * Updated the contact info.
368
     * @param ContactPoint $contactPoint
369
     */
370
    public function updateContactPoint(ContactPoint $contactPoint)
371
    {
372
        if (is_null($this->contactPoint) || !$this->contactPoint->sameAs($contactPoint)) {
373
            $this->apply(
374
                $this->createContactPointUpdatedEvent($contactPoint)
375
            );
376
        }
377
    }
378
379
    /**
380
     * @param AbstractContactPointUpdated $contactPointUpdated
381
     */
382
    protected function applyContactPointUpdated(AbstractContactPointUpdated $contactPointUpdated)
383
    {
384
        $this->contactPoint = $contactPointUpdated->getContactPoint();
385
    }
386
387
    /**
388
     * @param Coordinates $coordinates
389
     */
390
    public function updateGeoCoordinates(Coordinates $coordinates)
391
    {
392
        // Note: DON'T compare to previous coordinates and apply only on
393
        // changes. Various projectors expect GeoCoordinatesUpdated after
394
        // MajorInfoUpdated and PlaceUpdatedFromUDB2, even if the address
395
        // and thus the coordinates haven't actually changed.
396
        $this->apply(
397
            $this->createGeoCoordinatesUpdatedEvent($coordinates)
398
        );
399
    }
400
401
    /**
402
     * Updated the booking info.
403
     *
404
     * @param BookingInfo $bookingInfo
405
     */
406
    public function updateBookingInfo(BookingInfo $bookingInfo)
407
    {
408
        $this->apply(
409
            $this->createBookingInfoUpdatedEvent($bookingInfo)
410
        );
411
    }
412
413
    /**
414
     * @param PriceInfo $priceInfo
415
     */
416
    public function updatePriceInfo(PriceInfo $priceInfo)
417
    {
418
        if (is_null($this->priceInfo) || $priceInfo->serialize() !== $this->priceInfo->serialize()) {
419
            $this->apply(
420
                $this->createPriceInfoUpdatedEvent($priceInfo)
421
            );
422
        }
423
    }
424
425
    /**
426
     * @param AbstractPriceInfoUpdated $priceInfoUpdated
427
     */
428
    protected function applyPriceInfoUpdated(AbstractPriceInfoUpdated $priceInfoUpdated)
429
    {
430
        $this->priceInfo = $priceInfoUpdated->getPriceInfo();
431
    }
432
433
    /**
434
     * @param AbstractLabelAdded $labelAdded
435
     */
436
    protected function applyLabelAdded(AbstractLabelAdded $labelAdded)
437
    {
438
        $this->labels = $this->labels->with($labelAdded->getLabel());
439
    }
440
441
    /**
442
     * @param AbstractLabelRemoved $labelRemoved
443
     */
444
    protected function applyLabelRemoved(AbstractLabelRemoved $labelRemoved)
445
    {
446
        $this->labels = $this->labels->without($labelRemoved->getLabel());
447
    }
448
449
    /**
450
     * @param AbstractThemeUpdated $themeUpdated
451
     */
452
    protected function applyThemeUpdated(AbstractThemeUpdated $themeUpdated)
453
    {
454
        $this->themeId = $themeUpdated->getTheme()->getId();
455
    }
456
457
    /**
458
     * @param AbstractTypeUpdated $themeUpdated
459
     */
460
    protected function applyTypeUpdated(AbstractTypeUpdated $themeUpdated)
461
    {
462
        $this->typeId = $themeUpdated->getType()->getId();
463
    }
464
465
    protected function applyDescriptionUpdated(AbstractDescriptionUpdated $descriptionUpdated)
466
    {
467
        $mainLanguageCode = $this->mainLanguage->getCode();
468
        $this->descriptions[$mainLanguageCode] = new Description($descriptionUpdated->getDescription());
469
    }
470
471
    protected function applyDescriptionTranslated(AbstractDescriptionTranslated $descriptionTranslated)
472
    {
473
        $languageCode = $descriptionTranslated->getLanguage()->getCode();
474
        $this->descriptions[$languageCode] = $descriptionTranslated->getDescription();
475
    }
476
477
    /**
478
     * Add a new image.
479
     *
480
     * @param Image $image
481
     */
482
    public function addImage(Image $image)
483
    {
484
        if (!$this->images->contains($image)) {
485
            $this->apply(
486
                $this->createImageAddedEvent($image)
487
            );
488
        }
489
    }
490
491
    /**
492
     * @param AbstractUpdateImage $updateImageCommand
493
     */
494
    public function updateImage(AbstractUpdateImage $updateImageCommand)
495
    {
496
        if ($this->images->findImageByUUID($updateImageCommand->getMediaObjectId())) {
497
            $this->apply(
498
                $this->createImageUpdatedEvent($updateImageCommand)
499
            );
500
        }
501
    }
502
503
    /**
504
     * Remove an image.
505
     *
506
     * @param Image $image
507
     */
508
    public function removeImage(Image $image)
509
    {
510
        if ($this->images->contains($image)) {
511
            $this->apply(
512
                $this->createImageRemovedEvent($image)
513
            );
514
        }
515
    }
516
517
    /**
518
     * Make an existing image of the item the main image.
519
     *
520
     * @param Image $image
521
     */
522
    public function selectMainImage(Image $image)
523
    {
524
        if (!$this->images->contains($image)) {
525
            throw new \InvalidArgumentException('You can not select a random image to be main, it has to be added to the item.');
526
        }
527
528
        $oldMainImage = $this->images->getMain();
529
530
        if (!isset($oldMainImage) || $oldMainImage->getMediaObjectId() !== $image->getMediaObjectId()) {
531
            $this->apply(
532
                $this->createMainImageSelectedEvent($image)
533
            );
534
        }
535
    }
536
537
    /**
538
     * Delete the offer.
539
     */
540
    public function delete()
541
    {
542
        $this->apply(
543
            $this->createOfferDeletedEvent()
544
        );
545
    }
546
547
    /**
548
     * @param CultureFeed_Cdb_Item_Base $cdbItem
549
     */
550
    protected function importWorkflowStatus(CultureFeed_Cdb_Item_Base $cdbItem)
551
    {
552
        try {
553
            $workflowStatus = WorkflowStatus::fromNative($cdbItem->getWfStatus());
554
        } catch (\InvalidArgumentException $exception) {
555
            $workflowStatus = WorkflowStatus::READY_FOR_VALIDATION();
556
        }
557
        $this->workflowStatus = $workflowStatus;
558
    }
559
560
    /**
561
     * Publish the offer when it has workflowstatus draft.
562
     * @param \DateTimeInterface $publicationDate
563
     */
564
    public function publish(\DateTimeInterface $publicationDate)
565
    {
566
        $this->guardPublish() ?: $this->apply(
567
            $this->createPublishedEvent($publicationDate)
568
        );
569
    }
570
571
    /**
572
     * @return bool
573
     * @throws Exception
574
     */
575 View Code Duplication
    private function guardPublish()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
576
    {
577
        if ($this->workflowStatus === WorkflowStatus::READY_FOR_VALIDATION()) {
578
            return true; // nothing left to do if the offer has already been published
579
        }
580
581
        if ($this->workflowStatus !== WorkflowStatus::DRAFT()) {
582
            throw new Exception('You can not publish an offer that is not draft');
583
        }
584
585
        return false;
586
    }
587
588
    /**
589
     * Approve the offer when it's waiting for validation.
590
     */
591
    public function approve()
592
    {
593
        $this->guardApprove() ?: $this->apply($this->createApprovedEvent());
594
    }
595
596
    /**
597
     * @return bool
598
     * @throws Exception
599
     */
600 View Code Duplication
    private function guardApprove()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
601
    {
602
        if ($this->workflowStatus === WorkflowStatus::APPROVED()) {
603
            return true; // nothing left to do if the offer has already been approved
604
        }
605
606
        if ($this->workflowStatus !== WorkflowStatus::READY_FOR_VALIDATION()) {
607
            throw new Exception('You can not approve an offer that is not ready for validation');
608
        }
609
610
        return false;
611
    }
612
613
    /**
614
     * Reject an offer that is waiting for validation with a given reason.
615
     * @param StringLiteral $reason
616
     */
617
    public function reject(StringLiteral $reason)
618
    {
619
        $this->guardRejection($reason) ?: $this->apply($this->createRejectedEvent($reason));
620
    }
621
622
    public function flagAsDuplicate()
623
    {
624
        $reason = new StringLiteral(self::DUPLICATE_REASON);
625
        $this->guardRejection($reason) ?: $this->apply($this->createFlaggedAsDuplicate());
626
    }
627
628
    public function flagAsInappropriate()
629
    {
630
        $reason = new StringLiteral(self::INAPPROPRIATE_REASON);
631
        $this->guardRejection($reason) ?: $this->apply($this->createFlaggedAsInappropriate());
632
    }
633
634
    /**
635
     * @param StringLiteral $reason
636
     * @return bool
637
     *  false when the offer can still be rejected, true when the offer is already rejected for the same reason
638
     * @throws Exception
639
     */
640
    private function guardRejection(StringLiteral $reason)
641
    {
642
        if ($this->workflowStatus === WorkflowStatus::REJECTED()) {
643
            if ($this->rejectedReason && $reason->sameValueAs($this->rejectedReason)) {
644
                return true; // nothing left to do if the offer has already been rejected for the same reason
645
            } else {
646
                throw new Exception('The offer has already been rejected for another reason: ' . $this->rejectedReason);
647
            }
648
        }
649
650
        if ($this->workflowStatus !== WorkflowStatus::READY_FOR_VALIDATION()) {
651
            throw new Exception('You can not reject an offer that is not ready for validation');
652
        }
653
654
        return false;
655
    }
656
657
    /**
658
     * @param Title $title
659
     * @param Language $language
660
     * @return bool
661
     */
662 View Code Duplication
    private function isTitleChanged(Title $title, Language $language)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
663
    {
664
        $languageCode = $language->getCode();
665
666
        return !isset($this->titles[$languageCode]) ||
667
            !$title->sameValueAs($this->titles[$languageCode]);
668
    }
669
670
    /**
671
     * @param Description $description
672
     * @param Language $language
673
     * @return bool
674
     */
675 View Code Duplication
    private function isDescriptionChanged(Description $description, Language $language)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
676
    {
677
        $languageCode = $language->getCode();
678
679
        return !isset($this->descriptions[$languageCode]) ||
680
            !$description->sameValueAs($this->descriptions[$languageCode]);
681
    }
682
683
    /**
684
     * Overwrites or resets the main image and all media objects
685
     * by importing a new collection of images from UDB2.
686
     *
687
     * @param ImageCollection $images
688
     */
689
    public function importImagesFromUDB2(ImageCollection $images)
690
    {
691
        $this->apply($this->createImagesImportedFromUDB2($images));
692
    }
693
694
    /**
695
     * Overwrites or resets the main image and all media objects
696
     * by updating with a new collection of images from UDB2.
697
     *
698
     * @param ImageCollection $images
699
     */
700
    public function updateImagesFromUDB2(ImageCollection $images)
701
    {
702
        $this->apply($this->createImagesUpdatedFromUDB2($images));
703
    }
704
705
    /**
706
     * @param AbstractPublished $published
707
     */
708
    protected function applyPublished(AbstractPublished $published)
0 ignored issues
show
Unused Code introduced by
The parameter $published 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...
709
    {
710
        $this->workflowStatus = WorkflowStatus::READY_FOR_VALIDATION();
711
    }
712
713
    /**
714
     * @param AbstractApproved $approved
715
     */
716
    protected function applyApproved(AbstractApproved $approved)
0 ignored issues
show
Unused Code introduced by
The parameter $approved 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...
717
    {
718
        $this->workflowStatus = WorkflowStatus::APPROVED();
719
    }
720
721
    /**
722
     * @param AbstractRejected $rejected
723
     */
724
    protected function applyRejected(AbstractRejected $rejected)
725
    {
726
        $this->rejectedReason = $rejected->getReason();
727
        $this->workflowStatus = WorkflowStatus::REJECTED();
728
    }
729
730
    /**
731
     * @param AbstractFlaggedAsDuplicate $flaggedAsDuplicate
732
     */
733
    protected function applyFlaggedAsDuplicate(AbstractFlaggedAsDuplicate $flaggedAsDuplicate)
0 ignored issues
show
Unused Code introduced by
The parameter $flaggedAsDuplicate 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...
734
    {
735
        $this->rejectedReason = new StringLiteral(self::DUPLICATE_REASON);
736
        $this->workflowStatus = WorkflowStatus::REJECTED();
737
    }
738
739
    /**
740
     * @param AbstractFlaggedAsInappropriate $flaggedAsInappropriate
741
     */
742
    protected function applyFlaggedAsInappropriate(AbstractFlaggedAsInappropriate $flaggedAsInappropriate)
0 ignored issues
show
Unused Code introduced by
The parameter $flaggedAsInappropriate 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...
743
    {
744
        $this->rejectedReason = new StringLiteral(self::INAPPROPRIATE_REASON);
745
        $this->workflowStatus = WorkflowStatus::REJECTED();
746
    }
747
748
    protected function applyImageAdded(AbstractImageAdded $imageAdded)
749
    {
750
        $this->images = $this->images->with($imageAdded->getImage());
751
    }
752
753
    protected function applyImageRemoved(AbstractImageRemoved $imageRemoved)
754
    {
755
        $this->images = $this->images->without($imageRemoved->getImage());
756
    }
757
758
    protected function applyMainImageSelected(AbstractMainImageSelected $mainImageSelected)
759
    {
760
        $this->images = $this->images->withMain($mainImageSelected->getImage());
761
    }
762
763
    protected function applyOrganizerUpdated(AbstractOrganizerUpdated $organizerUpdated)
764
    {
765
        $this->organizerId = $organizerUpdated->getOrganizerId();
766
    }
767
768
    protected function applyOrganizerDeleted(AbstractOrganizerDeleted $organizerDeleted)
0 ignored issues
show
Unused Code introduced by
The parameter $organizerDeleted 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...
769
    {
770
        $this->organizerId = null;
771
    }
772
773
    /**
774
     * @param AbstractImagesImportedFromUDB2 $imagesImportedFromUDB2
775
     */
776
    protected function applyImagesImportedFromUDB2(AbstractImagesImportedFromUDB2 $imagesImportedFromUDB2)
777
    {
778
        $this->applyUdb2ImagesEvent($imagesImportedFromUDB2);
779
    }
780
781
    /**
782
     * @param AbstractImagesUpdatedFromUDB2 $imagesUpdatedFromUDB2
783
     */
784
    protected function applyImagesUpdatedFromUDB2(AbstractImagesUpdatedFromUDB2 $imagesUpdatedFromUDB2)
785
    {
786
        $this->applyUdb2ImagesEvent($imagesUpdatedFromUDB2);
787
    }
788
789
    /**
790
     * This indirect apply method can be called internally to deal with images coming from UDB2.
791
     * Imports from UDB2 only contain the native Dutch content.
792
     * @see https://github.com/cultuurnet/udb3-udb2-bridge/blob/db0a7ab2444f55bb3faae3d59b82b39aaeba253b/test/Media/ImageCollectionFactoryTest.php#L79-L103
793
     * Because of this we have to make sure translated images are left in place.
794
     *
795
     * @param AbstractImagesEvent $imagesEvent
796
     */
797
    protected function applyUdb2ImagesEvent(AbstractImagesEvent $imagesEvent)
798
    {
799
        $newMainImage = $imagesEvent->getImages()->getMain();
800
        $dutchImagesList = $imagesEvent->getImages()->toArray();
801
        $translatedImagesList = array_filter(
802
            $this->images->toArray(),
803
            function (Image $image) {
804
                return $image->getLanguage()->getCode() !== 'nl';
805
            }
806
        );
807
808
        $imagesList = array_merge($dutchImagesList, $translatedImagesList);
809
        $images = ImageCollection::fromArray($imagesList);
810
811
        $this->images = isset($newMainImage) ? $images->withMain($newMainImage) : $images;
812
    }
813
814
    /**
815
     * @param Label $label
816
     * @return AbstractLabelAdded
817
     */
818
    abstract protected function createLabelAddedEvent(Label $label);
819
820
    /**
821
     * @param Label $label
822
     * @return AbstractLabelRemoved
823
     */
824
    abstract protected function createLabelRemovedEvent(Label $label);
825
826
    /**
827
     * @param Language $language
828
     * @param StringLiteral $title
829
     * @return AbstractTitleTranslated
830
     */
831
    abstract protected function createTitleTranslatedEvent(Language $language, StringLiteral $title);
832
833
    /**
834
     * @param Language $language
835
     * @param StringLiteral $description
836
     * @return AbstractDescriptionTranslated
837
     */
838
    abstract protected function createDescriptionTranslatedEvent(Language $language, StringLiteral $description);
839
840
    /**
841
     * @param Image $image
842
     * @return AbstractImageAdded
843
     */
844
    abstract protected function createImageAddedEvent(Image $image);
845
846
    /**
847
     * @param Image $image
848
     * @return AbstractImageRemoved
849
     */
850
    abstract protected function createImageRemovedEvent(Image $image);
851
852
    /**
853
     * @param AbstractUpdateImage $updateImageCommand
854
     * @return AbstractImageUpdated
855
     */
856
    abstract protected function createImageUpdatedEvent(
857
        AbstractUpdateImage $updateImageCommand
858
    );
859
860
    /**
861
     * @param Image $image
862
     * @return AbstractMainImageSelected
863
     */
864
    abstract protected function createMainImageSelectedEvent(Image $image);
865
866
    /**
867
     * @return AbstractOfferDeleted
868
     */
869
    abstract protected function createOfferDeletedEvent();
870
871
    /**
872
     * @param Title $title
873
     * @return AbstractTitleUpdated
874
     */
875
    abstract protected function createTitleUpdatedEvent(Title $title);
876
877
    /**
878
     * @param string $description
879
     * @return AbstractDescriptionUpdated
880
     */
881
    abstract protected function createDescriptionUpdatedEvent($description);
882
883
    /**
884
     * @param Calendar $calendar
885
     * @return AbstractCalendarUpdated
886
     */
887
    abstract protected function createCalendarUpdatedEvent(Calendar $calendar);
888
889
    /**
890
     * @param string $typicalAgeRange
891
     * @return AbstractTypicalAgeRangeUpdated
892
     */
893
    abstract protected function createTypicalAgeRangeUpdatedEvent($typicalAgeRange);
894
895
    /**
896
     * @return AbstractTypicalAgeRangeDeleted
897
     */
898
    abstract protected function createTypicalAgeRangeDeletedEvent();
899
900
    /**
901
     * @param string $organizerId
902
     * @return AbstractOrganizerUpdated
903
     */
904
    abstract protected function createOrganizerUpdatedEvent($organizerId);
905
906
    /**
907
     * @param string $organizerId
908
     * @return AbstractOrganizerDeleted
909
     */
910
    abstract protected function createOrganizerDeletedEvent($organizerId);
911
912
    /**
913
     * @param ContactPoint $contactPoint
914
     * @return AbstractContactPointUpdated
915
     */
916
    abstract protected function createContactPointUpdatedEvent(ContactPoint $contactPoint);
917
918
    /**
919
     * @param Coordinates $coordinates
920
     * @return AbstractGeoCoordinatesUpdated
921
     */
922
    abstract protected function createGeoCoordinatesUpdatedEvent(Coordinates $coordinates);
923
924
    /**
925
     * @param BookingInfo $bookingInfo
926
     * @return AbstractBookingInfoUpdated
927
     */
928
    abstract protected function createBookingInfoUpdatedEvent(BookingInfo $bookingInfo);
929
930
    /**
931
     * @param PriceInfo $priceInfo
932
     * @return AbstractPriceInfoUpdated
933
     */
934
    abstract protected function createPriceInfoUpdatedEvent(PriceInfo $priceInfo);
935
936
    /**
937
     * @param \DateTimeInterface $publicationDate
938
     * @return AbstractPublished
939
     */
940
    abstract protected function createPublishedEvent(\DateTimeInterface $publicationDate);
941
942
    /**
943
     * @return AbstractApproved
944
     */
945
    abstract protected function createApprovedEvent();
946
947
    /**
948
     * @param StringLiteral $reason
949
     * @return AbstractRejected
950
     */
951
    abstract protected function createRejectedEvent(StringLiteral $reason);
952
953
    /**
954
     * @return AbstractFlaggedAsDuplicate
955
     */
956
    abstract protected function createFlaggedAsDuplicate();
957
958
    /**
959
     * @return AbstractFlaggedAsInappropriate
960
     */
961
    abstract protected function createFlaggedAsInappropriate();
962
963
    /**
964
     * @param ImageCollection $images
965
     * @return AbstractImagesImportedFromUDB2
966
     */
967
    abstract protected function createImagesImportedFromUDB2(ImageCollection $images);
968
969
    /**
970
     * @param ImageCollection $images
971
     * @return AbstractImagesUpdatedFromUDB2
972
     */
973
    abstract protected function createImagesUpdatedFromUDB2(ImageCollection $images);
974
975
    /**
976
     * @param EventType $type
977
     * @return AbstractTypeUpdated
978
     */
979
    abstract protected function createTypeUpdatedEvent(EventType $type);
980
981
    /**
982
     * @param Theme $theme
983
     * @return AbstractThemeUpdated
984
     */
985
    abstract protected function createThemeUpdatedEvent(Theme $theme);
986
987
    /**
988
     * @param array $facilities
989
     * @return AbstractFacilitiesUpdated
990
     */
991
    abstract protected function createFacilitiesUpdatedEvent(array $facilities);
992
}
993