Passed
Pull Request — master (#5831)
by
unknown
07:40
created

SessionRepetitionCommand::duplicateSession()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 60
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 38
nc 12
nop 3
dl 0
loc 60
rs 8.6897
c 1
b 0
f 0

How to fix   Long Method   

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\AccessUrl;
10
use Chamilo\CoreBundle\Entity\Session;
11
use Chamilo\CoreBundle\Repository\SessionRepository;
12
use Doctrine\ORM\EntityManagerInterface;
13
use Symfony\Component\Console\Command\Command;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Input\InputOption;
17
use Symfony\Component\Mailer\MailerInterface;
18
use Symfony\Component\Mime\Email;
19
use Symfony\Contracts\Translation\TranslatorInterface;
20
21
class SessionRepetitionCommand extends Command
22
{
23
    protected static $defaultName = 'app:session-repetition';
24
25
    private SessionRepository $sessionRepository;
26
    private EntityManagerInterface $entityManager;
27
    private MailerInterface $mailer;
28
    private TranslatorInterface $translator;
29
30
    public function __construct(
31
        SessionRepository $sessionRepository,
32
        EntityManagerInterface $entityManager,
33
        MailerInterface $mailer,
34
        TranslatorInterface $translator
35
    ) {
36
        parent::__construct();
37
        $this->sessionRepository = $sessionRepository;
38
        $this->entityManager = $entityManager;
39
        $this->mailer = $mailer;
40
        $this->translator = $translator;
41
    }
42
43
    protected function configure(): void
44
    {
45
        $this
46
            ->setDescription('Automatically duplicates sessions that meet the repetition criteria.')
47
            ->addOption('debug', null, InputOption::VALUE_NONE, 'Enable debug mode');
48
    }
49
50
    protected function execute(InputInterface $input, OutputInterface $output): int
51
    {
52
        $debug = $input->getOption('debug');
53
54
        // Find sessions that meet the repetition criteria
55
        $sessions = $this->sessionRepository->findSessionsWithoutChildAndReadyForRepetition();
56
57
        if ($debug) {
58
            $output->writeln(sprintf('Found %d session(s) ready for repetition.', count($sessions)));
59
        }
60
61
        foreach ($sessions as $session) {
62
            if ($debug) {
63
                $output->writeln(sprintf('Processing session: %d', $session->getId()));
64
            }
65
66
            // Duplicate session
67
            $newSession = $this->duplicateSession($session, $debug, $output);
68
69
            // Notify general coach of the new session
70
            $this->notifyGeneralCoach($newSession, $debug, $output);
71
72
            $output->writeln('Created new session: ' . $newSession->getId() . ' from session: ' . $session->getId());
73
        }
74
75
        return Command::SUCCESS;
76
    }
77
78
    /**
79
     * Duplicates a session and creates a new session with adjusted dates.
80
     */
81
    private function duplicateSession(Session $session, bool $debug, OutputInterface $output): Session
82
    {
83
        // Calculate new session dates based on the duration of the original session
84
        $duration = $session->getAccessEndDate()->diff($session->getAccessStartDate());
85
        $newStartDate = (clone $session->getAccessEndDate())->modify('+1 day');
86
        $newEndDate = (clone $newStartDate)->add($duration);
87
88
        if ($debug) {
89
            $output->writeln(sprintf('Duplicating session %d. New start date: %s, New end date: %s',
90
                $session->getId(),
91
                $newStartDate->format('Y-m-d H:i:s'),
92
                $newEndDate->format('Y-m-d H:i:s')
93
            ));
94
        }
95
96
        // Create a new session with the same details as the original session
97
        $newSession = new Session();
98
        $newSession
99
            ->setTitle($session->getTitle() . ' (Repetition ' . $session->getId() . ' - ' . time() . ')')
100
            ->setAccessStartDate($newStartDate)
101
            ->setAccessEndDate($newEndDate)
102
            ->setDisplayStartDate($newStartDate)
103
            ->setDisplayEndDate($newEndDate)
104
            ->setCoachAccessStartDate($newStartDate)
105
            ->setCoachAccessEndDate($newEndDate)
106
            ->setVisibility($session->getVisibility())
107
            ->setDuration($session->getDuration())
108
            ->setDescription($session->getDescription() ?? '')
109
            ->setShowDescription($session->getShowDescription() ?? false)
110
            ->setCategory($session->getCategory())
111
            ->setPromotion($session->getPromotion())
112
            ->setLastRepetition(false);
113
114
        // Copy the AccessUrls from the original session
115
        $accessUrls = $session->getUrls();
116
117
        if ($accessUrls->isEmpty()) {
118
            // Handle the case where the session does not have any AccessUrl
119
            if ($debug) {
120
                $output->writeln('No AccessUrl found for session ' . $session->getId() . '. Assigning default AccessUrl.');
121
            }
122
123
            // Retrieve or create a default AccessUrl (you need to adjust this based on your system's needs)
124
            $defaultAccessUrl = $this->getDefaultAccessUrl();
125
            $newSession->addAccessUrl($defaultAccessUrl);
126
        } else {
127
            foreach ($accessUrls as $accessUrl) {
128
                $newSession->addAccessUrl($accessUrl->getUrl());
129
            }
130
        }
131
132
        // Save the new session
133
        $this->entityManager->persist($newSession);
134
        $this->entityManager->flush();
135
136
        if ($debug) {
137
            $output->writeln(sprintf('New session %d created successfully.', $newSession->getId()));
138
        }
139
140
        return $newSession;
141
    }
142
143
    /**
144
     * Retrieves or creates a default AccessUrl for sessions.
145
     */
146
    private function getDefaultAccessUrl()
147
    {
148
        return $this->entityManager->getRepository(AccessUrl::class)->findOneBy([]);
149
    }
150
151
152
    /**
153
     * Notifies the general coach of the session about the new repetition.
154
     */
155
    private function notifyGeneralCoach(Session $newSession, bool $debug, OutputInterface $output): void
156
    {
157
        $generalCoach = $newSession->getGeneralCoaches()->first();
158
        if ($generalCoach) {
159
            $message = sprintf(
160
                'A new repetition of the session "%s" has been created. Please review the details: %s',
161
                $newSession->getTitle(),
162
                $this->generateSessionSummaryLink($newSession)
163
            );
164
165
            if ($debug) {
166
                $output->writeln(sprintf('Notifying coach (ID: %d) for session %d', $generalCoach->getId(), $newSession->getId()));
167
            }
168
169
            // Send message to the general coach
170
            $this->sendMessage($generalCoach->getEmail(), $message);
171
172
            if ($debug) {
173
                $output->writeln('Notification sent.');
174
            }
175
        } else {
176
            if ($debug) {
177
                $output->writeln('No general coach found for session ' . $newSession->getId());
178
            }
179
        }
180
    }
181
182
    /**
183
     * Sends an email message to a user.
184
     */
185
    private function sendMessage(string $recipientEmail, string $message): void
186
    {
187
        $subject = $this->translator->trans('New Session Repetition Created');
188
189
        $email = (new Email())
190
            ->from('[email protected]')
191
            ->to($recipientEmail)
192
            ->subject($subject)
193
            ->html('<p>' . $message . '</p>');
194
195
        $this->mailer->send($email);
196
    }
197
198
    /**
199
     * Generates a link to the session summary page.
200
     */
201
    private function generateSessionSummaryLink(Session $session): string
202
    {
203
        return '/main/session/resume_session.php?id_session=' . $session->getId();
204
    }
205
}
206