1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @file |
5
|
|
|
* Contains CultuurNet\UDB3\Organizer\ReadModel\Index\Projector. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace CultuurNet\UDB3\ReadModel\Index; |
9
|
|
|
|
10
|
|
|
use Broadway\Domain\DomainMessage; |
11
|
|
|
use Broadway\EventHandling\EventListenerInterface; |
12
|
|
|
use CultureFeed_Cdb_Item_Event; |
13
|
|
|
use CultuurNet\UDB3\Cdb\ActorItemFactory; |
14
|
|
|
use CultuurNet\UDB3\Cdb\EventItemFactory; |
15
|
|
|
use CultuurNet\UDB3\Event\Events\EventImportedFromUDB2; |
16
|
|
|
use CultuurNet\UDB3\Event\Events\EventCreated; |
17
|
|
|
use CultuurNet\UDB3\Event\Events\EventDeleted; |
18
|
|
|
use CultuurNet\UDB3\EventHandling\DelegateEventHandlingToSpecificMethodTrait; |
19
|
|
|
use CultuurNet\UDB3\Organizer\Events\OrganizerCreated; |
20
|
|
|
use CultuurNet\UDB3\Organizer\Events\OrganizerImportedFromUDB2; |
21
|
|
|
use CultuurNet\UDB3\Place\Events\PlaceCreated; |
22
|
|
|
use CultuurNet\UDB3\Place\Events\PlaceDeleted; |
23
|
|
|
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2; |
24
|
|
|
use CultuurNet\UDB3\Place\Events\PlaceImportedFromUDB2Event; |
25
|
|
|
use DateTime; |
26
|
|
|
use DateTimeZone; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Logs new events / updates to an index for querying. |
30
|
|
|
*/ |
31
|
|
|
class Projector implements EventListenerInterface |
32
|
|
|
{ |
33
|
|
|
use DelegateEventHandlingToSpecificMethodTrait; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var RepositoryInterface |
37
|
|
|
*/ |
38
|
|
|
protected $repository; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @param RepositoryInterface $repository |
42
|
|
|
*/ |
43
|
|
|
public function __construct(RepositoryInterface $repository) |
44
|
|
|
{ |
45
|
|
|
$this->repository = $repository; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* |
50
|
|
|
* @param EventImportedFromUDB2 $eventImportedFromUDB2 |
51
|
|
|
*/ |
52
|
|
|
protected function applyEventImportedFromUDB2( |
53
|
|
|
EventImportedFromUDB2 $eventImportedFromUDB2 |
54
|
|
|
) { |
55
|
|
|
$eventId = $eventImportedFromUDB2->getEventId(); |
56
|
|
|
$userId = ''; // imported = no uid. |
57
|
|
|
|
58
|
|
|
$udb2Event = EventItemFactory::createEventFromCdbXml( |
59
|
|
|
$eventImportedFromUDB2->getCdbXmlNamespaceUri(), |
60
|
|
|
$eventImportedFromUDB2->getCdbXml() |
61
|
|
|
); |
62
|
|
|
|
63
|
|
|
$this->updateIndexWithUDB2Event($eventId, EntityType::EVENT(), $userId, $udb2Event); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param PlaceImportedFromUDB2Event $placeImportedFromUDB2Event |
68
|
|
|
*/ |
69
|
|
|
protected function applyPlaceImportedFromUDB2Event( |
70
|
|
|
PlaceImportedFromUDB2Event $placeImportedFromUDB2Event |
71
|
|
|
) { |
72
|
|
|
$placeId = $placeImportedFromUDB2Event->getActorId(); |
73
|
|
|
$userId = ''; // imported = no uid. |
74
|
|
|
|
75
|
|
|
$udb2Event = EventItemFactory::createEventFromCdbXml( |
76
|
|
|
$placeImportedFromUDB2Event->getCdbXmlNamespaceUri(), |
77
|
|
|
$placeImportedFromUDB2Event->getCdbXml() |
78
|
|
|
); |
79
|
|
|
|
80
|
|
|
$this->updateIndexWithUDB2Event($placeId, EntityType::PLACE(), $userId, $udb2Event); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @param string $itemId |
85
|
|
|
* @param EntityType $itemType |
86
|
|
|
* @param string $userId |
87
|
|
|
* @param CultureFeed_Cdb_Item_Event $udb2Event |
88
|
|
|
*/ |
89
|
|
|
protected function updateIndexWithUDB2Event( |
90
|
|
|
$itemId, |
91
|
|
|
EntityType $itemType, |
92
|
|
|
$userId, |
93
|
|
|
CultureFeed_Cdb_Item_Event $udb2Event |
94
|
|
|
) { |
95
|
|
|
/** @var \CultureFeed_Cdb_Data_EventDetail $detail */ |
96
|
|
|
$detail = null; |
97
|
|
|
$postalCode = ''; |
98
|
|
|
|
99
|
|
|
$details = $udb2Event->getDetails(); |
100
|
|
|
foreach ($details as $languageDetail) { |
101
|
|
|
// The first language detail found will be used. |
102
|
|
|
$detail = $languageDetail; |
103
|
|
|
break; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
$name = trim($detail->getTitle()); |
107
|
|
|
|
108
|
|
|
// Ignore items without a name. They might occur in UDB2 although this |
109
|
|
|
// is not considered normal. |
110
|
|
|
if (empty($name)) { |
111
|
|
|
return; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
$contact_cdb = $udb2Event->getContactInfo(); |
115
|
|
|
if ($contact_cdb) { |
116
|
|
|
$addresses = $contact_cdb->getAddresses(); |
117
|
|
|
|
118
|
|
|
/** @var \CultureFeed_Cdb_Data_Address $address */ |
119
|
|
|
foreach ($addresses as $address) { |
120
|
|
|
/** @var \CultureFeed_Cdb_Data_Address_PhysicalAddress $physicalAddress */ |
121
|
|
|
$physicalAddress = $address->getPhysicalAddress(); |
122
|
|
|
if ($physicalAddress) { |
123
|
|
|
$postalCode = $physicalAddress->getZip(); |
124
|
|
|
} |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$dateString = $udb2Event->getCreationDate(); |
129
|
|
|
$creationDate = DateTime::createFromFormat( |
130
|
|
|
'Y-m-d?H:i:s', |
131
|
|
|
$dateString, |
132
|
|
|
new DateTimeZone('Europe/Brussels') |
133
|
|
|
); |
134
|
|
|
|
135
|
|
|
$this->updateIndex($itemId, $itemType, $userId, $name, $postalCode, $creationDate); |
|
|
|
|
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* |
140
|
|
|
* @param PlaceImportedFromUDB2 $placeImportedFromUDB2 |
141
|
|
|
*/ |
142
|
|
|
protected function applyPlaceImportedFromUDB2(PlaceImportedFromUDB2 $placeImportedFromUDB2) |
143
|
|
|
{ |
144
|
|
|
|
145
|
|
|
$placeId = $placeImportedFromUDB2->getActorId(); |
146
|
|
|
$userId = ''; // imported = no uid. |
147
|
|
|
/** @var \CultureFeed_Cdb_Data_ActorDetail $detail */ |
148
|
|
|
$detail = null; |
149
|
|
|
$postalCode = ''; |
150
|
|
|
|
151
|
|
|
$udb2Actor = ActorItemFactory::createActorFromCdbXml( |
152
|
|
|
$placeImportedFromUDB2->getCdbXmlNamespaceUri(), |
153
|
|
|
$placeImportedFromUDB2->getCdbXml() |
154
|
|
|
); |
155
|
|
|
|
156
|
|
|
$details = $udb2Actor->getDetails(); |
157
|
|
|
foreach ($details as $languageDetail) { |
158
|
|
|
// The first language detail found will be used. |
159
|
|
|
$detail = $languageDetail; |
160
|
|
|
break; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
$name = trim($detail->getTitle()); |
164
|
|
|
|
165
|
|
|
// Ignore items without a name. They might occur in UDB2 although this |
166
|
|
|
// is not considered normal. |
167
|
|
|
if (empty($name)) { |
168
|
|
|
return; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
$contact_cdb = $udb2Actor->getContactInfo(); |
172
|
|
|
if ($contact_cdb) { |
173
|
|
|
$addresses = $contact_cdb->getAddresses(); |
174
|
|
|
|
175
|
|
|
/** @var \CultureFeed_Cdb_Data_Address $address */ |
176
|
|
|
foreach ($addresses as $address) { |
177
|
|
|
$physicalAddress = $address->getPhysicalAddress(); |
178
|
|
|
if ($physicalAddress) { |
179
|
|
|
$postalCode = $physicalAddress->getZip(); |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$dateString = $udb2Actor->getCreationDate(); |
185
|
|
|
$creationDate = DateTime::createFromFormat( |
186
|
|
|
'Y-m-d?H:i:s', |
187
|
|
|
$dateString, |
188
|
|
|
new DateTimeZone('Europe/Brussels') |
189
|
|
|
); |
190
|
|
|
|
191
|
|
|
$this->updateIndex($placeId, EntityType::PLACE(), $userId, $name, $postalCode, $creationDate); |
|
|
|
|
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Listener for event created commands. |
196
|
|
|
*/ |
197
|
|
View Code Duplication |
protected function applyEventCreated(EventCreated $eventCreated, DomainMessage $domainMessage) |
|
|
|
|
198
|
|
|
{ |
199
|
|
|
|
200
|
|
|
$eventId = $eventCreated->getEventId(); |
201
|
|
|
|
202
|
|
|
$metaData = $domainMessage->getMetadata()->serialize(); |
203
|
|
|
$userId = isset($metaData['user_id']) ? $metaData['user_id'] : ''; |
204
|
|
|
|
205
|
|
|
$location = $eventCreated->getLocation(); |
206
|
|
|
|
207
|
|
|
$creationDate = new DateTime('now', new DateTimeZone('Europe/Brussels')); |
208
|
|
|
|
209
|
|
|
$this->updateIndex($eventId, EntityType::EVENT(), $userId, $eventCreated->getTitle(), $location->getPostalcode(), $creationDate); |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Listener for place created commands. |
214
|
|
|
*/ |
215
|
|
View Code Duplication |
protected function applyPlaceCreated(PlaceCreated $placeCreated, DomainMessage $domainMessage) |
|
|
|
|
216
|
|
|
{ |
217
|
|
|
|
218
|
|
|
$placeId = $placeCreated->getPlaceId(); |
219
|
|
|
|
220
|
|
|
$metaData = $domainMessage->getMetadata()->serialize(); |
221
|
|
|
$userId = isset($metaData['user_id']) ? $metaData['user_id'] : ''; |
222
|
|
|
|
223
|
|
|
$address = $placeCreated->getAddress(); |
224
|
|
|
|
225
|
|
|
$creationDate = new DateTime('now', new DateTimeZone('Europe/Brussels')); |
226
|
|
|
$this->updateIndex($placeId, EntityType::PLACE(), $userId, $placeCreated->getTitle(), $address->getPostalcode(), $creationDate); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Listener for organizer created commands. |
231
|
|
|
*/ |
232
|
|
|
protected function applyOrganizerCreated(OrganizerCreated $organizer, DomainMessage $domainMessage) |
233
|
|
|
{ |
234
|
|
|
|
235
|
|
|
$organizerId = $organizer->getOrganizerId(); |
236
|
|
|
|
237
|
|
|
$metaData = $domainMessage->getMetadata()->serialize(); |
238
|
|
|
$userId = isset($metaData['user_id']) ? $metaData['user_id'] : ''; |
239
|
|
|
|
240
|
|
|
$addresses = $organizer->getAddresses(); |
241
|
|
|
if (isset($addresses[0])) { |
242
|
|
|
$creationDate = new DateTime('now', new DateTimeZone('Europe/Brussels')); |
243
|
|
|
$this->updateIndex($organizerId, EntityType::ORGANIZER(), $userId, $organizer->getTitle(), $addresses[0]->getPostalCode(), $creationDate); |
244
|
|
|
} |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
protected function applyOrganizerImportedFromUDB2(OrganizerImportedFromUDB2 $organizerImportedFromUDB2) |
248
|
|
|
{ |
249
|
|
|
|
250
|
|
|
$organizerId = $organizerImportedFromUDB2->getActorId(); |
251
|
|
|
$userId = ''; // imported = no uid. |
252
|
|
|
/** @var \CultureFeed_Cdb_Data_ActorDetail $detail */ |
253
|
|
|
$detail = null; |
254
|
|
|
$postalCode = ''; |
255
|
|
|
|
256
|
|
|
$udb2Actor = ActorItemFactory::createActorFromCdbXml( |
257
|
|
|
$organizerImportedFromUDB2->getCdbXmlNamespaceUri(), |
258
|
|
|
$organizerImportedFromUDB2->getCdbXml() |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
$details = $udb2Actor->getDetails(); |
262
|
|
|
foreach ($details as $languageDetail) { |
263
|
|
|
// The first language detail found will be used. |
264
|
|
|
$detail = $languageDetail; |
265
|
|
|
break; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
$name = trim($detail->getTitle()); |
269
|
|
|
|
270
|
|
|
// Ignore items without a name. They might occur in UDB2 although this |
271
|
|
|
// is not considered normal. |
272
|
|
|
if (empty($name)) { |
273
|
|
|
return; |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
$dateString = $udb2Actor->getCreationDate(); |
277
|
|
|
$creationDate = DateTime::createFromFormat( |
278
|
|
|
'Y-m-d?H:i:s', |
279
|
|
|
$dateString, |
280
|
|
|
new DateTimeZone('Europe/Brussels') |
281
|
|
|
); |
282
|
|
|
|
283
|
|
|
$this->updateIndex($organizerId, EntityType::ORGANIZER(), $userId, $name, $postalCode, $creationDate); |
|
|
|
|
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Update the index |
288
|
|
|
*/ |
289
|
|
|
protected function updateIndex($id, EntityType $type, $userId, $name, $postalCode, \DateTimeInterface $creationDate = null) |
290
|
|
|
{ |
291
|
|
|
$this->repository->updateIndex($id, $type, $userId, $name, $postalCode, $creationDate); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Remove the index for events |
296
|
|
|
*/ |
297
|
|
|
public function applyEventDeleted(EventDeleted $eventDeleted, DomainMessage $domainMessage) |
|
|
|
|
298
|
|
|
{ |
299
|
|
|
$this->repository->deleteIndex($eventDeleted->getEventId(), EntityType::EVENT()); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Remove the index for places |
304
|
|
|
*/ |
305
|
|
|
public function applyPlaceDeleted(PlaceDeleted $placeDeleted, DomainMessage $domainMessage) |
|
|
|
|
306
|
|
|
{ |
307
|
|
|
$this->repository->deleteIndex($placeDeleted->getPlaceId(), EntityType::PLACE()); |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.