Completed
Pull Request — master (#336)
by Luc
04:39
created

EventLDProjector::getFacilitiesUpdatedClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace CultuurNet\UDB3\Event\ReadModel\JSONLD;
4
5
use Broadway\Domain\DateTime;
6
use Broadway\Domain\DomainMessage;
7
use Broadway\Domain\Metadata;
8
use Broadway\EventHandling\EventListenerInterface;
9
use CultuurNet\UDB3\Cdb\EventItemFactory;
10
use CultuurNet\UDB3\EntityNotFoundException;
11
use CultuurNet\UDB3\Event\Events\AudienceUpdated;
12
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated;
13
use CultuurNet\UDB3\Event\Events\CalendarUpdated;
14
use CultuurNet\UDB3\Event\Events\ContactPointUpdated;
15
use CultuurNet\UDB3\Event\Events\DescriptionTranslated;
16
use CultuurNet\UDB3\Event\Events\DescriptionUpdated;
17
use CultuurNet\UDB3\Event\Events\EventCopied;
18
use CultuurNet\UDB3\Event\Events\EventCreated;
19
use CultuurNet\UDB3\Event\Events\EventDeleted;
20
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
21
use CultuurNet\UDB3\Event\Events\EventUpdatedFromUDB2;
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\Iri\IriGeneratorInterface;
53
use CultuurNet\UDB3\Language;
54
use CultuurNet\UDB3\Offer\AvailableTo;
55
use CultuurNet\UDB3\Offer\IriOfferIdentifierFactoryInterface;
56
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\OfferLDProjector;
57
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\OfferUpdate;
58
use CultuurNet\UDB3\Offer\WorkflowStatus;
59
use CultuurNet\UDB3\Organizer\OrganizerProjectedToJSONLD;
60
use CultuurNet\UDB3\OrganizerService;
61
use CultuurNet\UDB3\Place\Events\PlaceProjectedToJSONLD;
62
use CultuurNet\UDB3\PlaceService;
63
use CultuurNet\UDB3\ReadModel\JsonDocument;
64
use CultuurNet\UDB3\ReadModel\JsonDocumentMetaDataEnricherInterface;
65
use CultuurNet\UDB3\Theme;
66
use Symfony\Component\Serializer\SerializerInterface;
67
use ValueObjects\StringLiteral\StringLiteral;
68
use ValueObjects\Web\Url;
69
70
/**
71
 * Projects state changes on Event entities to a JSON-LD read model in a
72
 * document repository.
73
 *
74
 * Implements PlaceServiceInterface and OrganizerServiceInterface to do a double
75
 * dispatch with CdbXMLImporter.
76
 */
77
class EventLDProjector extends OfferLDProjector implements
78
    EventListenerInterface,
79
    PlaceServiceInterface,
80
    OrganizerServiceInterface
81
{
82
    /**
83
     * @var PlaceService
84
     */
85
    protected $placeService;
86
87
    /**
88
     * @var EventServiceInterface
89
     */
90
    protected $eventService;
91
92
    /**
93
     * @var IriOfferIdentifierFactoryInterface
94
     */
95
    protected $iriOfferIdentifierFactory;
96
97
    /**
98
     * @var CdbXMLImporter
99
     */
100
    protected $cdbXMLImporter;
101
102
    /**
103
     * @param DocumentRepositoryInterface $repository
104
     * @param IriGeneratorInterface $iriGenerator
105
     * @param EventServiceInterface $eventService
106
     * @param PlaceService $placeService
107
     * @param OrganizerService $organizerService
108
     * @param SerializerInterface $mediaObjectSerializer
109
     * @param IriOfferIdentifierFactoryInterface $iriOfferIdentifierFactory
110
     * @param CdbXMLImporter $cdbXMLImporter
111
     * @param JsonDocumentMetaDataEnricherInterface $jsonDocumentMetaDataEnricher
112
     */
113
    public function __construct(
114
        DocumentRepositoryInterface $repository,
115
        IriGeneratorInterface $iriGenerator,
116
        EventServiceInterface $eventService,
117
        PlaceService $placeService,
118
        OrganizerService $organizerService,
119
        SerializerInterface $mediaObjectSerializer,
120
        IriOfferIdentifierFactoryInterface $iriOfferIdentifierFactory,
121
        CdbXMLImporter $cdbXMLImporter,
122
        JsonDocumentMetaDataEnricherInterface $jsonDocumentMetaDataEnricher
123
    ) {
124
        parent::__construct(
125
            $repository,
126
            $iriGenerator,
127
            $organizerService,
128
            $mediaObjectSerializer,
129
            $jsonDocumentMetaDataEnricher
130
        );
131
132
        $this->placeService = $placeService;
133
        $this->eventService = $eventService;
134
        $this->cdbXMLImporter = $cdbXMLImporter;
135
136
        $this->iriOfferIdentifierFactory = $iriOfferIdentifierFactory;
137
    }
138
139
    /**
140
     * @param string $id
141
     * @return JsonDocument
142
     */
143 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...
144
    {
145
        $document = new JsonDocument($id);
146
147
        $offerLd = $document->getBody();
148
        $offerLd->{'@id'} = $this->iriGenerator->iri($id);
149
        $offerLd->{'@context'} = '/contexts/event';
150
151
        return $document->withBody($offerLd);
152
    }
153
154
    protected function applyOrganizerProjectedToJSONLD(OrganizerProjectedToJSONLD $organizerProjectedToJSONLD)
155
    {
156
        $eventIds = $this->eventsOrganizedByOrganizer(
157
            $organizerProjectedToJSONLD->getId()
158
        );
159
160
        $organizer = $this->organizerService->getEntity(
161
            $organizerProjectedToJSONLD->getId()
162
        );
163
164
        $documents = [];
165
166 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...
167
            $document = $this->loadDocumentFromRepositoryByItemId(
168
                $eventId
169
            );
170
            $eventLD = $document->getBody();
171
172
            $newEventLD = clone $eventLD;
173
            $newEventLD->organizer = json_decode($organizer);
174
175
            if ($newEventLD != $eventLD) {
176
                $documents[] = $document->withBody($newEventLD);
177
            }
178
        }
179
180
        return $documents;
181
    }
182
183
    protected function applyPlaceProjectedToJSONLD(
184
        PlaceProjectedToJSONLD $placeProjectedToJSONLD
185
    ) {
186
        $identifier = $this->iriOfferIdentifierFactory->fromIri(
187
            Url::fromNative($placeProjectedToJSONLD->getIri())
188
        );
189
190
        $eventsLocatedAtPlace = $this->eventsLocatedAtPlace(
191
            $identifier->getId()
192
        );
193
194
        $placeJSONLD = $this->placeService->getEntity(
195
            $identifier->getId()
196
        );
197
198
        $documents = [];
199
200 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...
201
            $document = $this->loadDocumentFromRepositoryByItemId(
202
                $eventId
203
            );
204
            $eventLD = $document->getBody();
205
206
            $newEventLD = clone $eventLD;
207
            $newEventLD->location = json_decode($placeJSONLD);
208
209
            if ($newEventLD != $eventLD) {
210
                $documents[] = $document->withBody($newEventLD);
211
            }
212
        }
213
214
        return $documents;
215
    }
