Completed
Pull Request — master (#337)
by Luc
05:26
created

EventLDProjector::projectEventCdbXmlToObject()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 47
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 26
nc 8
nop 4
1
<?php
2
3
namespace CultuurNet\UDB3\Event\ReadModel\JSONLD;
4
5
use Broadway\Domain\DomainMessage;
6
use Broadway\Domain\Metadata;
7
use Broadway\EventHandling\EventListenerInterface;
8
use CultuurNet\UDB3\Cdb\EventItemFactory;
9
use CultuurNet\UDB3\EntityNotFoundException;
10
use CultuurNet\UDB3\Event\Events\AudienceUpdated;
11
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated;
12
use CultuurNet\UDB3\Event\Events\CalendarUpdated;
13
use CultuurNet\UDB3\Event\Events\ContactPointUpdated;
14
use CultuurNet\UDB3\Event\Events\DescriptionTranslated;
15
use CultuurNet\UDB3\Event\Events\DescriptionUpdated;
16
use CultuurNet\UDB3\Event\Events\EventCopied;
17
use CultuurNet\UDB3\Event\Events\EventCreated;
18
use CultuurNet\UDB3\Event\Events\EventDeleted;
19
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
20
use CultuurNet\UDB3\Event\Events\EventUpdatedFromUDB2;
21
use CultuurNet\UDB3\Event\Events\FacilitiesUpdated;
22
use CultuurNet\UDB3\Event\Events\ImageAdded;
23
use CultuurNet\UDB3\Event\Events\ImageRemoved;
24
use CultuurNet\UDB3\Event\Events\Image\ImagesImportedFromUDB2;
25
use CultuurNet\UDB3\Event\Events\Image\ImagesUpdatedFromUDB2;
26
use CultuurNet\UDB3\Event\Events\ImageUpdated;
27
use CultuurNet\UDB3\Event\Events\LabelAdded;
28
use CultuurNet\UDB3\Event\Events\LabelRemoved;
29
use CultuurNet\UDB3\Event\Events\LocationUpdated;
30
use CultuurNet\UDB3\Event\Events\MainImageSelected;
31
use CultuurNet\UDB3\Event\Events\MajorInfoUpdated;
32
use CultuurNet\UDB3\Event\Events\Moderation\Approved;
33
use CultuurNet\UDB3\Event\Events\Moderation\FlaggedAsDuplicate;
34
use CultuurNet\UDB3\Event\Events\Moderation\FlaggedAsInappropriate;
35
use CultuurNet\UDB3\Event\Events\Moderation\Published;
36
use CultuurNet\UDB3\Event\Events\Moderation\Rejected;
37
use CultuurNet\UDB3\Event\Events\OrganizerDeleted;
38
use CultuurNet\UDB3\Event\Events\OrganizerUpdated;
39
use CultuurNet\UDB3\Event\Events\PriceInfoUpdated;
40
use CultuurNet\UDB3\Event\Events\ThemeUpdated;
41
use CultuurNet\UDB3\Event\Events\TitleTranslated;
42
use CultuurNet\UDB3\Event\Events\TitleUpdated;
43
use CultuurNet\UDB3\Event\Events\TypeUpdated;
44
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeDeleted;
45
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeUpdated;
46
use CultuurNet\UDB3\Event\EventType;
47
use CultuurNet\UDB3\Event\ReadModel\DocumentGoneException;
48
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
49
use CultuurNet\UDB3\Event\EventServiceInterface;
50
use CultuurNet\UDB3\Event\ValueObjects\Audience;
51
use CultuurNet\UDB3\Event\ValueObjects\AudienceType;
52
use CultuurNet\UDB3\EventListener\EventFilterInterface;
53
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
54
use CultuurNet\UDB3\Language;
55
use CultuurNet\UDB3\Offer\AvailableTo;
56
use CultuurNet\UDB3\Offer\IriOfferIdentifierFactoryInterface;
57
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\OfferLDProjector;
58
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\OfferUpdate;
59
use CultuurNet\UDB3\Offer\WorkflowStatus;
60
use CultuurNet\UDB3\Organizer\OrganizerProjectedToJSONLD;
61
use CultuurNet\UDB3\OrganizerService;
62
use CultuurNet\UDB3\Place\Events\PlaceProjectedToJSONLD;
63
use CultuurNet\UDB3\PlaceService;
64
use CultuurNet\UDB3\ReadModel\JsonDocument;
65
use CultuurNet\UDB3\ReadModel\JsonDocumentMetaDataEnricherInterface;
66
use CultuurNet\UDB3\RecordedOn;
67
use CultuurNet\UDB3\Theme;
68
use Symfony\Component\Serializer\SerializerInterface;
69
use ValueObjects\StringLiteral\StringLiteral;
70
use ValueObjects\Web\Url;
71
72
/**
73
 * Projects state changes on Event entities to a JSON-LD read model in a
74
 * document repository.
75
 *
76
 * Implements PlaceServiceInterface and OrganizerServiceInterface to do a double
77
 * dispatch with CdbXMLImporter.
78
 */
79
class EventLDProjector extends OfferLDProjector implements
80
    EventListenerInterface,
81
    PlaceServiceInterface,
82
    OrganizerServiceInterface
83
{
84
    /**
85
     * @var PlaceService
86
     */
87
    protected $placeService;
88
89
    /**
90
     * @var EventServiceInterface
91
     */
92
    protected $eventService;
93
94
    /**
95
     * @var IriOfferIdentifierFactoryInterface
96
     */
97
    protected $iriOfferIdentifierFactory;
98
99
    /**
100
     * @var CdbXMLImporter
101
     */
102
    protected $cdbXMLImporter;
103
104
    /**
105
     * @param DocumentRepositoryInterface $repository
106
     * @param IriGeneratorInterface $iriGenerator
107
     * @param EventServiceInterface $eventService
108
     * @param PlaceService $placeService
109
     * @param OrganizerService $organizerService
110
     * @param SerializerInterface $mediaObjectSerializer
111
     * @param IriOfferIdentifierFactoryInterface $iriOfferIdentifierFactory
112
     * @param CdbXMLImporter $cdbXMLImporter
113
     * @param JsonDocumentMetaDataEnricherInterface $jsonDocumentMetaDataEnricher
114
     * @param EventFilterInterface $eventFilter
115
     */
116
    public function __construct(
117
        DocumentRepositoryInterface $repository,
118
        IriGeneratorInterface $iriGenerator,
119
        EventServiceInterface $eventService,
120
        PlaceService $placeService,
121
        OrganizerService $organizerService,
122
        SerializerInterface $mediaObjectSerializer,
123
        IriOfferIdentifierFactoryInterface $iriOfferIdentifierFactory,
124
        CdbXMLImporter $cdbXMLImporter,
125
        JsonDocumentMetaDataEnricherInterface $jsonDocumentMetaDataEnricher,
126
        EventFilterInterface $eventFilter
127
    ) {
128
        parent::__construct(
129
            $repository,
130
            $iriGenerator,
131
            $organizerService,
132
            $mediaObjectSerializer,
133
            $jsonDocumentMetaDataEnricher,
134
            $eventFilter
135
        );
136
137
        $this->placeService = $placeService;
138
        $this->eventService = $eventService;
139
        $this->cdbXMLImporter = $cdbXMLImporter;
140
141
        $this->iriOfferIdentifierFactory = $iriOfferIdentifierFactory;
142
    }
143
144
    /**
145
     * @param string $id
146
     * @return JsonDocument
147
     */
148 View Code Duplication
    protected function newDocument($id)
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...
149
    {
150
        $document = new JsonDocument($id);
151
152
        $offerLd = $document->getBody();
153
        $offerLd->{'@id'} = $this->iriGenerator->iri($id);
154
        $offerLd->{'@context'} = '/contexts/event';
155
156
        return $document->withBody($offerLd);
157
    }
158
159
    protected function applyOrganizerProjectedToJSONLD(OrganizerProjectedToJSONLD $organizerProjectedToJSONLD)
160
    {
161
        $eventIds = $this->eventsOrganizedByOrganizer(
162
            $organizerProjectedToJSONLD->getId()
163
        );
164
165
        $organizer = $this->organizerService->getEntity(
166
            $organizerProjectedToJSONLD->getId()
167
        );
168
169
        $documents = [];
170
171 View Code Duplication
        foreach ($eventIds as $eventId) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
172
            $document = $this->loadDocumentFromRepositoryByItemId(
173
                $eventId
174
            );
175
            $eventLD = $document->getBody();
176
177
            $newEventLD = clone $eventLD;
178
            $newEventLD->organizer = json_decode($organizer);
179
180
            if ($newEventLD != $eventLD) {
181
                $documents[] = $document->withBody($newEventLD);
182
            }
183
        }
184
185
        return $documents;
186
    }
187
188
    protected function applyPlaceProjectedToJSONLD(
189
        PlaceProjectedToJSONLD $placeProjectedToJSONLD
190
    ) {
191
        $identifier = $this->iriOfferIdentifierFactory->fromIri(
192
            Url::fromNative($placeProjectedToJSONLD->getIri())
193
        );
194
195
        $eventsLocatedAtPlace = $this->eventsLocatedAtPlace(
196
            $identifier->getId()
197
        );
198
199
        $placeJSONLD = $this->placeService->getEntity(
200
            $identifier->getId()
201
        );
202
203
        $documents = [];
204
205 View Code Duplication
        foreach ($eventsLocatedAtPlace as $eventId) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
206
            $document = $this->loadDocumentFromRepositoryByItemId(
207
                $eventId
208
            );
209
            $eventLD = $document->getBody();
210
211
            $newEventLD = clone $eventLD;
212
            $newEventLD->location = json_decode($placeJSONLD);
213
214
            if ($newEventLD != $eventLD) {
215
                $documents[] = $document->withBody($newEventLD);
216
            }
217
        }
218
219
        return $documents;
220
    }
