Completed
Pull Request — master (#306)
by Luc
07:37
created

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