216
217
    /**
218
     * @param string $organizerId
219
     * @return string[]
220
     */
221
    protected function eventsOrganizedByOrganizer($organizerId)
222
    {
223
        return $this->eventService->eventsOrganizedByOrganizer(
224
            $organizerId
225
        );
226
    }
227
228
    /**
229
     * @param string $placeId
230
     * @return string[]
231
     */
232
    protected function eventsLocatedAtPlace($placeId)
233
    {
234
        return $this->eventService->eventsLocatedAtPlace(
235
            $placeId
236
        );
237
    }
238
239
    /**
240
     * @param EventImportedFromUDB2 $eventImportedFromUDB2
241
     * @return JsonDocument
242
     */
243
    protected function applyEventImportedFromUDB2(
244
        EventImportedFromUDB2 $eventImportedFromUDB2
245
    ) {
246
        return $this->applyEventCdbXmlFromUDB2(
247
            $eventImportedFromUDB2->getEventId(),
248
            $eventImportedFromUDB2->getCdbXmlNamespaceUri(),
249
            $eventImportedFromUDB2->getCdbXml()
250
        );
251
    }
252
253
    /**
254
     * @param EventUpdatedFromUDB2 $eventUpdatedFromUDB2
255
     * @return JsonDocument
256
     */
257
    protected function applyEventUpdatedFromUDB2(
258
        EventUpdatedFromUDB2 $eventUpdatedFromUDB2
259
    ) {
260
        return $this->applyEventCdbXmlFromUDB2(
261
            $eventUpdatedFromUDB2->getEventId(),
262
            $eventUpdatedFromUDB2->getCdbXmlNamespaceUri(),
263
            $eventUpdatedFromUDB2->getCdbXml()
264
        );
265
    }
