Passed
Push — dependabot/npm_and_yarn/microm... ( f2f212...f35bf2 )
by
unknown
13:36 queued 05:58
created

SendEventRemindersCommand::getInviteesForEvent()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 11
rs 10
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\Settings\SettingsManager;
12
use Chamilo\CourseBundle\Entity\CCalendarEvent;
13
use Doctrine\ORM\EntityManagerInterface;
14
use MessageManager;
15
use Symfony\Component\Console\Command\Command;
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Style\SymfonyStyle;
20
use DateTime;
21
use DateTimeZone;
22
23
class SendEventRemindersCommand extends Command
24
{
25
    protected static $defaultName = 'app:send-event-reminders';
26
27
    public function __construct(
28
        private readonly EntityManagerInterface $entityManager,
29
        private readonly SettingsManager $settingsManager
30
    ) {
31
        parent::__construct();
32
    }
33
34
    protected function configure(): void
35
    {
36
        $this
37
            ->setDescription('Send notification messages to users that have reminders from events in their agenda.')
38
            ->addOption('debug', null, InputOption::VALUE_NONE, 'Enable debug mode')
39
            ->setHelp('This command sends notifications to users who have pending reminders for calendar events.');
40
    }
41
42
    protected function execute(InputInterface $input, OutputInterface $output): int
43
    {
44
        $io = new SymfonyStyle($input, $output);
45
        $debug = $input->getOption('debug');
46
        $now = new DateTime('now', new DateTimeZone('UTC'));
47
48
        if ($debug) {
49
            error_log('Debug mode activated');
50
            $io->note('Debug mode activated');
51
        }
52
53
        $remindersRepo = $this->entityManager->getRepository(AgendaReminder::class);
54
        $reminders = $remindersRepo->findBy(['sent' => false]);
55
56
        $senderId = $this->settingsManager->getSetting('agenda.agenda_reminders_sender_id');
57
        $senderId = (int) $senderId ?: $this->getFirstAdminId();
58
59
        $batchCounter = 0;
60
        $batchSize = 100;
61
62
        foreach ($reminders as $reminder) {
63
            $event = $reminder->getEvent();
64
65
            if (!$event) {
66
                if ($debug) {
67
                    error_log('No event found for reminder ID: ' . $reminder->getId());
68
                    $io->note('No event found for reminder ID: ' . $reminder->getId());
69
                }
70
                continue;
71
            }
72
73
            $eventId = $event->getIid();
74
            $eventEntity = $this->entityManager->getRepository(CCalendarEvent::class)->find($eventId);
75
76
            if (!$eventEntity) {
77
                if ($debug) {
78
                    error_log('No event entity found for event ID: ' . $eventId);
79
                    $io->note('No event entity found for event ID: ' . $eventId);
80
                }
81
                continue;
82
            }
83
84
            $notificationDate = clone $event->getStartDate();
85
            $notificationDate->sub($reminder->getDateInterval());
86
            if ($notificationDate > $now) {
87
                continue;
88
            }
89
90
            $messageSubject = sprintf('Reminder for event: %s', $event->getTitle());
91
            $messageContent = $this->generateEventDetails($event);
92
            $invitees = $this->getInviteesForEvent($event);
93
94
            foreach ($invitees as $userId) {
95
                MessageManager::send_message_simple(
96
                    $userId,
97
                    $messageSubject,
98
                    $messageContent,
99
                    $senderId
100
                );
101
102
                if ($debug) {
103
                    error_log("Message sent to user ID: $userId for event: " . $event->getTitle());
104
                    $io->note("Message sent to user ID: $userId for event: " . $event->getTitle());
105
                }
106
            }
107
108
            $reminder->setSent(true);
109
            $batchCounter++;
110
111
            if (($batchCounter % $batchSize) === 0) {
112
                $this->entityManager->flush();
113
114
                if ($debug) {
115
                    error_log('Batch of reminders flushed');
116
                    $io->note('Batch of reminders flushed');
117
                }
118
            }
119
        }
120
121
        $this->entityManager->flush();
122
        if ($debug) {
123
            error_log('Final batch of reminders flushed');
124
            $io->note('Final batch of reminders flushed');
125
        }
126
127
        $io->success('Event reminders have been sent successfully.');
128
129
        return Command::SUCCESS;
130
    }
131
132
    private function getFirstAdminId(): int
133
    {
134
        $admin = $this->entityManager->getRepository(User::class)->findOneByRole('ROLE_ADMIN');
135
        return $admin ? $admin->getId() : 1;
136
    }
137
138
    private function generateEventDetails(CCalendarEvent $event): string
139
    {
140
        $details = [];
141
        $details[] = sprintf('<p><strong>%s</strong></p>', $event->getTitle());
142
143
        if ($event->isAllDay()) {
144
            $details[] = '<p class="small">All Day</p>';
145
        } else {
146
            $details[] = sprintf('<p class="small">From %s</p>', $event->getStartDate()->format('Y-m-d H:i:s'));
147
            if ($event->getEndDate()) {
148
                $details[] = sprintf('<p class="small">Until %s</p>', $event->getEndDate()->format('Y-m-d H:i:s'));
149
            }
150
        }
151
152
        if ($event->getContent()) {
153
            $details[] = $event->getContent();
154
        }
155
156
        return implode(PHP_EOL, $details);
157
    }
158
159
    private function getInviteesForEvent(CCalendarEvent $event): array
160
    {
161
        $inviteeList = [];
162
163
        foreach ($event->getResourceNode()->getResourceLinks() as $resourceLink) {
164
            if ($user = $resourceLink->getUser()) {
165
                $inviteeList[] = $user->getId();
166
            }
167
        }
168
169
        return $inviteeList;
170
    }
171
}
172