Completed
Push — master ( dc82d8...d048aa )
by Kristof
14:05
created

loadDocumentFromRepositoryByEventId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 10
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
/**
3
 * @file
4
 */
5
6
namespace CultuurNet\UDB3\Event;
7
8
use Broadway\Domain\DateTime;
9
use Broadway\Domain\DomainMessage;
10
use Broadway\Domain\Metadata;
11
use Broadway\EventHandling\EventListenerInterface;
12
use CultuurNet\UDB3\Cdb\EventItemFactory;
13
use CultuurNet\UDB3\CulturefeedSlugger;
14
use CultuurNet\UDB3\EntityNotFoundException;
15
use CultuurNet\UDB3\Event\Events\EventCreatedFromCdbXml;
16
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated;
17
use CultuurNet\UDB3\Event\Events\ContactPointUpdated;
18
use CultuurNet\UDB3\Event\Events\DescriptionUpdated;
19
use CultuurNet\UDB3\Event\Events\EventCreated;
20
use CultuurNet\UDB3\Event\Events\EventDeleted;
21
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
22
use CultuurNet\UDB3\Event\Events\EventUpdatedFromCdbXml;
23
use CultuurNet\UDB3\Event\Events\EventUpdatedFromUDB2;
24
use CultuurNet\UDB3\Event\Events\EventWasLabelled;
25
use CultuurNet\UDB3\Event\Events\ImageAdded;
26
use CultuurNet\UDB3\Event\Events\ImageDeleted;
27
use CultuurNet\UDB3\Event\Events\ImageUpdated;
28
use CultuurNet\UDB3\Event\Events\LabelsMerged;
29
use CultuurNet\UDB3\Event\Events\MajorInfoUpdated;
30
use CultuurNet\UDB3\Event\Events\OrganizerDeleted;
31
use CultuurNet\UDB3\Event\Events\OrganizerUpdated;
32
use CultuurNet\UDB3\Event\Events\TranslationApplied;
33
use CultuurNet\UDB3\Event\Events\TranslationDeleted;
34
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeDeleted;
35
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeUpdated;
36
use CultuurNet\UDB3\Event\Events\Unlabelled;
37
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
38
use CultuurNet\UDB3\Event\ReadModel\JSONLD\CdbXMLImporter;
39
use CultuurNet\UDB3\Event\ReadModel\JSONLD\OrganizerServiceInterface;
40
use CultuurNet\UDB3\Event\ReadModel\JSONLD\PlaceServiceInterface;
41
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait;
42
use CultuurNet\UDB3\EventServiceInterface;
43
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
44
use CultuurNet\UDB3\Label;
45
use CultuurNet\UDB3\LabelCollection;
46
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
47
use CultuurNet\UDB3\Media\Serialization\MediaObjectSerializer;
48
use CultuurNet\UDB3\Organizer\OrganizerProjectedToJSONLD;
49
use CultuurNet\UDB3\OrganizerService;
50
use CultuurNet\UDB3\Place\PlaceProjectedToJSONLD;
51
use CultuurNet\UDB3\PlaceService;
52
use CultuurNet\UDB3\ReadModel\JsonDocument;
53
use CultuurNet\UDB3\SluggerInterface;
54
use CultuurNet\UDB3\StringFilter\StringFilterInterface;
55
use CultuurNet\UDB3\Theme;
56
use Symfony\Component\Serializer\SerializerInterface;
57
use ValueObjects\String\String;
58
59
/**
60
 * Projects state changes on Event entities to a JSON-LD read model in a
61
 * document repository.
62
 *
63
 * Implements PlaceServiceInterface and OrganizerServiceInterface to do a double
64
 * dispatch with CdbXMLImporter.
65
 */
