Passed
Push — master ( 6aa0ea...459dda )
by
unknown
14:01 queued 05:01
created

configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 4
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\User;
10
use DateTime;
11
use DateTimeZone;
12
use Doctrine\ORM\EntityManagerInterface;
13
use Symfony\Component\Console\Attribute\AsCommand;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Input\InputOption;
17
use Symfony\Component\Console\Output\OutputInterface;
18
use Symfony\Component\Console\Style\SymfonyStyle;
19
20
#[AsCommand(
21
    name: 'app:deactivate-users-with-no-active-session',
22
    description: 'Deactivate users who are not part of any active session (where session end date has passed).'
23
)]
24
class DeactivateUsersWithNoActiveSessionCommand extends Command
25
{
26
    public function __construct(
27
        private readonly EntityManagerInterface $entityManager
28
    ) {
29
        parent::__construct();
30
    }
31
32
    protected function configure(): void
33
    {
34
        $this
35
            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Run without saving changes');
36
    }
37
38
    protected function execute(InputInterface $input, OutputInterface $output): int
39
    {
40
        $io = new SymfonyStyle($input, $output);
41
        $dryRun = $input->getOption('dry-run');
42
        $now = new DateTime('now', new DateTimeZone('UTC'));
43
44
        $io->title('Deactivating users without active sessions...');
45
        $io->text('Checking users as of ' . $now->format('Y-m-d H:i:s'));
46
47
        // Subquery: user IDs with at least one session where end date is in the future
48
        $subQuery = $this->entityManager->createQueryBuilder()
49
            ->select('IDENTITY(sru.user)')
50
            ->from('Chamilo\CoreBundle\Entity\SessionRelUser', 'sru')
51
            ->join('sru.session', 's')
52
            ->where('s.displayEndDate > :now')
53
            ->getDQL();
54
55
        // Main query: get all active users not in the subquery
56
        $qb = $this->entityManager->createQueryBuilder();
57
        $usersToDeactivate = $qb
58
            ->select('u')
59
            ->from(User::class, 'u')
60
            ->where('u.active = 1')
61
            ->andWhere($qb->expr()->notIn('u.id', $subQuery))
62
            ->setParameter('now', $now)
63
            ->getQuery()
64
            ->getResult();
65
66
        $deactivatedCount = 0;
67
68
        /* @var User $user */
69
        foreach ($usersToDeactivate as $user) {
70
            $user->setActive(0);
71
            $this->entityManager->persist($user);
72
            $io->writeln("Deactivated user ID {$user->getId()} ({$user->getUsername()})");
73
            $deactivatedCount++;
74
        }
75
76
        if ($dryRun) {
77
            $io->warning("Dry run mode enabled. {$deactivatedCount} users would be deactivated.");
78
        } else {
79
            $this->entityManager->flush();
80
            $io->success("Successfully deactivated {$deactivatedCount} users without active sessions.");
81
        }
82
83
        return Command::SUCCESS;
84
    }
85
}
86