Passed
Push — master ( 131c23...309a4e )
by Angel Fernando Quiroz
07:28
created

Version20230904173400::up()   D

Complexity

Conditions 18
Paths 63

Size

Total Lines 99
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 59
nc 63
nop 1
dl 0
loc 99
rs 4.8666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\User;
10
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
11
use Chamilo\CoreBundle\Repository\Node\UserRepository;
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
        $userRepo = $this->container->get(UserRepository::class);
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

42
        /** @scrutinizer ignore-call */ 
43
        $userRepo = $this->container->get(UserRepository::class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
43
44
        $personalAgendas = $this->getPersonalEvents();
45
46
        $utc = new DateTimeZone('UTC');
47
        $oldNewEventIdMap = [];
48
49
        /** @var array $personalAgenda */
50
        foreach ($personalAgendas as $personalAgenda) {
51
            $oldParentId = (int) $personalAgenda['parent_event_id'];
52
            $user = $userRepo->find($personalAgenda['user']);
53
54
            $newParent = null;
55
56
            if ($oldParentId && isset($map[$oldParentId])) {
57
                $newParent = $map[$oldParentId];
58
            }
59
60
            $calendarEvent = $this->createCCalendarEvent(
61
                $personalAgenda['title'] ?: '-',
62
                $personalAgenda['text'],
63
                $personalAgenda['date'] ? new DateTime($personalAgenda['date'], $utc) : null,
64
                $personalAgenda['enddate'] ? new DateTime($personalAgenda['enddate'], $utc) : null,
65
                (bool) $personalAgenda['all_day'],
66
                $personalAgenda['color'],
67
                $user,
68
                $newParent
69
            );
70
71
            $map[$personalAgenda['id']] = $calendarEvent;
72
73
            $this->entityManager->persist($calendarEvent);
0 ignored issues
show
Bug introduced by
The method persist() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
            $this->entityManager->/** @scrutinizer ignore-call */ 
74
                                  persist($calendarEvent);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
74
            $this->entityManager->flush();
75
76
            if ($collectiveInvitationsEnabled) {
77
                $invitationsOrSubscriptionsInfo = [];
78
79
                if ($subscriptionsEnabled) {
80
                    $subscriptionsInfo = $this->getSubscriptions((int) $personalAgenda['id']);
81
82
                    if (\count($subscriptionsInfo) > 0
83
                        && 0 !== $personalAgenda['subscription_visibility']
84
                    ) {
85
                        $invitationsOrSubscriptionsInfo = $subscriptionsInfo;
86
                    }
87
                }
88
89
                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...
90
                    $calendarEvent
91
                        ->setInvitationType(CCalendarEvent::TYPE_SUBSCRIPTION)
92
                        ->setSubscriptionVisibility($personalAgenda['subscription_visibility'])
93
                        ->setSubscriptionItemId($personalAgenda['subscription_item_id'])
94
                        ->setMaxAttendees($invitationsOrSubscriptionsInfo[0]['max_attendees'])
95
                    ;
96
                } else {
97
                    $invitationsInfo = $this->getInvitations($subscriptionsEnabled, (int) $personalAgenda['id']);
98
99
                    if (\count($invitationsInfo) > 0) {
100
                        $calendarEvent
101
                            ->setCollective((bool) $personalAgenda['collective'])
102
                            ->setInvitationType(CCalendarEvent::TYPE_INVITATION)
103
                        ;
104
105
                        $invitationsOrSubscriptionsInfo = $invitationsInfo;
106
                    }
107
                }
108
109
                foreach ($invitationsOrSubscriptionsInfo as $invitationOrSubscriptionInfo) {
110
                    $inviteesOrSubscribersInfo = $this->getInviteesOrSubscribers($invitationOrSubscriptionInfo['id']);
111
112
                    foreach ($inviteesOrSubscribersInfo as $oldInviteeOrSubscriberInfo) {
113
                        $user = $this->entityManager->find(User::class, $oldInviteeOrSubscriberInfo['user_id']);
114
115
                        if ($user) {
116
                            $calendarEvent->addUserLink($user);
117
                        }
118
                    }
119
                }
120
            }
121
            $oldNewEventIdMap[$personalAgenda['id']] = $calendarEvent;
122
        }
123
124
        $this->entityManager->flush();