221
222
    /**
223
     * @param string $organizerId
224
     * @return string[]
225
     */
226
    protected function eventsOrganizedByOrganizer($organizerId)
227
    {
228
        return $this->eventService->eventsOrganizedByOrganizer(
229
            $organizerId
230
        );
231
    }
232
233
    /**
234
     * @param string $placeId
235
     * @return string[]
236
     */
237
    protected function eventsLocatedAtPlace($placeId)
238
    {
239
        return $this->eventService->eventsLocatedAtPlace(
240
            $placeId
241
        );
242
    }
243
244
    /**
245
     * @param EventImportedFromUDB2 $eventImportedFromUDB2
246
     * @return JsonDocument
247
     */
248
    protected function applyEventImportedFromUDB2(
249
        EventImportedFromUDB2 $eventImportedFromUDB2
250
    ) {
251
        return $this->applyEventCdbXmlFromUDB2(
252
            $eventImportedFromUDB2->getEventId(),
253
            $eventImportedFromUDB2->getCdbXmlNamespaceUri(),
254
            $eventImportedFromUDB2->getCdbXml()
255
        );
256
    }
257
258
    /**
259
     * @param EventUpdatedFromUDB2 $eventUpdatedFromUDB2
260
     * @return JsonDocument
261
     */
262
    protected function applyEventUpdatedFromUDB2(
263
        EventUpdatedFromUDB2 $eventUpdatedFromUDB2
264
    ) {
265
        return $this->applyEventCdbXmlFromUDB2(
266
            $eventUpdatedFromUDB2->getEventId(),
267
            $eventUpdatedFromUDB2->getCdbXmlNamespaceUri(),
268
            $eventUpdatedFromUDB2->getCdbXml()
269
        );
270
    }
