chill-bundles/src/Bundle/ChillMainBundle/Command/ChillUserSendRenewPasswordCodeCommand.php

214 lines
5.6 KiB
PHP

<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Command;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Notification\Mailer;
use Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use InvalidArgumentException;
use League\Csv\Reader;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use function array_key_exists;
use function array_merge;
use function in_array;
use function trim;
/**
* Class ChillUserSendRenewPasswordCodeCommand.
*/
class ChillUserSendRenewPasswordCodeCommand extends Command
{
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @var Mailer
*/
protected $mailer;
/**
* @var RecoverPasswordHelper
*/
protected $recoverPasswordHelper;
/**
* The current input interface.
*
* @var InputInterface
*/
private $input;
/**
* The current output interface.
*
* @var OutputInterface
*/
private $output;
public function __construct(
LoggerInterface $logger,
EntityManagerInterface $em,
RecoverPasswordHelper $recoverPasswordHelper,
EventDispatcherInterface $eventDispatcher
) {
$this->logger = $logger;
$this->em = $em;
$this->recoverPasswordHelper = $recoverPasswordHelper;
$this->eventDispatcher = $eventDispatcher;
parent::__construct();
}
protected function configure()
{
$this
->setName('chill:user:send-password-recover-code')
->setDescription('Send a message with code to recover password')
->addArgument('csvfile', InputArgument::REQUIRED, 'CSV file with the list of users')
->addOption('template', null, InputOption::VALUE_REQUIRED, 'Template for email')
->addOption('expiration', null, InputOption::VALUE_REQUIRED, 'Expiration of the link, as an unix timestamp')
->addOption('subject', null, InputOption::VALUE_REQUIRED, 'Subject of the email', 'Recover your password');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
$this->output = $output;
$reader = $this->getReader();
foreach ($reader->getRecords() as $offset => $r) {
$user = $this->getUser($r);
if (null === $user) {
$this->onUserNotFound($r, $offset);
continue;
}
$this->sendRecoverCode($user);
}
}
/**
* @throws Exception
*
* @return Reader
*/
protected function getReader()
{
try {
$reader = Reader::createFromPath($this->input->getArgument('csvfile'));
} catch (Exception $e) {
$this->logger->error('The csv file could not be read', [
'path' => $this->input->getArgument('csvfile'),
]);
throw $e;
}
$reader->setHeaderOffset(0);
$headers = $reader->getHeader();
if (
false === in_array('username', $headers, true)
&& false === in_array('email', $headers, true)
) {
throw new InvalidArgumentException('The csv file does not have an '
. 'username or email header');
}
return $reader;
}
protected function getUser($row)
{
/** @var \Chill\MainBundle\Repository\UserRepository $userRepository */
$userRepository = $this->em->getRepository(User::class);
try {
if (array_key_exists('email', $row)) {
return $userRepository->findOneByUsernameOrEmail(trim($row['email']));
}
} catch (\Doctrine\ORM\NoResultException $e) {
// continue, we will try username
}
try {
if (array_key_exists('username', $row)) {
return $userRepository->findOneByUsernameOrEmail(trim($row['username']));
}
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
protected function onUserNotFound($row, $offset)
{
$this->logger->alert('User not found', array_merge([
'offset' => $offset,
], $row));
}
protected function sendRecoverCode(User $user)
{
if (empty($user->getEmail())) {
$this->logger->alert('User without email', [
'user_id' => $user->getId(),
'username' => $user->getUsername(),
]);
return;
}
$template = $this->input->getOption('template');
$expiration = DateTime::createFromFormat(
'U',
$this->input->getOption('expiration')
);
$this->recoverPasswordHelper
->sendRecoverEmail(
$user,
$expiration,
$template,
['expiration' => $expiration],
false,
['_locale' => 'fr'],
$this->input->getOption('subject')
);
}
}