Completed
Pull Request — master (#359)
by Luc
08:30
created

CdbXMLImporter::importOrganizer()   D

Complexity

Conditions 9
Paths 12

Size

Total Lines 39
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 4.909
c 0
b 0
f 0
cc 9
eloc 26
nc 12
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
        /** @var \CultureFeed_Cdb_Data_EventDetail $detail */
86
        $detail = null;
87
88
        /** @var \CultureFeed_Cdb_Data_EventDetail[] $details */
89
        $details = $event->getDetails();
90
91
        foreach ($details as $languageDetail) {
92
            $language = $languageDetail->getLanguage();
93
94
            // The first language detail found will be used to retrieve
95
            // properties from which in UDB3 are not any longer considered
96
            // to be language specific.
97
            if (!$detail) {
98
                $detail = $languageDetail;
99
            }
100
101
            $jsonLD->name[$language] = $languageDetail->getTitle();
102
103
            $this->importDescription($languageDetail, $jsonLD, $language);
104
        }
105
106
        $this->cdbXMLItemBaseImporter->importAvailable($event, $jsonLD);
107
108
        $labelImporter = new LabelImporter();
109
        $labelImporter->importLabels($event, $jsonLD);
110
111
        $jsonLD->calendarSummary = $detail->getCalendarSummary();
112
113
        $this->importLocation($event, $placeManager, $jsonLD);
114
115
        $this->importOrganizer($event, $organizerManager, $jsonLD);
116
117 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...
118
            $this->cdbXmlContactInfoImporter->importBookingInfo(
119
                $jsonLD,
120
                $event->getContactInfo(),
121
                $detail->getPrice(),
122
                $event->getBookingPeriod()
123
            );
124
125
            $this->cdbXmlContactInfoImporter->importContactPoint(
126
                $jsonLD,
127
                $event->getContactInfo()
128
            );
129
        }
130
131
        $this->cdbXMLItemBaseImporter->importPriceInfo($details, $jsonLD);
0 ignored issues
show
Documentation introduced by
$details is of type array<integer,object<Cul..._Cdb_Data_EventDetail>>, but the function expects a object<CultureFeed_Cdb_Data_DetailList>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
132
133
        $this->importTerms($event, $jsonLD);
134
135
        $this->cdbXMLItemBaseImporter->importPublicationInfo($event, $jsonLD);
136
137
        $calendar = $this->calendarFactory->createFromCdbCalendar($event->getCalendar());
138
        $jsonLD = (object)array_merge((array)$jsonLD, $calendar->toJsonLd());
139
140
        $this->importTypicalAgeRange($event, $jsonLD);
141
142
        $this->importPerformers($detail, $jsonLD);
143
144
        $this->importUitInVlaanderenReference($event, $slugger, $jsonLD);
145
146
        $this->cdbXMLItemBaseImporter->importExternalId($event, $jsonLD);
147
148
        $this->importSeeAlso($event, $jsonLD);
149
150
        $this->cdbXMLItemBaseImporter->importWorkflowStatus($event, $jsonLD);
151
152
        $this->importAudience($event, $jsonLD);
153
154
        return $jsonLD;
155
    }
156
157
    /**
158
     * @param \CultureFeed_Cdb_Data_EventDetail $languageDetail
159
     * @param \stdClass $jsonLD
160
     * @param string $language
161
     */
162
    private function importDescription($languageDetail, $jsonLD, $language)
163
    {
164
        try {
165
            $description = MergedDescription::fromCdbDetail($languageDetail);
166
            $jsonLD->description[$language] = $description->toNative();
167
        } catch (\InvalidArgumentException $e) {
168
            return;
169
        }
170
    }
171
172
    /**
173
     * @param \CultureFeed_Cdb_Item_Event $event
174
     * @param PlaceServiceInterface $placeManager
175
     * @param \stdClass $jsonLD
176
     */
177
    private function importLocation(\CultureFeed_Cdb_Item_Event $event, PlaceServiceInterface $placeManager, $jsonLD)