271
272
    /**
273
     * Helper function to save JSONLD document from entryapi cdbxml.
274
     *
275
     * @param string $eventId
276
     * @param string $cdbXmlNamespaceUri
277
     * @param string $cdbXml
278
     * @param DomainMessage $domainMessage
279
     * @return JsonDocument
280
     */
281
    protected function applyEventFromCdbXml(
282
        $eventId,
283
        $cdbXmlNamespaceUri,
284
        $cdbXml,
285
        $domainMessage
286
    ) {
287
        $document = $this->newDocument($eventId);
288
289
        $eventLd = $this->projectEventCdbXmlToObject(
290
            $document->getBody(),
291
            $eventId,
292
            $cdbXmlNamespaceUri,
293
            $cdbXml
294
        );
295
296
        // Add creation date and update date from domain message.
297
        $created = RecordedOn::fromDomainMessage($domainMessage);
298
        $eventLd->created = $created->toString();
299
        $eventLd->modified = $created->toString();
300
301
        // Add creator.
302
        $eventLd->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
303
304
        // Add publisher, which is the consumer name.
305
        $eventLd->publisher = $this->getConsumerFromMetadata($domainMessage->getMetadata())->toNative();
306
307
        return $document->withBody($eventLd);
308
    }
309
310
    /**
311
     * Helper function to save a JSON-LD document from cdbxml coming from UDB2.
312
     *
313
     * @param string $eventId
314
     * @param string $cdbXmlNamespaceUri
315
     * @param string $cdbXml
316
     *
317
     * @return JsonDocument
318
     */
