Completed
Pull Request — master (#359)
by Luc
10:56 queued 05:32
created

CdbXMLImporter::importDescription()   A

Complexity

Conditions 2
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 6
nc 3
nop 3
1
<?php
2
3
namespace CultuurNet\UDB3\Event\ReadModel\JSONLD;
4
5
use CultuurNet\UDB3\CalendarFactoryInterface;
6
use CultuurNet\UDB3\Cdb\CdbId\EventCdbIdExtractorInterface;
7
use CultuurNet\UDB3\Cdb\Description\MergedDescription;
8
use CultuurNet\UDB3\Event\ValueObjects\Audience;
9
use CultuurNet\UDB3\Event\ValueObjects\AudienceType;
10
use CultuurNet\UDB3\LabelImporter;
11
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXmlContactInfoImporterInterface;
12
use CultuurNet\UDB3\Offer\ReadModel\JSONLD\CdbXMLItemBaseImporter;
13
use CultuurNet\UDB3\SluggerInterface;
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 CalendarFactoryInterface
33
     */
34
    private $calendarFactory;
35
36
    /**
37
     * @var CdbXmlContactInfoImporterInterface
38
     */
39
    private $cdbXmlContactInfoImporter;
40
41
    /**
42
     * @param CdbXMLItemBaseImporter $cdbXMLItemBaseImporter
43
     * @param EventCdbIdExtractorInterface $cdbIdExtractor
44
     * @param CalendarFactoryInterface $calendarFactory
45
     * @param CdbXmlContactInfoImporterInterface $cdbXmlContactInfoImporter
46
     */
47
    public function __construct(
48
        CdbXMLItemBaseImporter $cdbXMLItemBaseImporter,
49
        EventCdbIdExtractorInterface $cdbIdExtractor,
50
        CalendarFactoryInterface $calendarFactory,
51
        CdbXmlContactInfoImporterInterface $cdbXmlContactInfoImporter
52
    ) {
53
        $this->cdbXMLItemBaseImporter = $cdbXMLItemBaseImporter;
54
        $this->cdbIdExtractor = $cdbIdExtractor;
55
        $this->calendarFactory = $calendarFactory;
56
        $this->cdbXmlContactInfoImporter = $cdbXmlContactInfoImporter;
57
    }
58
59
    /**
60
     * Imports a UDB2 event into a UDB3 JSON-LD document.
61
     *
62
     * @param \stdClass $base
63
     *   The JSON-LD document to start from.
64
     * @param \CultureFeed_Cdb_Item_Event $event
65
     *   The cultural event data from UDB2 to import.
66
     * @param PlaceServiceInterface $placeManager
67
     *   The manager from which to retrieve the JSON-LD of a place.
68
     * @param OrganizerServiceInterface $organizerManager
69
     *   The manager from which to retrieve the JSON-LD of an organizer.
70
     * @param SluggerInterface $slugger
71
     *   The slugger that's used to generate a sameAs reference.
72
     *
73
     * @return \stdClass
74
     *   The document with the UDB2 event data merged in.
75
     */
76
    public function documentWithCdbXML(
77
        $base,
78
        \CultureFeed_Cdb_Item_Event $event,
79
        PlaceServiceInterface $placeManager,
80
        OrganizerServiceInterface $organizerManager,
81
        SluggerInterface $slugger
82
    ) {
83
        $jsonLD = clone $base;
84
85
        $detail = null;
86
87
        $details = $event->getDetails();
88
89
        foreach ($details as $languageDetail) {
90
            $language = $languageDetail->getLanguage();
91
92
            // The first language detail found will be used to retrieve
93
            // properties from which in UDB3 are not any longer considered
94
            // to be language specific.
95
            if (!$detail) {
96
                $detail = $languageDetail;
97
            }
98
99
            $jsonLD->name[$language] = $languageDetail->getTitle();
100
101
            $this->importDescription($languageDetail, $jsonLD, $language);
102
        }
103
104
        $this->cdbXMLItemBaseImporter->importAvailable($event, $jsonLD);
105
106
        $labelImporter = new LabelImporter();
107
        $labelImporter->importLabels($event, $jsonLD);
108
109
        $jsonLD->calendarSummary = $detail->getCalendarSummary();
110
111
        $this->importLocation($event, $placeManager, $jsonLD);
112
113
        $this->importOrganizer($event, $organizerManager, $jsonLD);
114
115 View Code Duplication
        if ($event->getContactInfo()) {
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...
116
            $this->cdbXmlContactInfoImporter->importBookingInfo(
117
                $jsonLD,
118
                $event->getContactInfo(),
119
                $detail->getPrice(),
120
                $event->getBookingPeriod()
121
            );
122
123
            $this->cdbXmlContactInfoImporter->importContactPoint(
124
                $jsonLD,
125
                $event->getContactInfo()
126
            );
127
        }
128
129
        $this->cdbXMLItemBaseImporter->importPriceInfo($details, $jsonLD);
130
131
        $this->importTerms($event, $jsonLD);
132
133
        $this->cdbXMLItemBaseImporter->importPublicationInfo($event, $jsonLD);
134
135
        $calendar = $this->calendarFactory->createFromCdbCalendar($event->getCalendar());
136
        $jsonLD = (object)array_merge((array)$jsonLD, $calendar->toJsonLd());
137
138
        $this->importTypicalAgeRange($event, $jsonLD);
139
140
        $this->importPerformers($detail, $jsonLD);
141
142
        $this->importUitInVlaanderenReference($event, $slugger, $jsonLD);
143
144
        $this->cdbXMLItemBaseImporter->importExternalId($event, $jsonLD);
145
146
        $this->importSeeAlso($event, $jsonLD);
147
148
        $this->cdbXMLItemBaseImporter->importWorkflowStatus($event, $jsonLD);
149
150
        $this->importAudience($event, $jsonLD);
151
152
        return $jsonLD;
153
    }
154
155
    /**
156
     * @param \CultureFeed_Cdb_Data_EventDetail $languageDetail
157
     * @param \stdClass $jsonLD
158
     * @param string $language
159
     */
160
    private function importDescription($languageDetail, $jsonLD, $language)
161
    {
162
        try {
163
            $description = MergedDescription::fromCdbDetail($languageDetail);
164
            $jsonLD->description[$language] = $description->toNative();
165
        } catch (\InvalidArgumentException $e) {
166
            return;
167
        }
168
    }
169
170
    /**
171
     * @param \CultureFeed_Cdb_Item_Event $event
172
     * @param PlaceServiceInterface $placeManager
173
     * @param \stdClass $jsonLD
174
     */
175
    private function importLocation(\CultureFeed_Cdb_Item_Event $event, PlaceServiceInterface $placeManager, $jsonLD)
176
    {
177
        $location = array();
178
        $location['@type'] = 'Place';
179
180
        $location_id = $this->cdbIdExtractor->getRelatedPlaceCdbId($event);
181
182
        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...
183
            $location += (array)$placeManager->placeJSONLD($location_id);
184
        } else {
185
            $location_cdb = $event->getLocation();
186
            $location['name']['nl'] = $location_cdb->getLabel();
187
            $address = $location_cdb->getAddress()->getPhysicalAddress();
188
            if ($address) {
189
                $location['address'] = array(
190
                    'addressCountry' => $address->getCountry(),
191
                    'addressLocality' => $address->getCity(),
192
                    'postalCode' => $address->getZip(),
193
                    'streetAddress' => $address->getStreet() . ' ' . $address->getHouseNumber(),
194
                );
195
            }
196
        }
197
        $jsonLD->location = $location;
198
    }