178
    {
179
        $location = array();
180
        $location['@type'] = 'Place';
181
182
        $location_id = $this->cdbIdExtractor->getRelatedPlaceCdbId($event);
183
184
        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...
185
            $location += (array)$placeManager->placeJSONLD($location_id);
186
        } else {
187
            $location_cdb = $event->getLocation();
188
            $location['name']['nl'] = $location_cdb->getLabel();
189
            $address = $location_cdb->getAddress()->getPhysicalAddress();
190
            if ($address) {
191
                $location['address'] = array(
192
                    'addressCountry' => $address->getCountry(),
193
                    'addressLocality' => $address->getCity(),
194
                    'postalCode' => $address->getZip(),
195
                    'streetAddress' => $address->getStreet() . ' ' . $address->getHouseNumber(),
196
                );
197
            }
198
        }
199
        $jsonLD->location = $location;
200
    }
201
202
    /**
203
     * @param \CultureFeed_Cdb_Item_Event $event
204
     * @param OrganizerServiceInterface $organizerManager
205
     * @param \stdClass $jsonLD
206
     */
207
    private function importOrganizer(
208
        \CultureFeed_Cdb_Item_Event $event,
209
        OrganizerServiceInterface $organizerManager,
210
        $jsonLD
211
    ) {
212
        $organizer = null;
213
        $organizer_id = $this->cdbIdExtractor->getRelatedOrganizerCdbId($event);
214
        $organizer_cdb = $event->getOrganiser();
215
        $contact_info_cdb = $event->getContactInfo();
216
217
        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...
218
            $organizer = (array)$organizerManager->organizerJSONLD($organizer_id);
219
        } elseif ($organizer_cdb && $contact_info_cdb) {
220
            $organizer = array();
221
            $organizer['name'] = $organizer_cdb->getLabel();
222
223
            $emails_cdb = $contact_info_cdb->getMails();
224
            if (count($emails_cdb) > 0) {
225
                $organizer['email'] = array();
226
                foreach ($emails_cdb as $email) {
227
                    $organizer['email'][] = $email->getMailAddress();
228
                }
229
            }
230
231
            /** @var \CultureFeed_Cdb_Data_Phone[] $phones_cdb */
232
            $phones_cdb = $contact_info_cdb->getPhones();
233
            if (count($phones_cdb) > 0) {
234
                $organizer['phone'] = array();
235
                foreach ($phones_cdb as $phone) {
236
                    $organizer['phone'][] = $phone->getNumber();
237
                }
238
            }
239
        }
240
241
        if (!is_null($organizer)) {
242
            $organizer['@type'] = 'Organizer';
243
            $jsonLD->organizer = $organizer;
244
        }
245
    }
246
247
    /**
248
     * @param \CultureFeed_Cdb_Item_Event $event
249
     * @param \stdClass $jsonLD
250
     */
251
    private function importTerms(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
252
    {
253
        $themeBlacklist = [
254
            'Thema onbepaald',
255
            'Meerder kunstvormen',
256
            'Meerdere filmgenres',
257
        ];
258
        $categories = array();
259 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...
260
            /* @var \Culturefeed_Cdb_Data_Category $category */
261
            if ($category && !in_array($category->getName(), $themeBlacklist)) {
262
                $categories[] = array(
263
                    'label' => $category->getName(),
264
                    'domain' => $category->getType(),
265
                    'id' => $category->getId(),
266
                );
267
            }
268
        }
269
        $jsonLD->terms = $categories;
270
    }
271
272
    /**
273
     * @param \CultureFeed_Cdb_Item_Event $event
274
     * @param \stdClass $jsonLD
275
     */
276
    private function importTypicalAgeRange(\CultureFeed_Cdb_Item_Event $event, $jsonLD)
