1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* For licensing terms, see /license.txt */ |
4
|
|
|
|
5
|
|
|
declare(strict_types=1); |
6
|
|
|
|
7
|
|
|
namespace Chamilo\CoreBundle\Migrations\Schema\V200; |
8
|
|
|
|
9
|
|
|
use Chamilo\CoreBundle\Entity\AgendaReminder; |
10
|
|
|
use Chamilo\CoreBundle\Entity\User; |
11
|
|
|
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo; |
12
|
|
|
use Chamilo\CourseBundle\Entity\CCalendarEvent; |
13
|
|
|
use DateTime; |
14
|
|
|
use DateTimeZone; |
15
|
|
|
use Doctrine\DBAL\Schema\Schema; |
16
|
|
|
use Doctrine\ORM\Exception\ORMException; |
17
|
|
|
use Exception; |
18
|
|
|
|
19
|
|
|
class Version20230904173400 extends AbstractMigrationChamilo |
20
|
|
|
{ |
21
|
|
|
public function getDescription(): string |
22
|
|
|
{ |
23
|
|
|
return 'Migrate personal_agenda to c_calendar_event and update agenda_reminder'; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @throws ORMException |
28
|
|
|
* @throws Exception |
29
|
|
|
*/ |
30
|
|
|
public function up(Schema $schema): void |
31
|
|
|
{ |
32
|
|
|
$collectiveInvitationsEnabled = $this->getConfigurationValue('agenda_collective_invitations'); |
33
|
|
|
$subscriptionsEnabled = $this->getConfigurationValue('agenda_event_subscriptions'); |
34
|
|
|
|
35
|
|
|
$this->addSql("UPDATE personal_agenda SET parent_event_id = NULL WHERE parent_event_id = 0 OR parent_event_id = ''"); |
36
|
|
|
$this->addSql('UPDATE personal_agenda SET parent_event_id = NULL WHERE parent_event_id NOT IN (SELECT id FROM personal_agenda)'); |
37
|
|
|
$this->addSql('DELETE FROM personal_agenda WHERE user NOT IN (SELECT id FROM user)'); |
38
|
|
|
|
39
|
|
|
/** @var array<int, CCalendarEvent> $map */ |
40
|
|
|
$map = []; |
41
|
|
|
|
42
|
|
|
$em = $this->getEntityManager(); |
43
|
|
|
$userRepo = $em->getRepository(User::class); |
44
|
|
|
|
45
|
|
|
$personalAgendas = $this->getPersonalEvents(); |
46
|
|
|
|
47
|
|
|
$utc = new DateTimeZone('UTC'); |
48
|
|
|
$oldNewEventIdMap = []; |
49
|
|
|
|
50
|
|
|
/** @var array $personalAgenda */ |
51
|
|
|
foreach ($personalAgendas as $personalAgenda) { |
52
|
|
|
$oldParentId = (int) $personalAgenda['parent_event_id']; |
53
|
|
|
$user = $userRepo->find($personalAgenda['user']); |
54
|
|
|
|
55
|
|
|
$newParent = null; |
56
|
|
|
|
57
|
|
|
if ($oldParentId && isset($map[$oldParentId])) { |
58
|
|
|
$newParent = $map[$oldParentId]; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
$calendarEvent = $this->createCCalendarEvent( |
62
|
|
|
$personalAgenda['title'] ?: '-', |
63
|
|
|
$personalAgenda['text'], |
64
|
|
|
$personalAgenda['date'] ? new DateTime($personalAgenda['date'], $utc) : null, |
65
|
|
|
$personalAgenda['enddate'] ? new DateTime($personalAgenda['enddate'], $utc) : null, |
66
|
|
|
(bool) $personalAgenda['all_day'], |
67
|
|
|
$personalAgenda['color'], |
68
|
|
|
$user, |
69
|
|
|
$newParent |
70
|
|
|
); |
71
|
|
|
|
72
|
|
|
$map[$personalAgenda['id']] = $calendarEvent; |
73
|
|
|
|
74
|
|
|
$em->persist($calendarEvent); |
75
|
|
|
$em->flush(); |
76
|
|
|
|
77
|
|
|
if ($collectiveInvitationsEnabled) { |
78
|
|
|
$invitationsOrSubscriptionsInfo = []; |
79
|
|
|
|
80
|
|
|
if ($subscriptionsEnabled) { |
81
|
|
|
$subscriptionsInfo = $this->getSubscriptions((int) $personalAgenda['id']); |
82
|
|
|
|
83
|
|
|
if (\count($subscriptionsInfo) > 0 |
84
|
|
|
&& 0 !== $personalAgenda['subscription_visibility'] |
85
|
|
|
) { |
86
|
|
|
$invitationsOrSubscriptionsInfo = $subscriptionsInfo; |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
if ($invitationsOrSubscriptionsInfo) { |
|
|
|
|
91
|
|
|
$calendarEvent |
92
|
|
|
->setInvitationType(CCalendarEvent::TYPE_SUBSCRIPTION) |
93
|
|
|
->setSubscriptionVisibility($personalAgenda['subscription_visibility']) |
94
|
|
|
->setSubscriptionItemId($personalAgenda['subscription_item_id']) |
95
|
|
|
->setMaxAttendees($invitationsOrSubscriptionsInfo[0]['max_attendees']) |
96
|
|
|
; |
97
|
|
|
} else { |
98
|
|
|
$invitationsInfo = $this->getInvitations($subscriptionsEnabled, (int) $personalAgenda['id']); |
99
|
|
|
|
100
|
|
|
if (\count($invitationsInfo) > 0) { |
101
|
|
|
$calendarEvent |
102
|
|
|
->setCollective((bool) $personalAgenda['collective']) |
103
|
|
|
->setInvitationType(CCalendarEvent::TYPE_INVITATION) |
104
|
|
|
; |
105
|
|
|
|
106
|
|
|
$invitationsOrSubscriptionsInfo = $invitationsInfo; |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
foreach ($invitationsOrSubscriptionsInfo as $invitationOrSubscriptionInfo) { |
111
|
|
|
$inviteesOrSubscribersInfo = $this->getInviteesOrSubscribers($invitationOrSubscriptionInfo['id']); |
112
|
|
|
|
113
|
|
|
foreach ($inviteesOrSubscribersInfo as $oldInviteeOrSubscriberInfo) { |
114
|
|
|
$user = $em->find(User::class, $oldInviteeOrSubscriberInfo['user_id']); |
115
|
|
|
|
116
|
|
|
if ($user) { |
117
|
|
|
$calendarEvent->addUserLink($user); |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
$oldNewEventIdMap[$personalAgenda['id']] = $calendarEvent->getIid(); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
$em->flush(); |
126
|
|
|
$this->updateAgendaReminders($oldNewEventIdMap, $em); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
private function getPersonalEvents(): array |
130
|
|
|
{ |
131
|
|
|
$sql = 'SELECT * FROM personal_agenda ORDER BY id'; |
132
|
|
|
$result = $this->connection->executeQuery($sql); |
133
|
|
|
|
134
|
|
|
return $result->fetchAllAssociative(); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
private function createCCalendarEvent( |
138
|
|
|
string $title, |
139
|
|
|
string $content, |
140
|
|
|
?DateTime $startDate, |
141
|
|
|
?DateTime $endDate, |
142
|
|
|
bool $allDay, |
143
|
|
|
string $color, |
144
|
|
|
User $creator, |
145
|
|
|
?CCalendarEvent $parentEvent = null |
146
|
|
|
): CCalendarEvent { |
147
|
|
|
$calendarEvent = new CCalendarEvent(); |
148
|
|
|
|
149
|
|
|
$calendarEvent |
150
|
|
|
->setTitle($title) |
151
|
|
|
->setContent($content) |
152
|
|
|
->setStartDate($startDate) |
153
|
|
|
->setEndDate($endDate) |
154
|
|
|
->setAllDay($allDay) |
155
|
|
|
->setColor($color) |
156
|
|
|
->setCreator($creator) |
157
|
|
|
->setResourceName($title) |
158
|
|
|
; |
159
|
|
|
|
160
|
|
|
if ($parentEvent) { |
161
|
|
|
$calendarEvent |
162
|
|
|
->setParentEvent($parentEvent) |
163
|
|
|
->setParentResourceNode($parentEvent->getResourceNode()->getId()) |
164
|
|
|
; |
165
|
|
|
} else { |
166
|
|
|
$calendarEvent->setParentResourceNode($creator->getResourceNode()->getId()); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
return $calendarEvent; |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
private function getInvitations(bool $subscriptionsEnabled, int $personalAgendaId): array |
173
|
|
|
{ |
174
|
|
|
$sql = "SELECT i.id, i.creator_id, i.created_at, i.updated_at |
175
|
|
|
FROM agenda_event_invitation i |
176
|
|
|
INNER JOIN personal_agenda pa ON i.id = pa.agenda_event_invitation_id |
177
|
|
|
WHERE pa.id = $personalAgendaId"; |
178
|
|
|
|
179
|
|
|
if ($subscriptionsEnabled) { |
180
|
|
|
$sql .= " AND i.type = 'invitation'"; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
try { |
184
|
|
|
$result = $this->connection->executeQuery($sql); |
185
|
|
|
|
186
|
|
|
return $result->fetchAllAssociative(); |
187
|
|
|
} catch (\Doctrine\DBAL\Exception) { |
188
|
|
|
return []; |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
private function getInviteesOrSubscribers(int $invitationId): array |
193
|
|
|
{ |
194
|
|
|
$sql = "SELECT id, user_id, created_at, updated_at |
195
|
|
|
FROM agenda_event_invitee |
196
|
|
|
WHERE invitation_id = $invitationId |
197
|
|
|
ORDER BY created_at ASC"; |
198
|
|
|
|
199
|
|
|
try { |
200
|
|
|
$result = $this->connection->executeQuery($sql); |
201
|
|
|
|
202
|
|
|
return $result->fetchAllAssociative(); |
203
|
|
|
} catch (\Doctrine\DBAL\Exception) { |
204
|
|
|
return []; |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
private function getSubscriptions(int $personalAgendaId): array |
209
|
|
|
{ |
210
|
|
|
$sql = "SELECT i.id, i.creator_id, i.created_at, i.updated_at, i.max_attendees |
211
|
|
|
FROM agenda_event_invitation i |
212
|
|
|
INNER JOIN personal_agenda pa ON i.id = pa.agenda_event_invitation_id |
213
|
|
|
WHERE pa.id = $personalAgendaId |
214
|
|
|
AND i.type = 'subscription'"; |
215
|
|
|
|
216
|
|
|
try { |
217
|
|
|
$result = $this->connection->executeQuery($sql); |
218
|
|
|
|
219
|
|
|
return $result->fetchAllAssociative(); |
220
|
|
|
} catch (\Doctrine\DBAL\Exception) { |
221
|
|
|
return []; |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
private function updateAgendaReminders(array $oldNewEventIdMap, $em): void |
226
|
|
|
{ |
227
|
|
|
$reminders = $em->getRepository(AgendaReminder::class)->findBy(['type' => 'personal']); |
228
|
|
|
foreach ($reminders as $reminder) { |
229
|
|
|
$oldEventId = $reminder->getEventId(); |
230
|
|
|
if (array_key_exists($oldEventId, $oldNewEventIdMap)) { |
231
|
|
|
$newEventId = $oldNewEventIdMap[$oldEventId]; |
232
|
|
|
$reminder->setEventId($newEventId); |
233
|
|
|
$em->persist($reminder); |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
$em->flush(); |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.