199
200
    /**
201
     * @param \CultureFeed_Cdb_Item_Event $event
202
     * @param OrganizerServiceInterface $organizerManager
203
     * @param \stdClass $jsonLD
204
     */
205
    private function importOrganizer(
206
        \CultureFeed_Cdb_Item_Event $event,
207
        OrganizerServiceInterface $organizerManager,
208
        $jsonLD
209
    ) {
210
        $organizer = null;
211
        $organizer_id = $this->cdbIdExtractor->getRelatedOrganizerCdbId($event);
212
        $organizer_cdb = $event->getOrganiser();
213
        $contact_info_cdb = $event->getContactInfo();
214
215
        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...
216
            $organizer = (array)$organizerManager->organizerJSONLD($organizer_id);
217
        } elseif ($organizer_cdb && $contact_info_cdb) {
218
            $organizer = array();
219
            $organizer['name'] = $organizer_cdb->getLabel();
220
221
            $emails_cdb = $contact_info_cdb->getMails();
222
            if (count($emails_cdb) > 0) {
223
                $organizer['email'] = array();
224
                foreach ($emails_cdb as $email) {
225
                    $organizer['email'][] = $email->getMailAddress();
226
                }
227
            }
228
229
            /** @var \CultureFeed_Cdb_Data_Phone[] $phones_cdb */
230
            $phones_cdb = $contact_info_cdb->getPhones();
231
            if (count($phones_cdb) > 0) {
232
                $organizer['phone'] = array();
233
                foreach ($phones_cdb as $phone) {
234
                    $organizer['phone'][] = $phone->getNumber();
235
                }
236
            }
237
        }
238
239
        if (!is_null($organizer)) {
240
            $organizer['@type'] = 'Organizer';
241
            $jsonLD->organizer = $organizer;
242
        }
243
    }
244
245
    /**
246
     * @param \CultureFeed_Cdb_Item_Event $event
247
     * @param \stdClass $jsonLD
248
     */