319
    protected function applyEventCdbXmlFromUDB2(
320
        $eventId,
321
        $cdbXmlNamespaceUri,
322
        $cdbXml
323
    ) {
324
        $document = $this->newDocument($eventId);
325
326
        $eventLd = $this->projectEventCdbXmlToObject(
327
            $document->getBody(),
328
            $eventId,
329
            $cdbXmlNamespaceUri,
330
            $cdbXml
331
        );
332
333
        return $document->withBody($eventLd);
334
    }
335
336
    /**
337
     * @param \stdClass $jsonLd
338
     * @param string $eventId
339
     * @param string $cdbXmlNamespaceUri
340
     * @param string $cdbXml
341
     *
342
     * @return \stdClass
343
     */
344
    protected function projectEventCdbXmlToObject(
345
        \stdClass $jsonLd,
346
        $eventId,
347
        $cdbXmlNamespaceUri,
348
        $cdbXml
349
    ) {
350
        $udb2Event = EventItemFactory::createEventFromCdbXml(
351
            $cdbXmlNamespaceUri,
352
            $cdbXml
353
        );
354
355
        $jsonLd = $this->cdbXMLImporter->documentWithCdbXML(
356
            $jsonLd,
357
            $udb2Event,
358
            $this,
359
            $this,
360
            $this->slugger
361
        );
362
363
        $this->setMainLanguage($jsonLd, new Language('nl'));
364
365
        // Because we can not properly track media coming from UDB2 we simply
366
        // ignore it and give priority to content added through UDB3.
367
        // It's possible that an event has been deleted in udb3, but never
368
        // in udb2. If an update comes for that event from udb2, it should
369
        // be imported again. This is intended by design.
370
        // @see https://jira.uitdatabank.be/browse/III-1092
371
        try {
372
            $document = $this->loadDocumentFromRepositoryByItemId($eventId);
373
        } catch (DocumentGoneException $documentGoneException) {
374
            $document = $this->newDocument($eventId);
375
        }
376
377
        $media = $this->UDB3Media($document);
378
        if (!empty($media)) {
379
            $jsonLd->mediaObject = $media;
380
        }
381
382
        // Because UDB2 cannot keep track of UDB3 places as a location
383
        // ignore it and give priority to content added through UDB3.
384
        $location = $this->UDB3Location($document);
385
        if (!empty($location)) {
386
            $jsonLd->location = $location;
387
        }
388
389
        return $jsonLd;
390
    }
391
392
    /**
393
     * Return the media of an event if it already exists.
394
     *
395
     * @param JsonDocument $document The JsonDocument.
396
     *
397
     * @return array
398
     *  A list of media objects.
399
     */
400
    private function UDB3Media($document)
401
    {
402
        $media = [];
403
404
        if ($document) {
405
            $item = $document->getBody();
406
            // At the moment we do not include any media coming from UDB2.
407
            // If the mediaObject property contains data it's coming from UDB3.
408
            $item->mediaObject = isset($item->mediaObject) ? $item->mediaObject : [];
409
        }
410
411
        return $media;
412
    }
413
414
    /**
415
     * Return the location of an event if it already exists.
416
     *
417
     * @param JsonDocument $document The JsonDocument.
418
     *
419
     * @return array|null
420
     *  The location
421
     */
422
    private function UDB3Location($document)
423
    {
424
        $location = null;
425
426
        if ($document) {
427
            $item = $document->getBody();
428
            $location = isset($item->location) ? $item->location : null;
429
        }
430
431
        return $location;
432
    }
433
434
    /**
435
     * @param EventCreated $eventCreated
436
     * @param DomainMessage $domainMessage
437
     * @return JsonDocument
438
     */
439
    protected function applyEventCreated(
440
        EventCreated $eventCreated,
441
        DomainMessage $domainMessage
442
    ) {
443
        $document = $this->newDocument($eventCreated->getEventId());
444
        $jsonLD = $document->getBody();
445
446
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
447
            $eventCreated->getEventId()
448
        );