266
267
    /**
268
     * Helper function to save JSONLD document from entryapi cdbxml.
269
     *
270
     * @param string $eventId
271
     * @param string $cdbXmlNamespaceUri
272
     * @param string $cdbXml
273
     * @param DomainMessage $domainMessage
274
     * @return JsonDocument
275
     */
276
    protected function applyEventFromCdbXml(
277
        $eventId,
278
        $cdbXmlNamespaceUri,
279
        $cdbXml,
280
        $domainMessage
281
    ) {
282
        $document = $this->newDocument($eventId);
283
284
        $eventLd = $this->projectEventCdbXmlToObject(
285
            $document->getBody(),
286
            $eventId,
287
            $cdbXmlNamespaceUri,
288
            $cdbXml
289
        );
290
291
        // Add creation date and update date from metadata.
292
        $created = $this->getCreated($domainMessage);
293
        $eventLd->created = $created;
294
        $eventLd->modified = $created;
295
296
        // Add creator.
297
        $eventLd->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
298
299
        // Add publisher, which is the consumer name.
300
        $eventLd->publisher = $this->getConsumerFromMetadata($domainMessage->getMetadata())->toNative();
301
302
        return $document->withBody($eventLd);
303
    }
304
305
    /**
306
     * Helper function to save a JSON-LD document from cdbxml coming from UDB2.
307
     *
308
     * @param string $eventId
309
     * @param string $cdbXmlNamespaceUri
310
     * @param string $cdbXml
311
     *
312
     * @return JsonDocument
313
     */
314
    protected function applyEventCdbXmlFromUDB2(
315
        $eventId,
316
        $cdbXmlNamespaceUri,
317
        $cdbXml
318
    ) {
319
        $document = $this->newDocument($eventId);
320
321
        $eventLd = $this->projectEventCdbXmlToObject(
322
            $document->getBody(),
323
            $eventId,
324
            $cdbXmlNamespaceUri,
325
            $cdbXml
326
        );
327
328
        return $document->withBody($eventLd);
329
    }
330
331
    /**
332
     * @param \stdClass $jsonLd
333
     * @param string $eventId
334
     * @param string $cdbXmlNamespaceUri
335
     * @param string $cdbXml
336
     *
337
     * @return \stdClass
338
     */
339
    protected function projectEventCdbXmlToObject(
340
        \stdClass $jsonLd,
341
        $eventId,
342
        $cdbXmlNamespaceUri,
343
        $cdbXml
344
    ) {
345
        $udb2Event = EventItemFactory::createEventFromCdbXml(
346
            $cdbXmlNamespaceUri,
347
            $cdbXml
348
        );
349
350
        $jsonLd = $this->cdbXMLImporter->documentWithCdbXML(
351
            $jsonLd,
352
            $udb2Event,
353
            $this,
354
            $this,
355
            $this->slugger
356
        );
357
358
        $this->setMainLanguage($jsonLd, new Language('nl'));
359
360
        // Because we can not properly track media coming from UDB2 we simply
361
        // ignore it and give priority to content added through UDB3.
362
        // It's possible that an event has been deleted in udb3, but never
363
        // in udb2. If an update comes for that event from udb2, it should
364
        // be imported again. This is intended by design.
365
        // @see https://jira.uitdatabank.be/browse/III-1092
366
        try {
367
            $document = $this->loadDocumentFromRepositoryByItemId($eventId);
368
        } catch (DocumentGoneException $documentGoneException) {
369
            $document = $this->newDocument($eventId);
370
        }
371
372
        $media = $this->UDB3Media($document);
373
        if (!empty($media)) {
374
            $jsonLd->mediaObject = $media;
375
        }
376
377
        // Because UDB2 cannot keep track of UDB3 places as a location
378
        // ignore it and give priority to content added through UDB3.
379
        $location = $this->UDB3Location($document);
380
        if (!empty($location)) {
381
            $jsonLd->location = $location;
382
        }
383
384
        return $jsonLd;
385
    }
386
387
    /**
388
     * Return the media of an event if it already exists.
389
     *
390
     * @param JsonDocument $document The JsonDocument.
391
     *
392
     * @return array
393
     *  A list of media objects.
394
     */
395
    private function UDB3Media($document)
