Completed
Pull Request — master (#306)
by Luc
10:58
created

OrganizerLDProjector::applyTitle()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 14
nc 4
nop 2
1
<?php
2
3
namespace CultuurNet\UDB3\Organizer;
4
5
use Broadway\Domain\DateTime;
6
use Broadway\Domain\DomainMessage;
7
use Broadway\EventHandling\EventBusInterface;
8
use Broadway\EventHandling\EventListenerInterface;
9
use CultuurNet\UDB3\Actor\ActorEvent;
10
use CultuurNet\UDB3\Cdb\ActorItemFactory;
11
use CultuurNet\UDB3\Event\ReadModel\DocumentGoneException;
12
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface;
13
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait;
14
use CultuurNet\UDB3\Iri\IriGeneratorInterface;
15
use CultuurNet\UDB3\Label;
16
use CultuurNet\UDB3\Language;
17
use CultuurNet\UDB3\Organizer\Events\AddressUpdated;
18
use CultuurNet\UDB3\Organizer\Events\ContactPointUpdated;
19
use CultuurNet\UDB3\Organizer\Events\LabelAdded;
20
use CultuurNet\UDB3\Organizer\Events\LabelRemoved;
21
use CultuurNet\UDB3\Organizer\Events\OrganizerCreated;
22
use CultuurNet\UDB3\Organizer\Events\OrganizerCreatedWithUniqueWebsite;
23
use CultuurNet\UDB3\Organizer\Events\OrganizerDeleted;
24
use CultuurNet\UDB3\Organizer\Events\OrganizerImportedFromUDB2;
25
use CultuurNet\UDB3\Organizer\Events\OrganizerUpdatedFromUDB2;
26
use CultuurNet\UDB3\Organizer\Events\TitleTranslated;
27
use CultuurNet\UDB3\Organizer\Events\TitleUpdated;
28
use CultuurNet\UDB3\Organizer\Events\WebsiteUpdated;
29
use CultuurNet\UDB3\Organizer\ReadModel\JSONLD\CdbXMLImporter;
30
use CultuurNet\UDB3\ReadModel\JsonDocument;
31
use CultuurNet\UDB3\ReadModel\MultilingualJsonLDProjectorTrait;
32
33
class OrganizerLDProjector implements EventListenerInterface
34
{
35
    use MultilingualJsonLDProjectorTrait;
36
    /**
37
     * @uses applyOrganizerImportedFromUDB2
38
     * @uses applyOrganizerCreated
39
     * @uses applyOrganizerCreatedWithUniqueWebsite
40
     * @uses applyWebsiteUpdated
41
     * @uses applyTitleUpdated
42
     * @uses applyTitleTranslated
43
     * @uses applyAddressUpdated
44
     * @uses applyContactPointUpdated
45
     * @uses applyOrganizerUpdatedFRomUDB2
46
     * @uses applyLabelAdded
47
     * @uses applyLabelRemoved
48
     * @uses applyOrganizerDeleted
49
     */
50
    use DelegateEventHandlingToSpecificMethodTrait;
51
52
    /**
53
     * @var DocumentRepositoryInterface
54
     */
55
    protected $repository;
56
57
    /**
58
     * @var IriGeneratorInterface
59
     */
60
    protected $iriGenerator;
61
62
    /**
63
     * @var EventBusInterface
64
     */
65
    protected $eventBus;
66
67
    /**
68
     * @var CdbXMLImporter
69
     */
70
    private $cdbXMLImporter;
71
72
    /**
73
     * @param DocumentRepositoryInterface $repository
74
     * @param IriGeneratorInterface $iriGenerator
75
     * @param EventBusInterface $eventBus
76
     */
77
    public function __construct(
78
        DocumentRepositoryInterface $repository,
79
        IriGeneratorInterface $iriGenerator,
80
        EventBusInterface $eventBus
81
    ) {
82
        $this->repository = $repository;
83
        $this->iriGenerator = $iriGenerator;
84
        $this->eventBus = $eventBus;
85
        $this->cdbXMLImporter = new CdbXMLImporter();
86
    }
87
88
    /**
89
     * @param OrganizerImportedFromUDB2 $organizerImportedFromUDB2
90
     */
91 View Code Duplication
    private function applyOrganizerImportedFromUDB2(
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...
92
        OrganizerImportedFromUDB2 $organizerImportedFromUDB2
93
    ) {
94
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
95
            $organizerImportedFromUDB2->getCdbXmlNamespaceUri(),
96
            $organizerImportedFromUDB2->getCdbXml()
97
        );
98
99
        $document = $this->newDocument($organizerImportedFromUDB2->getActorId());
100
        $actorLd = $document->getBody();
101
102
        $this->setMainLanguage($actorLd, new Language('nl'));
103
104
        $actorLd = $this->cdbXMLImporter->documentWithCdbXML(
105
            $actorLd,
106
            $udb2Actor
107
        );
108
109
        $this->repository->save($document->withBody($actorLd));
110
    }
111
112
    /**
113
     * @param OrganizerCreated $organizerCreated
114
     * @param DomainMessage $domainMessage
115
     */
116
    private function applyOrganizerCreated(OrganizerCreated $organizerCreated, DomainMessage $domainMessage)
117
    {
118
        $document = $this->newDocument($organizerCreated->getOrganizerId());
119
120
        $jsonLD = $document->getBody();
121
122
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
123
            $organizerCreated->getOrganizerId()
124
        );
125
126
        $this->setMainLanguage($jsonLD, new Language('nl'));
127
128
        $jsonLD->name = [
129
            $this->getMainLanguage($jsonLD)->getCode() => $organizerCreated->getTitle()
130
        ];
131
132
        $addresses = $organizerCreated->getAddresses();
133
        $jsonLD->addresses = array();
134
        foreach ($addresses as $address) {
135
            $jsonLD->addresses[] = array(
136
                'addressCountry' => $address->getCountry(),
137
                'addressLocality' => $address->getLocality(),
138
                'postalCode' => $address->getPostalCode(),
139
                'streetAddress' => $address->getStreetAddress(),
140
            );
141
        }
142
143
        $jsonLD->phone = $organizerCreated->getPhones();
144
        $jsonLD->email = $organizerCreated->getEmails();
145
        $jsonLD->url = $organizerCreated->getUrls();
146
147
        $recordedOn = $domainMessage->getRecordedOn()->toString();
148
        $jsonLD->created = \DateTime::createFromFormat(
149
            DateTime::FORMAT_STRING,
150
            $recordedOn
151
        )->format('c');
152
153
        $metaData = $domainMessage->getMetadata()->serialize();
154 View Code Duplication
        if (isset($metaData['user_id']) && isset($metaData['user_nick'])) {
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...
155
            $jsonLD->creator = "{$metaData['user_id']} ({$metaData['user_nick']})";
156
        }
157
158
        $this->repository->save($document->withBody($jsonLD));
159
    }
