Completed
Pull Request — master (#358)
by
unknown
08:21
created

addLabelName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 2
1
<?php
2
3
namespace CultuurNet\UDB3;
4
5
use Broadway\Serializer\SerializerInterface;
6
use Broadway\Serializer\SimpleInterfaceSerializer;
7
use CultuurNet\UDB3\Event\Events\BookingInfoUpdated as EventBookingInfoUpdated;
8
use CultuurNet\UDB3\Event\Events\ContactPointUpdated as EventContactPointUpdated;
9
use CultuurNet\UDB3\Event\Events\DescriptionTranslated;
10
use CultuurNet\UDB3\Event\Events\DescriptionUpdated as EventDescriptionUpdated;
11
use CultuurNet\UDB3\Event\Events\EventDeleted;
12
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2;
13
use CultuurNet\UDB3\Event\Events\LabelAdded;
14
use CultuurNet\UDB3\Event\Events\LabelRemoved;
15
use CultuurNet\UDB3\Event\Events\MajorInfoUpdated;
16
use CultuurNet\UDB3\Event\Events\OrganizerDeleted as EventOrganizerDeleted;
17
use CultuurNet\UDB3\Event\Events\OrganizerUpdated as EventOrganizerUpdated;
18
use CultuurNet\UDB3\Event\Events\TitleTranslated;
19
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeDeleted as EventTypicalAgeRangeDeleted;
20
use CultuurNet\UDB3\Event\Events\TypicalAgeRangeUpdated as EventTypicalAgeRangeUpdated;
21
use CultuurNet\UDB3\EventSourcing\PayloadManipulatingSerializer;
22
use CultuurNet\UDB3\Label\ReadModels\JSON\Repository\ReadRepositoryInterface;
23
use CultuurNet\UDB3\Label\ValueObjects\Visibility;
24
use CultuurNet\UDB3\Offer\Item\Events\BookingInfoUpdated;
25
use CultuurNet\UDB3\Place\Events\BookingInfoUpdated as PlaceBookingInfoUpdated;
26
use CultuurNet\UDB3\Place\Events\ContactPointUpdated as PlaceContactPointUpdated;
27
use CultuurNet\UDB3\Place\Events\DescriptionUpdated as PlaceDescriptionUpdated;
28
use CultuurNet\UDB3\Place\Events\OrganizerDeleted as PlaceOrganizerDeleted;
29
use CultuurNet\UDB3\Place\Events\OrganizerUpdated as PlaceOrganizerUpdated;
30
use CultuurNet\UDB3\Place\Events\PlaceDeleted;
31
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeDeleted as PlaceTypicalAgeRangeDeleted;
32
use CultuurNet\UDB3\Place\Events\TypicalAgeRangeUpdated as PlaceTypicalAgeRangeUpdated;
33
use ValueObjects\Identity\UUID;
34
35
/**
36
 * Factory chaining together the logic to manipulate the payload of old events
37
 * in order to make it usable by new events.
38
 *
39
 * Some cases:
40
 * - changing the class name / namespace after class renames
41
 * - changing the names of properties
42
 */
43
class BackwardsCompatiblePayloadSerializerFactory
44
{
45
    private function __construct()
46
    {
47
48
    }
49
50
    /**
51
     * @param ReadRepositoryInterface $labelRepository
52
     * @return SerializerInterface
53
     */
54
    public static function createSerializer(ReadRepositoryInterface $labelRepository)
55
    {
56
        $payloadManipulatingSerializer = new PayloadManipulatingSerializer(
57
            new SimpleInterfaceSerializer()
58
        );
59
60
        /*
61
         * CREATE EVENTS
62
         *
63
         */
64
65
        $payloadManipulatingSerializer->manipulateEventsOfClass(
66
            'CultuurNet\UDB3\Event\Events\EventCreated',
67
            function (array $serializedObject) {
68
                return self::addDefaultMainLanguage($serializedObject);
69
            }
70
        );
71
72
        $payloadManipulatingSerializer->manipulateEventsOfClass(
73
            'CultuurNet\UDB3\Place\Events\PlaceCreated',
74
            function (array $serializedObject) {
75
                return self::addDefaultMainLanguage($serializedObject);
76
            }
77
        );
78
79
        $payloadManipulatingSerializer->manipulateEventsOfClass(
80
            'CultuurNet\UDB3\Organizer\Events\OrganizerCreatedWithUniqueWebsite',
81
            function (array $serializedObject) {
82
                return self::addDefaultMainLanguage($serializedObject);
83
            }
84
        );
85
86
        /*
87
         * TRANSLATION EVENTS
88
         */
89
90
        $payloadManipulatingSerializer->manipulateEventsOfClass(
91
            'CultuurNet\UDB3\Event\TitleTranslated',
92
            function (array $serializedObject) {
93
                $serializedObject['class'] = TitleTranslated::class;
94
95
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
96
97
                return $serializedObject;
98
            }
99
        );
100
101
        $payloadManipulatingSerializer->manipulateEventsOfClass(
102
            'CultuurNet\UDB3\Event\DescriptionTranslated',
103
            function (array $serializedObject) {
104
                $serializedObject['class'] = DescriptionTranslated::class;
105
106
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
107
108
                return $serializedObject;
109
            }
110
        );
111
112
        /*
113
         * LABEL EVENTS
114
         */
115
116
        $payloadManipulatingSerializer->manipulateEventsOfClass(
117
            'CultuurNet\UDB3\Label\Events\MadeInvisible',
118
            function (array $serializedObject) use ($labelRepository) {
119
                return self::addLabelName($serializedObject, $labelRepository);
120
            }
121
        );
122
123
        $payloadManipulatingSerializer->manipulateEventsOfClass(
124
            'CultuurNet\UDB3\Label\Events\MadeVisible',
125
            function (array $serializedObject) use ($labelRepository) {
126
                return self::addLabelName($serializedObject, $labelRepository);
127
            }
128
        );
129
130
        $payloadManipulatingSerializer->manipulateEventsOfClass(
131
            'CultuurNet\UDB3\Label\Events\MadePrivate',
132
            function (array $serializedObject) use ($labelRepository) {
133
                return self::addLabelName($serializedObject, $labelRepository);
134
            }
135
        );
136
137
        $payloadManipulatingSerializer->manipulateEventsOfClass(
138
            'CultuurNet\UDB3\Label\Events\MadePublic',
139
            function (array $serializedObject) use ($labelRepository) {
140
                return self::addLabelName($serializedObject, $labelRepository);
141
            }
142
        );
143
144
        $payloadManipulatingSerializer->manipulateEventsOfClass(
145
            'CultuurNet\UDB3\Organizer\Events\LabelAdded',
146
            function (array $serializedObject) use ($labelRepository) {
147
                return self::fixOrganizerLabelEvent($serializedObject, $labelRepository);
148
            }
149
        );
150
151
        $payloadManipulatingSerializer->manipulateEventsOfClass(
152
            'CultuurNet\UDB3\Organizer\Events\LabelRemoved',
153
            function (array $serializedObject) use ($labelRepository) {
154
                return self::fixOrganizerLabelEvent($serializedObject, $labelRepository);
155
            }
156
        );
157
158
        $payloadManipulatingSerializer->manipulateEventsOfClass(
159
            'CultuurNet\UDB3\Event\Events\EventWasLabelled',
160
            function (array $serializedObject) {
161
                $serializedObject['class'] = LabelAdded::class;
162
163
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
164
165
                return $serializedObject;
166
            }
167
        );
168
169
        $payloadManipulatingSerializer->manipulateEventsOfClass(
170
            'CultuurNet\UDB3\Event\EventWasTagged',
171 View Code Duplication
            function (array $serializedObject) {
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...
172
                $serializedObject['class'] = LabelAdded::class;
173
174
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
175
176
                $serializedObject = self::replaceKeywordWithLabel($serializedObject);
177
178
                return $serializedObject;
179
            }
180
        );
181
182
        $payloadManipulatingSerializer->manipulateEventsOfClass(
183
            'CultuurNet\UDB3\Event\TagErased',
184 View Code Duplication
            function (array $serializedObject) {
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...
185
                $serializedObject['class'] = LabelRemoved::class;
186
187
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
188
189
                $serializedObject = self::replaceKeywordWithLabel($serializedObject);
190
191
                return $serializedObject;
192
            }
193
        );
194
195
        $payloadManipulatingSerializer->manipulateEventsOfClass(
196
            'CultuurNet\UDB3\Event\Events\Unlabelled',
197
            function (array $serializedObject) {
198
                $serializedObject['class'] = LabelRemoved::class;
199
200
                $serializedObject = self::replaceEventIdWithItemId($serializedObject);
201
202
                return $serializedObject;
203
            }
204
        );
205
206
        /**
207
         * UBD2 IMPORT
208
         */
209
210
        $payloadManipulatingSerializer->manipulateEventsOfClass(
211
            'CultuurNet\UDB3\Event\EventImportedFromUDB2',
212
            function (array $serializedObject) {
213
                $serializedObject['class'] = EventImportedFromUDB2::class;
214
215
                return $serializedObject;
216
            }
217
        );
218
219
        /**
220
         * PLACE FACILITIES EVENT
221
         */
222
        $payloadManipulatingSerializer->manipulateEventsOfClass(
223
            'CultuurNet\UDB3\Place\Events\FacilitiesUpdated',
224
            function (array $serializedObject) {
225
                $serializedObject = self::replacePlaceIdWithItemId($serializedObject);
226
227
                return $serializedObject;
228
            }
229
        );
230
231
        /**
232
         * GEOCOORDINATES UPDATED EVENT
233
         */
234
        $payloadManipulatingSerializer->manipulateEventsOfClass(
235
            'CultuurNet\UDB3\Place\Events\GeoCoordinatesUpdated',
236
            function (array $serializedObject) {
237
                $serializedObject = self::replacePlaceIdWithItemId($serializedObject);
238
239
                return $serializedObject;
240
            }
241
        );
242
243
        /**
244
         * BOOKING INFO EVENT
245
         */
246
        $manipulateAvailability = function (array $serializedBookingInfo, $propertyName) {
247
            if (!isset($serializedBookingInfo[$propertyName]) || empty($serializedBookingInfo[$propertyName])) {
248
                $serializedBookingInfo[$propertyName] = null;
249
                return $serializedBookingInfo;
250
            }
251
252
            $dateTimeString = $serializedBookingInfo[$propertyName];
253
254
            $dateTimeFromAtom = \DateTimeImmutable::createFromFormat(\DATE_ATOM, $dateTimeString);
255
            if ($dateTimeFromAtom) {
256
                $serializedBookingInfo[$propertyName] = $dateTimeFromAtom->format(\DATE_ATOM);
257
                return $serializedBookingInfo;
258
            }
259
260
            $dateTimeFromAtomWithMilliseconds = \DateTimeImmutable::createFromFormat(
261
                'Y-m-d\TH:i:s.uP',
262
                $dateTimeString
263
            );
264
            if ($dateTimeFromAtomWithMilliseconds) {
265
                $serializedBookingInfo[$propertyName] = $dateTimeFromAtomWithMilliseconds->format(\DATE_ATOM);
266
                return $serializedBookingInfo;
267
            }
268
269
            unset($serializedBookingInfo[$propertyName]);
270
            return $serializedBookingInfo;
271
        };
272
273
        $manipulateBookingInfoEvent = function (array $serializedEvent) use ($manipulateAvailability) {
274
            $serializedEvent = self::replaceEventIdWithItemId($serializedEvent);
275
            $serializedEvent = self::replacePlaceIdWithItemId($serializedEvent);
276
277
            $serializedBookingInfo = $serializedEvent['payload']['bookingInfo'];
278
            $serializedBookingInfo = $manipulateAvailability($serializedBookingInfo, 'availabilityStarts');
279
            $serializedBookingInfo = $manipulateAvailability($serializedBookingInfo, 'availabilityEnds');
280
            $serializedEvent['payload']['bookingInfo'] = $serializedBookingInfo;
281
282
            return $serializedEvent;
283
        };
284
285
        $payloadManipulatingSerializer->manipulateEventsOfClass(
286
            EventBookingInfoUpdated::class,
287
            $manipulateBookingInfoEvent
288
        );
289
290
        $payloadManipulatingSerializer->manipulateEventsOfClass(
291
            PlaceBookingInfoUpdated::class,
292
            $manipulateBookingInfoEvent
293
        );
294
295
        /**
296
         * EventEvent to AbstractEvent (Offer)
297
         */
298
        $refactoredEventEvents = [
299
            EventTypicalAgeRangeDeleted::class,
300
            EventTypicalAgeRangeUpdated::class,
301
            EventContactPointUpdated::class,
302
            MajorInfoUpdated::class,
303
            EventOrganizerUpdated::class,
304
            EventOrganizerDeleted::class,
305
            EventDescriptionUpdated::class,
306
            EventDeleted::class,
307
        ];
308
309
        foreach ($refactoredEventEvents as $refactoredEventEvent) {
310
            $payloadManipulatingSerializer->manipulateEventsOfClass(
311
                $refactoredEventEvent,
312
                function (array $serializedObject) {
313
                    $serializedObject = self::replaceEventIdWithItemId($serializedObject);
314
                    return $serializedObject;
315
                }
316
            );
317
        }
318
319
        /**
320
         * PlaceEvent to AbstractEvent (Offer)
321
         */
322
        $refactoredPlaceEvents = [
323
            PlaceOrganizerUpdated::class,
324
            PlaceOrganizerDeleted::class,
325
            PlaceTypicalAgeRangeDeleted::class,
326
            PlaceTypicalAgeRangeUpdated::class,
327
            PlaceContactPointUpdated::class,
328
            PlaceDescriptionUpdated::class,
329
            PlaceDeleted::class,
330
        ];
331
332
        foreach ($refactoredPlaceEvents as $refactoredPlaceEvent) {
333
            $payloadManipulatingSerializer->manipulateEventsOfClass(
334
                $refactoredPlaceEvent,
335
                function (array $serializedObject) {
336
                    $serializedObject = self::replacePlaceIdWithItemId($serializedObject);
337
                    return $serializedObject;
338
                }
339
            );
340
        }
341
342
        return $payloadManipulatingSerializer;
343
    }
344
345
    /**
346
     * @param array $serializedObject
347
     * @return array
348
     */
349
    private static function replaceEventIdWithItemId(array $serializedObject)
350
    {
351
        return self::replaceKeys('event_id', 'item_id', $serializedObject);
352
    }
353
354
    /**
355
     * @param array $serializedObject
356
     * @return array
357
     */
358
    private static function replacePlaceIdWithItemId(array $serializedObject)
359
    {
360
        return self::replaceKeys('place_id', 'item_id', $serializedObject);
361
    }
362
363
    /**
364
     * @param string $oldKey
365
     * @param string $newKey
366
     * @param array $serializedObject
367
     * @return array
368
     */
369
    private static function replaceKeys($oldKey, $newKey, $serializedObject)
370
    {
371
        if (isset($serializedObject['payload'][$oldKey])) {
372
            $value = $serializedObject['payload'][$oldKey];
373
            $serializedObject['payload'][$newKey] = $value;
374
            unset($serializedObject['payload'][$oldKey]);
375
        }
376
377
        return $serializedObject;
378
    }
379
380
    /**
381
     * @param array $serializedObject
382
     * @return array
383
     */
384
    private static function replaceKeywordWithLabel(array $serializedObject)
385
    {
386
        $keyword = $serializedObject['payload']['keyword'];
387
        $serializedObject['payload']['label'] = $keyword;
388
        unset($serializedObject['payload']['keyword']);
389
390
        return $serializedObject;
391
    }
392
393
    /**
394
     * @param array $serializedObject
395
     * @param ReadRepositoryInterface $labelRepository
396
     * @return array
397
     */
398
    private static function addLabelName(
399
        array $serializedObject,
400
        ReadRepositoryInterface $labelRepository
401
    ) {
402
        if (!isset($serializedObject['payload']['name'])) {
403
            $uuid = $serializedObject['payload']['uuid'];
404
            $label = $labelRepository->getByUuid(new UUID($uuid));
405
406
            $serializedObject['payload']['name'] = $label->getName()->toNative();
407
        }
408
409
        return $serializedObject;
410
    }
411
412
    /**
413
     * @param array $serializedObject
414
     * @param ReadRepositoryInterface $labelRepository
415
     * @return array
416
     */
417
    private static function fixOrganizerLabelEvent(
418
        array $serializedObject,
419
        ReadRepositoryInterface $labelRepository
420
    ) {
421
        if (!isset($serializedObject['payload']['label']) ||
422
            !isset($serializedObject['payload']['visibility'])) {
423
            $uuid = $serializedObject['payload']['labelId'];
424
            $label = $labelRepository->getByUuid(new UUID($uuid));
425
426
            $serializedObject['payload']['label'] = $label->getName()->toNative();
427
            $serializedObject['payload']['visibility'] = $label->getVisibility() === Visibility::VISIBLE();
428
        }
429
430
        return $serializedObject;
431
    }
432
433
    /**
434
     * @param array $serializedObject
435
     * @return array
436
     */
437
    private static function addDefaultMainLanguage(array $serializedObject)
438
    {
439
        if (!isset($serializedObject['payload']['main_language'])) {
440
            $mainLanguage = new Language('nl');
441
            $serializedObject['payload']['main_language'] = $mainLanguage->getCode();
442
        }
443
444
        return $serializedObject;
445
    }
446
}
447