396
    {
397
        $media = [];
398
399
        if ($document) {
400
            $item = $document->getBody();
401
            // At the moment we do not include any media coming from UDB2.
402
            // If the mediaObject property contains data it's coming from UDB3.
403
            $item->mediaObject = isset($item->mediaObject) ? $item->mediaObject : [];
404
        }
405
406
        return $media;
407
    }
408
409
    /**
410
     * Return the location of an event if it already exists.
411
     *
412
     * @param JsonDocument $document The JsonDocument.
413
     *
414
     * @return array|null
415
     *  The location
416
     */
417
    private function UDB3Location($document)
418
    {
419
        $location = null;
420
421
        if ($document) {
422
            $item = $document->getBody();
423
            $location = isset($item->location) ? $item->location : null;
424
        }
425
426
        return $location;
427
    }
428
429
    /**
430
     * @param EventCreated $eventCreated
431
     * @param DomainMessage $domainMessage
432
     * @return JsonDocument
433
     */
434
    protected function applyEventCreated(
435
        EventCreated $eventCreated,
436
        DomainMessage $domainMessage
437
    ) {
438
        $document = $this->newDocument($eventCreated->getEventId());
439
        $jsonLD = $document->getBody();
440
441
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
442
            $eventCreated->getEventId()
443
        );
444
445
        $this->setMainLanguage($jsonLD, new Language('nl'));
446
447
        $jsonLD->name['nl'] = $eventCreated->getTitle();
448
        $jsonLD->location = array(
449
                '@type' => 'Place',
450
            ) + (array)$this->placeJSONLD(
451
                $eventCreated->getLocation()->getCdbid()
452
            );
453
454
        $calendarJsonLD = $eventCreated->getCalendar()->toJsonLd();
455
        $jsonLD = (object)array_merge((array)$jsonLD, $calendarJsonLD);
456
457
        $availableTo = AvailableTo::createFromCalendar($eventCreated->getCalendar());
458
        $jsonLD->availableTo = (string)$availableTo;
459
460
        // Same as.
461
        $jsonLD->sameAs = $this->generateSameAs(
462
            $eventCreated->getEventId(),
463
            reset($jsonLD->name)
464
        );
465
466
        $eventType = $eventCreated->getEventType();
467
        $jsonLD->terms = [
468
            $eventType->toJsonLd(),
469
        ];
470
471
        $theme = $eventCreated->getTheme();
472
        if (!empty($theme)) {
473
            $jsonLD->terms[] = $theme->toJsonLd();
474
        }
475
476
        $created = $this->getCreated($domainMessage);
477
        $jsonLD->created = $created;
478
        $jsonLD->modified = $created;
479
480
        $metaData = $domainMessage->getMetadata()->serialize();
481 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...
482
            $jsonLD->creator = $metaData['user_email'];
483
        } elseif (isset($metaData['user_nick'])) {
484
            $jsonLD->creator = $metaData['user_nick'];
485
        }
486
487
        $jsonLD->workflowStatus = WorkflowStatus::DRAFT()->getName();
488
489
        $defaultAudience = new Audience(AudienceType::EVERYONE());
490
        $jsonLD->audience = $defaultAudience->serialize();
491
492
        return $document->withBody($jsonLD);
493
    }
494
495
    /**
496
     * @param EventCopied $eventCopied
497
     * @param DomainMessage $domainMessage
498
     * @return JsonDocument
499
     */
500
    protected function applyEventCopied(
501
        EventCopied $eventCopied,
502
        DomainMessage $domainMessage
503
    ) {
504
        $originalDocument = $this->repository->get($eventCopied->getOriginalEventId());
505
        $eventJsonLD = $originalDocument->getBody();
506
507
        // Set the created and modified date.
508
        $created = $this->getCreated($domainMessage);
509
        $eventJsonLD->created = $created;
510
        $eventJsonLD->modified = $created;
511
512
        // Set the creator.
513
        $eventJsonLD->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
514
515
        // Set the id.
516
        $eventJsonLD->{'@id'} = $this->iriGenerator->iri($eventCopied->getItemId());
517
518
        // Set the new calendar.
519
        $eventJsonLD = (object) array_merge(
520
            (array) $eventJsonLD,
521
            $eventCopied->getCalendar()->toJsonLd()
522
        );
523
524
        // Set workflow status.
525
        $eventJsonLD->workflowStatus = WorkflowStatus::DRAFT()->getName();
526
527
        // Remove labels.
528
        unset($eventJsonLD->labels);
529
        unset($eventJsonLD->hiddenLabels);
530
531
        // Set available to and from.
532
        $availableTo = AvailableTo::createFromCalendar($eventCopied->getCalendar());
533
        $eventJsonLD->availableTo = (string) $availableTo;
534
        unset($eventJsonLD->availableFrom);
535
536
        $newDocument = new JsonDocument($eventCopied->getItemId());
537
        $newDocument = $newDocument->withBody($eventJsonLD);
538
        return $newDocument;
539
    }