66
class EventLDProjector implements EventListenerInterface, PlaceServiceInterface, OrganizerServiceInterface
67
{
68
    use DelegateEventHandlingToSpecificMethodTrait;
69
70
    /**
71
     * @var DocumentRepositoryInterface
72
     */
73
    protected $repository;
74
75
    /**
76
     * @var IriGeneratorInterface
77
     */
78
    protected $iriGenerator;
79
80
    /**
81
     * @var OrganizerService
82
     */
83
    protected $organizerService;
84
85
    /**
86
     * @var PlaceService
87
     */
88
    protected $placeService;
89
90
    /**
91
     * @var EventServiceInterface
92
     */
93
    protected $eventService;
94
95
    /**
96
     * @var SluggerInterface
97
     */
98
    protected $slugger;
99
100
    /**
101
     * @var CdbXMLImporter
102
     */
103
    protected $cdbXMLImporter;
104
105
    /**
106
     * @var SerializerInterface
107
     */
108
    protected $mediaObjectSerializer;
109
110
    /**
111
     * @param DocumentRepositoryInterface $repository
112
     * @param IriGeneratorInterface $iriGenerator
113
     * @param EventServiceInterface $eventService
114
     * @param PlaceService $placeService
115
     * @param OrganizerService $organizerService
116
     * @param SerializerInterface $mediaObjectSerializer
117
     */
118
    public function __construct(
119
        DocumentRepositoryInterface $repository,
120
        IriGeneratorInterface $iriGenerator,
121
        EventServiceInterface $eventService,
122
        PlaceService $placeService,
123
        OrganizerService $organizerService,
124
        SerializerInterface $mediaObjectSerializer
125
    ) {
126
        $this->repository = $repository;
127
        $this->iriGenerator = $iriGenerator;
128
        $this->organizerService = $organizerService;
129
        $this->placeService = $placeService;
130
        $this->eventService = $eventService;
131
        $this->mediaObjectSerializer = $mediaObjectSerializer;
132
133
        $this->slugger = new CulturefeedSlugger();
134
        $this->cdbXMLImporter = new CdbXMLImporter(new CdbXMLItemBaseImporter());
135
    }
136
137 View Code Duplication
    protected function applyOrganizerProjectedToJSONLD(OrganizerProjectedToJSONLD $organizerProjectedToJSONLD)
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...
138
    {
139
        $eventIds = $this->eventsOrganizedByOrganizer(
140
            $organizerProjectedToJSONLD->getId()
141
        );
142
143
        $organizer = $this->organizerService->getEntity(
144
            $organizerProjectedToJSONLD->getId()
145
        );
146
147
        foreach ($eventIds as $eventId) {
148
            $document = $this->loadDocumentFromRepositoryByEventId(
149
                $eventId
150
            );
151
            $eventLD = $document->getBody();
152
153
            $newEventLD = clone $eventLD;
154
            $newEventLD->organizer = json_decode($organizer);
155
156
            if ($newEventLD != $eventLD) {
157
                $this->repository->save($document->withBody($newEventLD));
158
            }
159
        }
160
    }
161
162 View Code Duplication
    protected function applyPlaceProjectedToJSONLD(
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...
163
        PlaceProjectedToJSONLD $placeProjectedToJSONLD
164
    ) {
165
        $eventsLocatedAtPlace = $this->eventsLocatedAtPlace(
166
            $placeProjectedToJSONLD->getId()
167
        );
168
169
        $placeJSONLD = $this->placeService->getEntity(
170
            $placeProjectedToJSONLD->getId()
171
        );
172
173
        foreach ($eventsLocatedAtPlace as $eventId) {
174
            $document = $this->loadDocumentFromRepositoryByEventId(
175
                $eventId
176
            );
177
            $eventLD = $document->getBody();
178
179
            $newEventLD = clone $eventLD;
180
            $newEventLD->location = json_decode($placeJSONLD);
181
182
            if ($newEventLD != $eventLD) {
183
                $this->repository->save($document->withBody($newEventLD));
184
            }
185
        }
186
    }
187
188
    /**
189
     * @param string $organizerId
190
     * @return string[]
191
     */
192
    protected function eventsOrganizedByOrganizer($organizerId)
193
    {
194
        return $this->eventService->eventsOrganizedByOrganizer(
195
            $organizerId
196
        );
197
    }
198
199
    /**
200
     * @param string $placeId
201
     * @return string[]
202
     */
203
    protected function eventsLocatedAtPlace($placeId)
204
    {
205
        return $this->eventService->eventsLocatedAtPlace(
206
            $placeId
207
        );
208
    }
209
210
    /**
211
     * @param EventImportedFromUDB2 $eventImportedFromUDB2
212
     */
213
    protected function applyEventImportedFromUDB2(
214
        EventImportedFromUDB2 $eventImportedFromUDB2
215
    ) {
216
        $this->applyEventCdbXml(
217
            $eventImportedFromUDB2->getEventId(),
218
            $eventImportedFromUDB2->getCdbXmlNamespaceUri(),
219
            $eventImportedFromUDB2->getCdbXml()
220
        );
221
    }
222
223
    /**
224
     * @param EventUpdatedFromUDB2 $eventUpdatedFromUDB2
225
     */
226
    protected function applyEventUpdatedFromUDB2(
227
        EventUpdatedFromUDB2 $eventUpdatedFromUDB2
228
    ) {
229
        $this->applyEventCdbXml(
230
            $eventUpdatedFromUDB2->getEventId(),
231
            $eventUpdatedFromUDB2->getCdbXmlNamespaceUri(),
232
            $eventUpdatedFromUDB2->getCdbXml()
233
        );
234
    }
235
236
    /**
237
     * @param EventCreatedFromCdbXml $eventCreatedFromCdbXml
238
     * @param DomainMessage $domainMessage
239
     */
240 View Code Duplication
    protected function applyEventCreatedFromCdbXml(
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...
241
        EventCreatedFromCdbXml $eventCreatedFromCdbXml,
242
        DomainMessage $domainMessage
243
    ) {
244
        $cdbXmlNamespaceUri = $eventCreatedFromCdbXml->getCdbXmlNamespaceUri()->toNative();
245
        $cdbXml = $eventCreatedFromCdbXml->getEventXmlString()->toEventXmlString();
246
        $eventId = $eventCreatedFromCdbXml->getEventId()->toNative();
247
248
        $this->applyEventFromCdbXml(
249
            $eventId,
250
            $cdbXmlNamespaceUri,
251
            $cdbXml,
252
            $domainMessage
253
        );
254
    }
255
256
    /**
257
     * @param EventUpdatedFromCdbXml $eventUpdatedFromCdbXml
258
     * @param DomainMessage $domainMessage
259
     */
260 View Code Duplication
    protected function applyEventUpdatedFromCdbXml(
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...
261
        EventUpdatedFromCdbXml $eventUpdatedFromCdbXml,
262
        DomainMessage $domainMessage
263
    ) {
264
        $cdbXmlNamespaceUri = $eventUpdatedFromCdbXml->getCdbXmlNamespaceUri()->toNative();
265
        $cdbXml = $eventUpdatedFromCdbXml->getEventXmlString()->toEventXmlString();
266
        $eventId = $eventUpdatedFromCdbXml->getEventId()->toNative();
267
268
        $this->applyEventFromCdbXml(
269
            $eventId,
270
            $cdbXmlNamespaceUri,
271
            $cdbXml,
272
            $domainMessage
273
        );
274
    }
275
276
    /**
277
     * Helper function to save JSONLD document from entryapi cdbxml.
278
     *
279
     * @param string $eventId
280
     * @param string $cdbXmlNamespaceUri
281
     * @param string $cdbXml
282
     * @param DomainMessage $domainMessage
283
     */
284
    protected function applyEventFromCdbXml(
285
        $eventId,
286
        $cdbXmlNamespaceUri,
287
        $cdbXml,
288
        $domainMessage
289
    ) {
290
        $udb2Event = EventItemFactory::createEventFromCdbXml(
291
            $cdbXmlNamespaceUri,
292
            $cdbXml
293
        );
294
295
        $document = $this->newDocument($eventId);
296
        $eventLd = $document->getBody();
297
298
        $eventLd = $this->cdbXMLImporter->documentWithCdbXML(
299
            $eventLd,
300
            $udb2Event,
301
            $this,
302
            $this,
303
            $this->slugger
304
        );
305
306
        // Add creation date and update date from metadata.
307
        $eventCreationDate = $domainMessage->getRecordedOn();
308
309
        $eventCreationString = $eventCreationDate->toString();
310
        $eventCreationDateTime = \DateTime::createFromFormat(
311
            DateTime::FORMAT_STRING,
312
            $eventCreationString
313
        );
314
        $eventLd->created = $eventCreationDateTime->format('c');
315
        $eventLd->modified = $eventCreationDateTime->format('c');
316
317
        // Add creator.
318
        $eventLd->creator = $this->getAuthorFromMetadata($domainMessage->getMetadata())->toNative();
319
320
        // Add publisher, which is the consumer name.
321
        $eventLd->publisher = $this->getConsumerFromMetadata($domainMessage->getMetadata())->toNative();
322
323
        $this->repository->save($document->withBody($eventLd));
324
    }
325
326
    /**
327
     * @param string $eventId
328
     * @param string $cdbXmlNamespaceUri
329
     * @param string $cdbXml
330
     */
331
    protected function applyEventCdbXml(
332
        $eventId,
333
        $cdbXmlNamespaceUri,
334
        $cdbXml
335
    ) {
336
        $udb2Event = EventItemFactory::createEventFromCdbXml(
337
            $cdbXmlNamespaceUri,
338
            $cdbXml
339
        );
340
341
        $document = $this->newDocument($eventId);
342
        $eventLd = $document->getBody();
343
344
        $eventLd = $this->cdbXMLImporter->documentWithCdbXML(
345
            $eventLd,
346
            $udb2Event,
347
            $this,
348
            $this,
349
            $this->slugger
350
        );
351
352
        $this->repository->save($document->withBody($eventLd));
353
    }
354
355
    /**
356
     * @param EventCreated $eventCreated
357
     * @param DomainMessage $domainMessage
358
     */
359
    protected function applyEventCreated(
360
        EventCreated $eventCreated,
361
        DomainMessage $domainMessage
362
    ) {
363
        $document = $this->newDocument($eventCreated->getEventId());
364
365
        $jsonLD = $document->getBody();
366
367
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
368
            $eventCreated->getEventId()
369
        );
370
        $jsonLD->name['nl'] = $eventCreated->getTitle();
371
        $jsonLD->location = array(
372
          '@type' => 'Place',
373
        ) + (array)$this->placeJSONLD($eventCreated->getLocation()->getCdbid());
374
375
        $calendarJsonLD = $eventCreated->getCalendar()->toJsonLd();
376
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
377
378
        // Same as.
379
        $jsonLD->sameAs = $this->generateSameAs(
380
            $eventCreated->getEventId(),
381
            reset($jsonLD->name)
382
        );
383
384
        $eventType = $eventCreated->getEventType();
385
        $jsonLD->terms = [
386
            $eventType->toJsonLd()
387
        ];
388
389
        $theme = $eventCreated->getTheme();
390
        if (!empty($theme)) {
391
            $jsonLD->terms[] = $theme->toJsonLd();
392
        }
393
394
        $recordedOn = $domainMessage->getRecordedOn()->toString();
395
        $jsonLD->created = \DateTime::createFromFormat(
396
            DateTime::FORMAT_STRING,
397
            $recordedOn
398
        )->format('c');
399
        $jsonLD->modified = $jsonLD->created;
400
401
        $metaData = $domainMessage->getMetadata()->serialize();
402 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...
403
            $jsonLD->creator = $metaData['user_email'];
404
        } elseif (isset($metaData['user_nick'])) {
405
            $jsonLD->creator = $metaData['user_nick'];
406
        }
