Skip to content

Internal: Add command to deactivate users without active sessions - refs BT#22642 #6325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

/* For licensing terms, see /license.txt */

namespace Chamilo\CoreBundle\Command;

use Chamilo\CoreBundle\Entity\User;
use DateTime;
use DateTimeZone;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
name: 'app:deactivate-users-with-no-active-session',
description: 'Deactivate users who are not part of any active session (where session end date has passed).'
)]
class DeactivateUsersWithNoActiveSessionCommand extends Command
{
public function __construct(
private readonly EntityManagerInterface $entityManager
) {
parent::__construct();
}

protected function configure(): void
{
$this
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Run without saving changes');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$dryRun = $input->getOption('dry-run');
$now = new DateTime('now', new DateTimeZone('UTC'));

$io->title('Deactivating users without active sessions...');
$io->text('Checking users as of ' . $now->format('Y-m-d H:i:s'));

// Subquery: user IDs with at least one session where end date is in the future
$subQuery = $this->entityManager->createQueryBuilder()
->select('IDENTITY(sru.user)')
->from('Chamilo\CoreBundle\Entity\SessionRelUser', 'sru')
->join('sru.session', 's')
->where('s.displayEndDate > :now')
->getDQL();

// Main query: get all active users not in the subquery
$qb = $this->entityManager->createQueryBuilder();
$usersToDeactivate = $qb
->select('u')
->from(User::class, 'u')
->where('u.active = 1')
->andWhere($qb->expr()->notIn('u.id', $subQuery))
->setParameter('now', $now)

Check failure on line 62 in src/CoreBundle/Command/DeactivateUsersWithNoActiveSessionCommand.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 Test on ubuntu-latest

QueryBuilderSetParameter

src/CoreBundle/Command/DeactivateUsersWithNoActiveSessionCommand.php:62:35: QueryBuilderSetParameter: To improve performance set explicit type for objects
->getQuery()
->getResult();

$deactivatedCount = 0;

/* @var User $user */
foreach ($usersToDeactivate as $user) {
$user->setActive(0);
$this->entityManager->persist($user);
$io->writeln("Deactivated user ID {$user->getId()} ({$user->getUsername()})");
$deactivatedCount++;
}

if ($dryRun) {
$io->warning("Dry run mode enabled. {$deactivatedCount} users would be deactivated.");
} else {
$this->entityManager->flush();
$io->success("Successfully deactivated {$deactivatedCount} users without active sessions.");
}

return Command::SUCCESS;
}
}
Loading