540
541
    /**
542
     * @param EventDeleted $eventDeleted
543
     * @return null
544
     */
545 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...
546
    {
547
        $document = $this->loadDocumentFromRepository($eventDeleted);
548
549
        $jsonLD = $document->getBody();
550
551
        $jsonLD->workflowStatus = WorkflowStatus::DELETED()->getName();
552
553
        return $document->withBody($jsonLD);
554
    }
555
556
    /**
557
     * Apply the major info updated command to the projector.
558
     * @param MajorInfoUpdated $majorInfoUpdated
559
     * @return JsonDocument
560
     */
561
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
562
    {
563
        $document = $this
564
            ->loadDocumentFromRepository($majorInfoUpdated)
565
            ->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...
566
567
        $jsonLD = $document->getBody();
568
569
        $jsonLD->name->nl = $majorInfoUpdated->getTitle();
570
        $jsonLD->location = array(
571
          '@type' => 'Place',
572
        ) + (array)$this->placeJSONLD($majorInfoUpdated->getLocation()->getCdbid());
573
574
        $availableTo = AvailableTo::createFromCalendar($majorInfoUpdated->getCalendar());
575
        $jsonLD->availableTo = (string)$availableTo;
576
577
        // Remove old theme and event type.
578
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
579
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
580
        });
581
        $jsonLD->terms = array_values($jsonLD->terms);
582
583
        $eventType = $majorInfoUpdated->getEventType();
584
        $jsonLD->terms[] = $eventType->toJsonLd();
585
586
        $theme = $majorInfoUpdated->getTheme();
587
        if (!empty($theme)) {
588
            $jsonLD->terms[] = $theme->toJsonLd();
589
        }
590
591
        return $document->withBody($jsonLD);
592
    }
593
594
    /**
595
     * @param LocationUpdated $locationUpdated
596
     *
597
     * @return JsonDocument
598
     */
599
    public function applyLocationUpdated(LocationUpdated $locationUpdated)
600
    {
601
        $document = $this->loadDocumentFromRepository($locationUpdated);
602
603
        $jsonLD = $document->getBody();
604
605
        $jsonLD->location = [
606
            '@type' => 'Place',
607
         ] + (array) $this->placeJSONLD($locationUpdated->getLocationId()->toNative());
608
609
        return $document->withBody($jsonLD);
610
    }
611
612
    /**
613
     * @param AudienceUpdated $audienceUpdated
614
     * @return JsonDocument
615
     */
616
    protected function applyAudienceUpdated(AudienceUpdated $audienceUpdated)
617
    {
618
        $document = $this->loadDocumentFromRepository($audienceUpdated);
619
        $jsonLD = $document->getBody();
620
621
        $jsonLD->audience = $audienceUpdated->getAudience()->serialize();
622
623
        return $document->withBody($jsonLD);
624
    }
625
626
    /**
627
     * @inheritdoc
628
     */
629
    public function placeJSONLD($placeId)
630
    {
631
        if (empty($placeId)) {
632
            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...
633
        }
634
635
        try {
636
            $placeJSONLD = $this->placeService->getEntity(
637
                $placeId
638
            );
639
640
            return json_decode($placeJSONLD);
641
        } catch (EntityNotFoundException $e) {
642
            // In case the place can not be found at the moment, just add its ID
643
            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...
644
                '@id' => $this->placeService->iri($placeId),
645
            );
646
        } catch (DocumentGoneException $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
        }
652
    }
653
654
    private function generateSameAs($eventId, $name)
655
    {
656
        $eventSlug = $this->slugger->slug($name);
657
        return array(
658
            'http://www.uitinvlaanderen.be/agenda/e/' . $eventSlug . '/' . $eventId,
659
        );
660
    }
661
662 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...
663
    {
664
        $properties = $metadata->serialize();
665
666
        if (isset($properties['user_nick'])) {
667
            return new StringLiteral($properties['user_nick']);
668
        }
669
    }
670
671 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...
672
    {
673
        $properties = $metadata->serialize();
674
675
        if (isset($properties['consumer']['name'])) {
676
            return new StringLiteral($properties['consumer']['name']);
677
        }
678
    }