160
161
    /**
162
     * @param OrganizerCreatedWithUniqueWebsite $organizerCreated
163
     * @param DomainMessage $domainMessage
164
     */
165
    private function applyOrganizerCreatedWithUniqueWebsite(
166
        OrganizerCreatedWithUniqueWebsite $organizerCreated,
167
        DomainMessage $domainMessage
168
    ) {
169
        $document = $this->newDocument($organizerCreated->getOrganizerId());
170
171
        $jsonLD = $document->getBody();
172
173
        $jsonLD->{'@id'} = $this->iriGenerator->iri(
174
            $organizerCreated->getOrganizerId()
175
        );
176
177
        $this->setMainLanguage($jsonLD, new Language('nl'));
178
179
        $jsonLD->url = (string) $organizerCreated->getWebsite();
180
181
        $jsonLD->name = [
182
            $this->getMainLanguage($jsonLD)->getCode() => $organizerCreated->getTitle()
183
        ];
184
185
        $recordedOn = $domainMessage->getRecordedOn()->toString();
186
        $jsonLD->created = \DateTime::createFromFormat(
187
            DateTime::FORMAT_STRING,
188
            $recordedOn
189
        )->format('c');
190
191
        $metaData = $domainMessage->getMetadata()->serialize();
192 View Code Duplication
        if (isset($metaData['user_id']) && isset($metaData['user_nick'])) {
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...
193
            $jsonLD->creator = "{$metaData['user_id']} ({$metaData['user_nick']})";
194
        }
195
196
        $this->repository->save($document->withBody($jsonLD));
197
    }
