Completed
Pull Request — master (#322)
by Luc
04:41
created

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