Completed
Push — master ( 96a58d...53a723 )
by Luc
11s
created

Offer::applyDescriptionTranslated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
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\Media\Properties\CopyrightHolder;
20
use \CultuurNet\UDB3\Media\Properties\Description as ImageDescription;
21
use CultuurNet\UDB3\Offer\Commands\Image\AbstractUpdateImage;
22
use CultuurNet\UDB3\Language;
23
use CultuurNet\UDB3\Offer\Events\AbstractBookingInfoUpdated;
24
use CultuurNet\UDB3\Offer\Events\AbstractCalendarUpdated;
25
use CultuurNet\UDB3\Offer\Events\AbstractContactPointUpdated;
26
use CultuurNet\UDB3\Offer\Events\AbstractFacilitiesUpdated;
27
use CultuurNet\UDB3\Offer\Events\AbstractGeoCoordinatesUpdated;
28
use CultuurNet\UDB3\Offer\Events\AbstractThemeUpdated;
29
use CultuurNet\UDB3\Offer\Events\AbstractTitleTranslated;
30
use CultuurNet\UDB3\Offer\Events\AbstractTitleUpdated;
31
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionTranslated;
32
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionUpdated;
33
use CultuurNet\UDB3\Offer\Events\AbstractLabelAdded;
34
use CultuurNet\UDB3\Offer\Events\AbstractLabelRemoved;
35
use CultuurNet\UDB3\Offer\Events\AbstractOfferDeleted;
36
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerDeleted;
37
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerUpdated;
38
use CultuurNet\UDB3\Offer\Events\AbstractPriceInfoUpdated;
39
use CultuurNet\UDB3\Offer\Events\AbstractTypeUpdated;
40
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeDeleted;
41
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeUpdated;
42
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageAdded;
43
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageRemoved;
44
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesEvent;
45
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesImportedFromUDB2;
46
use CultuurNet\UDB3\Offer\Events\Image\AbstractImagesUpdatedFromUDB2;
47
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageUpdated;
48
use CultuurNet\UDB3\Offer\Events\Image\AbstractMainImageSelected;
49
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractApproved;
50
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsDuplicate;
51
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsInappropriate;
52
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractPublished;
53
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractRejected;
54
use CultuurNet\UDB3\PriceInfo\PriceInfo;
55
use CultuurNet\UDB3\Theme;
56
use CultuurNet\UDB3\Title;
57
use Exception;
58
use ValueObjects\Identity\UUID;
59
use ValueObjects\StringLiteral\StringLiteral;
60
61
abstract class Offer extends EventSourcedAggregateRoot implements LabelAwareAggregateRoot
62
{
63
    const DUPLICATE_REASON = 'duplicate';
64
    const INAPPROPRIATE_REASON = 'inappropriate';
65
66
    /**
67
     * @var LabelCollection
68
     */
69
    protected $labels;
70
71
    /**
72
     * @var ImageCollection
73
     */
74
    protected $images;
75
76
    /**
77
     * @var string
78
     *
79
     * Organizer ids can come from UDB2 which does not strictly use UUIDs.
80
     */
81
    protected $organizerId;
82
83
    /**
84
     * @var WorkflowStatus
85
     */
86
    protected $workflowStatus;
87
88
    /**
89
     * @var StringLiteral|null
90
     */
91
    protected $rejectedReason;
92
93
    /**
94
     * @var PriceInfo
95
     */
96
    protected $priceInfo;
97
98
    /**
99
     * @var StringLiteral[]
100
     */
101
    protected $titles;
102
103
    /**
104
     * @var Description[]
105
     */
106
    protected $descriptions;
107
108
    /**
109
     * @var Language
110
     */
111
    protected $mainLanguage;
112
113
    /**
114
     * @var string;
115
     */
116
    protected $typeId;
117
118
    /**
119
     * @var string;
120
     */
121
    protected $themeId;
122
123
    /**
124
     * @var array
125
     */
126
    protected $facilities;
127
128
    /**
129
     * @var ContactPoint
130
     */
131
    protected $contactPoint;
132
133
    /**
134
     * @var Calendar
135
     */
136
    protected $calendar;
137
138
    /**
139
     * @var AgeRange
140
     */
141
    protected $typicalAgeRange;
142
143
    /**
144
     * @var BookingInfo
145
     */
146
    protected $bookingInfo;
147
148
    /**
149
     * Offer constructor.
150
     */
151
    public function __construct()
152
    {
153
        $this->titles = [];
154
        $this->descriptions = [];
155
        $this->labels = new LabelCollection();
156
        $this->images = new ImageCollection();
157
        $this->facilities = [];
158
        $this->contactPoint = null;
159
        $this->calendar = null;
160
        $this->typicalAgeRange = null;
161
        $this->bookingInfo = null;
162
    }
163
164
    /**
165
     * @param EventType $type
166
     */
167
    public function updateType(EventType $type)
168
    {
169
        if (!$this->typeId || $this->typeId !== $type->getId()) {
170
            $this->apply($this->createTypeUpdatedEvent($type));
171
        }
172
    }
173
174
    /**
175
     * @param Theme $theme
176
     */
177
    public function updateTheme(Theme $theme)
178
    {
179
        if (!$this->themeId || $this->themeId !== $theme->getId()) {
180
            $this->apply($this->createThemeUpdatedEvent($theme));
181
        }
182
    }
183
184
    /**
185
     * @param array $facilities
186
     */
187
    public function updateFacilities(array $facilities)
188
    {
189
        if (empty($this->facilities) || !$this->sameFacilities($this->facilities, $facilities)) {
190
            $this->apply($this->createFacilitiesUpdatedEvent($facilities));
191
        }
192
    }
193
194
    /**
195
     * @param AbstractFacilitiesUpdated $facilitiesUpdated
196
     */
197
    protected function applyFacilitiesUpdated(AbstractFacilitiesUpdated $facilitiesUpdated)
198
    {
199
        $this->facilities = $facilitiesUpdated->getFacilities();
200
    }
201
202
    /**
203
     * @param array $facilities1
204
     * @param array $facilities2
205
     * @return bool
206
     */
207
    private function sameFacilities($facilities1, $facilities2)
208
    {
209
        if (count($facilities1) !== count($facilities2)) {
210
            return false;
211
        }
212
213
        $sameFacilities = array_uintersect(
214
            $facilities1,
215
            $facilities2,
216
            function (Facility $facility1, Facility $facility2) {
217
                return strcmp($facility1->getId(), $facility2->getId());
218
            }
219
        );
220
221
        return count($sameFacilities) === count($facilities2);
222
    }
223
224
    /**
225
     * Get the id of the main image if one is selected for this offer.
226
     *
227
     * @return UUID|null
228
     */
229
    protected function getMainImageId()
230
    {
231
        $mainImage = $this->images->getMain();
232
        return isset($mainImage) ? $mainImage->getMediaObjectId() : null;
233
    }
234
235
    /**
236
     * @inheritdoc
237
     */
238
    public function addLabel(Label $label)
239
    {
240
        if (!$this->labels->contains($label)) {
241
            $this->apply(
242
                $this->createLabelAddedEvent($label)
243
            );
244
        }
245
    }
246
247
    /**
248
     * @inheritdoc
249
     */
250
    public function removeLabel(Label $label)
251
    {
252
        if ($this->labels->contains($label)) {
253
            $this->apply(
254
                $this->createLabelRemovedEvent($label)
255
            );
256
        }
257
    }
258
259
    /**
260
     * @param Language $language
261
     * @param Title $title
262
     */
263
    public function updateTitle(Language $language, Title $title)
264
    {
265
        if ($this->isTitleChanged($title, $language)) {
266
            if ($language->getCode() !== $this->mainLanguage->getCode()) {
267
                $event = $this->createTitleTranslatedEvent($language, $title);
268
            } else {
269
                $event = $this->createTitleUpdatedEvent($title);
270
            }
271
272
            $this->apply($event);
273
        }
274
    }
275
276
    /**
277
     * @param Description $description
278
     * @param Language $language
279
     */
280
    public function updateDescription(Description $description, Language $language)
281
    {
282
        if ($this->isDescriptionChanged($description, $language)) {
283
            if ($language->getCode() !== $this->mainLanguage->getCode()) {
284
                $event = $this->createDescriptionTranslatedEvent($language, $description);
285
            } else {
286
                $event = $this->createDescriptionUpdatedEvent((string) $description);
287
            }
288
289
            $this->apply($event);
290
        }
291
    }
292
293
    /**
294
     * @param Calendar $calendar
295
     */
296
    public function updateCalendar(Calendar $calendar)
297
    {
298
        if (is_null($this->calendar) || !$this->calendar->sameAs($calendar)) {
299
            $this->apply(
300
                $this->createCalendarUpdatedEvent($calendar)
301
            );
302
        }
303
    }
304
305
    /**
306
     * @param AbstractCalendarUpdated $calendarUpdated
307
     */
308
    protected function applyCalendarUpdated(AbstractCalendarUpdated $calendarUpdated)
309
    {
310
        $this->calendar = $calendarUpdated->getCalendar();
311
    }
312
313
    /**
314
     * @param string $typicalAgeRange
315
     */
316
    public function updateTypicalAgeRange($typicalAgeRange)
317
    {
318
        $typicalAgeRangeUpdatedEvent = $this->createTypicalAgeRangeUpdatedEvent($typicalAgeRange);
319
320
        if (empty($this->typicalAgeRange) || !$this->typicalAgeRange->sameAs($typicalAgeRangeUpdatedEvent->getTypicalAgeRange())) {
321
            $this->apply($typicalAgeRangeUpdatedEvent);
322
        }
323
    }
324
325
    /**
326
     * @param AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated
327
     */
328
    protected function applyTypicalAgeRangeUpdated(AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated)
329
    {
330
        $this->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
331
    }
332
333
    public function deleteTypicalAgeRange()
334
    {
335
        if (!is_null($this->typicalAgeRange)) {
336
            $this->apply(
337
                $this->createTypicalAgeRangeDeletedEvent()
338
            );
339
        }
340
    }
341
342
    /**
343
     * @param AbstractTypicalAgeRangeDeleted $typicalAgeRangeDeleted
344
     */
345
    public 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...
346
    {
347
        $this->typicalAgeRange = null;
348
    }
349
350
    /**
351
     * @param string $organizerId
352
     */
353
    public function updateOrganizer($organizerId)
354
    {
355
        if ($this->organizerId !== $organizerId) {
356
            $this->apply(
357
                $this->createOrganizerUpdatedEvent($organizerId)
358
            );
359
        }
360
    }
361
362
    /**
363
     * Delete the given organizer.
364
     *
365
     * @param string $organizerId
366
     */
367
    public function deleteOrganizer($organizerId)
368
    {
369
        if ($this->organizerId === $organizerId) {
370
            $this->apply(
371
                $this->createOrganizerDeletedEvent($organizerId)
372
            );
373
        }
374
    }
375
376
    /**
377
     * Updated the contact info.
378
     * @param ContactPoint $contactPoint
379
     */
380
    public function updateContactPoint(ContactPoint $contactPoint)
381
    {
382
        if (is_null($this->contactPoint) || !$this->contactPoint->sameAs($contactPoint)) {
383
            $this->apply(
384
                $this->createContactPointUpdatedEvent($contactPoint)
385
            );
386
        }
387
    }
388
389
    /**
390
     * @param AbstractContactPointUpdated $contactPointUpdated
391
     */
392
    protected function applyContactPointUpdated(AbstractContactPointUpdated $contactPointUpdated)
393
    {
394
        $this->contactPoint = $contactPointUpdated->getContactPoint();
395
    }
396
397
    /**
398
     * @param Coordinates $coordinates
399
     */
400
    public function updateGeoCoordinates(Coordinates $coordinates)
401
    {
402
        // Note: DON'T compare to previous coordinates and apply only on
403
        // changes. Various projectors expect GeoCoordinatesUpdated after
404
        // MajorInfoUpdated and PlaceUpdatedFromUDB2, even if the address
405
        // and thus the coordinates haven't actually changed.
406
        $this->apply(
407
            $this->createGeoCoordinatesUpdatedEvent($coordinates)
408
        );
409
    }
410
411
    /**
412
     * Updated the booking info.
413
     *
414
     * @param BookingInfo $bookingInfo
415
     */
416
    public function updateBookingInfo(BookingInfo $bookingInfo)
417
    {
418
        if (is_null($this->bookingInfo) || !$this->bookingInfo->sameAs($bookingInfo)) {
419
            $this->apply(
420
                $this->createBookingInfoUpdatedEvent($bookingInfo)
421
            );
422
        }
423
    }
424
425
    /**
426
     * @param AbstractBookingInfoUpdated $bookingInfoUpdated
427
     */
428
    public function applyBookingInfoUpdated(AbstractBookingInfoUpdated $bookingInfoUpdated)
429
    {
430
        $this->bookingInfo = $bookingInfoUpdated->getBookingInfo();
431
    }
432
433
    /**
434
     * @param PriceInfo $priceInfo
435
     */
436
    public function updatePriceInfo(PriceInfo $priceInfo)
437
    {
438
        if (is_null($this->priceInfo) || $priceInfo->serialize() !== $this->priceInfo->serialize()) {
439
            $this->apply(
440
                $this->createPriceInfoUpdatedEvent($priceInfo)
441
            );
442
        }
443
    }
444
445
    /**
446
     * @param AbstractPriceInfoUpdated $priceInfoUpdated
447
     */
448
    protected function applyPriceInfoUpdated(AbstractPriceInfoUpdated $priceInfoUpdated)
449
    {
450
        $this->priceInfo = $priceInfoUpdated->getPriceInfo();
451
    }
452
453
    /**
454
     * @param AbstractLabelAdded $labelAdded
455
     */
456
    protected function applyLabelAdded(AbstractLabelAdded $labelAdded)
457
    {
458
        $this->labels = $this->labels->with($labelAdded->getLabel());
459
    }
460
461
    /**
462
     * @param AbstractLabelRemoved $labelRemoved
463
     */
464
    protected function applyLabelRemoved(AbstractLabelRemoved $labelRemoved)
465
    {
466
        $this->labels = $this->labels->without($labelRemoved->getLabel());
467
    }
468
469
    /**
470
     * @param AbstractThemeUpdated $themeUpdated
471
     */
472
    protected function applyThemeUpdated(AbstractThemeUpdated $themeUpdated)
473
    {
474
        $this->themeId = $themeUpdated->getTheme()->getId();
475
    }
476
477
    /**
478
     * @param AbstractTypeUpdated $themeUpdated
479
     */
480
    protected function applyTypeUpdated(AbstractTypeUpdated $themeUpdated)
481
    {
482
        $this->typeId = $themeUpdated->getType()->getId();
483
    }
484
485
    protected function applyDescriptionUpdated(AbstractDescriptionUpdated $descriptionUpdated)
486
    {
487
        $mainLanguageCode = $this->mainLanguage->getCode();
488
        $this->descriptions[$mainLanguageCode] = new Description($descriptionUpdated->getDescription());
489
    }
490
491
    protected function applyDescriptionTranslated(AbstractDescriptionTranslated $descriptionTranslated)
492
    {
493
        $languageCode = $descriptionTranslated->getLanguage()->getCode();
494
        $this->descriptions[$languageCode] = $descriptionTranslated->getDescription();
495
    }
496
497
    /**
498
     * Add a new image.
499
     *
500
     * @param Image $image
501
     */
502
    public function addImage(Image $image)
503
    {
504
        if (!$this->images->contains($image)) {
505
            $this->apply(
506
                $this->createImageAddedEvent($image)
507
            );
508
        }
509
    }
510
511
    /**
512
     * @param AbstractUpdateImage $updateImageCommand
513
     */
514
    public function updateImage(AbstractUpdateImage $updateImageCommand)
515
    {
516
        if ($this->updateImageAllowed($updateImageCommand)) {
517
            $this->apply(
518
                $this->createImageUpdatedEvent($updateImageCommand)
519
            );
520
        }
521
    }
522
523
    /**
524
     * @param AbstractUpdateImage $updateImageCommand
525
     * @return bool
526
     */
527
    private function updateImageAllowed(AbstractUpdateImage $updateImageCommand)
528
    {
529
        $image = $this->images->findImageByUUID($updateImageCommand->getMediaObjectId());
530
531
        // Don't update if the image is not found based on UUID.
532
        if (!$image) {
533
            return false;
534
        }
535
536
        // Update when copyright or description is changed.
537
        return !$updateImageCommand->getCopyrightHolder()->sameValueAs($image->getCopyrightHolder()) ||
538
            !$updateImageCommand->getDescription()->sameValueAs($image->getDescription());
539
    }
540
541
    /**
542
     * Remove an image.
543
     *
544
     * @param Image $image
545
     */
546
    public function removeImage(Image $image)
547
    {
548
        if ($this->images->contains($image)) {
549
            $this->apply(
550
                $this->createImageRemovedEvent($image)
551
            );
552
        }
553
    }
554
555
    /**
556
     * Make an existing image of the item the main image.
557
     *
558
     * @param Image $image
559
     */
560
    public function selectMainImage(Image $image)
561
    {
562
        if (!$this->images->contains($image)) {
563
            throw new \InvalidArgumentException('You can not select a random image to be main, it has to be added to the item.');
564
        }
565
566
        $oldMainImage = $this->images->getMain();
567
568
        if (!isset($oldMainImage) || $oldMainImage->getMediaObjectId() !== $image->getMediaObjectId()) {
569
            $this->apply(
570
                $this->createMainImageSelectedEvent($image)
571
            );
572
        }
573
    }
574
575
    /**
576
     * Delete the offer.
577
     */
578
    public function delete()
579
    {
580
        $this->apply(
581
            $this->createOfferDeletedEvent()
582
        );
583
    }
584
585
    /**
586
     * @param CultureFeed_Cdb_Item_Base $cdbItem
587
     */
588
    protected function importWorkflowStatus(CultureFeed_Cdb_Item_Base $cdbItem)
589
    {
590
        try {
591
            $workflowStatus = WorkflowStatus::fromNative($cdbItem->getWfStatus());
592
        } catch (\InvalidArgumentException $exception) {
593
            $workflowStatus = WorkflowStatus::READY_FOR_VALIDATION();
594
        }
595
        $this->workflowStatus = $workflowStatus;
596
    }
597
598
    /**
599
     * Publish the offer when it has workflowstatus draft.
600
     * @param \DateTimeInterface $publicationDate
601
     */
602
    public function publish(\DateTimeInterface $publicationDate)
603
    {
604
        $this->guardPublish() ?: $this->apply(
605
            $this->createPublishedEvent($publicationDate)
606
        );
607
    }
608
609
    /**
610
     * @return bool
611
     * @throws Exception
612
     */
613 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...
614
    {
615
        if ($this->workflowStatus === WorkflowStatus::READY_FOR_VALIDATION()) {
616
            return true; // nothing left to do if the offer has already been published
617
        }
618
619
        if ($this->workflowStatus !== WorkflowStatus::DRAFT()) {
620
            throw new Exception('You can not publish an offer that is not draft');
621
        }
622
623
        return false;
624
    }
625
626
    /**
627
     * Approve the offer when it's waiting for validation.
628
     */
629
    public function approve()
630
    {
631
        $this->guardApprove() ?: $this->apply($this->createApprovedEvent());
632
    }
633
634
    /**
635
     * @return bool
636
     * @throws Exception
637
     */
638 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...
639
    {
640
        if ($this->workflowStatus === WorkflowStatus::APPROVED()) {
641
            return true; // nothing left to do if the offer has already been approved
642
        }
643
644
        if ($this->workflowStatus !== WorkflowStatus::READY_FOR_VALIDATION()) {
645
            throw new Exception('You can not approve an offer that is not ready for validation');
646
        }
647
648
        return false;
649
    }
650
651
    /**
652
     * Reject an offer that is waiting for validation with a given reason.
653
     * @param StringLiteral $reason
654
     */
655
    public function reject(StringLiteral $reason)
656
    {
657
        $this->guardRejection($reason) ?: $this->apply($this->createRejectedEvent($reason));
658
    }
659
660
    public function flagAsDuplicate()
661
    {
662
        $reason = new StringLiteral(self::DUPLICATE_REASON);
663
        $this->guardRejection($reason) ?: $this->apply($this->createFlaggedAsDuplicate());
664
    }
665
666
    public function flagAsInappropriate()
667
    {
668
        $reason = new StringLiteral(self::INAPPROPRIATE_REASON);
669
        $this->guardRejection($reason) ?: $this->apply($this->createFlaggedAsInappropriate());
670
    }
671
672
    /**
673
     * @param StringLiteral $reason
674
     * @return bool
675
     *  false when the offer can still be rejected, true when the offer is already rejected for the same reason
676
     * @throws Exception
677
     */
678
    private function guardRejection(StringLiteral $reason)
679
    {
680
        if ($this->workflowStatus === WorkflowStatus::REJECTED()) {
681
            if ($this->rejectedReason && $reason->sameValueAs($this->rejectedReason)) {
682
                return true; // nothing left to do if the offer has already been rejected for the same reason
683
            } else {
684
                throw new Exception('The offer has already been rejected for another reason: ' . $this->rejectedReason);
685
            }
686
        }
687
688
        if ($this->workflowStatus !== WorkflowStatus::READY_FOR_VALIDATION()) {
689
            throw new Exception('You can not reject an offer that is not ready for validation');
690
        }
691
692
        return false;
693
    }
694
695
    /**
696
     * @param Title $title
697
     * @param Language $language
698
     * @return bool
699
     */
700 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...
701
    {
702
        $languageCode = $language->getCode();
703
704
        return !isset($this->titles[$languageCode]) ||
705
            !$title->sameValueAs($this->titles[$languageCode]);
706
    }
707
708
    /**
709
     * @param Description $description
710
     * @param Language $language
711
     * @return bool
712
     */
713 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...
714
    {
715
        $languageCode = $language->getCode();
716
717
        return !isset($this->descriptions[$languageCode]) ||
718
            !$description->sameValueAs($this->descriptions[$languageCode]);
719
    }
720
721
    /**
722
     * Overwrites or resets the main image and all media objects
723
     * by importing a new collection of images from UDB2.
724
     *
725
     * @param ImageCollection $images
726
     */
727
    public function importImagesFromUDB2(ImageCollection $images)
728
    {
729
        $this->apply($this->createImagesImportedFromUDB2($images));
730
    }
731
732
    /**
733
     * Overwrites or resets the main image and all media objects
734
     * by updating with a new collection of images from UDB2.
735
     *
736
     * @param ImageCollection $images
737
     */
738
    public function updateImagesFromUDB2(ImageCollection $images)
739
    {
740
        $this->apply($this->createImagesUpdatedFromUDB2($images));
741
    }
742
743
    /**
744
     * @param AbstractPublished $published
745
     */
746
    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...
747
    {
748
        $this->workflowStatus = WorkflowStatus::READY_FOR_VALIDATION();
749
    }
750
751
    /**
752
     * @param AbstractApproved $approved
753
     */
754
    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...
755
    {
756
        $this->workflowStatus = WorkflowStatus::APPROVED();
757
    }
758
759
    /**
760
     * @param AbstractRejected $rejected
761
     */
762
    protected function applyRejected(AbstractRejected $rejected)
763
    {
764
        $this->rejectedReason = $rejected->getReason();
765
        $this->workflowStatus = WorkflowStatus::REJECTED();
766
    }
767
768
    /**
769
     * @param AbstractFlaggedAsDuplicate $flaggedAsDuplicate
770
     */
771
    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...
772
    {
773
        $this->rejectedReason = new StringLiteral(self::DUPLICATE_REASON);
774
        $this->workflowStatus = WorkflowStatus::REJECTED();
775
    }
776
777
    /**
778
     * @param AbstractFlaggedAsInappropriate $flaggedAsInappropriate
779
     */
780
    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...
781
    {
782
        $this->rejectedReason = new StringLiteral(self::INAPPROPRIATE_REASON);
783
        $this->workflowStatus = WorkflowStatus::REJECTED();
784
    }
785
786
    protected function applyImageAdded(AbstractImageAdded $imageAdded)
787
    {
788
        $this->images = $this->images->with($imageAdded->getImage());
789
    }
790
791
    protected function applyImageUpdated(AbstractImageUpdated $imageUpdated)
792
    {
793
        $image = $this->images->findImageByUUID($imageUpdated->getMediaObjectId());
794
795
        $updatedImage = new Image(
796
            $image->getMediaObjectId(),
797
            $image->getMimeType(),
798
            new ImageDescription($imageUpdated->getDescription()->toNative()),
799
            new CopyrightHolder($imageUpdated->getCopyrightHolder()->toNative()),
800
            $image->getSourceLocation(),
801
            $image->getLanguage()
802
        );
803
804
        // Currently no other option to update an item inside a collection.
805
        $this->images = $this->images->without($image);
806
        $this->images = $this->images->with($updatedImage);
807
    }
808
809
    protected function applyImageRemoved(AbstractImageRemoved $imageRemoved)
810
    {
811
        $this->images = $this->images->without($imageRemoved->getImage());
812
    }
813
814
    protected function applyMainImageSelected(AbstractMainImageSelected $mainImageSelected)
815
    {
816
        $this->images = $this->images->withMain($mainImageSelected->getImage());
817
    }
818
819
    protected function applyOrganizerUpdated(AbstractOrganizerUpdated $organizerUpdated)
820
    {
821
        $this->organizerId = $organizerUpdated->getOrganizerId();
822
    }
823
824
    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...
825
    {
826
        $this->organizerId = null;
827
    }
828
829
    /**
830
     * @param AbstractImagesImportedFromUDB2 $imagesImportedFromUDB2
831
     */
832
    protected function applyImagesImportedFromUDB2(AbstractImagesImportedFromUDB2 $imagesImportedFromUDB2)
833
    {
834
        $this->applyUdb2ImagesEvent($imagesImportedFromUDB2);
835
    }
836
837
    /**
838
     * @param AbstractImagesUpdatedFromUDB2 $imagesUpdatedFromUDB2
839
     */
840
    protected function applyImagesUpdatedFromUDB2(AbstractImagesUpdatedFromUDB2 $imagesUpdatedFromUDB2)
841
    {
842
        $this->applyUdb2ImagesEvent($imagesUpdatedFromUDB2);
843
    }
844
845
    /**
846
     * This indirect apply method can be called internally to deal with images coming from UDB2.
847
     * Imports from UDB2 only contain the native Dutch content.
848
     * @see https://github.com/cultuurnet/udb3-udb2-bridge/blob/db0a7ab2444f55bb3faae3d59b82b39aaeba253b/test/Media/ImageCollectionFactoryTest.php#L79-L103
849
     * Because of this we have to make sure translated images are left in place.
850
     *
851
     * @param AbstractImagesEvent $imagesEvent
852
     */
853
    protected function applyUdb2ImagesEvent(AbstractImagesEvent $imagesEvent)
854
    {
855
        $newMainImage = $imagesEvent->getImages()->getMain();
856
        $dutchImagesList = $imagesEvent->getImages()->toArray();
857
        $translatedImagesList = array_filter(
858
            $this->images->toArray(),
859
            function (Image $image) {
860
                return $image->getLanguage()->getCode() !== 'nl';
861
            }
862
        );
863
864
        $imagesList = array_merge($dutchImagesList, $translatedImagesList);
865
        $images = ImageCollection::fromArray($imagesList);
866
867
        $this->images = isset($newMainImage) ? $images->withMain($newMainImage) : $images;
868
    }
869
870
    /**
871
     * @param Label $label
872
     * @return AbstractLabelAdded
873
     */
874
    abstract protected function createLabelAddedEvent(Label $label);
875
876
    /**
877
     * @param Label $label
878
     * @return AbstractLabelRemoved
879
     */
880
    abstract protected function createLabelRemovedEvent(Label $label);
881
882
    /**
883
     * @param Language $language
884
     * @param StringLiteral $title
885
     * @return AbstractTitleTranslated
886
     */
887
    abstract protected function createTitleTranslatedEvent(Language $language, StringLiteral $title);
888
889
    /**
890
     * @param Language $language
891
     * @param StringLiteral $description
892
     * @return AbstractDescriptionTranslated
893
     */
894
    abstract protected function createDescriptionTranslatedEvent(Language $language, StringLiteral $description);
895
896
    /**
897
     * @param Image $image
898
     * @return AbstractImageAdded
899
     */
900
    abstract protected function createImageAddedEvent(Image $image);
901
902
    /**
903
     * @param Image $image
904
     * @return AbstractImageRemoved
905
     */
906
    abstract protected function createImageRemovedEvent(Image $image);
907
908
    /**
909
     * @param AbstractUpdateImage $updateImageCommand
910
     * @return AbstractImageUpdated
911
     */
912
    abstract protected function createImageUpdatedEvent(
913
        AbstractUpdateImage $updateImageCommand
914
    );
915
916
    /**
917
     * @param Image $image
918
     * @return AbstractMainImageSelected
919
     */
920
    abstract protected function createMainImageSelectedEvent(Image $image);
921
922
    /**
923
     * @return AbstractOfferDeleted
924
     */
925
    abstract protected function createOfferDeletedEvent();
926
927
    /**
928
     * @param Title $title
929
     * @return AbstractTitleUpdated
930
     */
931
    abstract protected function createTitleUpdatedEvent(Title $title);
932
933
    /**
934
     * @param string $description
935
     * @return AbstractDescriptionUpdated
936
     */
937
    abstract protected function createDescriptionUpdatedEvent($description);
938
939
    /**
940
     * @param Calendar $calendar
941
     * @return AbstractCalendarUpdated
942
     */
943
    abstract protected function createCalendarUpdatedEvent(Calendar $calendar);
944
945
    /**
946
     * @param string $typicalAgeRange
947
     * @return AbstractTypicalAgeRangeUpdated
948
     */
949
    abstract protected function createTypicalAgeRangeUpdatedEvent($typicalAgeRange);
950
951
    /**
952
     * @return AbstractTypicalAgeRangeDeleted
953
     */
954
    abstract protected function createTypicalAgeRangeDeletedEvent();
955
956
    /**
957
     * @param string $organizerId
958
     * @return AbstractOrganizerUpdated
959
     */
960
    abstract protected function createOrganizerUpdatedEvent($organizerId);
961
962
    /**
963
     * @param string $organizerId
964
     * @return AbstractOrganizerDeleted
965
     */
966
    abstract protected function createOrganizerDeletedEvent($organizerId);
967
968
    /**
969
     * @param ContactPoint $contactPoint
970
     * @return AbstractContactPointUpdated
971
     */
972
    abstract protected function createContactPointUpdatedEvent(ContactPoint $contactPoint);
973
974
    /**
975
     * @param Coordinates $coordinates
976
     * @return AbstractGeoCoordinatesUpdated
977
     */
978
    abstract protected function createGeoCoordinatesUpdatedEvent(Coordinates $coordinates);
979
980
    /**
981
     * @param BookingInfo $bookingInfo
982
     * @return AbstractBookingInfoUpdated
983
     */
984
    abstract protected function createBookingInfoUpdatedEvent(BookingInfo $bookingInfo);
985
986
    /**
987
     * @param PriceInfo $priceInfo
988
     * @return AbstractPriceInfoUpdated
989
     */
990
    abstract protected function createPriceInfoUpdatedEvent(PriceInfo $priceInfo);
991
992
    /**
993
     * @param \DateTimeInterface $publicationDate
994
     * @return AbstractPublished
995
     */
996
    abstract protected function createPublishedEvent(\DateTimeInterface $publicationDate);
997
998
    /**
999
     * @return AbstractApproved
1000
     */
1001
    abstract protected function createApprovedEvent();
1002
1003
    /**
1004
     * @param StringLiteral $reason
1005
     * @return AbstractRejected
1006
     */
1007
    abstract protected function createRejectedEvent(StringLiteral $reason);
1008
1009
    /**
1010
     * @return AbstractFlaggedAsDuplicate
1011
     */
1012
    abstract protected function createFlaggedAsDuplicate();
1013
1014
    /**
1015
     * @return AbstractFlaggedAsInappropriate
1016
     */
1017
    abstract protected function createFlaggedAsInappropriate();
1018
1019
    /**
1020
     * @param ImageCollection $images
1021
     * @return AbstractImagesImportedFromUDB2
1022
     */
1023
    abstract protected function createImagesImportedFromUDB2(ImageCollection $images);
1024
1025
    /**
1026
     * @param ImageCollection $images
1027
     * @return AbstractImagesUpdatedFromUDB2
1028
     */
1029
    abstract protected function createImagesUpdatedFromUDB2(ImageCollection $images);
1030
1031
    /**
1032
     * @param EventType $type
1033
     * @return AbstractTypeUpdated
1034
     */
1035
    abstract protected function createTypeUpdatedEvent(EventType $type);
1036
1037
    /**
1038
     * @param Theme $theme
1039
     * @return AbstractThemeUpdated
1040
     */
1041
    abstract protected function createThemeUpdatedEvent(Theme $theme);
1042
1043
    /**
1044
     * @param array $facilities
1045
     * @return AbstractFacilitiesUpdated
1046
     */
1047
    abstract protected function createFacilitiesUpdatedEvent(array $facilities);
1048
}
1049