Completed
Push — master ( c9e2d7...abf4f6 )
by Kristof
05:21
created

TabularDataEventFormatter::contactPoint()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace CultuurNet\UDB3\EventExport\Format\TabularData;
4
5
use CultuurNet\UDB3\EventExport\Format\HTML\Uitpas\EventInfo\EventInfoServiceInterface;
6
use CultuurNet\UDB3\EventExport\PriceFormatter;
7
use CultuurNet\UDB3\EventExport\UitpasInfoFormatter;
8
use CultuurNet\UDB3\StringFilter\StripHtmlStringFilter;
9
10
class TabularDataEventFormatter
11
{
12
    /**
13
     * Class used to filter out HTML from strings.
14
     * @var StripHtmlStringFilter
15
     */
16
    protected $htmlFilter;
17
18
    /**
19
     * A list of all included properties
20
     * @var string[]
21
     */
22
    protected $includedProperties;
23
24
    /**
25
     * @var UitpasInfoFormatter
26
     */
27
    protected $uitpasInfoFormatter;
28
29
    /**
30
     * @var EventInfoServiceInterface|null
31
     */
32
    protected $uitpas;
33
34
    /**
35
     * @param string[] $include A list of properties to include
36
     * @param EventInfoServiceInterface|null $uitpas
37
     */
38
    public function __construct(
39
        array $include,
40
        EventInfoServiceInterface $uitpas = null
41
    ) {
42
        $this->htmlFilter = new StripHtmlStringFilter();
43
        $this->includedProperties = $this->includedOrDefaultProperties($include);
44
        $this->uitpas = $uitpas;
45
        $this->uitpasInfoFormatter = new UitpasInfoFormatter(new PriceFormatter(2, ',', '.', 'Gratis'));
46
    }
47
48
    public function formatHeader()
49
    {
50
        $columns = array();
51
        foreach ($this->includedProperties as $property) {
52
            $columns[] = $this->columns()[$property]['name'];
53
        }
54
55
        return $columns;
56
    }
57
58
    public function formatEvent($event)
59
    {
60
        $event = json_decode($event);
61
        $includedProperties = $this->includedProperties;
62
        $row = $this->emptyRow();
63
64
        foreach ($includedProperties as $property) {
65
            $column = $this->columns()[$property];
66
            $value = $column['include']($event);
67
68
            if ($value) {
69
                $row[$property] = $value;
70
            } else {
71
                $row[$property] = '';
72
            }
73
        }
74
75
        return $row;
76
    }
77
78
    /**
79
     * @param string $date Date in ISO 8601 format.
80
     * @return string Date formatted for tabular data export.
81
     */
82
    protected function formatDate($date)
83
    {
84
        $timezone = new \DateTimeZone('Europe/Brussels');
85
86
        // Try to create from various formats to maintain backwards
87
        // compatibility with external systems with older json-ld
88
        // projections (eg. OMD).
89
        $formats = [\DateTime::ATOM, \DateTime::ISO8601, 'Y-m-d\TH:i:s'];
90
91
        do {
92
            $datetime = \DateTime::createFromFormat(current($formats), $date, $timezone);
93
        } while ($datetime === false && next($formats));
94
95
        if ($datetime instanceof \DateTime) {
96
            return $datetime->format('Y-m-d H:i');
97
        } else {
98
            return '';
99
        }
100
    }
101
102
    /**
103
     * @param string $date Date in ISO 8601 format.
104
     * @return string Date formatted for tabular data export.
105
     */
106
    protected function formatDateWithoutTime($date)
107
    {
108
        $timezone = new \DateTimeZone('Europe/Brussels');
109
        $datetime = \DateTime::createFromFormat(\DateTime::ATOM, $date, $timezone);
110
        return $datetime->format('Y-m-d');
111
    }
112
113
    public function emptyRow()
114
    {
115
        $row = array();
116
117
        foreach ($this->includedProperties as $property) {
118
            $row[$property] = '';
119
        }
120
121
        return $row;
122
    }
123
124
    protected function expandMultiColumnProperties($properties)
125
    {
126
        $expandedProperties = [];
127
128
        $expansions = [
129
            'address' => [
130
                'address.streetAddress',
131
                'address.postalCode',
132
                'address.addressLocality',
133
                'address.addressCountry',
134
            ],
135
            'contactPoint' => [
136
                'contactPoint.email',
137
                'contactPoint.telephone',
138
                'contactPoint.url',
139
                'contactPoint.reservations.email',
140
                'contactPoint.reservations.telephone',
141
                'contactPoint.reservations.url',
142
            ],
143
            'bookingInfo' => [
144
                'bookingInfo.price',
145
                'bookingInfo.url',
146
            ],
147
        ];
148
149
        foreach ($properties as $property) {
150
            if (isset($expansions[$property])) {
151
                $expandedProperties = array_merge($expandedProperties, $expansions[$property]);
152
            } else {
153
                $expandedProperties[] = $property;
154
            }
155
        }
156
157
        return $expandedProperties;
158
    }
159
160
    protected function includedOrDefaultProperties($include)
161
    {
162
        if ($include) {
163
            $properties = $this->expandMultiColumnProperties($include);
164
165
            array_unshift($properties, 'id');
166
        } else {
167
            $properties = array_keys($this->columns());
168
        }
169
170
        return $properties;
171
    }
172
173
    protected function columns()
174
    {
175
        $formatter = $this;
176
        $contactPoint = function (\stdClass $event) use ($formatter) {
177
            return $formatter->contactPoint($event);
178
        };
179
180
        return [
181
            'id' => [
182
                'name' => 'id',
183
                'include' => function ($event) {
184
                    $eventUri = $event->{'@id'};
185
                    $uriParts = explode('/', $eventUri);
186
                    $eventId = array_pop($uriParts);
187
188
                    return $eventId;
189
                },
190
                'property' => 'id'
191
            ],
192
            'name' => [
193
                'name' => 'titel',
194
                'include' => function ($event) {
195
                    if ($event->name) {
196
                        return reset($event->name);
197
                    }
198
                },
199
                'property' => 'name'
200
            ],
201
            'creator' => [
202
                'name' => 'auteur',
203
                'include' => function ($event) {
204
                    return $event->creator;
205
                },
206
                'property' => 'creator'
207
            ],
208
            'bookingInfo.price' => [
209
                'name' => 'prijs',
210 View Code Duplication
                'include' => function ($event) {
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...
211
                    if (property_exists($event, 'bookingInfo') && is_array($event->bookingInfo)) {
212
                        $first = reset($event->bookingInfo);
213
                        if (is_object($first) && property_exists($first, 'price')) {
214
                            return $first->price;
215
                        }
216
                    }
217
                },
218
                'property' => 'bookingInfo'
219
            ],
220
            'kansentarief' => [
221
                'name' => 'kansentarief',
222
                'include' => function ($event) {
223
                    $eventUri = $event->{'@id'};
224
                    $uriParts = explode('/', $eventUri);
225
                    $eventId = array_pop($uriParts);
226
227
                    $uitpasInfo = $this->uitpas->getEventInfo($eventId);
228
                    if ($uitpasInfo) {
229
                        $uitpasInfo = $this->uitpasInfoFormatter->format($uitpasInfo);
230
231
                        $cardSystems = array_reduce($uitpasInfo['prices'], function ($cardSystems, $tariff) {
232
                            $cardSystem = isset($cardSystems[$tariff['cardSystem']]) ? $cardSystems[$tariff['cardSystem']] : '';
233
                            $cardSystem = empty($cardSystem)
234
                                ? $tariff['cardSystem'] .': € ' . $tariff['price']
235
                                : $cardSystem . ' / € ' . $tariff['price'];
236
237
                            $cardSystems[$tariff['cardSystem']] = $cardSystem;
238
                            return $cardSystems;
239
                        }, []);
240
241
                        $formattedTariffs = array_reduce($cardSystems, function ($tariffs, $cardSystemPrices) {
242
                            return $tariffs ? $tariffs . ' | ' . $cardSystemPrices : $cardSystemPrices;
243
                        });
244
245
                        if (!empty($formattedTariffs)) {
246
                            return $formattedTariffs;
247
                        }
248
                    }
249
                },
250
                'property' => 'kansentarief'
251
            ],
252
            'bookingInfo.url' => [
253
                'name' => 'ticket link',
254 View Code Duplication
                'include' => function ($event) {
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...
255
                    if (property_exists($event, 'bookingInfo')) {
256
                        $first = reset($event->bookingInfo);
257
                        if (is_object($first) && property_exists($first, 'url')) {
258
                            return $first->url;
259
                        }
260
                    }
261
                },
262
                'property' => 'bookingInfo'
263
            ],
264
            'description' => [
265
                'name' => 'omschrijving',
266
                'include' => function ($event) {
267
                    if (property_exists($event, 'description')) {
268
                        $description = reset($event->description);
269
270
                        // the following preg replace statements will strip unwanted line-breaking characters
271
                        // except for markup
272
273
                        // do not add a whitespace when a line break follows a break tag
274
                        $description = preg_replace('/<br\ ?\/?>\s+/', '<br>', $description);
275
276
                        // replace all leftover line breaks with a space to prevent words from sticking together
277
                        $description = trim(preg_replace('/\s+/', ' ', $description));
278
279
                        return $this->htmlFilter->filter($description);
280
                    }
281
                },
282
                'property' => 'description'
283
            ],
284
            'organizer' => [
285
                'name' => 'organisatie',
286
                'include' => function ($event) {
287
                    if (property_exists($event, 'organizer') &&
288
                        isset($event->organizer->name)
289
                    ) {
290
                        return $event->organizer->name;
291
                    }
292
                },
293
                'property' => 'organizer'
294
            ],
295
            'calendarSummary' => [
296
                'name' => 'tijdsinformatie',
297
                'include' => function ($event) {
298
                    return $event->calendarSummary;
299
                },
300
                'property' => 'calendarSummary'
301
            ],
302
            'labels' => [
303
                'name' => 'labels',
304
                'include' => function ($event) {
305
                    if (isset($event->labels)) {
306
                        return implode(';', $event->labels);
307
                    }
308
                },
309
                'property' => 'labels'
310
            ],
311
            'typicalAgeRange' => [
312
                'name' => 'leeftijd',
313
                'include' => function ($event) {
314
                    return $event->typicalAgeRange;
315
                },
316
                'property' => 'typicalAgeRange'
317
            ],
318
            'performer' => [
319
                'name' => 'uitvoerders',
320
                'include' => function ($event) {
321
                    if (property_exists($event, 'performer')) {
322
                        $performerNames = [];
323
                        foreach ($event->performer as $performer) {
324
                            $performerNames[] = $performer->name;
325
                        }
326
327
                        return implode(';', $performerNames);
328
                    }
329
                },
330
                'property' => 'performer'
331
            ],
332
            'language' => [
333
                'name' => 'taal van het aanbod',
334
                'include' => function ($event) {
335
                    if (property_exists($event, 'language')) {
336
                        return implode(';', $event->language);
337
                    }
338
                },
339
                'property' => 'language'
340
            ],
341
            'terms.theme' => [
342
                'name' => 'thema',
343 View Code Duplication
                'include' => function ($event) {
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...
344
                    if (property_exists($event, 'terms')) {
345
                        foreach ($event->terms as $term) {
346
                            if ($term->domain && $term->label && $term->domain == 'theme') {
347
                                return $term->label;
348
                            }
349
                        }
350
                    }
351
                },
352
                'property' => 'terms.theme'
353
            ],
354
            'terms.eventtype' => [
355
                'name' => 'soort aanbod',
356 View Code Duplication
                'include' => function ($event) {
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...
357
                    if (property_exists($event, 'terms')) {
358
                        foreach ($event->terms as $term) {
359
                            if ($term->domain && $term->label && $term->domain == 'eventtype') {
360
                                return $term->label;
361
                            }
362
                        }
363
                    }
364
                },
365
                'property' => 'terms.eventtype'
366
            ],
367
            'created' => [
368
                'name' => 'datum aangemaakt',
369
                'include' => function ($event) {
370
                    if (!empty($event->created)) {
371
                        return $this->formatDate($event->created);
372
                    } else {
373
                        return '';
374
                    }
375
                },
376
                'property' => 'created'
377
            ],
378
            'modified' => [
379
                'name' => 'datum laatste aanpassing',
380
                'include' => function ($event) {
381
                    if (!empty($event->modified)) {
382
                        return $this->formatDate($event->modified);
383
                    } else {
384
                        return '';
385
                    }
386
                },
387
                'property' => 'modified'
388
            ],
389
            'available' => [
390
                'name' => 'embargodatum',
391
                'include' => function ($event) {
392
                    if (!empty($event->available)) {
393
                        return $this->formatDateWithoutTime($event->available);
394
                    } else {
395
                        return '';
396
                    }
397
                },
398
                'property' => 'available'
399
            ],
400
            'startDate' => [
401
                'name' => 'startdatum',
402
                'include' => function ($event) {
403
                    if (!empty($event->startDate)) {
404
                        return $this->formatDate($event->startDate);
405
                    } else {
406
                        return '';
407
                    }
408
                },
409
                'property' => 'startDate'
410
            ],
411
            'endDate' => [
412
                'name' => 'einddatum',
413
                'include' => function ($event) {
414
                    if (!empty($event->endDate)) {
415
                        return $this->formatDate($event->endDate);
416
                    } else {
417
                        return '';
418
                    }
419
                },
420
                'property' => 'endDate'
421
            ],
422
            'calendarType' => [
423
                'name' => 'tijd type',
424
                'include' => function ($event) {
425
                    return $event->calendarType;
426
                },
427
                'property' => 'calendarType'
428
            ],
429
            'location' => [
430
                'name' => 'locatie naam',
431
                'include' => function ($event) {
432
                    if (property_exists($event, 'location') && isset($event->location->name)) {
433
                        return reset($event->location->name);
434
                    }
435
                },
436
                'property' => 'location'
437
            ],
438
            'address.streetAddress' => [
439
                'name' => 'straat',
440
                'include' => function ($event) {
441
                    if (isset($event->location->address->streetAddress)) {
442
                        return $event->location->address->streetAddress;
443
                    }
444
                },
445
                'property' => 'address.streetAddress'
446
            ],
447
            'address.postalCode' => [
448
                'name' => 'postcode',
449
                'include' => function ($event) {
450
                    if (isset($event->location->address->postalCode)) {
451
                        return $event->location->address->postalCode;
452
                    }
453
                },
454
                'property' => 'address.postalCode'
455
            ],
456
            'address.addressLocality' => [
457
                'name' => 'gemeente',
458
                'include' => function ($event) {
459
                    if (isset($event->location->address->addressLocality)) {
460
                        return $event->location->address->addressLocality;
461
                    }
462
                },
463
                'property' => 'address.addressLocality'
464
            ],
465
            'address.addressCountry' => [
466
                'name' => 'land',
467
                'include' => function ($event) {
468
                    if (isset($event->location->address->addressCountry)) {
469
                        return $event->location->address->addressCountry;
470
                    }
471
                },
472
                'property' => 'address.addressCountry'
473
            ],
474
            'image' => [
475
                'name' => 'afbeelding',
476
                'include' => function ($event) {
477
                    return !empty($event->image) ? $event->image : '';
478
                },
479
                'property' => 'image'
480
            ],
481
            'sameAs' => [
482
                'name' => 'externe ids',
483
                'include' => function ($event) {
484
                    if (property_exists($event, 'sameAs')) {
485
                        $ids = array();
486
487
                        foreach ($event->sameAs as $externalId) {
488
                            $ids[] = $externalId;
489
                        }
490
491
                        return implode("\r\n", $ids);
492
                    }
493
                },
494
                'property' => 'sameAs'
495
            ],
496
            'contactPoint.email' => [
497
                'name' => 'e-mail',
498
                'include' => function ($event) use ($contactPoint) {
499
                    return $this->listJsonldProperty(
500
                        $contactPoint($event),
501
                        'email'
502
                    );
503
                },
504
                'property' => 'contactPoint'
505
            ],
506
            'contactPoint.telephone' => [
507
                'name' => 'telefoon',
508
                'include' => function ($event) use ($contactPoint) {
509
                    return $this->listJsonldProperty(
510
                        $contactPoint($event),
511
                        'telephone'
512
                    );
513
                },
514
                'property' => 'contactPoint'
515
            ],
516
            'contactPoint.url' => [
517
                'name' => 'url',
518
                'include' => function ($event) use ($contactPoint) {
519
                    $contactUrls = $this->listJsonldProperty(
520
                        $contactPoint($event),
521
                        'url'
522
                    );
523
                    return implode("\r\n", $contactUrls);
524
                },
525
                'property' => 'contactPoint'
526
            ],
527
            'contactPoint.reservations.email' => [
528
                'name' => 'e-mail reservaties',
529
                'include' => function ($event) use ($contactPoint) {
530
                    return $this->listJsonldProperty(
531
                        $contactPoint($event, 'Reservations'),
532
                        'email'
533
                    );
534
                },
535
                'property' => 'contactPoint'
536
            ],
537
            'contactPoint.reservations.telephone' => [
538
                'name' => 'telefoon reservaties',
539
                'include' => function ($event) use ($contactPoint) {
540
                    return $this->listJsonldProperty(
541
                        $contactPoint($event, 'Reservations'),
542
                        'telephone'
543
                    );
544
                },
545
                'property' => 'contactPoint'
546
            ],
547
            'contactPoint.reservations.url' => [
548
                'name' => 'online reservaties',
549
                'include' => function ($event) use ($contactPoint) {
550
                    return $this->listJsonldProperty(
551
                        $contactPoint($event, 'Reservations'),
552
                        'url'
553
                    );
554
                },
555
                'property' => 'contactPoint'
556
            ],
557
        ];
558
    }
559
560
    /**
561
     * @param object $jsonldData
562
     *  An object that contains the jsonld data.
563
     *
564
     * @param string $propertyName
565
     *  The name of the property that contains an array of values.
566
     *
567
     * @return string
568
     */
569
    private function listJsonldProperty($jsonldData, $propertyName)
570
    {
571
        if (property_exists($jsonldData, $propertyName)) {
572
            return implode("\r\n", $jsonldData->{$propertyName});
573
        } else {
574
            return '';
575
        }
576
    }
577
578
    /**
579
     * @param object $event
580
     * @return object
581
     */
582
    private function contactPoint($event)
583
    {
584
        if (property_exists($event, 'contactPoint')) {
585
            return $event->contactPoint;
586
        }
587
588
        return new \stdClass();
589
    }
590
}
591