407
408
        $this->repository->save($document->withBody($jsonLD));
409
    }
410
411
    /**
412
     * @param EventDeleted $eventDeleted
413
     */
414
    protected function applyEventDeleted(EventDeleted $eventDeleted)
415
    {
416
        $this->repository->remove($eventDeleted->getEventId());
417
    }
418
419
    /**
420
     * Apply the major info updated command to the projector.
421
     */
422
    protected function applyMajorInfoUpdated(MajorInfoUpdated $majorInfoUpdated)
423
    {
424
425
        $document = $this->loadDocumentFromRepository($majorInfoUpdated);
426
        $jsonLD = $document->getBody();
427
428
        $jsonLD->name->nl = $majorInfoUpdated->getTitle();
429
        $jsonLD->location = array(
430
          '@type' => 'Place',
431
        ) + (array)$this->placeJSONLD($majorInfoUpdated->getLocation()->getCdbid());
432
433
        $calendarJsonLD = $majorInfoUpdated->getCalendar()->toJsonLd();
434
        $jsonLD = (object) array_merge((array) $jsonLD, $calendarJsonLD);
435
436
        // Remove old theme and event type.
437
        $jsonLD->terms = array_filter($jsonLD->terms, function ($term) {
438
            return $term->domain !== EventType::DOMAIN &&  $term->domain !== Theme::DOMAIN;
439
        });
440
441
        $eventType = $majorInfoUpdated->getEventType();
442
        $jsonLD->terms = [
443
            $eventType->toJsonLd()
444
        ];
445
446
        $theme = $majorInfoUpdated->getTheme();
447
        if (!empty($theme)) {
448
            $jsonLD->terms[] = $theme->toJsonLd();
449
        }
450
451
        $this->repository->save($document->withBody($jsonLD));
452
453
    }