198
199
    /**
200
     * @param WebsiteUpdated $websiteUpdated
201
     */
202
    private function applyWebsiteUpdated(WebsiteUpdated $websiteUpdated)
203
    {
204
        $organizerId = $websiteUpdated->getOrganizerId();
205
206
        $document = $this->repository->get($organizerId);
207
208
        $jsonLD = $document->getBody();
209
        $jsonLD->url = (string) $websiteUpdated->getWebsite();
210
211
        $this->repository->save($document->withBody($jsonLD));
212
    }
213
214
    /**
215
     * @param TitleUpdated $titleUpdated
216
     */
217
    private function applyTitleUpdated(TitleUpdated $titleUpdated)
218
    {
219
        $this->applyTitle($titleUpdated);
220
    }
221
222
    /**
223
     * @param TitleTranslated $titleTranslated
224
     */
225
    private function applyTitleTranslated(TitleTranslated $titleTranslated)
226
    {
227
        $this->applyTitle($titleTranslated, $titleTranslated->getLanguage());
228
    }
229
230
    /**
231
     * @param AddressUpdated $addressUpdated
232
     */
233 View Code Duplication
    private function applyAddressUpdated(AddressUpdated $addressUpdated)
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...
234
    {
235
        $organizerId = $addressUpdated->getOrganizerId();
236
        $address = $addressUpdated->getAddress();
237
238
        $document = $this->repository->get($organizerId);
239
240
        $jsonLD = $document->getBody();
241
        $jsonLD->address = $address->toJsonLd();
242
243
        $this->repository->save($document->withBody($jsonLD));
244
    }
245
246
    /**
247
     * @param ContactPointUpdated $contactPointUpdated
248
     */
249 View Code Duplication
    private function applyContactPointUpdated(ContactPointUpdated $contactPointUpdated)
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...
250
    {
251
        $organizerId = $contactPointUpdated->getOrganizerId();
252
        $contactPoint = $contactPointUpdated->getContactPoint();
253
254
        $document = $this->repository->get($organizerId);
255
256
        $jsonLD = $document->getBody();
257
        $jsonLD->contactPoint = $contactPoint->toJsonLd();
258
259
        $this->repository->save($document->withBody($jsonLD));
260
    }
261
262
    /**
263
     * @param OrganizerUpdatedFromUDB2 $organizerUpdatedFromUDB2
264
     */
265 View Code Duplication
    private function applyOrganizerUpdatedFromUDB2(
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...
266
        OrganizerUpdatedFromUDB2 $organizerUpdatedFromUDB2
267
    ) {
268
        // It's possible that an organizer has been deleted in udb3, but never
269
        // in udb2. If an update comes for that organizer from udb2, it should
270
        // be imported again. This is intended by design.
271
        // @see https://jira.uitdatabank.be/browse/III-1092
272
        try {
273
            $document = $this->loadDocumentFromRepository(
274
                $organizerUpdatedFromUDB2
275
            );
276
        } catch (DocumentGoneException $e) {
277
            $document = $this->newDocument($organizerUpdatedFromUDB2->getActorId());
278
        }
279
280
        $udb2Actor = ActorItemFactory::createActorFromCdbXml(
281
            $organizerUpdatedFromUDB2->getCdbXmlNamespaceUri(),
282
            $organizerUpdatedFromUDB2->getCdbXml()
283
        );
284
285
        $actorLd = $this->cdbXMLImporter->documentWithCdbXML(
286
            $document->getBody(),
287
            $udb2Actor
288
        );
289
290
        $this->setMainLanguage($actorLd, new Language('nl'));
291
292
        $this->repository->save($document->withBody($actorLd));
293
    }
294
295
    /**
296
     * @param LabelAdded $labelAdded
297
     */