679
680
    /**
681
     * @param DomainMessage $domainMessage
682
     * @return string
683
     */
684
    private function getCreated(DomainMessage $domainMessage)
685
    {
686
        $recordedOn = $domainMessage->getRecordedOn()->toString();
687
688
        return \DateTime::createFromFormat(
689
            DateTime::FORMAT_STRING,
690
            $recordedOn
691
        )->format('c');
692
    }
693
694
    /**
695
     * @return string
696
     */
697
    protected function getLabelAddedClassName()
698
    {
699
        return LabelAdded::class;
700
    }
701
702
    /**
703
     * @return string
704
     */
705
    protected function getLabelRemovedClassName()
706
    {
707
        return LabelRemoved::class;
708
    }
709
710
    /**
711
     * @return string
712
     */
713
    protected function getImageAddedClassName()
714
    {
715
        return ImageAdded::class;
716
    }
717
718
    /**
719
     * @return string
720
     */
721
    protected function getImageRemovedClassName()
722
    {
723
        return ImageRemoved::class;
724
    }
725
726
    /**
727
     * @return string
728
     */
729
    protected function getImageUpdatedClassName()
730
    {
731
        return ImageUpdated::class;
732
    }
733
734
    protected function getMainImageSelectedClassName()
735
    {
736
        return MainImageSelected::class;
737
    }
738
739
    /**
740
     * @return string
741
     */
742
    protected function getTitleTranslatedClassName()
743
    {
744
        return TitleTranslated::class;
745
    }
746
747
    /**
748
     * @return string
749
     */
750
    protected function getDescriptionTranslatedClassName()
751
    {
752
        return DescriptionTranslated::class;
753
    }
754
755
    /**
756
     * @return string
757
     */
758
    protected function getOrganizerUpdatedClassName()
759
    {
760
        return OrganizerUpdated::class;
761
    }
762
763
    /**
764
     * @return string
765
     */
766
    protected function getOrganizerDeletedClassName()
767
    {
768
        return OrganizerDeleted::class;
769
    }
770
771
    protected function getBookingInfoUpdatedClassName()
772
    {
773
        return BookingInfoUpdated::class;
774
    }
775
776
    /**
777
     * @return string
778
     */
779
    protected function getPriceInfoUpdatedClassName()
780
    {
781
        return PriceInfoUpdated::class;
782
    }
783
784
    protected function getContactPointUpdatedClassName()
785
    {
786
        return ContactPointUpdated::class;
787
    }
788
789
    protected function getDescriptionUpdatedClassName()
790
    {
791
        return DescriptionUpdated::class;
792
    }
793
794
    protected function getCalendarUpdatedClassName()
795
    {
796
        return CalendarUpdated::class;
797
    }
798
799
    protected function getTypicalAgeRangeUpdatedClassName()
800
    {
801
        return TypicalAgeRangeUpdated::class;
802
    }
803
804
    protected function getTypicalAgeRangeDeletedClassName()
805
    {
806
        return TypicalAgeRangeDeleted::class;
807
    }
808
809
    protected function getPublishedClassName()
810
    {
811
        return Published::class;
812
    }
813
814
    protected function getApprovedClassName()
815
    {
816
        return Approved::class;
817
    }
818
819
    protected function getRejectedClassName()
820
    {
821
        return Rejected::class;
822
    }
823
824
    protected function getFlaggedAsDuplicateClassName()
825
    {
826
        return FlaggedAsDuplicate::class;
827
    }
828
829
    protected function getFlaggedAsInappropriateClassName()
830
    {
831
        return FlaggedAsInappropriate::class;
832
    }
833
834
    protected function getImagesImportedFromUdb2ClassName()
835
    {
836
        return ImagesImportedFromUDB2::class;
837
    }
838
839
    protected function getImagesUpdatedFromUdb2ClassName()
840
    {
841
        return ImagesUpdatedFromUDB2::class;
842
    }
843
844
    protected function getTitleUpdatedClassName()
845
    {
846
        return TitleUpdated::class;
847
    }
848
849
    protected function getTypeUpdatedClassName()
850
    {
851
        return TypeUpdated::class;
852
    }
853
854
    protected function getThemeUpdatedClassName()
855
    {
856
        return ThemeUpdated::class;
857
    }
858
859
    protected function getFacilitiesUpdatedClassName()
860
    {
861
        return FacilitiesUpdated::class;
862
    }
863
}
864