454
455
    /**
456
     * @inheritdoc
457
     */
458
    public function placeJSONLD($placeId)
459
    {
460
        try {
461
            $placeJSONLD = $this->placeService->getEntity(
462
                $placeId
463
            );
464
465
            return json_decode($placeJSONLD);
466
        } catch (EntityNotFoundException $e) {
467
            // In case the place can not be found at the moment, just add its ID
468
            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...
469
                '@id' => $this->placeService->iri($placeId)
470
            );
471
        }
472
    }
473
474
    /**
475
     * @inheritdoc
476
     */
477 View Code Duplication
    public function organizerJSONLD($organizerId)
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...
478
    {
479
480
        try {
481
            $organizerJSONLD = $this->organizerService->getEntity(
482
                $organizerId
483
            );
484
485
            return json_decode($organizerJSONLD);
486
        } catch (EntityNotFoundException $e) {
487
            // In case the place can not be found at the moment, just add its ID
488
            return array(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return array('@id' => $t...ce->iri($organizerId)); (array<string,string>) is incompatible with the return type declared by the interface CultuurNet\UDB3\Event\Re...erface::organizerJSONLD 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...
489
                '@id' => $this->organizerService->iri($organizerId)
490
            );
491
        }
492
    }
493
494
    /**
495
     * @param EventWasLabelled $eventWasLabelled
496
     */
