Completed
Pull Request — master (#340)
by Luc
05:42
created

EventLDProjector::getThemeUpdatedClassName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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