125
126
        if ($schema->hasTable('agenda_reminder')) {
127
            if ($tblAgendaReminder->hasColumn('type')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tblAgendaReminder seems to be never defined.
Loading history...
128
                $this->updateAgendaReminders($oldNewEventIdMap);
129
            }
130
        }
131
    }
132
133
    private function getPersonalEvents(): array
134
    {
135
        $sql = 'SELECT * FROM personal_agenda ORDER BY id';
136
        $result = $this->connection->executeQuery($sql);
137
138
        return $result->fetchAllAssociative();
139
    }
140
141
    private function createCCalendarEvent(
142
        string $title,
143
        string $content,
144
        ?DateTime $startDate,
145
        ?DateTime $endDate,
146
        bool $allDay,
147
        string $color,
148
        User $creator,
149
        ?CCalendarEvent $parentEvent = null
150
    ): CCalendarEvent {
151
        $calendarEvent = new CCalendarEvent();
152
153
        $calendarEvent
154
            ->setTitle($title)
155
            ->setContent($content)
156
            ->setStartDate($startDate)
157
            ->setEndDate($endDate)
158
            ->setAllDay($allDay)
159
            ->setColor($color)
160
            ->setCreator($creator)
161
            ->setResourceName($title)
162
        ;
163
164
        if ($parentEvent) {
165
            $calendarEvent
166
                ->setParentEvent($parentEvent)
167
                ->setParentResourceNode($parentEvent->getResourceNode()->getId())
168
            ;
169
        } else {
170
            $calendarEvent->setParentResourceNode($creator->getResourceNode()->getId());
171
        }
172
173
        return $calendarEvent;
174
    }
175
176
    private function getInvitations(bool $subscriptionsEnabled, int $personalAgendaId): array
177
    {
178
        $sql = "SELECT i.id, i.creator_id, i.created_at, i.updated_at
179
            FROM agenda_event_invitation i
180
            INNER JOIN personal_agenda pa ON i.id = pa.agenda_event_invitation_id
181
            WHERE pa.id = $personalAgendaId";
182
183
        if ($subscriptionsEnabled) {
184
            $sql .= " AND i.type = 'invitation'";
185
        }
186
187
        try {
188
            $result = $this->connection->executeQuery($sql);
189
190
            return $result->fetchAllAssociative();
191
        } catch (\Doctrine\DBAL\Exception) {
192
            return [];
193
        }
194
    }
195
196
    private function getInviteesOrSubscribers(int $invitationId): array
197
    {
198
        $sql = "SELECT id, user_id, created_at, updated_at
199
            FROM agenda_event_invitee
200
            WHERE invitation_id = $invitationId
201
            ORDER BY created_at ASC";
202
203
        try {
204
            $result = $this->connection->executeQuery($sql);
205
206
            return $result->fetchAllAssociative();
207
        } catch (\Doctrine\DBAL\Exception) {
208
            return [];
209
        }
210
    }
211
212
    private function getSubscriptions(int $personalAgendaId): array
213
    {
214
        $sql = "SELECT i.id, i.creator_id, i.created_at, i.updated_at, i.max_attendees
215
            FROM agenda_event_invitation i
216
            INNER JOIN personal_agenda pa ON i.id = pa.agenda_event_invitation_id
217
            WHERE pa.id = $personalAgendaId
218
                AND i.type = 'subscription'";
219
220
        try {
221
            $result = $this->connection->executeQuery($sql);
222
223
            return $result->fetchAllAssociative();
224
        } catch (\Doctrine\DBAL\Exception) {
225
            return [];
226
        }
227
    }
228
229
    /**
230
     * @param array<int, CCalendarEvent> $oldNewEventIdMap
231
     */
232
    private function updateAgendaReminders(array $oldNewEventIdMap): void
233
    {
234
        $result = $this->connection->executeQuery("SELECT * FROM agenda_reminder WHERE type = 'personal'");
235
236
        while (($reminder = $result->fetchAssociative()) !== false) {
237
            $oldEventId = $reminder['event_id'];
238
            if (\array_key_exists($oldEventId, $oldNewEventIdMap)) {
239
                $newEvent = $oldNewEventIdMap[$oldEventId];
240
                $this->addSql(
241
                    sprintf(
242
                        'UPDATE agenda_reminder SET event_id = %d WHERE id = %d',
243
                        $newEvent->getIid(),
244
                        $reminder['id']
245
                    )
246
                );
247
            }
248
        }
249
    }
250
}
251