497
    protected function applyEventWasLabelled(EventWasLabelled $eventWasLabelled)
498
    {
499
        $document = $this->loadDocumentFromRepository($eventWasLabelled);
500
501
        $eventLd = $document->getBody();
502
503
        $labels = isset($eventLd->labels) ? $eventLd->labels : [];
504
        $label = (string) $eventWasLabelled->getLabel();
505
506
        $labels[] = $label;
507
        $eventLd->labels = array_unique($labels);
508
509
        $this->repository->save($document->withBody($eventLd));
510
    }
511
512
    protected function applyUnlabelled(Unlabelled $unlabelled)
513
    {
514
        $document = $this->loadDocumentFromRepository($unlabelled);
515
516
        $eventLd = $document->getBody();
517
518
        if (is_array($eventLd->labels)) {
519
            $eventLd->labels = array_filter(
520
                $eventLd->labels,
521
                function ($label) use ($unlabelled) {
522
                    return !$unlabelled->getLabel()->equals(
523
                        new Label($label)
524
                    );
525
                }
526
            );
527
            // Ensure array keys start with 0 so json_encode() does encode it
528
            // as an array and not as an object.
529
            $eventLd->labels = array_values($eventLd->labels);
530
        }
531
532
        $this->repository->save($document->withBody($eventLd));
533
    }