277
    {
278
        $ageFrom = $event->getAgeFrom();
279
        $ageTo = $event->getAgeTo();
280
281
        if (!is_int($ageFrom) && !is_int($ageTo)) {
282
            return;
283
        }
284
285
        $jsonLD->typicalAgeRange = "{$ageFrom}-{$ageTo}";
286
    }
287
288
    /**
289
     * @param \CultureFeed_Cdb_Data_EventDetail $detail
290
     * @param \stdClass $jsonLD
291
     */
292
    private function importPerformers(\CultureFeed_Cdb_Data_EventDetail $detail, $jsonLD)
293
    {
294
        /** @var \CultureFeed_Cdb_Data_Performer $performer */
295
        $performers = $detail->getPerformers();
296
        if ($performers) {
297
            foreach ($performers as $performer) {
298
                if ($performer->getLabel()) {
299
                    $performerData = new \stdClass();
300
                    $performerData->name = $performer->getLabel();
301
                    $jsonLD->performer[] = $performerData;
302
                }
303
            }
304
        }
305
    }
306
307
    /**
308
     * @param \CultureFeed_Cdb_Item_Event $event
309
     * @param \stdClass $jsonLD
310
     */
311
    private function importSeeAlso(
312
        \CultureFeed_Cdb_Item_Event $event,
313
        \stdClass $jsonLD
314
    ) {
315
        if (!property_exists($jsonLD, 'seeAlso')) {
316
            $jsonLD->seeAlso = [];
317
        }
318
319
        // Add contact info url, if it's not for reservations.
320
        if ($contactInfo = $event->getContactInfo()) {
321
            /** @var \CultureFeed_Cdb_Data_Url[] $contactUrls */
322
            $contactUrls = $contactInfo->getUrls();
323
            if (is_array($contactUrls) && count($contactUrls) > 0) {
324
                foreach ($contactUrls as $contactUrl) {
325
                    if (!$contactUrl->isForReservations()) {
326
                        $jsonLD->seeAlso[] = $contactUrl->getUrl();
327
                    }
328
                }
329
            }
330
        }
331
    }
332
333
    /**
334
     * @param \CultureFeed_Cdb_Item_Event $event
335
     * @param SluggerInterface $slugger
336
     * @param \stdClass $jsonLD
337
     */
338
    private function importUitInVlaanderenReference(
339
        \CultureFeed_Cdb_Item_Event $event,
340
        SluggerInterface $slugger,
341
        $jsonLD
342
    ) {
343
344
        // Some events seem to not have a Dutch name, even though this is
345
        // required. If there's no Dutch name, we just leave the slug empty as
346
        // that seems to be the behaviour on http://m.uitinvlaanderen.be
347
        if (isset($jsonLD->name['nl'])) {
348
            $name = $jsonLD->name['nl'];
349
            $slug = $slugger->slug($name);
350
        } else {
351
            $slug = '';
352
        }
353
354
        $reference = 'http://www.uitinvlaanderen.be/agenda/e/' . $slug . '/' . $event->getCdbId();
355
356
357
        if (!property_exists($jsonLD, 'sameAs')) {
358
            $jsonLD->sameAs = [];
359
        }
360
361
        if (!in_array($reference, $jsonLD->sameAs)) {
362
            array_push($jsonLD->sameAs, $reference);
363
        }
364
    }
365
366
    /**
367
     * @param \CultureFeed_Cdb_Item_Event $event
368
     * @param \stdClass $jsonLD
369
     */
370
    private function importAudience(\CultureFeed_Cdb_Item_Event $event, \stdClass $jsonLD)
371
    {
372
        $eventIsPrivate = (bool) $event->isPrivate();
373
        $eventTargetsEducation = $eventIsPrivate && $event->getCategories()->hasCategory('2.1.3.0.0');
374
375
        $audienceType = $eventTargetsEducation ? 'education' : ($eventIsPrivate ? 'members' : 'everyone');
376
        $audience = new Audience(AudienceType::fromNative($audienceType));
377
378
        $jsonLD->audience = $audience->serialize();
379
    }
380
}
381