449
450
        $this->setMainLanguage($jsonLD, new Language('nl'));
451
452
        $jsonLD->name['nl'] = $eventCreated->getTitle();
453
        $jsonLD->location = array(
454
                '@type' => 'Place',
455
            ) + (array)$this->placeJSONLD(
456
                $eventCreated->getLocation()->getCdbid()
457
            );
458
459
        $calendarJsonLD = $eventCreated->getCalendar()->toJsonLd();
460
        $jsonLD = (object)array_merge((array)$jsonLD, $calendarJsonLD);
461
462
        $availableTo = AvailableTo::createFromCalendar($eventCreated->getCalendar());
463
        $jsonLD->availableTo = (string)$availableTo;
464
465
        // Same as.
466
        $jsonLD->sameAs = $this->generateSameAs(
467
            $eventCreated->getEventId(),
468
            reset($jsonLD->name)
469
        );
470
471
        $eventType = $eventCreated->getEventType();
472
        $jsonLD->terms = [
473
            $eventType->toJsonLd(),
474
        ];
475
476
        $theme = $eventCreated->getTheme();
477
        if (!empty($theme)) {
478
            $jsonLD->terms[] = $theme->toJsonLd();
479
        }
480
481
        $created = RecordedOn::fromDomainMessage($domainMessage);
482
        $jsonLD->created = $created->toString();
483
        $jsonLD->modified = $created->toString();
484
485
        $metaData = $domainMessage->getMetadata()->serialize();
486 View Code Duplication
        if (isset($metaData['user_email'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
487
            $jsonLD->creator = $metaData['user_email'];
488
        } elseif (isset($metaData['user_nick'])) {
489
            $jsonLD->creator = $metaData['user_nick'];
490
        }
491
492
        $jsonLD->workflowStatus = WorkflowStatus::DRAFT()->getName();
493
494
        $defaultAudience = new Audience(AudienceType::EVERYONE());
495
        $jsonLD->audience = $defaultAudience->serialize();
496
497
        return $document->withBody($jsonLD);
498
    }
499
500
    /**
501
     * @param EventCopied $eventCopied
502
     * @param DomainMessage $domainMessage
503
     * @return JsonDocument
504
     */
505
    protected function applyEventCopied(
506
        EventCopied $eventCopied,
507
        DomainMessage $domainMessage
508
    ) {
509
        $originalDocument = $this->repository->get($eventCopied->getOriginalEventId());
510
        $eventJsonLD = $originalDocument->getBody();
511
512
        // Set the created and modified date.
513
        $created = RecordedOn::fromDomainMessage($domainMessage);
514
        $eventJsonLD->created = $created->toString();
515
        $eventJsonLD->modified = $created->toString();
516
517
        // Set the creator.
518
        $eventJsonLD->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
519
520
        // Set the id.
521
        $eventJsonLD->{'@id'} = $this->iriGenerator->iri($eventCopied->getItemId());
522
523
        // Set the new calendar.
524
        $eventJsonLD = (object) array_merge(
525
            (array) $eventJsonLD,
526
            $eventCopied->getCalendar()->toJsonLd()
527
        );
528
529
        // Set workflow status.
530
        $eventJsonLD->workflowStatus = WorkflowStatus::DRAFT()->getName();
531
532
        // Remove labels.
533
        unset($eventJsonLD->labels);
534
        unset($eventJsonLD->hiddenLabels);
535
536
        // Set available to and from.
537
        $availableTo = AvailableTo::createFromCalendar($eventCopied->getCalendar());
538
        $eventJsonLD->availableTo = (string) $availableTo;
539
        unset($eventJsonLD->availableFrom);
540
541
        $newDocument = new JsonDocument($eventCopied->getItemId());
542
        $newDocument = $newDocument->withBody($eventJsonLD);
543
        return $newDocument;
544
    }
545
546
    /**
547
     * @param EventDeleted $eventDeleted
548
     * @return null
549
     */
550 View Code Duplication
    protected function applyEventDeleted(EventDeleted $eventDeleted)
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...
551
    {
552
        $document = $this->loadDocumentFromRepository($eventDeleted);
553
554
        $jsonLD = $document->getBody();
555
556
        $jsonLD->workflowStatus = WorkflowStatus::DELETED()->getName();
557
558
        return $document->withBody($jsonLD);
559
    }
560
561
    /**
562
     * Apply the major info updated command to the projector.
563
     * @param MajorInfoUpdated $majorInfoUpdated
564
     * @return JsonDocument
565
     */
566
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
567
    {
568
        $document = $this
569
            ->loadDocumentFromRepository($majorInfoUpdated)
570
            ->apply(OfferUpdate::calendar($majorInfoUpdated->getCalendar()));
0 ignored issues
show
Compatibility introduced by
$majorInfoUpdated->getCalendar() of type object<CultuurNet\UDB3\CalendarInterface> is not a sub-type of object<CultuurNet\UDB3\Calendar>. It seems like you assume a concrete implementation of the interface CultuurNet\UDB3\CalendarInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
571
572
        $jsonLD = $document->getBody();
573
574
        $jsonLD->name->nl = $majorInfoUpdated->getTitle();
575
        $jsonLD->location = array(
576
          '@type' => 'Place',
577
        ) + (array)$this->placeJSONLD($majorInfoUpdated->getLocation()->getCdbid());
578
579
        $availableTo = AvailableTo::createFromCalendar($majorInfoUpdated->getCalendar());
580
        $jsonLD->availableTo = (string)$availableTo;
581
582
        // Remove old theme and event type.
583
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
584
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
585
        });
