Passed
Pull Request — master (#5909)
by
unknown
08:18
created

SendEventRemindersCommand::execute()   F

Complexity

Conditions 31
Paths 240

Size

Total Lines 132
Code Lines 86

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 31
eloc 86
c 3
b 0
f 0
nc 240
nop 2
dl 0
loc 132
rs 2.8333

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