249
    private function importTerms(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
250
    {
251
        $themeBlacklist = [
252
            'Thema onbepaald',
253
            'Meerder kunstvormen',
254
            'Meerdere filmgenres',
255
        ];
256
        $categories = array();
257 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...
258
            /* @var \Culturefeed_Cdb_Data_Category $category */
259
            if ($category && !in_array($category->getName(), $themeBlacklist)) {
260
                $categories[] = array(
261
                    'label' => $category->getName(),
262
                    'domain' => $category->getType(),
263
                    'id' => $category->getId(),
264
                );
265
            }
266
        }
267
        $jsonLD->terms = $categories;
268
    }
269
270
    /**
271
     * @param \CultureFeed_Cdb_Item_Event $event
272
     * @param \stdClass $jsonLD
273
     */
274
    private function importTypicalAgeRange(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
275
    {
276
        $ageFrom = $event->getAgeFrom();
277
        $ageTo = $event->getAgeTo();
278
279
        if (!is_int($ageFrom) && !is_int($ageTo)) {
280
            return;
281
        }
282
283
        $jsonLD->typicalAgeRange = "{$ageFrom}-{$ageTo}";
284
    }
285
286
    /**
287
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
288
     * @param \stdClass $jsonLD
289
     */
290
    private function importPerformers(\CultureFeed_Cdb_Data_EventDetail $detail, $jsonLD)
291
    {
292
        /** @var \CultureFeed_Cdb_Data_Performer $performer */
293
        $performers = $detail->getPerformers();
294
        if ($performers) {
295
            foreach ($performers as $performer) {
296
                if ($performer->getLabel()) {
297
                    $performerData = new \stdClass();
298
                    $performerData->name = $performer->getLabel();
299
                    $jsonLD->performer[] = $performerData;
300
                }
301
            }
302
        }
303
    }
304
305
    /**
306
     * @param \CultureFeed_Cdb_Item_Event $event
307
     * @param \stdClass $jsonLD
308
     */
309
    private function importSeeAlso(
310
        \CultureFeed_Cdb_Item_Event $event,
311
        \stdClass $jsonLD
312
    ) {
313
        if (!property_exists($jsonLD, 'seeAlso')) {
314
            $jsonLD->seeAlso = [];
315
        }
316
317
        // Add contact info url, if it's not for reservations.
318
        if ($contactInfo = $event->getContactInfo()) {
319
            /** @var \CultureFeed_Cdb_Data_Url[] $contactUrls */
320
            $contactUrls = $contactInfo->getUrls();
321
            if (is_array($contactUrls) && count($contactUrls) > 0) {
322
                foreach ($contactUrls as $contactUrl) {
323
                    if (!$contactUrl->isForReservations()) {
324
                        $jsonLD->seeAlso[] = $contactUrl->getUrl();
325
                    }
326
                }
327
            }
328
        }
329
    }
330
331
    /**
332
     * @param \CultureFeed_Cdb_Item_Event $event
333
     * @param SluggerInterface $slugger
334
     * @param \stdClass $jsonLD
335
     */
336
    private function importUitInVlaanderenReference(
337
        \CultureFeed_Cdb_Item_Event $event,
338
        SluggerInterface $slugger,
339
        $jsonLD
340
    ) {
341
342
        // Some events seem to not have a Dutch name, even though this is
343
        // required. If there's no Dutch name, we just leave the slug empty as
344
        // that seems to be the behaviour on http://m.uitinvlaanderen.be
345
        if (isset($jsonLD->name['nl'])) {
346
            $name = $jsonLD->name['nl'];
347
            $slug = $slugger->slug($name);
348
        } else {
349
            $slug = '';
350
        }
351
352
        $reference = 'http://www.uitinvlaanderen.be/agenda/e/' . $slug . '/' . $event->getCdbId();
353
354
355
        if (!property_exists($jsonLD, 'sameAs')) {
356
            $jsonLD->sameAs = [];
357
        }
358
359
        if (!in_array($reference, $jsonLD->sameAs)) {
360
            array_push($jsonLD->sameAs, $reference);
361
        }
362
    }
363
364
    /**
365
     * @param \CultureFeed_Cdb_Item_Event $event
366
     * @param \stdClass $jsonLD
367
     */
368
    private function importAudience(\CultureFeed_Cdb_Item_Event $event, \stdClass $jsonLD)
369
    {
370
        $eventIsPrivate = (bool) $event->isPrivate();
371
        $eventTargetsEducation = $eventIsPrivate && $event->getCategories()->hasCategory('2.1.3.0.0');
372
373
        $audienceType = $eventTargetsEducation ? 'education' : ($eventIsPrivate ? 'members' : 'everyone');
374
        $audience = new Audience(AudienceType::fromNative($audienceType));
375
376
        $jsonLD->audience = $audience->serialize();
377
    }
378
}
379