Passed
Push — master ( b88e45...b1cf97 )
by Angel Fernando Quiroz
07:42
created

Version20230904173400::updateAgendaReminders()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 12
rs 10
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $invitationsOrSubscriptionsInfo of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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