534
535
    /**
536
     * @param LabelsMerged $labelsMerged
537
     */
538
    protected function applyLabelsMerged(LabelsMerged $labelsMerged)
539
    {
540
        $document = $this->loadDocumentFromRepositoryByEventId($labelsMerged->getEventId()->toNative());
541
542
        $eventLd = $document->getBody();
543
544
        $labels = isset($eventLd->labels) ? $eventLd->labels : [];
545
546
        $currentCollection = LabelCollection::fromStrings($labels);
547
548
        $newLabels = $labelsMerged->getLabels();
549
550
        $eventLd->labels = $currentCollection->merge($newLabels)->toStrings();
551
552
        $this->repository->save($document->withBody($eventLd));
553
    }
554
555
    protected function applyTitleTranslated(TitleTranslated $titleTranslated)
556
    {
557
        $document = $this->loadDocumentFromRepository($titleTranslated);
558
559
        $eventLd = $document->getBody();
560
        $eventLd->name->{$titleTranslated->getLanguage()->getCode(
561
        )} = $titleTranslated->getTitle();
562
563
        $this->repository->save($document->withBody($eventLd));
564
    }
565
566 View Code Duplication
    protected function applyDescriptionTranslated(
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...
567
        DescriptionTranslated $descriptionTranslated
568
    ) {
569
        $document = $this->loadDocumentFromRepository($descriptionTranslated);
570
571
        $eventLd = $document->getBody();
572
        $eventLd->description->{$descriptionTranslated->getLanguage()->getCode(
573
        )} = $descriptionTranslated->getDescription();
574
575
        $this->repository->save($document->withBody($eventLd));
576
    }
577
578
    protected function applyTranslationApplied(
579
        TranslationApplied $translationApplied
580
    ) {
581
        $document = $this->loadDocumentFromRepositoryByEventId($translationApplied->getEventId()->toNative());
582
583
        $eventLd = $document->getBody();
584
585 View Code Duplication
        if ($translationApplied->getTitle() !== null) {
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...
586
            $eventLd->name->{$translationApplied->getLanguage()->getCode(
587
            )} = $translationApplied->getTitle()->toNative();
588
        }
589
590 View Code Duplication
        if ($translationApplied->getLongDescription() !== null) {
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...
591
            $eventLd->description->{$translationApplied->getLanguage()->getCode(
592
            )} = $translationApplied->getLongDescription()->toNative();
593
        }
594
595
        $this->repository->save($document->withBody($eventLd));
596
    }
597
598
    /**
599
     * Apply the translation deleted event to the event repository.
600
     * @param TranslationDeleted $translationDeleted
601
     */
602
    protected function applyTranslationDeleted(
603
        TranslationDeleted $translationDeleted
604
    ) {
605
        $document = $this->loadDocumentFromRepositoryByEventId($translationDeleted->getEventId()->toNative());
606
607
        $eventLd = $document->getBody();
608
609
        unset($eventLd->name->{$translationDeleted->getLanguage()->getCode()});
610
611
        unset($eventLd->description->{$translationDeleted->getLanguage()->getCode()});
612
613
        $this->repository->save($document->withBody($eventLd));
614
    }
615
616
    /**
617
     * Apply the description updated event to the event repository.
618
     * @param DescriptionUpdated $descriptionUpdated
619
     */
620 View Code Duplication
    protected function applyDescriptionUpdated(
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...
621
        DescriptionUpdated $descriptionUpdated
622
    ) {
623
        $document = $this->loadDocumentFromRepository($descriptionUpdated);
624
625
        $eventLd = $document->getBody();
626
        if (empty($eventLd->description)) {
627
            $eventLd->description = new \stdClass();
628
        }
629
        $eventLd->description->{'nl'} = $descriptionUpdated->getDescription();
630
631
        $this->repository->save($document->withBody($eventLd));
632
    }
633
634
    /**
635
     * Apply the typical age range updated event to the event repository.
636
     * @param TypicalAgeRangeUpdated $typicalAgeRangeUpdated
637
     */