586
        $jsonLD->terms = array_values($jsonLD->terms);
587
588
        $eventType = $majorInfoUpdated->getEventType();
589
        $jsonLD->terms[] = $eventType->toJsonLd();
590
591
        $theme = $majorInfoUpdated->getTheme();
592
        if (!empty($theme)) {
593
            $jsonLD->terms[] = $theme->toJsonLd();
594
        }
595
596
        return $document->withBody($jsonLD);
597
    }
598
599
    /**
600
     * @param LocationUpdated $locationUpdated
601
     *
602
     * @return JsonDocument
603
     */
604
    public function applyLocationUpdated(LocationUpdated $locationUpdated)
605
    {
606
        $document = $this->loadDocumentFromRepository($locationUpdated);
607
608
        $jsonLD = $document->getBody();
609
610
        $jsonLD->location = [
611
            '@type' => 'Place',
612
         ] + (array) $this->placeJSONLD($locationUpdated->getLocationId()->toNative());
613
614
        return $document->withBody($jsonLD);
615
    }
616
617
    /**
618
     * @param AudienceUpdated $audienceUpdated
619
     * @return JsonDocument
620
     */
621
    protected function applyAudienceUpdated(AudienceUpdated $audienceUpdated)
622
    {
623
        $document = $this->loadDocumentFromRepository($audienceUpdated);
624
        $jsonLD = $document->getBody();
625
626
        $jsonLD->audience = $audienceUpdated->getAudience()->serialize();
627
628
        return $document->withBody($jsonLD);
629
    }
630
631
    /**
632
     * @inheritdoc
633
     */
634
    public function placeJSONLD($placeId)
635
    {
636
        if (empty($placeId)) {
637
            return array();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array(); (array) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...eInterface::placeJSONLD of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
638
        }
639
640
        try {
641
            $placeJSONLD = $this->placeService->getEntity(
642
                $placeId
643
            );
644
645
            return json_decode($placeJSONLD);
646
        } catch (EntityNotFoundException $e) {
647
            // In case the place can not be found at the moment, just add its ID
648
            return array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('@id' => $t...ervice->iri($placeId)); (array<string,string>) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...eInterface::placeJSONLD of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
649
                '@id' => $this->placeService->iri($placeId),
650
            );
651
        } catch (DocumentGoneException $e) {
652
            // In case the place can not be found at the moment, just add its ID
653
            return array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('@id' => $t...ervice->iri($placeId)); (array<string,string>) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...eInterface::placeJSONLD of type stdClass.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
654
                '@id' => $this->placeService->iri($placeId),
655
            );
656
        }
657
    }
658
659
    private function generateSameAs($eventId, $name)
660
    {
661
        $eventSlug = $this->slugger->slug($name);
662
        return array(
663
            'http://www.uitinvlaanderen.be/agenda/e/' . $eventSlug . '/' . $eventId,
664
        );
665
    }
666
667 View Code Duplication
    private function getAuthorFromMetadata(Metadata $metadata)
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...
668
    {
669
        $properties = $metadata->serialize();
670
671
        if (isset($properties['user_nick'])) {
672
            return new StringLiteral($properties['user_nick']);
673
        }
674
    }
