Completed
Pull Request — master (#306)
by Luc
06:57 queued 01:33
created

applyOrganizerCreatedWithUniqueWebsite()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 33
Code Lines 20

Duplication

Lines 3
Ratio 9.09 %

Importance

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