638 View Code Duplication
    protected function applyTypicalAgeRangeUpdated(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
639
        TypicalAgeRangeUpdated $typicalAgeRangeUpdated
640
    ) {
641
        $document = $this->loadDocumentFromRepository($typicalAgeRangeUpdated);
642
643
        $eventLd = $document->getBody();
644
        $eventLd->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange();
645
646
        $this->repository->save($document->withBody($eventLd));
647
    }
648
649
    /**
650
     * Apply the typical age range deleted event to the event repository.
651
     * @param TypicalAgeRangeDeleted $typicalAgeRangeDeleted
652
     */
653
    protected function applyTypicalAgeRangeDeleted(
654
        TypicalAgeRangeDeleted $typicalAgeRangeDeleted
655
    ) {
656
        $document = $this->loadDocumentFromRepository($typicalAgeRangeDeleted);
657
658
        $eventLd = $document->getBody();
659
660
        unset($eventLd->typicalAgeRange);
661
662
        $this->repository->save($document->withBody($eventLd));
663
    }
664
665
    /**
666
     * Apply the organizer updated event to the event repository.
667
     * @param OrganizerUpdated $organizerUpdated
668
     */
669 View Code Duplication
    protected function applyOrganizerUpdated(OrganizerUpdated $organizerUpdated)
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...
670
    {
671
672
        $document = $this->loadDocumentFromRepository($organizerUpdated);
673
674
        $eventLd = $document->getBody();
675
676
        $eventLd->organizer = array(
677
          '@type' => 'Organizer',
678
        ) + (array)$this->organizerJSONLD($organizerUpdated->getOrganizerId());
679
680
        $this->repository->save($document->withBody($eventLd));
681
    }
682
683
    /**
684
     * Apply the organizer delete event to the event repository.
685
     * @param OrganizerDeleted $organizerDeleted
686
     */
687
    protected function applyOrganizerDeleted(OrganizerDeleted $organizerDeleted)
688
    {
689
690
        $document = $this->loadDocumentFromRepository($organizerDeleted);
691
692
        $eventLd = $document->getBody();
693
694
        unset($eventLd->organizer);
695
696
        $this->repository->save($document->withBody($eventLd));
697
    }
698
699
    /**
700
     * Apply the contact info updated event to the event repository.
701
     * @param ContactPointUpdated $contactPointUpdated
702
     */
703
    protected function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated)
704
    {
705
706
        $document = $this->loadDocumentFromRepository($contactPointUpdated);
707
708
        $eventLd = $document->getBody();
709
        $eventLd->contactPoint = $contactPointUpdated->getContactPoint()->toJsonLd();
710
711
        $this->repository->save($document->withBody($eventLd));
712
    }
713
714
    /**
715
     * Apply the booking info updated event to the event repository.
716
     * @param BookingInfoUpdated $bookingInfoUpdated
717
     */
718 View Code Duplication
    protected function applyBookingInfoUpdated(BookingInfoUpdated $bookingInfoUpdated)
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...
719
    {
720
721
        $document = $this->loadDocumentFromRepository($bookingInfoUpdated);
722
723
        $eventLd = $document->getBody();
724
        $eventLd->bookingInfo = $bookingInfoUpdated->getBookingInfo()->toJsonLd();
725
726
        $this->repository->save($document->withBody($eventLd));
727
728
    }
729
730
    /**
731
     * Apply the imageAdded event to the event repository.
732
     *
733
     * @param ImageAdded $imageAdded
734
     */
735 View Code Duplication
    protected function applyImageAdded(ImageAdded $imageAdded)
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...
736
    {
737
        $document = $this->loadDocumentFromRepository($imageAdded);
738
739
        $eventLd = $document->getBody();
740
        $eventLd->mediaObject = isset($eventLd->mediaObject) ? $eventLd->mediaObject : [];
741
742
        $imageData = $this->mediaObjectSerializer
743
            ->serialize($imageAdded->getImage(), 'json-ld');
744
        $eventLd->mediaObject[] = $imageData;
745
746
        $this->repository->save($document->withBody($eventLd));
747
    }