675
676 View Code Duplication
    private function getConsumerFromMetadata(Metadata $metadata)
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...
677
    {
678
        $properties = $metadata->serialize();
679
680
        if (isset($properties['consumer']['name'])) {
681
            return new StringLiteral($properties['consumer']['name']);
682
        }
683
    }
684
685
    /**
686
     * @return string
687
     */
688
    protected function getLabelAddedClassName()
689
    {
690
        return LabelAdded::class;
691
    }
692
693
    /**
694
     * @return string
695
     */
696
    protected function getLabelRemovedClassName()
697
    {
698
        return LabelRemoved::class;
699
    }
700
701
    /**
702
     * @return string
703
     */
704
    protected function getImageAddedClassName()
705
    {
706
        return ImageAdded::class;
707
    }
708
709
    /**
710
     * @return string
711
     */
712
    protected function getImageRemovedClassName()
713
    {
714
        return ImageRemoved::class;
715
    }
716
717
    /**
718
     * @return string
719
     */
720
    protected function getImageUpdatedClassName()
721
    {
722
        return ImageUpdated::class;
723
    }
724
725
    protected function getMainImageSelectedClassName()
726
    {
727
        return MainImageSelected::class;
728
    }
729
730
    /**
731
     * @return string
732
     */
733
    protected function getTitleTranslatedClassName()
734
    {
735
        return TitleTranslated::class;
736
    }
737
738
    /**
739
     * @return string
740
     */
741
    protected function getDescriptionTranslatedClassName()
742
    {
743
        return DescriptionTranslated::class;
744
    }
745
746
    /**
747
     * @return string
748
     */
749
    protected function getOrganizerUpdatedClassName()
750
    {
751
        return OrganizerUpdated::class;
752
    }
753
754
    /**
755
     * @return string
756
     */
757
    protected function getOrganizerDeletedClassName()
758
    {
759
        return OrganizerDeleted::class;
760
    }
761
762
    protected function getBookingInfoUpdatedClassName()
763
    {
764
        return BookingInfoUpdated::class;
765
    }
766
767
    /**
768
     * @return string
769
     */
770
    protected function getPriceInfoUpdatedClassName()
771
    {
772
        return PriceInfoUpdated::class;
773
    }
774
775
    protected function getContactPointUpdatedClassName()
776
    {
777
        return ContactPointUpdated::class;
778
    }
779
780
    protected function getDescriptionUpdatedClassName()
781
    {
782
        return DescriptionUpdated::class;
783
    }
784
785
    protected function getCalendarUpdatedClassName()
786
    {
787
        return CalendarUpdated::class;
788
    }
789
790
    protected function getTypicalAgeRangeUpdatedClassName()
791
    {
792
        return TypicalAgeRangeUpdated::class;
793
    }
794
795
    protected function getTypicalAgeRangeDeletedClassName()
796
    {
797
        return TypicalAgeRangeDeleted::class;
798
    }
799
800
    protected function getPublishedClassName()
801
    {
802
        return Published::class;
803
    }
804
805
    protected function getApprovedClassName()
806
    {
807
        return Approved::class;
808
    }
809
810
    protected function getRejectedClassName()
811
    {
812
        return Rejected::class;
813
    }
814
815
    protected function getFlaggedAsDuplicateClassName()
816
    {
817
        return FlaggedAsDuplicate::class;
818
    }
819
820
    protected function getFlaggedAsInappropriateClassName()
821
    {
822
        return FlaggedAsInappropriate::class;
823
    }
824
825
    protected function getImagesImportedFromUdb2ClassName()
826
    {
827
        return ImagesImportedFromUDB2::class;
828
    }
829
830
    protected function getImagesUpdatedFromUdb2ClassName()
831
    {
832
        return ImagesUpdatedFromUDB2::class;
833
    }
834
835
    protected function getTitleUpdatedClassName()
836
    {
837
        return TitleUpdated::class;
838
    }
839
840
    protected function getTypeUpdatedClassName()
841
    {
842
        return TypeUpdated::class;
843
    }
844
845
    protected function getThemeUpdatedClassName()
846
    {
847
        return ThemeUpdated::class;
848
    }
849
850
    protected function getFacilitiesUpdatedClassName()
851
    {
852
        return FacilitiesUpdated::class;
853
    }
854
}
855