setName('expire:users') ->addOption('username', null, InputOption::VALUE_REQUIRED, 'The username of the user to expire') ->addOption('last-login-before', null, InputOption::VALUE_REQUIRED, 'Users with a last login before this date will be expired') ->addOption('exclude-admins', null, InputOption::VALUE_NONE, 'Exclude admins from expiry') ->addOption('expire-date', null, InputOption::VALUE_REQUIRED, 'Set the expiry date of expired users to an other date.') ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Do not actually execute the expiration.'); } protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->getApplication() ->getKernel() ->getContainer() ->get('doctrine.orm.entity_manager'); /* @var $em \Doctrine\ORM\EntityManager */ $userRepo = $em->getRepository(User::class); $queryBuilder = $userRepo->createQueryBuilder('u'); $queryBuilder->leftJoin(ExpiredUser::class, 'eu', Join::WITH, 'eu.user = u.id'); $queryBuilder->where('eu.expiredAt IS NULL'); if ($input->getOption('username')) { $queryBuilder->andWhere('u.username = :username')->setParameter('username', $input->getOption('username')); } if ($input->getOption('exclude-admins')) { $queryBuilder->andWhere('u.role NOT IN (:admin_roles)')->setParameter('admin_roles', [ 'ROLE_ADMIN', 'ROLE_SUPER_ADMIN' ]); } if ($input->getOption('last-login-before')) { $queryBuilder->andWhere('eu.lastLogin < :lastLogin OR eu.lastLogin IS NULL')->setParameter('lastLogin', new \DateTime($input->getOption('last-login-before'))); } $expireDate = new \DateTime(); if ($input->getOption('expire-date')) { $expireDate = new \DateTime($input->getOption('expire-date')); } $style = new SymfonyStyle($input, $output); $style->comment('Query: ' . $queryBuilder->getDQL()); $countBuilder = clone $queryBuilder; $countBuilder->select('count(u.id)'); $count = $countBuilder->getQuery()->getSingleScalarResult(); if ($count == 0) { $style->warning('No users match these filters.'); return 0; } if (!$input->getOption('dry-run') && !$style->confirm('Will expire ' . $count . ' users. Continue?', true)) { $style->error('Expiration cancelled.'); return 1; } if ($input->getOption('dry-run')) { $style->note('Doing a dry-run.'); } $progressBar = $style->createProgressBar($count); $usersIterator = $queryBuilder->getQuery()->iterate(); foreach ($usersIterator as list ($user)) { /* @var $user \App\Entity\User */ $progressBar->clear(); $style->text('Expired user ' . $user->getUsername()); $progressBar->display(); $progressBar->advance(); $progressBar->setMessage($user->getUsername()); $expiryRecord = $em->find(ExpiredUser::class, $user); if (!$expiryRecord) { $expiryRecord = new ExpiredUser($user); $em->persist($expiryRecord); } $expiryRecord->setExpiredAt($expireDate); if (!$input->getOption('dry-run')) { $em->flush($expiryRecord); } } $progressBar->finish(); $style->success('Expired ' . $count . ' users'); } }