748
749
    /**
750
     * Apply the ImageUpdated event to the event repository.
751
     *
752
     * @param ImageUpdated $imageUpdated
753
     */
754
    protected function applyImageUpdated(ImageUpdated $imageUpdated)
755
    {
756
        $document = $this->loadDocumentFromRepositoryByEventId($imageUpdated->getItemId());
757
758
        $eventLd = $document->getBody();
759
760
        if (!isset($eventLd->mediaObject)) {
761
            throw new \Exception('The image to update could not be found.');
762
        }
763
764
        $updatedMediaObjects = [];
765
766 View Code Duplication
        foreach ($eventLd->mediaObject as $mediaObject) {
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...
767
            $mediaObjectMatches = (
768
                strpos(
769
                    $mediaObject->{'@id'},
770
                    (string)$imageUpdated->getMediaObjectId()
771
                ) > 0
772
            );
773
774
            if ($mediaObjectMatches) {
775
                $mediaObject->description = (string)$imageUpdated->getDescription();
776
                $mediaObject->copyrightHolder = (string)$imageUpdated->getCopyrightHolder();
777
778
                $updatedMediaObjects[] = $mediaObject;
779
            }
780
        };
781
782
        if (empty($updatedMediaObjects)) {
783
            throw new \Exception('The image to update could not be found.');
784
        }
785
786
        $this->repository->save($document->withBody($eventLd));
787
    }
788
789
    /**
790
     * Apply the imageDeleted event to the event repository.
791
     *
792
     * @param ImageDeleted $imageDeleted
793
     */
794 View Code Duplication
    protected function applyImageDeleted(ImageDeleted $imageDeleted)
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...
795
    {
796
797
        $document = $this->loadDocumentFromRepository($imageDeleted);
798
799
        $eventLd = $document->getBody();
800
        unset($eventLd->mediaObject[$imageDeleted->getIndexToDelete()]);
801
802
        // Generate new numeric keys.
803
        $eventLd->mediaObject = array_values($eventLd->mediaObject);
804
805
        $this->repository->save($document->withBody($eventLd));
806
807
    }
808
809
    /**
810
     * @param string $id
811
     * @return JsonDocument
812
     */
813 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...
814
    {
815
        $document = new JsonDocument($id);
816
817
        $eventLd = $document->getBody();
818
        $eventLd->{'@id'} = $this->iriGenerator->iri($id);
819
820
        // @todo provide Event-LD context here relative to the base URI
821
        $eventLd->{'@context'} = '/api/1.0/event.jsonld';
822
823
        return $document->withBody($eventLd);
824
    }
825
826
    /**
827
     * @param EventEvent $event
828
     * @return JsonDocument
829
     */
830
    protected function loadDocumentFromRepository(EventEvent $event)
831
    {
832
        return $this->loadDocumentFromRepositoryByEventId($event->getEventId());
833
    }
834
835
    /**
836
     * @param string $eventId
837
     * @return JsonDocument
838
     */
839
    protected function loadDocumentFromRepositoryByEventId($eventId)
840
    {
841
        $document = $this->repository->get($eventId);
842
843
        if (!$document) {
844
            return $this->newDocument($eventId);
845
        }
846
847
        return $document;
848
    }
849
850
    private function generateSameAs($eventId, $name)
851
    {
852
        $eventSlug = $this->slugger->slug($name);
853
        return array(
854
            'http://www.uitinvlaanderen.be/agenda/e/' . $eventSlug . '/' . $eventId,
855
        );
856
    }
857
858
    public function addDescriptionFilter(StringFilterInterface $filter)
859
    {
860
        $this->cdbXMLImporter->addDescriptionFilter($filter);
861
    }
862
863 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...
864
    {
865
        $properties = $metadata->serialize();
866
867
        if (isset($properties['user_nick'])) {
868
            return new String($properties['user_nick']);
869
        }
870
    }
871
872 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...
873
    {
874
        $properties = $metadata->serialize();
875
876
        if (isset($properties['consumer']['name'])) {
877
            return new String($properties['consumer']['name']);
878
        }
879
    }
880
}
881