|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace CultuurNet\UDB3\Offer\ReadModel\JSONLD; |
|
4
|
|
|
|
|
5
|
|
|
use Broadway\Domain\DomainMessage; |
|
6
|
|
|
use CommerceGuys\Intl\Currency\CurrencyRepository; |
|
7
|
|
|
use CommerceGuys\Intl\NumberFormat\NumberFormatRepository; |
|
8
|
|
|
use CultuurNet\UDB3\CalendarFactoryInterface; |
|
9
|
|
|
use CultuurNet\UDB3\Cdb\CdbId\EventCdbIdExtractorInterface; |
|
10
|
|
|
use CultuurNet\UDB3\Cdb\PriceDescriptionParser; |
|
11
|
|
|
use CultuurNet\UDB3\CulturefeedSlugger; |
|
12
|
|
|
use CultuurNet\UDB3\EntityNotFoundException; |
|
13
|
|
|
use CultuurNet\UDB3\EntityServiceInterface; |
|
14
|
|
|
use CultuurNet\UDB3\Event\ReadModel\DocumentRepositoryInterface; |
|
15
|
|
|
use CultuurNet\UDB3\Event\ReadModel\JSONLD\CdbXMLImporter; |
|
16
|
|
|
use CultuurNet\UDB3\Event\ReadModel\JSONLD\OrganizerServiceInterface; |
|
17
|
|
|
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait; |
|
18
|
|
|
use CultuurNet\UDB3\Iri\IriGeneratorInterface; |
|
19
|
|
|
use CultuurNet\UDB3\Label; |
|
20
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractBookingInfoUpdated; |
|
21
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractContactPointUpdated; |
|
22
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionTranslated; |
|
23
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractDescriptionUpdated; |
|
24
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractEvent; |
|
25
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractLabelAdded; |
|
26
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractLabelRemoved; |
|
27
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerDeleted; |
|
28
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractOrganizerUpdated; |
|
29
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractPriceInfoUpdated; |
|
30
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractTitleTranslated; |
|
31
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeDeleted; |
|
32
|
|
|
use CultuurNet\UDB3\Offer\Events\AbstractTypicalAgeRangeUpdated; |
|
33
|
|
|
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageAdded; |
|
34
|
|
|
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageRemoved; |
|
35
|
|
|
use CultuurNet\UDB3\Offer\Events\Image\AbstractImageUpdated; |
|
36
|
|
|
use CultuurNet\UDB3\Offer\Events\Image\AbstractMainImageSelected; |
|
37
|
|
|
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractApproved; |
|
38
|
|
|
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsDuplicate; |
|
39
|
|
|
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractFlaggedAsInappropriate; |
|
40
|
|
|
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractPublished; |
|
41
|
|
|
use CultuurNet\UDB3\Offer\Events\Moderation\AbstractRejected; |
|
42
|
|
|
use CultuurNet\UDB3\Offer\WorkflowStatus; |
|
43
|
|
|
use CultuurNet\UDB3\ReadModel\JsonDocument; |
|
44
|
|
|
use CultuurNet\UDB3\SluggerInterface; |
|
45
|
|
|
use Symfony\Component\Serializer\SerializerInterface; |
|
46
|
|
|
use ValueObjects\Identity\UUID; |
|
47
|
|
|
|
|
48
|
|
|
abstract class OfferLDProjector implements OrganizerServiceInterface |
|
49
|
|
|
{ |
|
50
|
|
|
use DelegateEventHandlingToSpecificMethodTrait { |
|
51
|
|
|
DelegateEventHandlingToSpecificMethodTrait::handle as handleUnknownEvents; |
|
52
|
|
|
} |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* @var DocumentRepositoryInterface |
|
56
|
|
|
*/ |
|
57
|
|
|
protected $repository; |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* @var IriGeneratorInterface |
|
61
|
|
|
*/ |
|
62
|
|
|
protected $iriGenerator; |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* @var EntityServiceInterface |
|
66
|
|
|
*/ |
|
67
|
|
|
protected $organizerService; |
|
68
|
|
|
|
|
69
|
|
|
/** |
|
70
|
|
|
* @var SluggerInterface |
|
71
|
|
|
*/ |
|
72
|
|
|
protected $slugger; |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* @var CdbXMLImporter |
|
76
|
|
|
*/ |
|
77
|
|
|
protected $cdbXMLImporter; |
|
78
|
|
|
|
|
79
|
|
|
/** |
|
80
|
|
|
* @var SerializerInterface |
|
81
|
|
|
*/ |
|
82
|
|
|
protected $mediaObjectSerializer; |
|
83
|
|
|
|
|
84
|
|
|
/** |
|
85
|
|
|
* @param DocumentRepositoryInterface $repository |
|
86
|
|
|
* @param IriGeneratorInterface $iriGenerator |
|
87
|
|
|
* @param EntityServiceInterface $organizerService |
|
88
|
|
|
* @param SerializerInterface $mediaObjectSerializer |
|
89
|
|
|
* @param EventCdbIdExtractorInterface $eventCdbIdExtractor |
|
90
|
|
|
* @param CalendarFactoryInterface $calendarFactory |
|
91
|
|
|
*/ |
|
92
|
|
|
public function __construct( |
|
93
|
|
|
DocumentRepositoryInterface $repository, |
|
94
|
|
|
IriGeneratorInterface $iriGenerator, |
|
95
|
|
|
EntityServiceInterface $organizerService, |
|
96
|
|
|
SerializerInterface $mediaObjectSerializer, |
|
97
|
|
|
EventCdbIdExtractorInterface $eventCdbIdExtractor, |
|
98
|
|
|
CalendarFactoryInterface $calendarFactory |
|
99
|
|
|
) { |
|
100
|
|
|
$this->repository = $repository; |
|
101
|
|
|
$this->iriGenerator = $iriGenerator; |
|
102
|
|
|
$this->organizerService = $organizerService; |
|
103
|
|
|
$this->slugger = new CulturefeedSlugger(); |
|
104
|
|
|
|
|
105
|
|
|
$this->cdbXMLImporter = new CdbXMLImporter( |
|
106
|
|
|
new CdbXMLItemBaseImporter(), |
|
107
|
|
|
$eventCdbIdExtractor, |
|
108
|
|
|
new PriceDescriptionParser( |
|
109
|
|
|
new NumberFormatRepository(), |
|
110
|
|
|
new CurrencyRepository() |
|
111
|
|
|
), |
|
112
|
|
|
$calendarFactory |
|
113
|
|
|
); |
|
114
|
|
|
|
|
115
|
|
|
$this->mediaObjectSerializer = $mediaObjectSerializer; |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
/** |
|
119
|
|
|
* {@inheritdoc} |
|
120
|
|
|
*/ |
|
121
|
|
View Code Duplication |
public function handle(DomainMessage $domainMessage) |
|
|
|
|
|
|
122
|
|
|
{ |
|
123
|
|
|
$event = $domainMessage->getPayload(); |
|
124
|
|
|
|
|
125
|
|
|
$eventName = get_class($event); |
|
126
|
|
|
$eventHandlers = $this->getEventHandlers(); |
|
127
|
|
|
|
|
128
|
|
|
if (isset($eventHandlers[$eventName])) { |
|
129
|
|
|
$handler = $eventHandlers[$eventName]; |
|
130
|
|
|
call_user_func(array($this, $handler), $event); |
|
131
|
|
|
} else { |
|
132
|
|
|
$this->handleUnknownEvents($domainMessage); |
|
133
|
|
|
} |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* @return string[] |
|
138
|
|
|
* An associative array of commands and their handler methods. |
|
139
|
|
|
*/ |
|
140
|
|
View Code Duplication |
private function getEventHandlers() |
|
|
|
|
|
|
141
|
|
|
{ |
|
142
|
|
|
$events = []; |
|
143
|
|
|
|
|
144
|
|
|
foreach (get_class_methods($this) as $method) { |
|
145
|
|
|
$matches = []; |
|
146
|
|
|
|
|
147
|
|
|
if (preg_match('/^apply(.+)$/', $method, $matches)) { |
|
148
|
|
|
$event = $matches[1]; |
|
149
|
|
|
$classNameMethod = 'get' . $event . 'ClassName'; |
|
150
|
|
|
|
|
151
|
|
|
if (method_exists($this, $classNameMethod)) { |
|
152
|
|
|
$eventFullClassName = call_user_func(array($this, $classNameMethod)); |
|
153
|
|
|
$events[$eventFullClassName] = $method; |
|
154
|
|
|
} |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
return $events; |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* @return string |
|
163
|
|
|
*/ |
|
164
|
|
|
abstract protected function getLabelAddedClassName(); |
|
165
|
|
|
|
|
166
|
|
|
/** |
|
167
|
|
|
* @return string |
|
168
|
|
|
*/ |
|
169
|
|
|
abstract protected function getLabelRemovedClassName(); |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* @return string |
|
173
|
|
|
*/ |
|
174
|
|
|
abstract protected function getImageAddedClassName(); |
|
175
|
|
|
|
|
176
|
|
|
/** |
|
177
|
|
|
* @return string |
|
178
|
|
|
*/ |
|
179
|
|
|
abstract protected function getImageRemovedClassName(); |
|
180
|
|
|
|
|
181
|
|
|
/** |
|
182
|
|
|
* @return string |
|
183
|
|
|
*/ |
|
184
|
|
|
abstract protected function getImageUpdatedClassName(); |
|
185
|
|
|
|
|
186
|
|
|
/** |
|
187
|
|
|
* @return string |
|
188
|
|
|
*/ |
|
189
|
|
|
abstract protected function getMainImageSelectedClassName(); |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* @return string |
|
193
|
|
|
*/ |
|
194
|
|
|
abstract protected function getTitleTranslatedClassName(); |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* @return string |
|
198
|
|
|
*/ |
|
199
|
|
|
abstract protected function getDescriptionTranslatedClassName(); |
|
200
|
|
|
|
|
201
|
|
|
/** |
|
202
|
|
|
* @return string |
|
203
|
|
|
*/ |
|
204
|
|
|
abstract protected function getOrganizerUpdatedClassName(); |
|
205
|
|
|
|
|
206
|
|
|
/** |
|
207
|
|
|
* @return string |
|
208
|
|
|
*/ |
|
209
|
|
|
abstract protected function getOrganizerDeletedClassName(); |
|
210
|
|
|
|
|
211
|
|
|
/** |
|
212
|
|
|
* @return string |
|
213
|
|
|
*/ |
|
214
|
|
|
abstract protected function getBookingInfoUpdatedClassName(); |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* @return string |
|
218
|
|
|
*/ |
|
219
|
|
|
abstract protected function getPriceInfoUpdatedClassName(); |
|
220
|
|
|
|
|
221
|
|
|
/** |
|
222
|
|
|
* @return string |
|
223
|
|
|
*/ |
|
224
|
|
|
abstract protected function getContactPointUpdatedClassName(); |
|
225
|
|
|
|
|
226
|
|
|
/** |
|
227
|
|
|
* @return string |
|
228
|
|
|
*/ |
|
229
|
|
|
abstract protected function getDescriptionUpdatedClassName(); |
|
230
|
|
|
|
|
231
|
|
|
/** |
|
232
|
|
|
* @return string |
|
233
|
|
|
*/ |
|
234
|
|
|
abstract protected function getTypicalAgeRangeUpdatedClassName(); |
|
235
|
|
|
|
|
236
|
|
|
/** |
|
237
|
|
|
* @return string |
|
238
|
|
|
*/ |
|
239
|
|
|
abstract protected function getTypicalAgeRangeDeletedClassName(); |
|
240
|
|
|
|
|
241
|
|
|
/** |
|
242
|
|
|
* @return string |
|
243
|
|
|
*/ |
|
244
|
|
|
abstract protected function getPublishedClassName(); |
|
245
|
|
|
|
|
246
|
|
|
/** |
|
247
|
|
|
* @return string |
|
248
|
|
|
*/ |
|
249
|
|
|
abstract protected function getApprovedClassName(); |
|
250
|
|
|
|
|
251
|
|
|
/** |
|
252
|
|
|
* @return string |
|
253
|
|
|
*/ |
|
254
|
|
|
abstract protected function getRejectedClassName(); |
|
255
|
|
|
|
|
256
|
|
|
/** |
|
257
|
|
|
* @return string |
|
258
|
|
|
*/ |
|
259
|
|
|
abstract protected function getFlaggedAsDuplicateClassName(); |
|
260
|
|
|
|
|
261
|
|
|
/** |
|
262
|
|
|
* @return string |
|
263
|
|
|
*/ |
|
264
|
|
|
abstract protected function getFlaggedAsInappropriateClassName(); |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* @param AbstractLabelAdded $labelAdded |
|
268
|
|
|
*/ |
|
269
|
|
View Code Duplication |
protected function applyLabelAdded(AbstractLabelAdded $labelAdded) |
|
|
|
|
|
|
270
|
|
|
{ |
|
271
|
|
|
$document = $this->loadDocumentFromRepository($labelAdded); |
|
272
|
|
|
|
|
273
|
|
|
$offerLd = $document->getBody(); |
|
274
|
|
|
|
|
275
|
|
|
// Check the visibility of the label to update the right property. |
|
276
|
|
|
$labelsProperty = $labelAdded->getLabel()->isVisible() ? 'labels' : 'hiddenLabels'; |
|
277
|
|
|
|
|
278
|
|
|
$labels = isset($offerLd->{$labelsProperty}) ? $offerLd->{$labelsProperty} : []; |
|
279
|
|
|
$label = (string) $labelAdded->getLabel(); |
|
280
|
|
|
|
|
281
|
|
|
$labels[] = $label; |
|
282
|
|
|
$offerLd->{$labelsProperty} = array_unique($labels); |
|
283
|
|
|
|
|
284
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
/** |
|
288
|
|
|
* @param AbstractLabelRemoved $labelRemoved |
|
289
|
|
|
*/ |
|
290
|
|
View Code Duplication |
protected function applyLabelRemoved(AbstractLabelRemoved $labelRemoved) |
|
|
|
|
|
|
291
|
|
|
{ |
|
292
|
|
|
$document = $this->loadDocumentFromRepository($labelRemoved); |
|
293
|
|
|
|
|
294
|
|
|
$offerLd = $document->getBody(); |
|
295
|
|
|
|
|
296
|
|
|
// Don't presume that the label visibility is correct when removing. |
|
297
|
|
|
// So iterate over both the visible and invisible labels. |
|
298
|
|
|
$labelsProperties = ['labels', 'hiddenLabels']; |
|
299
|
|
|
|
|
300
|
|
|
foreach ($labelsProperties as $labelsProperty) { |
|
301
|
|
|
if (isset($offerLd->{$labelsProperty}) && is_array($offerLd->{$labelsProperty})) { |
|
302
|
|
|
$offerLd->{$labelsProperty} = array_filter( |
|
303
|
|
|
$offerLd->{$labelsProperty}, |
|
304
|
|
|
function ($label) use ($labelRemoved) { |
|
305
|
|
|
return !$labelRemoved->getLabel()->equals( |
|
306
|
|
|
new Label($label) |
|
307
|
|
|
); |
|
308
|
|
|
} |
|
309
|
|
|
); |
|
310
|
|
|
// Ensure array keys start with 0 so json_encode() does encode it |
|
311
|
|
|
// as an array and not as an object. |
|
312
|
|
|
if (count($offerLd->{$labelsProperty}) > 0) { |
|
313
|
|
|
$offerLd->{$labelsProperty} = array_values($offerLd->{$labelsProperty}); |
|
314
|
|
|
} else { |
|
315
|
|
|
unset($offerLd->{$labelsProperty}); |
|
316
|
|
|
} |
|
317
|
|
|
} |
|
318
|
|
|
} |
|
319
|
|
|
|
|
320
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
321
|
|
|
} |
|
322
|
|
|
|
|
323
|
|
|
/** |
|
324
|
|
|
* Apply the imageAdded event to the item repository. |
|
325
|
|
|
* |
|
326
|
|
|
* @param AbstractImageAdded $imageAdded |
|
327
|
|
|
*/ |
|
328
|
|
|
protected function applyImageAdded(AbstractImageAdded $imageAdded) |
|
329
|
|
|
{ |
|
330
|
|
|
$document = $this->loadDocumentFromRepository($imageAdded); |
|
331
|
|
|
|
|
332
|
|
|
$offerLd = $document->getBody(); |
|
333
|
|
|
$offerLd->mediaObject = isset($offerLd->mediaObject) ? $offerLd->mediaObject : []; |
|
334
|
|
|
|
|
335
|
|
|
$imageData = $this->mediaObjectSerializer |
|
336
|
|
|
->serialize($imageAdded->getImage(), 'json-ld'); |
|
337
|
|
|
$offerLd->mediaObject[] = $imageData; |
|
338
|
|
|
|
|
339
|
|
|
if (count($offerLd->mediaObject) === 1) { |
|
340
|
|
|
$offerLd->image = $imageData['contentUrl']; |
|
341
|
|
|
} |
|
342
|
|
|
|
|
343
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
/** |
|
347
|
|
|
* Apply the ImageUpdated event to the item repository. |
|
348
|
|
|
* |
|
349
|
|
|
* @param AbstractImageUpdated $imageUpdated |
|
350
|
|
|
* @throws \Exception |
|
351
|
|
|
*/ |
|
352
|
|
|
protected function applyImageUpdated(AbstractImageUpdated $imageUpdated) |
|
353
|
|
|
{ |
|
354
|
|
|
$document = $this->loadDocumentFromRepository($imageUpdated); |
|
355
|
|
|
|
|
356
|
|
|
$offerLd = $document->getBody(); |
|
357
|
|
|
|
|
358
|
|
|
if (!isset($offerLd->mediaObject)) { |
|
359
|
|
|
throw new \Exception('The image to update could not be found.'); |
|
360
|
|
|
} |
|
361
|
|
|
|
|
362
|
|
|
$updatedMediaObjects = []; |
|
363
|
|
|
|
|
364
|
|
|
foreach ($offerLd->mediaObject as $mediaObject) { |
|
365
|
|
|
$mediaObjectMatches = ( |
|
366
|
|
|
strpos( |
|
367
|
|
|
$mediaObject->{'@id'}, |
|
368
|
|
|
(string)$imageUpdated->getMediaObjectId() |
|
369
|
|
|
) > 0 |
|
370
|
|
|
); |
|
371
|
|
|
|
|
372
|
|
|
if ($mediaObjectMatches) { |
|
373
|
|
|
$mediaObject->description = (string)$imageUpdated->getDescription(); |
|
374
|
|
|
$mediaObject->copyrightHolder = (string)$imageUpdated->getCopyrightHolder(); |
|
375
|
|
|
|
|
376
|
|
|
$updatedMediaObjects[] = $mediaObject; |
|
377
|
|
|
} |
|
378
|
|
|
}; |
|
379
|
|
|
|
|
380
|
|
|
if (empty($updatedMediaObjects)) { |
|
381
|
|
|
throw new \Exception('The image to update could not be found.'); |
|
382
|
|
|
} |
|
383
|
|
|
|
|
384
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
385
|
|
|
} |
|
386
|
|
|
|
|
387
|
|
|
/** |
|
388
|
|
|
* @param AbstractImageRemoved $imageRemoved |
|
389
|
|
|
*/ |
|
390
|
|
|
protected function applyImageRemoved(AbstractImageRemoved $imageRemoved) |
|
391
|
|
|
{ |
|
392
|
|
|
$document = $this->loadDocumentFromRepository($imageRemoved); |
|
393
|
|
|
|
|
394
|
|
|
$offerLd = $document->getBody(); |
|
395
|
|
|
|
|
396
|
|
|
// Nothing to remove if there are no media objects! |
|
397
|
|
|
if (!isset($offerLd->mediaObject)) { |
|
398
|
|
|
return; |
|
399
|
|
|
} |
|
400
|
|
|
|
|
401
|
|
|
$imageId = (string) $imageRemoved->getImage()->getMediaObjectId(); |
|
402
|
|
|
|
|
403
|
|
|
/** |
|
404
|
|
|
* Matches any object that is not the removed image. |
|
405
|
|
|
* |
|
406
|
|
|
* @param Object $mediaObject |
|
407
|
|
|
* An existing projection of a media object. |
|
408
|
|
|
* |
|
409
|
|
|
* @return bool |
|
410
|
|
|
* Returns true when the media object does not match the image to remove. |
|
411
|
|
|
*/ |
|
412
|
|
|
$shouldNotBeRemoved = function ($mediaObject) use ($imageId) { |
|
413
|
|
|
$containsId = !!strpos($mediaObject->{'@id'}, $imageId); |
|
414
|
|
|
return !$containsId; |
|
415
|
|
|
}; |
|
416
|
|
|
|
|
417
|
|
|
// Remove any media objects that match the image. |
|
418
|
|
|
$filteredMediaObjects = array_filter( |
|
419
|
|
|
$offerLd->mediaObject, |
|
420
|
|
|
$shouldNotBeRemoved |
|
421
|
|
|
); |
|
422
|
|
|
|
|
423
|
|
|
// Unset the main image if it matches the removed image |
|
424
|
|
|
if (isset($offerLd->image) && strpos($offerLd->{'image'}, $imageId)) { |
|
425
|
|
|
unset($offerLd->{"image"}); |
|
426
|
|
|
} |
|
427
|
|
|
|
|
428
|
|
|
if (!isset($offerLd->image) && count($filteredMediaObjects) > 0) { |
|
429
|
|
|
$offerLd->image = array_values($filteredMediaObjects)[0]->contentUrl; |
|
430
|
|
|
} |
|
431
|
|
|
|
|
432
|
|
|
// If no media objects are left remove the attribute. |
|
433
|
|
|
if (empty($filteredMediaObjects)) { |
|
434
|
|
|
unset($offerLd->{"mediaObject"}); |
|
435
|
|
|
} else { |
|
436
|
|
|
$offerLd->mediaObject = array_values($filteredMediaObjects); |
|
437
|
|
|
} |
|
438
|
|
|
|
|
439
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
440
|
|
|
} |
|
441
|
|
|
|
|
442
|
|
|
/** |
|
443
|
|
|
* @param AbstractMainImageSelected $mainImageSelected |
|
444
|
|
|
*/ |
|
445
|
|
|
protected function applyMainImageSelected(AbstractMainImageSelected $mainImageSelected) |
|
446
|
|
|
{ |
|
447
|
|
|
$document = $this->loadDocumentFromRepository($mainImageSelected); |
|
448
|
|
|
$offerLd = $document->getBody(); |
|
449
|
|
|
$imageId = $mainImageSelected->getImage()->getMediaObjectId(); |
|
450
|
|
|
$mediaObjectMatcher = function ($matchingMediaObject, $currentMediaObject) use ($imageId) { |
|
451
|
|
|
if (!$matchingMediaObject && $this->mediaObjectMatchesId($currentMediaObject, $imageId)) { |
|
452
|
|
|
$matchingMediaObject = $currentMediaObject; |
|
453
|
|
|
} |
|
454
|
|
|
|
|
455
|
|
|
return $matchingMediaObject; |
|
456
|
|
|
}; |
|
457
|
|
|
$mediaObject = array_reduce( |
|
458
|
|
|
$offerLd->mediaObject, |
|
459
|
|
|
$mediaObjectMatcher |
|
460
|
|
|
); |
|
461
|
|
|
|
|
462
|
|
|
$offerLd->image = $mediaObject->contentUrl; |
|
463
|
|
|
|
|
464
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
465
|
|
|
} |
|
466
|
|
|
|
|
467
|
|
|
/** |
|
468
|
|
|
* @param Object $mediaObject |
|
469
|
|
|
* @param UUID $mediaObjectId |
|
470
|
|
|
* |
|
471
|
|
|
* @return bool |
|
472
|
|
|
*/ |
|
473
|
|
|
protected function mediaObjectMatchesId($mediaObject, UUID $mediaObjectId) |
|
474
|
|
|
{ |
|
475
|
|
|
return strpos($mediaObject->{'@id'}, (string) $mediaObjectId) > 0; |
|
476
|
|
|
} |
|
477
|
|
|
|
|
478
|
|
|
/** |
|
479
|
|
|
* @param AbstractTitleTranslated $titleTranslated |
|
480
|
|
|
*/ |
|
481
|
|
|
protected function applyTitleTranslated(AbstractTitleTranslated $titleTranslated) |
|
482
|
|
|
{ |
|
483
|
|
|
$document = $this->loadDocumentFromRepository($titleTranslated); |
|
484
|
|
|
|
|
485
|
|
|
$offerLd = $document->getBody(); |
|
486
|
|
|
$offerLd->name->{$titleTranslated->getLanguage()->getCode( |
|
487
|
|
|
)} = $titleTranslated->getTitle()->toNative(); |
|
488
|
|
|
|
|
489
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
490
|
|
|
} |
|
491
|
|
|
|
|
492
|
|
|
/** |
|
493
|
|
|
* @param AbstractDescriptionTranslated $descriptionTranslated |
|
494
|
|
|
*/ |
|
495
|
|
|
protected function applyDescriptionTranslated( |
|
496
|
|
|
AbstractDescriptionTranslated $descriptionTranslated |
|
497
|
|
|
) { |
|
498
|
|
|
$document = $this->loadDocumentFromRepository($descriptionTranslated); |
|
499
|
|
|
|
|
500
|
|
|
$offerLd = $document->getBody(); |
|
501
|
|
|
$languageCode = $descriptionTranslated->getLanguage()->getCode(); |
|
502
|
|
|
$description = $descriptionTranslated->getDescription()->toNative(); |
|
|
|
|
|
|
503
|
|
|
if (empty($offerLd->description)) { |
|
504
|
|
|
$offerLd->description = new \stdClass(); |
|
505
|
|
|
} |
|
506
|
|
|
$offerLd->description->{$languageCode} = $description; |
|
507
|
|
|
|
|
508
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
509
|
|
|
} |
|
510
|
|
|
|
|
511
|
|
|
/** |
|
512
|
|
|
* Apply the organizer updated event to the offer repository. |
|
513
|
|
|
* @param AbstractOrganizerUpdated $organizerUpdated |
|
514
|
|
|
*/ |
|
515
|
|
|
protected function applyOrganizerUpdated(AbstractOrganizerUpdated $organizerUpdated) |
|
516
|
|
|
{ |
|
517
|
|
|
$document = $this->loadDocumentFromRepository($organizerUpdated); |
|
518
|
|
|
|
|
519
|
|
|
$offerLd = $document->getBody(); |
|
520
|
|
|
|
|
521
|
|
|
$offerLd->organizer = array( |
|
522
|
|
|
'@type' => 'Organizer', |
|
523
|
|
|
) + (array)$this->organizerJSONLD($organizerUpdated->getOrganizerId()); |
|
524
|
|
|
|
|
525
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
/** |
|
529
|
|
|
* Apply the organizer delete event to the offer repository. |
|
530
|
|
|
* @param AbstractOrganizerDeleted $organizerDeleted |
|
531
|
|
|
*/ |
|
532
|
|
|
protected function applyOrganizerDeleted(AbstractOrganizerDeleted $organizerDeleted) |
|
533
|
|
|
{ |
|
534
|
|
|
$document = $this->loadDocumentFromRepository($organizerDeleted); |
|
535
|
|
|
|
|
536
|
|
|
$offerLd = $document->getBody(); |
|
537
|
|
|
|
|
538
|
|
|
unset($offerLd->organizer); |
|
539
|
|
|
|
|
540
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
541
|
|
|
} |
|
542
|
|
|
|
|
543
|
|
|
/** |
|
544
|
|
|
* Apply the booking info updated event to the offer repository. |
|
545
|
|
|
* @param AbstractBookingInfoUpdated $bookingInfoUpdated |
|
546
|
|
|
*/ |
|
547
|
|
View Code Duplication |
protected function applyBookingInfoUpdated(AbstractBookingInfoUpdated $bookingInfoUpdated) |
|
|
|
|
|
|
548
|
|
|
{ |
|
549
|
|
|
$document = $this->loadDocumentFromRepository($bookingInfoUpdated); |
|
550
|
|
|
|
|
551
|
|
|
$offerLd = $document->getBody(); |
|
552
|
|
|
$offerLd->bookingInfo = $bookingInfoUpdated->getBookingInfo()->toJsonLd(); |
|
553
|
|
|
|
|
554
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
555
|
|
|
} |
|
556
|
|
|
|
|
557
|
|
|
/** |
|
558
|
|
|
* @param AbstractPriceInfoUpdated $priceInfoUpdated |
|
559
|
|
|
*/ |
|
560
|
|
|
protected function applyPriceInfoUpdated(AbstractPriceInfoUpdated $priceInfoUpdated) |
|
561
|
|
|
{ |
|
562
|
|
|
$document = $this->loadDocumentFromRepository($priceInfoUpdated); |
|
563
|
|
|
|
|
564
|
|
|
$offerLd = $document->getBody(); |
|
565
|
|
|
$offerLd->priceInfo = []; |
|
566
|
|
|
|
|
567
|
|
|
$basePrice = $priceInfoUpdated->getPriceInfo()->getBasePrice(); |
|
568
|
|
|
|
|
569
|
|
|
$offerLd->priceInfo[] = [ |
|
570
|
|
|
'category' => 'base', |
|
571
|
|
|
'name' => 'Basistarief', |
|
572
|
|
|
'price' => $basePrice->getPrice()->toFloat(), |
|
573
|
|
|
'priceCurrency' => $basePrice->getCurrency()->getCode()->toNative(), |
|
574
|
|
|
]; |
|
575
|
|
|
|
|
576
|
|
|
foreach ($priceInfoUpdated->getPriceInfo()->getTariffs() as $tariff) { |
|
577
|
|
|
$offerLd->priceInfo[] = [ |
|
578
|
|
|
'category' => 'tariff', |
|
579
|
|
|
'name' => $tariff->getName()->toNative(), |
|
580
|
|
|
'price' => $tariff->getPrice()->toFloat(), |
|
581
|
|
|
'priceCurrency' => $tariff->getCurrency()->getCode()->toNative(), |
|
582
|
|
|
]; |
|
583
|
|
|
} |
|
584
|
|
|
|
|
585
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
586
|
|
|
} |
|
587
|
|
|
|
|
588
|
|
|
/** |
|
589
|
|
|
* Apply the contact point updated event to the offer repository. |
|
590
|
|
|
* @param AbstractContactPointUpdated $contactPointUpdated |
|
591
|
|
|
*/ |
|
592
|
|
View Code Duplication |
protected function applyContactPointUpdated(AbstractContactPointUpdated $contactPointUpdated) |
|
|
|
|
|
|
593
|
|
|
{ |
|
594
|
|
|
$document = $this->loadDocumentFromRepository($contactPointUpdated); |
|
595
|
|
|
|
|
596
|
|
|
$offerLd = $document->getBody(); |
|
597
|
|
|
$offerLd->contactPoint = $contactPointUpdated->getContactPoint()->toJsonLd(); |
|
598
|
|
|
|
|
599
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
600
|
|
|
} |
|
601
|
|
|
|
|
602
|
|
|
/** |
|
603
|
|
|
* Apply the description updated event to the offer repository. |
|
604
|
|
|
* @param AbstractDescriptionUpdated $descriptionUpdated |
|
605
|
|
|
*/ |
|
606
|
|
|
protected function applyDescriptionUpdated( |
|
607
|
|
|
AbstractDescriptionUpdated $descriptionUpdated |
|
608
|
|
|
) { |
|
609
|
|
|
$document = $this->loadDocumentFromRepository($descriptionUpdated); |
|
610
|
|
|
|
|
611
|
|
|
$offerLd = $document->getBody(); |
|
612
|
|
|
if (empty($offerLd->description)) { |
|
613
|
|
|
$offerLd->description = new \stdClass(); |
|
614
|
|
|
} |
|
615
|
|
|
$offerLd->description->{'nl'} = $descriptionUpdated->getDescription(); |
|
616
|
|
|
|
|
617
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
618
|
|
|
} |
|
619
|
|
|
|
|
620
|
|
|
/** |
|
621
|
|
|
* Apply the typical age range updated event to the offer repository. |
|
622
|
|
|
* @param AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated |
|
623
|
|
|
*/ |
|
624
|
|
|
protected function applyTypicalAgeRangeUpdated( |
|
625
|
|
|
AbstractTypicalAgeRangeUpdated $typicalAgeRangeUpdated |
|
626
|
|
|
) { |
|
627
|
|
|
$document = $this->loadDocumentFromRepository($typicalAgeRangeUpdated); |
|
628
|
|
|
|
|
629
|
|
|
$offerLd = $document->getBody(); |
|
630
|
|
|
$offerLd->typicalAgeRange = $typicalAgeRangeUpdated->getTypicalAgeRange(); |
|
631
|
|
|
|
|
632
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
633
|
|
|
} |
|
634
|
|
|
|
|
635
|
|
|
/** |
|
636
|
|
|
* Apply the typical age range deleted event to the offer repository. |
|
637
|
|
|
* @param AbstractTypicalAgeRangeDeleted $typicalAgeRangeDeleted |
|
638
|
|
|
*/ |
|
639
|
|
|
protected function applyTypicalAgeRangeDeleted( |
|
640
|
|
|
AbstractTypicalAgeRangeDeleted $typicalAgeRangeDeleted |
|
641
|
|
|
) { |
|
642
|
|
|
$document = $this->loadDocumentFromRepository($typicalAgeRangeDeleted); |
|
643
|
|
|
|
|
644
|
|
|
$offerLd = $document->getBody(); |
|
645
|
|
|
|
|
646
|
|
|
unset($offerLd->typicalAgeRange); |
|
647
|
|
|
|
|
648
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
649
|
|
|
} |
|
650
|
|
|
|
|
651
|
|
|
/** |
|
652
|
|
|
* @param AbstractPublished $published |
|
653
|
|
|
*/ |
|
654
|
|
|
protected function applyPublished(AbstractPublished $published) |
|
655
|
|
|
{ |
|
656
|
|
|
$this->applyEventTransformation($published, function ($offerLd) use ($published) { |
|
657
|
|
|
$offerLd->workflowStatus = WorkflowStatus::READY_FOR_VALIDATION()->getName(); |
|
658
|
|
|
|
|
659
|
|
|
$publicationDate = $published->getPublicationDate(); |
|
660
|
|
|
$offerLd->availableFrom = $publicationDate->format(\DateTime::ATOM); |
|
661
|
|
|
}); |
|
662
|
|
|
} |
|
663
|
|
|
|
|
664
|
|
|
/** |
|
665
|
|
|
* @param AbstractApproved $approved |
|
666
|
|
|
*/ |
|
667
|
|
|
protected function applyApproved(AbstractApproved $approved) |
|
668
|
|
|
{ |
|
669
|
|
|
$this->applyEventTransformation($approved, function ($offerLd) { |
|
670
|
|
|
$offerLd->workflowStatus = WorkflowStatus::APPROVED()->getName(); |
|
671
|
|
|
}); |
|
672
|
|
|
} |
|
673
|
|
|
|
|
674
|
|
|
/** |
|
675
|
|
|
* @param AbstractRejected $rejected |
|
676
|
|
|
*/ |
|
677
|
|
|
protected function applyRejected(AbstractRejected $rejected) |
|
678
|
|
|
{ |
|
679
|
|
|
$this->applyEventTransformation($rejected, $this->reject()); |
|
680
|
|
|
} |
|
681
|
|
|
|
|
682
|
|
|
/** |
|
683
|
|
|
* @param AbstractFlaggedAsDuplicate $flaggedAsDuplicate |
|
684
|
|
|
*/ |
|
685
|
|
|
protected function applyFlaggedAsDuplicate( |
|
686
|
|
|
AbstractFlaggedAsDuplicate $flaggedAsDuplicate |
|
687
|
|
|
) { |
|
688
|
|
|
$this->applyEventTransformation($flaggedAsDuplicate, $this->reject()); |
|
689
|
|
|
} |
|
690
|
|
|
|
|
691
|
|
|
/** |
|
692
|
|
|
* @param AbstractFlaggedAsInappropriate $flaggedAsInappropriate |
|
693
|
|
|
*/ |
|
694
|
|
|
protected function applyFlaggedAsInappropriate( |
|
695
|
|
|
AbstractFlaggedAsInappropriate $flaggedAsInappropriate |
|
696
|
|
|
) { |
|
697
|
|
|
$this->applyEventTransformation($flaggedAsInappropriate, $this->reject()); |
|
698
|
|
|
} |
|
699
|
|
|
|
|
700
|
|
|
/** |
|
701
|
|
|
* @return callable |
|
702
|
|
|
*/ |
|
703
|
|
|
private function reject() |
|
704
|
|
|
{ |
|
705
|
|
|
return function ($offerLd) { |
|
706
|
|
|
$offerLd->workflowStatus = WorkflowStatus::REJECTED()->getName(); |
|
707
|
|
|
}; |
|
708
|
|
|
} |
|
709
|
|
|
|
|
710
|
|
|
/** |
|
711
|
|
|
* @param AbstractEvent $event |
|
712
|
|
|
* @param callable $transformation |
|
713
|
|
|
* a transformation that you want applied to the offer-ld document |
|
714
|
|
|
* the first parameter passed to the callback will be the document body |
|
715
|
|
|
*/ |
|
716
|
|
|
private function applyEventTransformation(AbstractEvent $event, callable $transformation) |
|
717
|
|
|
{ |
|
718
|
|
|
$document = $this->loadDocumentFromRepository($event); |
|
719
|
|
|
|
|
720
|
|
|
$offerLd = $document->getBody(); |
|
721
|
|
|
|
|
722
|
|
|
$transformation($offerLd); |
|
723
|
|
|
|
|
724
|
|
|
$this->repository->save($document->withBody($offerLd)); |
|
725
|
|
|
} |
|
726
|
|
|
|
|
727
|
|
|
/** |
|
728
|
|
|
* @param string $id |
|
729
|
|
|
* @return JsonDocument |
|
730
|
|
|
*/ |
|
731
|
|
View Code Duplication |
protected function newDocument($id) |
|
|
|
|
|
|
732
|
|
|
{ |
|
733
|
|
|
$document = new JsonDocument($id); |
|
734
|
|
|
|
|
735
|
|
|
$offerLd = $document->getBody(); |
|
736
|
|
|
$offerLd->{'@id'} = $this->iriGenerator->iri($id); |
|
737
|
|
|
$offerLd->{'@context'} = '/contexts/event'; |
|
738
|
|
|
|
|
739
|
|
|
return $document->withBody($offerLd); |
|
740
|
|
|
} |
|
741
|
|
|
|
|
742
|
|
|
/** |
|
743
|
|
|
* @param AbstractEvent $event |
|
744
|
|
|
* @return JsonDocument |
|
745
|
|
|
*/ |
|
746
|
|
|
protected function loadDocumentFromRepository(AbstractEvent $event) |
|
747
|
|
|
{ |
|
748
|
|
|
return $this->loadDocumentFromRepositoryByItemId($event->getItemId()); |
|
749
|
|
|
} |
|
750
|
|
|
|
|
751
|
|
|
/** |
|
752
|
|
|
* @param string $itemId |
|
753
|
|
|
* @return JsonDocument |
|
754
|
|
|
*/ |
|
755
|
|
|
protected function loadDocumentFromRepositoryByItemId($itemId) |
|
756
|
|
|
{ |
|
757
|
|
|
$document = $this->repository->get($itemId); |
|
758
|
|
|
|
|
759
|
|
|
if (!$document) { |
|
760
|
|
|
return $this->newDocument($itemId); |
|
761
|
|
|
} |
|
762
|
|
|
|
|
763
|
|
|
return $document; |
|
764
|
|
|
} |
|
765
|
|
|
|
|
766
|
|
|
/** |
|
767
|
|
|
* @inheritdoc |
|
768
|
|
|
*/ |
|
769
|
|
|
public function organizerJSONLD($organizerId) |
|
770
|
|
|
{ |
|
771
|
|
|
try { |
|
772
|
|
|
$organizerJSONLD = $this->organizerService->getEntity( |
|
773
|
|
|
$organizerId |
|
774
|
|
|
); |
|
775
|
|
|
|
|
776
|
|
|
return json_decode($organizerJSONLD); |
|
777
|
|
|
} catch (EntityNotFoundException $e) { |
|
778
|
|
|
// In case the place can not be found at the moment, just add its ID |
|
779
|
|
|
return array( |
|
|
|
|
|
|
780
|
|
|
'@id' => $this->organizerService->iri($organizerId) |
|
781
|
|
|
); |
|
782
|
|
|
} |
|
783
|
|
|
} |
|
784
|
|
|
} |
|
785
|
|
|
|
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.