Completed
Pull Request — master (#240)
by Kristof
07:54 queued 03:14
created

CdbXMLImporter   F

Complexity

Total Complexity 99

Size/Duplication

Total Lines 749
Duplicated Lines 11.75 %

Coupling/Cohesion

Components 1
Dependencies 24

Importance

Changes 0
Metric Value
wmc 99
lcom 1
cbo 24
dl 88
loc 749
rs 1.0434
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A documentWithCdbXML() 0 70 3
A addDescriptionFilter() 0 4 1
A dateFromUdb2UnixTime() 0 9 1
A __construct() 0 9 1
B importDescription() 0 26 4
B importLabels() 0 29 1
A addKeywordsAsLabelsProperty() 0 17 2
D importPicture() 39 39 9
B importLocation() 0 26 3
D importOrganizer() 0 38 9
C importPriceInfo() 0 47 9
F importBookingInfo() 0 61 15
B importContactPoint() 27 56 6
A importTerms() 10 20 4
C importCalendar() 12 74 11
A importTypicalAgeRange() 0 7 2
A importPerformers() 0 14 4
A importLanguages() 0 12 3
B importSeeAlso() 0 21 7
B importUitInVlaanderenReference() 0 27 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like CdbXMLImporter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CdbXMLImporter, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace CultuurNet\UDB3\Event\ReadModel\JSONLD;
4
5
use CultureFeed_Cdb_Data_File;
6
use CultureFeed_Cdb_Data_Keyword;
7
use CultuurNet\UDB3\Cdb\CdbId\EventCdbIdExtractorInterface;
8
use CultuurNet\UDB3\Cdb\DateTimeFactory;
9
use CultuurNet\UDB3\Cdb\PriceDescriptionParser;
10
use CultuurNet\UDB3\LabelCollection;
11
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
12
use CultuurNet\UDB3\SluggerInterface;
13
use CultuurNet\UDB3\StringFilter\StringFilterInterface;
14
15
/**
16
 * Takes care of importing cultural events in the CdbXML format (UDB2)
17
 * into a UDB3 JSON-LD document.
18
 */
19
class CdbXMLImporter
20
{
21
    /**
22
     * @var CdbXMLItemBaseImporter
23
     */
24
    private $cdbXMLItemBaseImporter;
25
26
    /**
27
     * @var EventCdbIdExtractorInterface
28
     */
29
    private $cdbIdExtractor;
30
31
    /**
32
     * @var PriceDescriptionParser
33
     */
34
    private $priceDescriptionParser;
35
36
    /**
37
     * @var StringFilterInterface[]
38
     */
39
    private $descriptionFilters = [];
40
41
    /**
42
     * @param CdbXMLItemBaseImporter $dbXMLItemBaseImporter
43
     * @param EventCdbIdExtractorInterface $cdbIdExtractor
44
     */
45
    public function __construct(
46
        CdbXMLItemBaseImporter $dbXMLItemBaseImporter,
47
        EventCdbIdExtractorInterface $cdbIdExtractor,
48
        PriceDescriptionParser $priceDescriptionParser
49
    ) {
50
        $this->cdbXMLItemBaseImporter = $dbXMLItemBaseImporter;
51
        $this->cdbIdExtractor = $cdbIdExtractor;
52
        $this->priceDescriptionParser = $priceDescriptionParser;
53
    }
54
55
    /**
56
     * Imports a UDB2 event into a UDB3 JSON-LD document.
57
     *
58
     * @param \stdClass $base
59
     *   The JSON-LD document to start from.
60
     * @param \CultureFeed_Cdb_Item_Event $event
61
     *   The cultural event data from UDB2 to import.
62
     * @param PlaceServiceInterface $placeManager
63
     *   The manager from which to retrieve the JSON-LD of a place.
64
     * @param OrganizerServiceInterface $organizerManager
65
     *   The manager from which to retrieve the JSON-LD of an organizer.
66
     * @param SluggerInterface $slugger
67
     *   The slugger that's used to generate a sameAs reference.
68
     *
69
     * @return \stdClass
70
     *   The document with the UDB2 event data merged in.
71
     */
72
    public function documentWithCdbXML(
73
        $base,
74
        \CultureFeed_Cdb_Item_Event $event,
75
        PlaceServiceInterface $placeManager,
76
        OrganizerServiceInterface $organizerManager,
77
        SluggerInterface $slugger
78
    ) {
79
        $jsonLD = clone $base;
80
81
        /** @var \CultureFeed_Cdb_Data_EventDetail $detail */
82
        $detail = null;
83
84
        /** @var \CultureFeed_Cdb_Data_EventDetail[] $details */
85
        $details = $event->getDetails();
86
87
        foreach ($details as $languageDetail) {
88
            $language = $languageDetail->getLanguage();
89
90
            // The first language detail found will be used to retrieve
91
            // properties from which in UDB3 are not any longer considered
92
            // to be language specific.
93
            if (!$detail) {
94
                $detail = $languageDetail;
95
            }
96
97
            $jsonLD->name[$language] = $languageDetail->getTitle();
98
99
            $this->importDescription($languageDetail, $jsonLD, $language);
100
        }
101
102
        $this->cdbXMLItemBaseImporter->importAvailable($event, $jsonLD);
103
104
        $this->importPicture($detail, $jsonLD);
105
106
        $this->importLabels($event, $jsonLD);
107
108
        $jsonLD->calendarSummary = $detail->getCalendarSummary();
109
110
        $this->importLocation($event, $placeManager, $jsonLD);
111
112
        $this->importOrganizer($event, $organizerManager, $jsonLD);
113
114
        $this->importBookingInfo($event, $detail, $jsonLD);
115
116
        $this->importPriceInfo($detail, $jsonLD);
117
118
        $this->importTerms($event, $jsonLD);
119
120
        $this->cdbXMLItemBaseImporter->importPublicationInfo($event, $jsonLD);
121
122
        $this->importCalendar($event, $jsonLD);
123
124
        $this->importTypicalAgeRange($event, $jsonLD);
125
126
        $this->importPerformers($detail, $jsonLD);
127
128
        $this->importLanguages($event, $jsonLD);
129
130
        $this->importUitInVlaanderenReference($event, $slugger, $jsonLD);
131
132
        $this->cdbXMLItemBaseImporter->importExternalId($event, $jsonLD);
133
134
        $this->importSeeAlso($event, $jsonLD);
135
136
        $this->importContactPoint($event, $jsonLD);
137
138
        $this->cdbXMLItemBaseImporter->importWorkflowStatus($event, $jsonLD);
139
140
        return $jsonLD;
141
    }
142
143
    /**
144
     * @param StringFilterInterface $filter
145
     */
146
    public function addDescriptionFilter(StringFilterInterface $filter)
147
    {
148
        $this->descriptionFilters[] = $filter;
149
    }
150
151
    /**
152
     * @param int $unixTime
153
     * @return \DateTime
154
     */
155
    private function dateFromUdb2UnixTime($unixTime)
156
    {
157
        $dateTime = new \DateTime(
158
            '@' . $unixTime,
159
            new \DateTimeZone('Europe/Brussels')
160
        );
161
162
        return $dateTime;
163
    }
164
165
    /**
166
     * @param \CultureFeed_Cdb_Data_EventDetail $languageDetail
167
     * @param \stdClass $jsonLD
168
     * @param string $language
169
     */
170
    private function importDescription($languageDetail, $jsonLD, $language)
171
    {
172
        $longDescription = trim($languageDetail->getLongDescription());
173
        $shortDescription = $languageDetail->getShortDescription();
174
175
        $descriptions = [];
176
177
        if ($shortDescription) {
178
            $shortDescription = trim($shortDescription);
179
180
            if (0 !== strncmp($longDescription, $shortDescription, mb_strlen($shortDescription))) {
181
                $descriptions[] = $shortDescription;
182
            }
183
        }
184
185
        foreach ($this->descriptionFilters as $descriptionFilter) {
186
            $longDescription = $descriptionFilter->filter($longDescription);
187
        };
188
189
        $descriptions[] = $longDescription;
190
191
        $descriptions = array_filter($descriptions);
192
        $description = implode("\n\n", $descriptions);
193
194
        $jsonLD->description[$language] = $description;
195
    }
196
197
    /**
198
     * @param \CultureFeed_Cdb_Item_Event $event
199
     * @param $jsonLD
200
     */
201
    private function importLabels(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
202
    {
203
        /** @var CultureFeed_Cdb_Data_Keyword[] $keywords */
204
        $keywords = array_values($event->getKeywords(true));
205
206
        $validKeywords = array_filter(
207
            $keywords,
208
            function (CultureFeed_Cdb_Data_Keyword $keyword) {
209
                return strlen(trim($keyword->getValue())) > 0;
210
            }
211
        );
212
213
        $visibleKeywords = array_filter(
214
            $validKeywords,
215
            function (CultureFeed_Cdb_Data_Keyword $keyword) {
216
                return $keyword->isVisible();
217
            }
218
        );
219
220
        $hiddenKeywords = array_filter(
221
            $validKeywords,
222
            function (CultureFeed_Cdb_Data_Keyword $keyword) {
223
                return !$keyword->isVisible();
224
            }
225
        );
226
227
        $this->addKeywordsAsLabelsProperty($jsonLD, 'labels', $visibleKeywords);
228
        $this->addKeywordsAsLabelsProperty($jsonLD, 'hiddenLabels', $hiddenKeywords);
229
    }
230
231
    /**
232
     * @param object $jsonLD
233
     * @param string $labelsPropertyName
234
     *  The property where the labels should be listed. Used the differentiate between visible and hidden labels.
235
     * @param CultureFeed_Cdb_Data_Keyword[] $keywords
236
     */
237
    private function addKeywordsAsLabelsProperty($jsonLD, $labelsPropertyName, array $keywords)
238
    {
239
        $labels = array_map(
240
            function ($keyword) {
241
                /** @var CultureFeed_Cdb_Data_Keyword $keyword */
242
                return $keyword->getValue();
243
            },
244
            $keywords
245
        );
246
247
        // Create a label collection to get rid of duplicates.
248
        $labelCollection = LabelCollection::fromStrings($labels);
249
250
        if (count($labelCollection) > 0) {
251
            $jsonLD->{$labelsPropertyName} = $labelCollection->toStrings();
252
        }
253
    }
254
255
    /**
256
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
257
     * @param \stdClass $jsonLD
258
     *
259
     * This is based on code found in the culturefeed theme.
260
     * @see https://github.com/cultuurnet/culturefeed/blob/master/culturefeed_agenda/theme/theme.inc#L266-L284
261
     */
262 View Code Duplication
    private function importPicture($detail, $jsonLD)
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
    {
264
        $mainPicture = null;
265
266
        // first check if there is a media file that is main and has the PHOTO media type
267
        $photos = $detail->getMedia()->byMediaType(CultureFeed_Cdb_Data_File::MEDIA_TYPE_PHOTO);
268
        foreach ($photos as $photo) {
269
            if ($photo->isMain()) {
270
                $mainPicture = $photo;
271
            }
272
        }
273
274
        // the IMAGEWEB media type is deprecated but can still be used as a main image if there is no PHOTO
275
        if (empty($mainPicture)) {
276
            $images = $detail->getMedia()->byMediaType(CultureFeed_Cdb_Data_File::MEDIA_TYPE_IMAGEWEB);
277
            foreach ($images as $image) {
278
                if ($image->isMain()) {
279
                    $mainPicture = $image;
280
                }
281
            }
282
        }
283
284
        // if there is no explicit main image we just use the oldest picture of any type
285
        if (empty($mainPicture)) {
286
            $pictures = $detail->getMedia()->byMediaTypes(
287
                [
288
                    CultureFeed_Cdb_Data_File::MEDIA_TYPE_PHOTO,
289
                    CultureFeed_Cdb_Data_File::MEDIA_TYPE_IMAGEWEB
290
                ]
291
            );
292
293
            $pictures->rewind();
294
            $mainPicture = count($pictures) > 0 ? $pictures->current() : null;
295
        }
296
297
        if ($mainPicture) {
298
            $jsonLD->image = $mainPicture->getHLink();
299
        }
300
    }
301
302
    /**
303
     * @param \CultureFeed_Cdb_Item_Event $event
304
     * @param PlaceServiceInterface $placeManager
305
     * @param \stdClass $jsonLD
306
     */
307
    private function importLocation(\CultureFeed_Cdb_Item_Event $event, PlaceServiceInterface $placeManager, $jsonLD)
308
    {
309
        $location = array();
310
        $location['@type'] = 'Place';
311
312
        $location_id = $this->cdbIdExtractor->getRelatedPlaceCdbId($event);
313
314
        if ($location_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $location_id of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
315
            $location += (array)$placeManager->placeJSONLD($location_id);
316
        } else {
317
            $location_cdb = $event->getLocation();
318
            $location['name']['nl'] = $location_cdb->getLabel();
319
            $address = $location_cdb->getAddress()->getPhysicalAddress();
320
            if ($address) {
321
                $location['address'] = array(
322
                    'addressCountry' => $address->getCountry(),
323
                    'addressLocality' => $address->getCity(),
324
                    'postalCode' => $address->getZip(),
325
                    'streetAddress' =>
326
                        $address->getStreet() . ' ' . $address->getHouseNumber(
327
                        ),
328
                );
329
            }
330
        }
331
        $jsonLD->location = $location;
332
    }
333
334
    /**
335
     * @param \CultureFeed_Cdb_Item_Event $event
336
     * @param OrganizerServiceInterface $organizerManager
337
     * @param \stdClass $jsonLD
338
     */
339
    private function importOrganizer(
340
        \CultureFeed_Cdb_Item_Event $event,
341
        OrganizerServiceInterface $organizerManager,
342
        $jsonLD
343
    ) {
344
        $organizer = null;
345
        $organizer_id = $this->cdbIdExtractor->getRelatedOrganizerCdbId($event);
346
        $organizer_cdb = $event->getOrganiser();
347
        $contact_info_cdb = $event->getContactInfo();
348
349
        if ($organizer_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $organizer_id of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
350
            $organizer = (array)$organizerManager->organizerJSONLD($organizer_id);
351
        } elseif ($organizer_cdb && $contact_info_cdb) {
352
            $organizer = array();
353
            $organizer['name'] = $organizer_cdb->getLabel();
354
355
            $emails_cdb = $contact_info_cdb->getMails();
356
            if (count($emails_cdb) > 0) {
357
                $organizer['email'] = array();
358
                foreach ($emails_cdb as $email) {
359
                    $organizer['email'][] = $email->getMailAddress();
360
                }
361
            }
362
363
            $phones_cdb = $contact_info_cdb->getPhones();
364
            if (count($phones_cdb) > 0) {
365
                $organizer['phone'] = array();
366
                foreach ($phones_cdb as $phone) {
367
                    $organizer['phone'][] = $phone->getNumber();
368
                }
369
            }
370
        }
371
372
        if (!is_null($organizer)) {
373
            $organizer['@type'] = 'Organizer';
374
            $jsonLD->organizer = $organizer;
375
        }
376
    }
377
378
    /**
379
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
380
     * @param \stdClass $jsonLD
381
     */
382
    private function importPriceInfo(
383
        \CultureFeed_Cdb_Data_EventDetail $detail,
384
        $jsonLD
385
    ) {
386
        $prices = array();
387
388
        $price = $detail->getPrice();
389
390
        if ($price) {
391
            $description = $price->getDescription();
392
393
            if ($description) {
394
                $prices = $this->priceDescriptionParser->parse($description);
395
            }
396
397
            // If price description was not interpretable, fall back to
398
            // price title and value.
399
            if (empty($prices) && $price->getValue() !== null) {
400
                $prices['Basistarief'] = floatval($price->getValue());
401
            }
402
        }
403
404
        if (!empty($prices)) {
405
            $priceInfo = array();
406
407
            /** @var \CultureFeed_Cdb_Data_Price $price */
408
            foreach ($prices as $title => $value) {
409
                $priceInfoItem = array(
410
                    'name' => $title,
411
                    'priceCurrency' => 'EUR',
412
                    'price' => $value,
413
                );
414
415
                $priceInfoItem['category'] = 'tariff';
416
417
                if ($priceInfoItem['name'] === 'Basistarief') {
418
                    $priceInfoItem['category'] = 'base';
419
                }
420
421
                $priceInfo[] = $priceInfoItem;
422
            }
423
424
            if (!empty($priceInfo)) {
425
                $jsonLD->priceInfo = $priceInfo;
426
            }
427
        }
428
    }
429
430
    /**
431
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
432
     * @param \stdClass $jsonLD
433
     */
434
    private function importBookingInfo(
435
        \CultureFeed_Cdb_Item_Event $event,
436
        \CultureFeed_Cdb_Data_EventDetail $detail,
437
        $jsonLD
438
    ) {
439
        $bookingInfo = array();
440
441
        $price = $detail->getPrice();
442
        if ($price) {
443
            if ($price->getDescription()) {
444
                $bookingInfo['description'] = $price->getDescription();
445
            }
446
            if ($price->getTitle()) {
447
                $bookingInfo['name'] = $price->getTitle();
448
            }
449
            if ($price->getValue() !== null) {
450
                $bookingInfo['priceCurrency'] = 'EUR';
451
                $bookingInfo['price'] = floatval($price->getValue());
452
            }
453
            if ($bookingPeriod = $event->getBookingPeriod()) {
454
                $startDate = $this->dateFromUdb2UnixTime($bookingPeriod->getDateFrom());
455
                $endDate = $this->dateFromUdb2UnixTime($bookingPeriod->getDateTill());
456
457
                $bookingInfo['availabilityStarts'] = $startDate->format('c');
458
                $bookingInfo['availabilityEnds'] = $endDate->format('c');
459
            }
460
        }
461
462
        // Add reservation contact data.
463
        $contactInfo = $event->getContactInfo();
464
        if ($contactInfo) {
465
            foreach ($contactInfo->getUrls() as $url) {
466
                if ($url->isForReservations()) {
467
                    $bookingInfo['url'] = $url->getUrl();
468
                    break;
469
                }
470
            }
471
472
            if (array_key_exists('url', $bookingInfo)) {
473
                $bookingInfo['urlLabel'] = 'Reserveer plaatsen';
474
            }
475
476
            foreach ($contactInfo->getPhones() as $phone) {
477
                if ($phone->isForReservations()) {
478
                    $bookingInfo['phone'] = $phone->getNumber();
479
                    break;
480
                }
481
            }
482
483
            foreach ($contactInfo->getMails() as $mail) {
484
                if ($mail->isForReservations()) {
485
                    $bookingInfo['email'] = $mail->getMailAddress();
486
                    break;
487
                }
488
            }
489
        }
490
491
        if (!empty($bookingInfo)) {
492
            $jsonLD->bookingInfo = $bookingInfo;
493
        }
494
    }
495
496
    /**
497
     * @param \CultureFeed_Cdb_Item_Event $event
498
     * @param \stdClass $jsonLD
499
     */
500
    private function importContactPoint(
501
        \CultureFeed_Cdb_Item_Event $event,
502
        \stdClass $jsonLD
503
    ) {
504
        $contactInfo = $event->getContactInfo();
505
506
        $notForReservations = function ($item) {
507
            /** @var \CultureFeed_Cdb_Data_Url|\CultureFeed_Cdb_Data_Phone|\CultureFeed_Cdb_Data_Mail $item */
508
            return !$item->isForReservations();
509
        };
510
511
        if ($contactInfo) {
512
            $contactPoint = array();
513
514
            $emails = array_filter($contactInfo->getMails(), $notForReservations);
515
516 View Code Duplication
            if (!empty($emails)) {
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...
517
                $contactPoint['email'] = array_map(
518
                    function (\CultureFeed_Cdb_Data_Mail $email) {
519
                        return $email->getMailAddress();
520
                    },
521
                    $emails
522
                );
523
                $contactPoint['email'] = array_values($contactPoint['email']);
524
            }
525
526
            $phones = array_filter($contactInfo->getPhones(), $notForReservations);
527
528 View Code Duplication
            if (!empty($phones)) {
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...
529
                $contactPoint['phone'] = array_map(
530
                    function (\CultureFeed_Cdb_Data_phone $phone) {
531
                        return $phone->getNumber();
532
                    },
533
                    $phones
534
                );
535
                $contactPoint['phone'] = array_values($contactPoint['phone']);
536
            }
537
538
            $urls = array_filter($contactInfo->getUrls(), $notForReservations);
539
540 View Code Duplication
            if (!empty($urls)) {
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...
541
                $contactPoint['url'] = array_map(
542
                    function (\CultureFeed_Cdb_Data_Url $url) {
543
                        return $url->getUrl();
544
                    },
545
                    $urls
546
                );
547
                $contactPoint['url'] = array_values($contactPoint['url']);
548
            }
549
550
            array_filter($contactPoint);
551
            if (!empty($contactPoint)) {
552
                $jsonLD->contactPoint = $contactPoint;
553
            }
554
        }
555
    }
556
557
    /**
558
     * @param \CultureFeed_Cdb_Item_Event $event
559
     * @param \stdClass $jsonLD
560
     */
561
    private function importTerms(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
562
    {
563
        $themeBlacklist = [
564
            'Thema onbepaald',
565
            'Meerder kunstvormen',
566
            'Meerdere filmgenres'
567
        ];
568
        $categories = array();
569 View Code Duplication
        foreach ($event->getCategories() as $category) {
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...
570
            /* @var \Culturefeed_Cdb_Data_Category $category */
571
            if ($category && !in_array($category->getName(), $themeBlacklist)) {
572
                $categories[] = array(
573
                    'label' => $category->getName(),
574
                    'domain' => $category->getType(),
575
                    'id' => $category->getId(),
576
                );
577
            }
578
        }
579
        $jsonLD->terms = $categories;
580
    }
581
582
    /**
583
     * @param \CultureFeed_Cdb_Item_Event $event
584
     * @param \stdClass $jsonLD
585
     */
586
    private function importCalendar(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
587
    {
588
        // To render the front-end we make a distinction between 4 calendar types
589
        // Permanent and Periodic map directly to the Cdb calendar classes
590
        // Simple timestamps are divided into single and multiple
591
        $calendarType = 'unknown';
592
        $calendar = $event->getCalendar();
593
594
        if ($calendar instanceof \CultureFeed_Cdb_Data_Calendar_Permanent) {
595
            $calendarType = 'permanent';
596
        } elseif ($calendar instanceof \CultureFeed_Cdb_Data_Calendar_PeriodList) {
597
            $calendarType = 'periodic';
598
            $calendar->rewind();
599
            $firstCalendarItem = $calendar->current();
600
            $startDateString = $firstCalendarItem->getDateFrom() . 'T00:00:00';
601
            $startDate = DateTimeFactory::dateTimeFromDateString($startDateString);
602
603 View Code Duplication
            if (iterator_count($calendar) > 1) {
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...
604
                $periodArray = iterator_to_array($calendar);
605
                $lastCalendarItem = end($periodArray);
606
            } else {
607
                $lastCalendarItem = $firstCalendarItem;
608
            }
609
610
            $endDateString = $lastCalendarItem->getDateTo() . 'T00:00:00';
611
            $endDate = DateTimeFactory::dateTimeFromDateString($endDateString);
612
613
            $jsonLD->startDate = $startDate->format('c');
614
            $jsonLD->endDate = $endDate->format('c');
615
        } elseif ($calendar instanceof \CultureFeed_Cdb_Data_Calendar_TimestampList) {
616
            $calendarType = 'single';
617
            $calendar->rewind();
618
            /** @var \CultureFeed_Cdb_Data_Calendar_Timestamp $firstCalendarItem */
619
            $firstCalendarItem = $calendar->current();
620
            if ($firstCalendarItem->getStartTime()) {
621
                $dateString =
622
                    $firstCalendarItem->getDate() . 'T' . $firstCalendarItem->getStartTime();
623
            } else {
624
                $dateString = $firstCalendarItem->getDate() . 'T00:00:00';
625
            }
626
627
            $startDate = DateTimeFactory::dateTimeFromDateString($dateString);
628
629 View Code Duplication
            if (iterator_count($calendar) > 1) {
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...
630
                $periodArray = iterator_to_array($calendar);
631
                $lastCalendarItem = end($periodArray);
632
            } else {
633
                $lastCalendarItem = $firstCalendarItem;
634
            }
635
636
            $endDateString = null;
637
            if ($lastCalendarItem->getEndTime()) {
638
                $endDateString =
639
                    $lastCalendarItem->getDate() . 'T' . $lastCalendarItem->getEndTime();
640
            } else {
641
                if (iterator_count($calendar) > 1) {
642
                    $endDateString = $lastCalendarItem->getDate() . 'T00:00:00';
643
                }
644
            }
645
646
            if ($endDateString) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $endDateString of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
647
                $endDate = DateTimeFactory::dateTimeFromDateString($endDateString);
648
                $jsonLD->endDate = $endDate->format('c');
649
650
                if ($startDate->format('Ymd') != $endDate->format('Ymd')) {
651
                    $calendarType = 'multiple';
652
                }
653
            }
654
655
            $jsonLD->startDate = $startDate->format('c');
656
        }
657
658
        $jsonLD->calendarType = $calendarType;
659
    }
660
661
    /**
662
     * @param \CultureFeed_Cdb_Item_Event $event
663
     * @param \stdClass $jsonLD
664
     */
665
    private function importTypicalAgeRange(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
666
    {
667
        $ageFrom = $event->getAgeFrom();
668
        if ($ageFrom) {
669
            $jsonLD->typicalAgeRange = "{$ageFrom}-";
670
        }
671
    }
672
673
    /**
674
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
675
     * @param \stdClass $jsonLD
676
     */
677
    private function importPerformers(\CultureFeed_Cdb_Data_EventDetail $detail, $jsonLD)
678
    {
679
        /** @var \CultureFeed_Cdb_Data_Performer $performer */
680
        $performers = $detail->getPerformers();
681
        if ($performers) {
682
            foreach ($performers as $performer) {
683
                if ($performer->getLabel()) {
684
                    $performerData = new \stdClass();
685
                    $performerData->name = $performer->getLabel();
686
                    $jsonLD->performer[] = $performerData;
687
                }
688
            }
689
        }
690
    }
691
692
    /**
693
     * @param \CultureFeed_Cdb_Item_Event $event
694
     * @param \stdClass $jsonLD
695
     */
696
    private function importLanguages(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
697
    {
698
        /** @var \CultureFeed_Cdb_Data_Language $udb2Language */
699
        $languages = $event->getLanguages();
700
        if ($languages) {
701
            $jsonLD->language = [];
702
            foreach ($languages as $udb2Language) {
703
                $jsonLD->language[] = $udb2Language->getLanguage();
704
            }
705
            $jsonLD->language = array_unique($jsonLD->language);
706
        }
707
    }
708
709
    /**
710
     * @param \CultureFeed_Cdb_Item_Event $event
711
     * @param \stdClass $jsonLD
712
     */
713
    private function importSeeAlso(
714
        \CultureFeed_Cdb_Item_Event $event,
715
        \stdClass $jsonLD
716
    ) {
717
        if (!property_exists($jsonLD, 'seeAlso')) {
718
            $jsonLD->seeAlso = [];
719
        }
720
721
        // Add contact info url, if it's not for reservations.
722
        if ($contactInfo = $event->getContactInfo()) {
723
            /** @var \CultureFeed_Cdb_Data_Url[] $contactUrls */
724
            $contactUrls = $contactInfo->getUrls();
725
            if (is_array($contactUrls) && count($contactUrls) > 0) {
726
                foreach ($contactUrls as $contactUrl) {
727
                    if (!$contactUrl->isForReservations()) {
728
                        $jsonLD->seeAlso[] = $contactUrl->getUrl();
729
                    }
730
                }
731
            }
732
        }
733
    }
734
735
    /**
736
     * @param \CultureFeed_Cdb_Item_Event $event
737
     * @param SluggerInterface $slugger
738
     * @param \stdClass $jsonLD
739
     */
740
    private function importUitInVlaanderenReference(
741
        \CultureFeed_Cdb_Item_Event $event,
742
        SluggerInterface $slugger,
743
        $jsonLD
744
    ) {
745
746
        // Some events seem to not have a Dutch name, even though this is
747
        // required. If there's no Dutch name, we just leave the slug empty as
748
        // that seems to be the behaviour on http://m.uitinvlaanderen.be
749
        if (isset($jsonLD->name['nl'])) {
750
            $name = $jsonLD->name['nl'];
751
            $slug = $slugger->slug($name);
752
        } else {
753
            $slug = '';
754
        }
755
756
        $reference = 'http://www.uitinvlaanderen.be/agenda/e/' . $slug . '/' . $event->getCdbId();
757
758
759
        if (!property_exists($jsonLD, 'sameAs')) {
760
            $jsonLD->sameAs = [];
761
        }
762
763
        if (!in_array($reference, $jsonLD->sameAs)) {
764
            array_push($jsonLD->sameAs, $reference);
765
        }
766
    }
767
}
768