298 View Code Duplication
    private function applyLabelAdded(LabelAdded $labelAdded)
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...
299
    {
300
        $document = $this->repository->get($labelAdded->getOrganizerId());
301
302
        $jsonLD = $document->getBody();
303
304
        // Check the visibility of the label to update the right property.
305
        $labelsProperty = $labelAdded->getLabel()->isVisible() ? 'labels' : 'hiddenLabels';
306
307
        $labels = isset($jsonLD->{$labelsProperty}) ? $jsonLD->{$labelsProperty} : [];
308
        $label = (string) $labelAdded->getLabel();
309
310
        $labels[] = $label;
311
        $jsonLD->{$labelsProperty} = array_unique($labels);
312
313
        $this->repository->save($document->withBody($jsonLD));
314
    }
315
316
    /**
317
     * @param LabelRemoved $labelRemoved
318
     */
319 View Code Duplication
    private function applyLabelRemoved(LabelRemoved $labelRemoved)
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...
320
    {
321
        $document = $this->repository->get($labelRemoved->getOrganizerId());
322
        $jsonLD = $document->getBody();
323
324
        // Don't presume that the label visibility is correct when removing.
325
        // So iterate over both the visible and invisible labels.
326
        $labelsProperties = ['labels', 'hiddenLabels'];
327
328
        foreach ($labelsProperties as $labelsProperty) {
329
            if (isset($jsonLD->{$labelsProperty}) && is_array($jsonLD->{$labelsProperty})) {
330
                $jsonLD->{$labelsProperty} = array_filter(
331
                    $jsonLD->{$labelsProperty},
332
                    function ($label) use ($labelRemoved) {
333
                        return !$labelRemoved->getLabel()->equals(
334
                            new Label($label)
335
                        );
336
                    }
337
                );
338
339
                // Ensure array keys start with 0 so json_encode() does encode it
340
                // as an array and not as an object.
341
                if (count($jsonLD->{$labelsProperty}) > 0) {
342
                    $jsonLD->{$labelsProperty} = array_values($jsonLD->{$labelsProperty});
343
                } else {
344
                    unset($jsonLD->{$labelsProperty});
345
                }
346
            }
347
        }
348
349
        $this->repository->save($document->withBody($jsonLD));
350
    }
351
352
    /**
353
     * @param OrganizerDeleted $organizerDeleted
354
     */
355
    private function applyOrganizerDeleted(
356
        OrganizerDeleted $organizerDeleted
357
    ) {
358
        $this->repository->remove($organizerDeleted->getOrganizerId());
359
    }
360
361
    /**
362
     * @param string $id
363
     * @return JsonDocument
364
     */
365 View Code Duplication
    private 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...
366
    {
367
        $document = new JsonDocument($id);
368
369
        $organizerLd = $document->getBody();
370
        $organizerLd->{'@id'} = $this->iriGenerator->iri($id);
371
        $organizerLd->{'@context'} = '/contexts/organizer';
372
373
        return $document->withBody($organizerLd);
374
    }
375
376
    /**
377
     * @param TitleUpdated $titleUpdated
378
     * @param Language|null $language
379
     */
380
    private function applyTitle(
381
        TitleUpdated $titleUpdated,
382
        Language $language = null
383
    ) {
384
        $organizerId = $titleUpdated->getOrganizerId();
385
386
        $document = $this->repository->get($organizerId);
387
388
        $jsonLD = $document->getBody();
389
390
        if ($language === null) {
391
            $language = new Language($this->getMainLanguage($jsonLD));
392
        }
393
394
        // For old projections the name is untranslated and just a string.
395
        // This needs to be upgraded to an object with languages and translation.
396
        // When a full replay is done this code becomes obsolete.
397
        if (isset($jsonLD->name) && is_string($jsonLD->name)) {
398
            $title = $jsonLD->name;
399
            $jsonLD->name = new \StdClass();
400
            $jsonLD->name->{$language->getCode()} = $title;
401
        }
402
403
        $jsonLD->name->{$language->getCode()} = $titleUpdated->getTitle()->toNative();
404
405
        $this->repository->save($document->withBody($jsonLD));
406
    }
407
408
    /**
409
     * @param ActorEvent $actor
410
     * @return JsonDocument
411
     */
412
    private function loadDocumentFromRepository(ActorEvent $actor)
413
    {
414
        $document = $this->repository->get($actor->getActorId());
415
416
        if (!$document) {
417
            return $this->newDocument($actor->getActorId());
418
        }
419
420
        return $document;
421
    }
422
}
423