Passed
Push — master ( 5ee64f...c22fd7 )
by
unknown
17:15 queued 08:09
created

SendEventRemindersCommand::execute()   D

Complexity

Conditions 26
Paths 120

Size

Total Lines 110
Code Lines 71

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 26
eloc 71
c 2
b 0
f 0
nc 120
nop 2
dl 0
loc 110
rs 4

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
        $sentRemindersCount = 0;
53
54
        if ($debug) {
55
            error_log('Debug mode activated');
56
            $io->note('Debug mode activated');
57
        }
58
59
        $remindersRepo = $this->entityManager->getRepository(AgendaReminder::class);
60
        $reminders = $remindersRepo->findBy(['sent' => false]);
61
62
        if ($debug) {
63
            error_log('Total reminders fetched: ' . count($reminders));
64
        }
65
66
        $senderId = $this->settingsManager->getSetting('agenda.agenda_reminders_sender_id');
67
        $senderId = (int) $senderId ?: $this->getFirstAdminId();
68
69
        foreach ($reminders as $reminder) {
70
            /** @var CCalendarEvent $event */
71
            $event = $reminder->getEvent();
72
73
            if (null === $event) {
74
                if ($debug) {
75
                    error_log('No event found for reminder ID: ' . $reminder->getId());
76
                }
77
                continue;
78
            }
79
80
            $eventType = $event->determineType();
81
            $notificationDate = clone $event->getStartDate();
82
            $notificationDate->sub($reminder->getDateInterval());
83
            if ($notificationDate > $now) {
84
                continue;
85
            }
86
87
            $eventDetails = $this->generateEventDetails($event);
88
            $messageSubject = sprintf('Reminder for event: %s', $event->getTitle());
89
            $messageContent = implode(PHP_EOL, $eventDetails);
90
91
            $resourceLink = $event->getResourceNode()->getResourceLinks()->first();
92
93
            if (!$resourceLink) {
94
                if ($debug) {
95
                    error_log("No ResourceLink found for event ID: {$event->getIid()}");
96
                }
97
                continue;
98
            }
99
100
            switch ($eventType) {
101
                case 'personal':
102
                    if ($user = $resourceLink->getUser()) {
103
                        $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
104
                        if ($debug) {
105
                            error_log("Message sent to user ID: {$user->getId()} for personal event: " . $event->getTitle());
106
                        }
107
                    }
108
                    break;
109
                case 'global':
110
                    foreach ($event->getResourceNode()->getResourceLinks() as $link) {
111
                        if ($user = $link->getUser()) {
112
                            $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
113
                            if ($debug) {
114
                                error_log("Message sent to user ID: {$user->getId()} for global event: " . $event->getTitle());
115
                            }
116
                        }
117
                    }
118
                    break;
119
                case 'course':
120
                    if ($course = $resourceLink->getCourse()) {
121
                        $users = $this->courseRepository->getSubscribedUsers($course)->getQuery()->getResult();
122
                        foreach ($users as $user) {
123
                            $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
124
                            if ($debug) {
125
                                error_log("Message sent to user ID: {$user->getId()} for course event: " . $event->getTitle());
126
                            }
127
                        }
128
                    }
129
                    break;
130
                case 'session':
131
                    if ($session = $resourceLink->getSession()) {
132
                        foreach ($session->getUsers() as $sessionRelUser) {
133
                            $user = $sessionRelUser->getUser();
134
                            $this->messageHelper->sendMessageSimple($user->getId(), $messageSubject, $messageContent, $senderId);
135
                            if ($debug) {
136
                                error_log("Message sent to user ID: {$user->getId()} for session event: " . $event->getTitle());
137
                            }
138
                        }
139
                    }
140
                    break;
141
            }
142
143
            $reminder->setSent(true);
144
            $this->entityManager->persist($reminder);
145
            $sentRemindersCount++;
146
        }
147
148
        $this->entityManager->flush();
149
150
        if ($sentRemindersCount > 0) {
151
            $io->success(sprintf('%d event reminders have been sent successfully.', $sentRemindersCount));
152
        } else {
153
            $io->warning('No event reminders were sent.');
154
        }
155
156
        return Command::SUCCESS;
157
    }
158
159
    private function getFirstAdminId(): int
160
    {
161
        $admin = $this->entityManager->getRepository(User::class)->findOneBy([]);
162
        return $admin && ($admin->hasRole('ROLE_ADMIN') || $admin->hasRole('ROLE_SUPER_ADMIN'))
163
            ? $admin->getId()
164
            : 1;
165
    }
166
167
    private function generateEventDetails(CCalendarEvent $event): array
168
    {
169
        $details = [];
170
        $details[] = sprintf('<p><strong>%s</strong></p>', $event->getTitle());
171
172
        if ($event->isAllDay()) {
173
            $details[] = sprintf('<p class="small">%s</p>', $this->translator->trans("All Day"));
174
        } else {
175
            $details[] = sprintf(
176
                '<p class="small">%s</p>',
177
                sprintf($this->translator->trans("From %s"), $event->getStartDate()->format('Y-m-d H:i:s'))
178
            );
179
180
            if ($event->getEndDate()) {
181
                $details[] = sprintf(
182
                    '<p class="small">%s</p>',
183
                    sprintf($this->translator->trans("Until %s"), $event->getEndDate()->format('Y-m-d H:i:s'))
184
                );
185
            }
186
        }
187
188
        if ($event->getContent()) {
189
            $cleanContent = strip_tags($event->getContent());
190
            $details[] = sprintf('<p>%s</p>', $cleanContent);
191
        }
192
193
        return $details;
194
    }
195
}
196