Passed
Pull Request — master (#5944)
by
unknown
07:41
created

SendEventRemindersCommand   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 226
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 126
c 4
b 0
f 0
dl 0
loc 226
rs 8.72
wmc 46

5 Methods

Rating   Name   Duplication   Size   Complexity  
F execute() 0 162 36
A getFirstAdminId() 0 7 4
A __construct() 0 8 1
A configure() 0 6 1
A generateEventDetails() 0 27 4

How to fix   Complexity   

Complex Class

Complex classes like SendEventRemindersCommand often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SendEventRemindersCommand, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Command;
8
9
use Chamilo\CoreBundle\Entity\AgendaReminder;
10
use Chamilo\CoreBundle\Entity\Session;
11
use Chamilo\CoreBundle\Entity\User;
12
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
13
use Chamilo\CoreBundle\ServiceHelper\MessageHelper;
14
use Chamilo\CoreBundle\Settings\SettingsManager;
15
use Chamilo\CourseBundle\Entity\CCalendarEvent;
16
use DateTime;
17
use DateTimeZone;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Symfony\Component\Console\Command\Command;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Style\SymfonyStyle;
24
use Symfony\Contracts\Translation\TranslatorInterface;
25
26
use const PHP_EOL;
27
28
class SendEventRemindersCommand extends Command
29
{
30
    /**
31
     * @var string
32
     */
33
    protected static $defaultName = 'app:send-event-reminders';
34
35
    public function __construct(
36
        private readonly EntityManagerInterface $entityManager,
37
        private readonly SettingsManager $settingsManager,
38
        private readonly CourseRepository $courseRepository,
39
        private readonly TranslatorInterface $translator,
40
        private readonly MessageHelper $messageHelper
41
    ) {
42
        parent::__construct();
43
    }
44
45
    protected function configure(): void
46
    {
47
        $this
48
            ->setDescription('Send notification messages to users that have reminders from events in their agenda.')
49
            ->addOption('debug', null, InputOption::VALUE_NONE, 'Enable debug mode')
50
            ->setHelp('This command sends notifications to users who have pending reminders for calendar events.')
51
        ;
52
    }
53
54
    protected function execute(InputInterface $input, OutputInterface $output): int
55
    {
56
        $io = new SymfonyStyle($input, $output);
57
        $debug = $input->getOption('debug');
58
        $now = new DateTime('now', new DateTimeZone('UTC'));
59
        $initialSentRemindersCount = 0;
60
        $sentRemindersCount = 0;
61
62
        if ($debug) {
63
            error_log('Debug mode activated');
64
            $io->note('Debug mode activated');
65
        }
66
67
        $remindersRepo = $this->entityManager->getRepository(AgendaReminder::class);
68
        $reminders = $remindersRepo->findBy(['sent' => false]);
69
70
        if ($debug) {
71
            error_log('Total reminders fetched: '.\count($reminders));
72
        }
73
74
        $senderId = $this->settingsManager->getSetting('agenda.agenda_reminders_sender_id');
75
        $senderId = (int) $senderId ?: $this->getFirstAdminId();
76
77
        foreach ($reminders as $reminder) {
78
            /** @var CCalendarEvent $event */
79
            $event = $reminder->getEvent();
80
81
            if (null === $event) {
82
                if ($debug) {
83
                    error_log('No event found for reminder ID: '.$reminder->getId());
84
                }
85
86
                continue;
87
            }
88
89
            $eventType = $event->determineType();
90
            $notificationDate = clone $event->getStartDate();
91
            $notificationDate->sub($reminder->getDateInterval());
92
            if ($notificationDate > $now) {
93
                continue;
94
            }
95
96
            $eventDetails = $this->generateEventDetails($event);
97
            $messageSubject = \sprintf('Reminder for event: %s', $event->getTitle());
98
            $messageContent = implode(PHP_EOL, $eventDetails);
99
100
            $initialSentRemindersCount = $sentRemindersCount;
101
102
            if ('personal' === $eventType) {
103
                $creator = $event->getResourceNode()->getCreator();
104
                if ($creator) {
105
                    $this->messageHelper->sendMessageSimple($creator->getId(), $messageSubject, $messageContent, $senderId);
106
                    if ($debug) {
107
                        error_log("Message sent to creator ID: {$creator->getId()} for personal event: ".$event->getTitle());
108
                    }
109
                    $sentRemindersCount++;
110
                }
111
112
                $resourceLinks = $event->getResourceNode()->getResourceLinks();
113
                if (!$resourceLinks->isEmpty()) {
114
                    foreach ($resourceLinks as $link) {
115
                        if ($user = $link->getUser()) {
116
                            $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
117
                            if ($debug) {
118
                                error_log("Message sent to user ID: {$user->getId()} for personal event: ".$event->getTitle());
119
                            }
120
                            $sentRemindersCount++;
121
                        }
122
                    }
123
                }
124
            } else {
125
                $resourceLink = $event->getResourceNode()->getResourceLinks()->first();
126
                if (!$resourceLink) {
127
                    if ($debug) {
128
                        error_log("No ResourceLink found for event ID: {$event->getIid()}");
129
                    }
130
131
                    continue;
132
                }
133
134
                switch ($eventType) {
135
                    case 'global':
136
                        foreach ($event->getResourceNode()->getResourceLinks() as $link) {
137
                            if ($user = $link->getUser()) {
138
                                $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
139
                                if ($debug) {
140
                                    error_log("Message sent to user ID: {$user->getId()} for global event: ".$event->getTitle());
141
                                }
142
                                $sentRemindersCount++;
143
                            }
144
                        }
145
146
                        break;
147
148
                    case 'course':
149
                        if ($course = $resourceLink->getCourse()) {
150
                            $users = $this->courseRepository->getSubscribedUsers($course)->getQuery()->getResult();
151
                            foreach ($users as $user) {
152
                                $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
153
                                if ($debug) {
154
                                    error_log("Message sent to user ID: {$user->getId()} for course event: ".$event->getTitle());
155
                                }
156
                                $sentRemindersCount++;
157
                            }
158
                        }
159
160
                        break;
161
162
                    case 'session':
163
                        if ($session = $resourceLink->getSession()) {
164
                            $course = $resourceLink->getCourse();
165
                            if (!$course) {
166
                                if ($debug) {
167
                                    error_log("No course found for resource link in session ID: {$session->getId()}");
168
                                }
169
                                break;
170
                            }
171
172
                            $usersToNotify = [];
173
                            $studentSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::STUDENT);
174
                            foreach ($studentSubscriptions as $studentSubscription) {
175
                                $usersToNotify[$studentSubscription->getUser()->getId()] = $studentSubscription->getUser();
176
                            }
177
178
                            $coachSubscriptions = $session->getSessionRelCourseRelUsersByStatus($course, Session::COURSE_COACH);
179
                            foreach ($coachSubscriptions as $coachSubscription) {
180
                                $usersToNotify[$coachSubscription->getUser()->getId()] = $coachSubscription->getUser();
181
                            }
182
183
                            $generalCoaches = $session->getGeneralCoaches();
184
                            foreach ($generalCoaches as $generalCoach) {
185
                                $usersToNotify[$generalCoach->getId()] = $generalCoach;
186
                            }
187
188
                            foreach ($usersToNotify as $user) {
189
                                $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
190
                                if ($debug) {
191
                                    error_log("Message sent to user ID: {$user->getId()} ({$user->getUsername()}) for session event: {$event->getTitle()}");
192
                                }
193
                                $sentRemindersCount++;
194
                            }
195
                        }
196
197
                        break;
198
                }
199
            }
200
201
            if ($sentRemindersCount > $initialSentRemindersCount) {
202
                $reminder->setSent(true);
203
                $this->entityManager->persist($reminder);
204
            }
205
        }
206
207
        $this->entityManager->flush();
208
209
        if ($sentRemindersCount > 0) {
210
            $io->success(\sprintf('%d event reminders have been sent successfully.', $sentRemindersCount));
211
        } else {
212
            $io->warning('No event reminders were sent.');
213
        }
214
215
        return Command::SUCCESS;
216
    }
217
218
    private function getFirstAdminId(): int
219
    {
220
        $admin = $this->entityManager->getRepository(User::class)->findOneBy([]);
221
222
        return $admin && ($admin->hasRole('ROLE_ADMIN') || $admin->hasRole('ROLE_SUPER_ADMIN'))
223
            ? $admin->getId()
224
            : 1;
225
    }
226
227
    private function generateEventDetails(CCalendarEvent $event): array
228
    {
229
        $details = [];
230
        $details[] = \sprintf('<p><strong>%s</strong></p>', $event->getTitle());
231
232
        if ($event->isAllDay()) {
233
            $details[] = \sprintf('<p class="small">%s</p>', $this->translator->trans('All Day'));
234
        } else {
235
            $details[] = \sprintf(
236
                '<p class="small">%s</p>',
237
                \sprintf($this->translator->trans('From %s'), $event->getStartDate()->format('Y-m-d H:i:s'))
238
            );
239
240
            if ($event->getEndDate()) {
241
                $details[] = \sprintf(
242
                    '<p class="small">%s</p>',
243
                    \sprintf($this->translator->trans('Until %s'), $event->getEndDate()->format('Y-m-d H:i:s'))
244
                );
245
            }
246
        }
247
248
        if ($event->getContent()) {
249
            $cleanContent = strip_tags($event->getContent());
250
            $details[] = \sprintf('<p>%s</p>', $cleanContent);
251
        }
252
253
        return $details;
254
    }
255
}
256