mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-21 15:13:50 +00:00
cs: Fix code style (safe rules only).
This commit is contained in:
@@ -1,47 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Entity\PermissionsGroup;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Writer;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
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 League\Csv\Reader;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Entity\PermissionsGroup;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use League\Csv\Writer;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use function array_key_exists;
|
||||
use function array_keys;
|
||||
use function array_merge;
|
||||
use function bin2hex;
|
||||
use function implode;
|
||||
use function random_bytes;
|
||||
use function trim;
|
||||
|
||||
class ChillImportUsersCommand extends Command
|
||||
{
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
protected ValidatorInterface $validator;
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
protected UserPasswordEncoderInterface $passwordEncoder;
|
||||
|
||||
protected UserRepository $userRepository;
|
||||
|
||||
protected bool $doChanges = true;
|
||||
|
||||
protected OutputInterface $tempOutput;
|
||||
|
||||
protected InputInterface $tempInput;
|
||||
|
||||
/**
|
||||
* Centers and aliases.
|
||||
*
|
||||
@@ -49,12 +49,28 @@ class ChillImportUsersCommand extends Command
|
||||
*/
|
||||
protected array $centers;
|
||||
|
||||
protected array $permissionGroups;
|
||||
protected bool $doChanges = true;
|
||||
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
protected array $groupCenters;
|
||||
|
||||
protected LoggerInterface $logger;
|
||||
|
||||
protected Writer $output;
|
||||
|
||||
protected UserPasswordEncoderInterface $passwordEncoder;
|
||||
|
||||
protected array $permissionGroups;
|
||||
|
||||
protected InputInterface $tempInput;
|
||||
|
||||
protected OutputInterface $tempOutput;
|
||||
|
||||
protected UserRepository $userRepository;
|
||||
|
||||
protected ValidatorInterface $validator;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
LoggerInterface $logger,
|
||||
@@ -71,6 +87,27 @@ class ChillImportUsersCommand extends Command
|
||||
parent::__construct('chill:main:import-users');
|
||||
}
|
||||
|
||||
protected function appendUserToFile(User $user)
|
||||
{
|
||||
$this->output->insertOne([
|
||||
$user->getEmail(),
|
||||
$user->getUsername(),
|
||||
$user->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function concatenateViolations(ConstraintViolationListInterface $list)
|
||||
{
|
||||
$str = [];
|
||||
|
||||
foreach ($list as $e) {
|
||||
/* @var $e \Symfony\Component\Validator\ConstraintViolationInterface */
|
||||
$str[] = $e->getMessage();
|
||||
}
|
||||
|
||||
return implode(';', $str);
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
@@ -82,6 +119,99 @@ class ChillImportUsersCommand extends Command
|
||||
->addOption('csv-dump', null, InputOption::VALUE_REQUIRED, 'A path to dump a summary of the created file');
|
||||
}
|
||||
|
||||
protected function createOrGetGroupCenter(Center $center, PermissionsGroup $pg): GroupCenter
|
||||
{
|
||||
if (array_key_exists($center->getId(), $this->groupCenters)) {
|
||||
if (array_key_exists($pg->getId(), $this->groupCenters[$center->getId()])) {
|
||||
return $this->groupCenters[$center->getId()][$pg->getId()];
|
||||
}
|
||||
}
|
||||
|
||||
$repository = $this->em->getRepository(GroupCenter::class);
|
||||
|
||||
$groupCenter = $repository->findOneBy([
|
||||
'center' => $center,
|
||||
'permissionsGroup' => $pg,
|
||||
]);
|
||||
|
||||
if (null === $groupCenter) {
|
||||
$groupCenter = new GroupCenter();
|
||||
$groupCenter
|
||||
->setCenter($center)
|
||||
->setPermissionsGroup($pg);
|
||||
|
||||
$this->em->persist($groupCenter);
|
||||
}
|
||||
|
||||
$this->groupCenters[$center->getId()][$pg->getId()] = $groupCenter;
|
||||
|
||||
return $groupCenter;
|
||||
}
|
||||
|
||||
protected function createUser($offset, $data)
|
||||
{
|
||||
$user = new User();
|
||||
$user
|
||||
->setEmail(trim($data['email']))
|
||||
->setUsername(trim($data['username']))
|
||||
->setEnabled(true)
|
||||
->setPassword($this->passwordEncoder->encodePassword(
|
||||
$user,
|
||||
bin2hex(random_bytes(32))
|
||||
));
|
||||
|
||||
$errors = $this->validator->validate($user);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$errorMessages = $this->concatenateViolations($errors);
|
||||
|
||||
$this->tempOutput->writeln(sprintf('%d errors found with user with username "%s" at line %d', $errors->count(), $data['username'], $offset));
|
||||
$this->tempOutput->writeln($errorMessages);
|
||||
|
||||
throw new RuntimeException('Found errors while creating an user. '
|
||||
. 'Watch messages in command output');
|
||||
}
|
||||
|
||||
$pgs = $this->getPermissionGroup($data['permission group']);
|
||||
$centers = $this->getCenters($data['center']);
|
||||
|
||||
foreach ($pgs as $pg) {
|
||||
foreach ($centers as $center) {
|
||||
$groupcenter = $this->createOrGetGroupCenter($center, $pg);
|
||||
|
||||
if (false === $user->getGroupCenters()->contains($groupcenter)) {
|
||||
$user->addGroupCenter($groupcenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->doChanges) {
|
||||
$this->em->persist($user);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
$this->logger->notice('Create user', [
|
||||
'username' => $user->getUsername(),
|
||||
'id' => $user->getId(),
|
||||
'nb_of_groupCenters' => $user->getGroupCenters()->count(),
|
||||
]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function doesUserExists($data)
|
||||
{
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['username']) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['email']) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->tempOutput = $output;
|
||||
@@ -99,221 +229,11 @@ class ChillImportUsersCommand extends Command
|
||||
|
||||
try {
|
||||
$this->loadUsers();
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareWriter()
|
||||
{
|
||||
$this->output = $output = Writer::createFromPath($this->tempInput
|
||||
->getOption('csv-dump'), 'a+');
|
||||
|
||||
$output->insertOne([
|
||||
'email',
|
||||
'username',
|
||||
'id'
|
||||
]);
|
||||
}
|
||||
|
||||
protected function appendUserToFile(User $user)
|
||||
{
|
||||
$this->output->insertOne( [
|
||||
$user->getEmail(),
|
||||
$user->getUsername(),
|
||||
$user->getId()
|
||||
]);
|
||||
}
|
||||
|
||||
protected function loadUsers()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getArgument('csvfile'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
foreach ($reader->getRecords() as $line => $r) {
|
||||
$this->logger->debug("starting handling new line", [
|
||||
'line' => $line
|
||||
]);
|
||||
|
||||
if ($this->doesUserExists($r)) {
|
||||
$this->tempOutput->writeln(sprintf("User with username '%s' already "
|
||||
. "exists, skipping", $r["username"]));
|
||||
|
||||
$this->logger->info("One user already exists, skipping creation", [
|
||||
'username_in_file' => $r['username'],
|
||||
'email_in_file' => $r['email'],
|
||||
'line' => $line
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$user = $this->createUser($line, $r);
|
||||
$this->appendUserToFile($user);
|
||||
}
|
||||
}
|
||||
|
||||
protected function doesUserExists($data)
|
||||
{
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['username']) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->userRepository->countByUsernameOrEmail($data['email']) > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function createUser($offset, $data)
|
||||
{
|
||||
$user = new User();
|
||||
$user
|
||||
->setEmail(\trim($data['email']))
|
||||
->setUsername(\trim($data['username']))
|
||||
->setEnabled(true)
|
||||
->setPassword($this->passwordEncoder->encodePassword($user,
|
||||
\bin2hex(\random_bytes(32))))
|
||||
;
|
||||
|
||||
$errors = $this->validator->validate($user);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$errorMessages = $this->concatenateViolations($errors);
|
||||
|
||||
$this->tempOutput->writeln(sprintf("%d errors found with user with username \"%s\" at line %d", $errors->count(), $data['username'], $offset));
|
||||
$this->tempOutput->writeln($errorMessages);
|
||||
|
||||
throw new \RuntimeException("Found errors while creating an user. "
|
||||
. "Watch messages in command output");
|
||||
}
|
||||
|
||||
$pgs = $this->getPermissionGroup($data['permission group']);
|
||||
$centers = $this->getCenters($data['center']);
|
||||
|
||||
foreach($pgs as $pg) {
|
||||
foreach ($centers as $center) {
|
||||
$groupcenter = $this->createOrGetGroupCenter($center, $pg);
|
||||
|
||||
if (FALSE === $user->getGroupCenters()->contains($groupcenter)) {
|
||||
$user->addGroupCenter($groupcenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($this->doChanges) {
|
||||
$this->em->persist($user);
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
$this->logger->notice("Create user", [
|
||||
'username' => $user->getUsername(),
|
||||
'id' => $user->getId(),
|
||||
'nb_of_groupCenters' => $user->getGroupCenters()->count()
|
||||
]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function getPermissionGroup($alias)
|
||||
{
|
||||
if (\array_key_exists($alias, $this->permissionGroups)) {
|
||||
return $this->permissionGroups[$alias];
|
||||
}
|
||||
|
||||
$permissionGroupsByName = [];
|
||||
|
||||
foreach($this->em->getRepository(PermissionsGroup::class)
|
||||
->findAll() as $permissionGroup) {
|
||||
$permissionGroupsByName[$permissionGroup->getName()] = $permissionGroup;
|
||||
}
|
||||
|
||||
if (count($permissionGroupsByName) === 0) {
|
||||
throw new \RuntimeException("no permission groups found. Create them "
|
||||
. "before importing users");
|
||||
}
|
||||
|
||||
$question = new ChoiceQuestion("To which permission groups associate with \"$alias\" ?",
|
||||
\array_keys($permissionGroupsByName));
|
||||
$question
|
||||
->setMultiselect(true)
|
||||
->setAutocompleterValues(\array_keys($permissionGroupsByName))
|
||||
->setNormalizer(function($value) {
|
||||
if (NULL === $value) { return ''; }
|
||||
|
||||
return \trim($value);
|
||||
})
|
||||
;
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
$keys = $helper->ask($this->tempInput, $this->tempOutput, $question);
|
||||
|
||||
$this->tempOutput->writeln("You have chosen ".\implode(", ", $keys));
|
||||
|
||||
if ($helper->ask($this->tempInput, $this->tempOutput,
|
||||
new ConfirmationQuestion("Are you sure ?", true))) {
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$this->permissionGroups[$alias][] = $permissionGroupsByName[$key];
|
||||
}
|
||||
|
||||
return $this->permissionGroups[$alias];
|
||||
}
|
||||
|
||||
$this->logger->error('Error while responding to a a question');
|
||||
$this->tempOutput->writeln('Ok, I accept, but I do not know what to do. Please try again.');
|
||||
|
||||
throw new \RuntimeException('Error while responding to a question');
|
||||
}
|
||||
|
||||
protected function createOrGetGroupCenter(Center $center, PermissionsGroup $pg): GroupCenter
|
||||
{
|
||||
if (\array_key_exists($center->getId(), $this->groupCenters)) {
|
||||
if (\array_key_exists($pg->getId(), $this->groupCenters[$center->getId()])) {
|
||||
return $this->groupCenters[$center->getId()][$pg->getId()];
|
||||
}
|
||||
}
|
||||
|
||||
$repository = $this->em->getRepository(GroupCenter::class);
|
||||
|
||||
$groupCenter = $repository->findOneBy(array(
|
||||
'center' => $center,
|
||||
'permissionsGroup' => $pg
|
||||
));
|
||||
|
||||
if ($groupCenter === NULL) {
|
||||
$groupCenter = new GroupCenter();
|
||||
$groupCenter
|
||||
->setCenter($center)
|
||||
->setPermissionsGroup($pg)
|
||||
;
|
||||
|
||||
$this->em->persist($groupCenter);
|
||||
}
|
||||
|
||||
$this->groupCenters[$center->getId()][$pg->getId()] = $groupCenter;
|
||||
|
||||
return $groupCenter;
|
||||
}
|
||||
|
||||
protected function prepareGroupingCenters()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getOption('grouping-centers'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
foreach ($reader->getRecords() as $r) {
|
||||
$this->centers[$r['alias']] =
|
||||
\array_merge(
|
||||
$this->centers[$r['alias']] ?? [],
|
||||
$this->getCenters($r['center']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return a list of centers matching the name of alias.
|
||||
*
|
||||
@@ -326,14 +246,15 @@ class ChillImportUsersCommand extends Command
|
||||
* and suggested to user
|
||||
*
|
||||
* @param string $name the name of the center or the alias regrouping center
|
||||
*
|
||||
* @return Center[]
|
||||
*/
|
||||
protected function getCenters($name)
|
||||
{
|
||||
// sanitize
|
||||
$name = \trim($name);
|
||||
$name = trim($name);
|
||||
|
||||
if (\array_key_exists($name, $this->centers)) {
|
||||
if (array_key_exists($name, $this->centers)) {
|
||||
return $this->centers[$name];
|
||||
}
|
||||
|
||||
@@ -351,23 +272,23 @@ class ChillImportUsersCommand extends Command
|
||||
$center = (new Center())
|
||||
->setName($name);
|
||||
|
||||
$this->tempOutput->writeln("Center with name \"$name\" not found.");
|
||||
$this->tempOutput->writeln("Center with name \"{$name}\" not found.");
|
||||
$qFormatter = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion("Create a center with name \"$name\" ?", true);
|
||||
$question = new ConfirmationQuestion("Create a center with name \"{$name}\" ?", true);
|
||||
|
||||
if ($qFormatter->ask($this->tempInput, $this->tempOutput, $question)) {
|
||||
$this->centers[$name] = [ $center ];
|
||||
$this->centers[$name] = [$center];
|
||||
|
||||
$errors = $this->validator->validate($center);
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$errorMessages = $this->concatenateViolations($errors);
|
||||
|
||||
$this->tempOutput->writeln(sprintf("%d errors found with center with name \"%s\"", $errors->count(), $name));
|
||||
$this->tempOutput->writeln(sprintf('%d errors found with center with name "%s"', $errors->count(), $name));
|
||||
$this->tempOutput->writeln($errorMessages);
|
||||
|
||||
throw new \RuntimeException("Found errors while creating one center. "
|
||||
. "Watch messages in command output");
|
||||
throw new RuntimeException('Found errors while creating one center. '
|
||||
. 'Watch messages in command output');
|
||||
}
|
||||
|
||||
$this->em->persist($center);
|
||||
@@ -378,16 +299,115 @@ class ChillImportUsersCommand extends Command
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function concatenateViolations(ConstraintViolationListInterface $list)
|
||||
protected function getPermissionGroup($alias)
|
||||
{
|
||||
$str = [];
|
||||
|
||||
foreach ($list as $e) {
|
||||
/* @var $e \Symfony\Component\Validator\ConstraintViolationInterface */
|
||||
$str[] = $e->getMessage();
|
||||
if (array_key_exists($alias, $this->permissionGroups)) {
|
||||
return $this->permissionGroups[$alias];
|
||||
}
|
||||
|
||||
return \implode(";", $str);
|
||||
$permissionGroupsByName = [];
|
||||
|
||||
foreach ($this->em->getRepository(PermissionsGroup::class)
|
||||
->findAll() as $permissionGroup) {
|
||||
$permissionGroupsByName[$permissionGroup->getName()] = $permissionGroup;
|
||||
}
|
||||
|
||||
if (count($permissionGroupsByName) === 0) {
|
||||
throw new RuntimeException('no permission groups found. Create them '
|
||||
. 'before importing users');
|
||||
}
|
||||
|
||||
$question = new ChoiceQuestion(
|
||||
"To which permission groups associate with \"{$alias}\" ?",
|
||||
array_keys($permissionGroupsByName)
|
||||
);
|
||||
$question
|
||||
->setMultiselect(true)
|
||||
->setAutocompleterValues(array_keys($permissionGroupsByName))
|
||||
->setNormalizer(function ($value) {
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return trim($value);
|
||||
});
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
$keys = $helper->ask($this->tempInput, $this->tempOutput, $question);
|
||||
|
||||
$this->tempOutput->writeln('You have chosen ' . implode(', ', $keys));
|
||||
|
||||
if ($helper->ask(
|
||||
$this->tempInput,
|
||||
$this->tempOutput,
|
||||
new ConfirmationQuestion('Are you sure ?', true)
|
||||
)) {
|
||||
foreach ($keys as $key) {
|
||||
$this->permissionGroups[$alias][] = $permissionGroupsByName[$key];
|
||||
}
|
||||
|
||||
return $this->permissionGroups[$alias];
|
||||
}
|
||||
|
||||
$this->logger->error('Error while responding to a a question');
|
||||
$this->tempOutput->writeln('Ok, I accept, but I do not know what to do. Please try again.');
|
||||
|
||||
throw new RuntimeException('Error while responding to a question');
|
||||
}
|
||||
|
||||
protected function loadUsers()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getArgument('csvfile'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
foreach ($reader->getRecords() as $line => $r) {
|
||||
$this->logger->debug('starting handling new line', [
|
||||
'line' => $line,
|
||||
]);
|
||||
|
||||
if ($this->doesUserExists($r)) {
|
||||
$this->tempOutput->writeln(sprintf("User with username '%s' already "
|
||||
. 'exists, skipping', $r['username']));
|
||||
|
||||
$this->logger->info('One user already exists, skipping creation', [
|
||||
'username_in_file' => $r['username'],
|
||||
'email_in_file' => $r['email'],
|
||||
'line' => $line,
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$user = $this->createUser($line, $r);
|
||||
$this->appendUserToFile($user);
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareGroupingCenters()
|
||||
{
|
||||
$reader = Reader::createFromPath($this->tempInput->getOption('grouping-centers'));
|
||||
$reader->setHeaderOffset(0);
|
||||
|
||||
foreach ($reader->getRecords() as $r) {
|
||||
$this->centers[$r['alias']] =
|
||||
array_merge(
|
||||
$this->centers[$r['alias']] ?? [],
|
||||
$this->getCenters(
|
||||
$r['center']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareWriter()
|
||||
{
|
||||
$this->output = $output = Writer::createFromPath($this->tempInput
|
||||
->getOption('csv-dump'), 'a+');
|
||||
|
||||
$output->insertOne([
|
||||
'email',
|
||||
'username',
|
||||
'id',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -1,88 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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 League\Csv\Reader;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Notification\Mailer;
|
||||
use Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper;
|
||||
use Chill\MainBundle\Security\PasswordRecover\PasswordRecoverEvent;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use function array_key_exists;
|
||||
use function array_merge;
|
||||
use function in_array;
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* Class ChillUserSendRenewPasswordCodeCommand
|
||||
*
|
||||
* @package Chill\MainBundle\Command
|
||||
* Class ChillUserSendRenewPasswordCodeCommand.
|
||||
*/
|
||||
class ChillUserSendRenewPasswordCodeCommand extends Command
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @var Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var RecoverPasswordHelper
|
||||
*/
|
||||
protected $recoverPasswordHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
|
||||
/**
|
||||
* The current input interface
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* @var RecoverPasswordHelper
|
||||
*/
|
||||
protected $recoverPasswordHelper;
|
||||
|
||||
/**
|
||||
* The current input interface.
|
||||
*
|
||||
* @var InputInterface
|
||||
*/
|
||||
private $input;
|
||||
|
||||
|
||||
/**
|
||||
* The current output interface
|
||||
* The current output interface.
|
||||
*
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
|
||||
public function __construct(
|
||||
LoggerInterface $logger,
|
||||
EntityManagerInterface $em,
|
||||
RecoverPasswordHelper $recoverPasswordHelper,
|
||||
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
|
||||
@@ -91,113 +95,114 @@ class ChillUserSendRenewPasswordCodeCommand extends Command
|
||||
->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')
|
||||
;
|
||||
->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) {
|
||||
|
||||
foreach ($reader->getRecords() as $offset => $r) {
|
||||
$user = $this->getUser($r);
|
||||
|
||||
if ($user === null) {
|
||||
|
||||
if (null === $user) {
|
||||
$this->onUserNotFound($r, $offset);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$this->sendRecoverCode($user);
|
||||
}
|
||||
}
|
||||
|
||||
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')
|
||||
);
|
||||
}
|
||||
|
||||
protected function onUserNotFound($row, $offset)
|
||||
{
|
||||
$this->logger->alert('User not found', \array_merge([
|
||||
'offset' => $offset
|
||||
], $row));
|
||||
}
|
||||
|
||||
protected function getUser($row)
|
||||
{
|
||||
/* @var $userRepository \Chill\MainBundle\Repository\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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* @return Reader
|
||||
* @throws \Exception
|
||||
*/
|
||||
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')
|
||||
} 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)
|
||||
&& FALSE === \in_array('email', $headers)) {
|
||||
throw new \InvalidArgumentException("The csv file does not have an "
|
||||
. "username or email header");
|
||||
|
||||
if (false === in_array('username', $headers)
|
||||
&& false === in_array('email', $headers)) {
|
||||
throw new InvalidArgumentException('The csv file does not have an '
|
||||
. 'username or email header');
|
||||
}
|
||||
|
||||
|
||||
return $reader;
|
||||
}
|
||||
|
||||
protected function getUser($row)
|
||||
{
|
||||
/* @var $userRepository \Chill\MainBundle\Repository\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')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,69 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
|
||||
/*
|
||||
* Load or update the languages entities command
|
||||
*/
|
||||
class LoadAndUpdateLanguagesCommand extends Command
|
||||
{
|
||||
public const INCLUDE_ANCIENT = 'include_ancient';
|
||||
|
||||
public const INCLUDE_REGIONAL_VERSION = 'include_regional';
|
||||
|
||||
// Array of ancien languages (to exclude)
|
||||
private $ancientToExclude = ['ang', 'egy', 'fro', 'goh', 'grc', 'la', 'non', 'peo', 'pro', 'sga',
|
||||
'dum', 'enm', 'frm', 'gmh', 'mga', 'akk', 'phn', 'zxx', 'got', 'und', ];
|
||||
|
||||
private $availableLanguages;
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
private $availableLanguages;
|
||||
|
||||
|
||||
// The regional version of language are language with _ in the code
|
||||
// This array contains regional code to not exclude
|
||||
private $regionalVersionToInclude = ["ro_MD"];
|
||||
private $regionalVersionToInclude = ['ro_MD'];
|
||||
|
||||
// Array of ancien languages (to exclude)
|
||||
private $ancientToExclude = ["ang", "egy", "fro", "goh", "grc", "la", "non", "peo", "pro", "sga",
|
||||
"dum", "enm", "frm", "gmh", "mga", "akk", "phn", "zxx", "got", "und"];
|
||||
|
||||
const INCLUDE_REGIONAL_VERSION = 'include_regional';
|
||||
const INCLUDE_ANCIENT = 'include_ancient';
|
||||
|
||||
/**
|
||||
* LoadCountriesCommand constructor.
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
* @param $availableLanguages
|
||||
*/
|
||||
public function __construct(EntityManager $entityManager, $availableLanguages)
|
||||
{
|
||||
$this->entityManager=$entityManager;
|
||||
$this->availableLanguages=$availableLanguages;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->availableLanguages = $availableLanguages;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::configure()
|
||||
@@ -72,23 +60,24 @@ class LoadAndUpdateLanguagesCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setName('chill:main:languages:populate')
|
||||
->setDescription('Load or update languages in db. This command does not delete existing '.
|
||||
->setDescription('Load or update languages in db. This command does not delete existing ' .
|
||||
'languages, but will update names according to available languages')
|
||||
->addOption(
|
||||
self::INCLUDE_REGIONAL_VERSION,
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Include the regional languages. The regional languages are languages with code containing _ excepted '
|
||||
. implode(',', $this->regionalVersionToInclude) . '.')
|
||||
self::INCLUDE_REGIONAL_VERSION,
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Include the regional languages. The regional languages are languages with code containing _ excepted '
|
||||
. implode(',', $this->regionalVersionToInclude) . '.'
|
||||
)
|
||||
->addOption(
|
||||
self::INCLUDE_ANCIENT,
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Include the ancient languages that are languages with code '
|
||||
. implode(', ', $this->ancientToExclude) . '.')
|
||||
;
|
||||
self::INCLUDE_ANCIENT,
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Include the ancient languages that are languages with code '
|
||||
. implode(', ', $this->ancientToExclude) . '.'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::execute()
|
||||
@@ -98,7 +87,7 @@ class LoadAndUpdateLanguagesCommand extends Command
|
||||
$em = $this->entityManager;
|
||||
$chillAvailableLanguages = $this->availableLanguages;
|
||||
$languageBundle = Intl::getLanguageBundle();
|
||||
$languages = array();
|
||||
$languages = [];
|
||||
|
||||
foreach ($chillAvailableLanguages as $avLang) {
|
||||
$languages[$avLang] = $languageBundle->getLanguageNames($avLang);
|
||||
@@ -109,25 +98,25 @@ class LoadAndUpdateLanguagesCommand extends Command
|
||||
foreach ($languageCodes as $code) {
|
||||
$excludeCode = (
|
||||
(
|
||||
! $input->getOption(self::INCLUDE_REGIONAL_VERSION)
|
||||
!$input->getOption(self::INCLUDE_REGIONAL_VERSION)
|
||||
and strpos($code, '_')
|
||||
and !in_array($code, $this->regionalVersionToInclude)
|
||||
) or (
|
||||
! $input->getOption(self::INCLUDE_ANCIENT)
|
||||
!$input->getOption(self::INCLUDE_ANCIENT)
|
||||
and in_array($code, $this->ancientToExclude)
|
||||
)
|
||||
);
|
||||
|
||||
$langageDB = $em->getRepository('ChillMainBundle:Language')->find($code);
|
||||
|
||||
if(! $excludeCode) {
|
||||
if (! $langageDB) {
|
||||
if (!$excludeCode) {
|
||||
if (!$langageDB) {
|
||||
$langageDB = new \Chill\MainBundle\Entity\Language();
|
||||
$langageDB->setId($code);
|
||||
$em->persist($langageDB);
|
||||
}
|
||||
|
||||
$avLangNames = array();
|
||||
$avLangNames = [];
|
||||
|
||||
foreach ($chillAvailableLanguages as $avLang) {
|
||||
$avLangNames[$avLang] = $languages[$avLang][$code];
|
||||
@@ -135,10 +124,10 @@ class LoadAndUpdateLanguagesCommand extends Command
|
||||
|
||||
$langageDB->setName($avLangNames);
|
||||
} else {
|
||||
if($langageDB) {
|
||||
if ($langageDB) {
|
||||
$em->remove($langageDB);
|
||||
}
|
||||
echo "Code excluded : ".$code." - ".$languageBundle->getLanguageName($code)."\n";
|
||||
echo 'Code excluded : ' . $code . ' - ' . $languageBundle->getLanguageName($code) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,74 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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 Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Intl\Intl;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop
|
||||
*
|
||||
*/
|
||||
class LoadCountriesCommand extends Command
|
||||
{
|
||||
private $availableLanguages;
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
private $availableLanguages;
|
||||
|
||||
/**
|
||||
* LoadCountriesCommand constructor.
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
* @param $availableLanguages
|
||||
*/
|
||||
public function __construct(EntityManager $entityManager, $availableLanguages)
|
||||
{
|
||||
$this->entityManager=$entityManager;
|
||||
$this->availableLanguages=$availableLanguages;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->availableLanguages = $availableLanguages;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::configure()
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:main:countries:populate')
|
||||
->setDescription('Load or update countries in db. This command does not delete existing countries, '.
|
||||
'but will update names according to available languages');
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::execute()
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$countries = static::prepareCountryList($this->availableLanguages);
|
||||
$em = $this->entityManager;
|
||||
|
||||
foreach($countries as $country) {
|
||||
$countryStored = $em->getRepository('ChillMainBundle:Country')
|
||||
->findOneBy(array('countryCode' => $country->getCountryCode()));
|
||||
|
||||
if (NULL === $countryStored) {
|
||||
$em->persist($country);
|
||||
} else {
|
||||
$countryStored->setName($country->getName());
|
||||
}
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public static function prepareCountryList($languages)
|
||||
{
|
||||
$regionBundle = Intl::getRegionBundle();
|
||||
@@ -78,10 +45,10 @@ class LoadCountriesCommand extends Command
|
||||
$countries[$language] = $regionBundle->getCountryNames($language);
|
||||
}
|
||||
|
||||
$countryEntities = array();
|
||||
$countryEntities = [];
|
||||
|
||||
foreach ($countries[$languages[0]] as $countryCode => $name) {
|
||||
$names = array();
|
||||
$names = [];
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$names[$language] = $countries[$language][$countryCode];
|
||||
@@ -94,4 +61,38 @@ class LoadCountriesCommand extends Command
|
||||
|
||||
return $countryEntities;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::configure()
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:main:countries:populate')
|
||||
->setDescription('Load or update countries in db. This command does not delete existing countries, ' .
|
||||
'but will update names according to available languages');
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::execute()
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$countries = static::prepareCountryList($this->availableLanguages);
|
||||
$em = $this->entityManager;
|
||||
|
||||
foreach ($countries as $country) {
|
||||
$countryStored = $em->getRepository('ChillMainBundle:Country')
|
||||
->findOneBy(['countryCode' => $country->getCountryCode()]);
|
||||
|
||||
if (null === $countryStored) {
|
||||
$em->persist($country);
|
||||
} else {
|
||||
$countryStored->setName($country->getName());
|
||||
}
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
}
|
||||
|
@@ -1,20 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Command;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\Point;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Chill\MainBundle\Entity\PostalCode;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
use RuntimeException;
|
||||
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\Console\Input\InputArgument;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Chill\MainBundle\Entity\PostalCode;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
|
||||
class LoadPostalCodesCommand extends Command
|
||||
@@ -33,38 +41,38 @@ class LoadPostalCodesCommand extends Command
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:main:postal-code:populate')
|
||||
->setDescription("Add the postal code from a csv file.")
|
||||
->setHelp("This script will try to avoid existing postal code "
|
||||
->setDescription('Add the postal code from a csv file.')
|
||||
->setHelp('This script will try to avoid existing postal code '
|
||||
. "using the postal code and name. \n"
|
||||
. "The CSV file must have the following columns: "
|
||||
. "postal code, label, country code."
|
||||
. "Optionally, the csv file can have the following "
|
||||
. "columns after the country code: reference code, latitude, longitude, source. "
|
||||
. "The latitude and longitude columns are supposed to be in WGS84 and expressed in decimal degrees. "
|
||||
. "The CSV file should not have any header row.")
|
||||
->addArgument('csv_file', InputArgument::REQUIRED, "the path to "
|
||||
. "the csv file. See the help for specifications.")
|
||||
->addOption(
|
||||
'delimiter',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"The delimiter character of the csv file",
|
||||
",")
|
||||
->addOption(
|
||||
'enclosure',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"The enclosure character of the csv file",
|
||||
'"'
|
||||
)
|
||||
->addOption(
|
||||
'escape',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
"The escape character of the csv file",
|
||||
"\\"
|
||||
)
|
||||
;
|
||||
. 'The CSV file must have the following columns: '
|
||||
. 'postal code, label, country code.'
|
||||
. 'Optionally, the csv file can have the following '
|
||||
. 'columns after the country code: reference code, latitude, longitude, source. '
|
||||
. 'The latitude and longitude columns are supposed to be in WGS84 and expressed in decimal degrees. '
|
||||
. 'The CSV file should not have any header row.')
|
||||
->addArgument('csv_file', InputArgument::REQUIRED, 'the path to '
|
||||
. 'the csv file. See the help for specifications.')
|
||||
->addOption(
|
||||
'delimiter',
|
||||
'd',
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The delimiter character of the csv file',
|
||||
','
|
||||
)
|
||||
->addOption(
|
||||
'enclosure',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The enclosure character of the csv file',
|
||||
'"'
|
||||
)
|
||||
->addOption(
|
||||
'escape',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'The escape character of the csv file',
|
||||
'\\'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
@@ -79,90 +87,77 @@ class LoadPostalCodesCommand extends Command
|
||||
$num = 0;
|
||||
$line = 0;
|
||||
|
||||
while (($row = fgetcsv(
|
||||
$csv,
|
||||
0,
|
||||
$input->getOption('delimiter'),
|
||||
$input->getOption('enclosure'),
|
||||
$input->getOption('escape'))) !== false) {
|
||||
|
||||
try{
|
||||
while (false !== ($row = fgetcsv(
|
||||
$csv,
|
||||
0,
|
||||
$input->getOption('delimiter'),
|
||||
$input->getOption('enclosure'),
|
||||
$input->getOption('escape')
|
||||
))) {
|
||||
try {
|
||||
$this->addPostalCode($row, $output);
|
||||
$num++;
|
||||
++$num;
|
||||
} catch (ExistingPostalCodeException $ex) {
|
||||
$output->writeln('<warning> on line '.$line.' : '.$ex->getMessage().'</warning>');
|
||||
$output->writeln('<warning> on line ' . $line . ' : ' . $ex->getMessage() . '</warning>');
|
||||
} catch (CountryCodeNotFoundException $ex) {
|
||||
$output->writeln('<warning> on line '.$line.' : '.$ex->getMessage().'</warning>');
|
||||
$output->writeln('<warning> on line ' . $line . ' : ' . $ex->getMessage() . '</warning>');
|
||||
} catch (PostalCodeNotValidException $ex) {
|
||||
$output->writeln('<warning> on line '.$line.' : '.$ex->getMessage().'</warning>');
|
||||
$output->writeln('<warning> on line ' . $line . ' : ' . $ex->getMessage() . '</warning>');
|
||||
}
|
||||
$line ++;
|
||||
++$line;
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$output->writeln('<info>'.$num.' were added !</info>');
|
||||
}
|
||||
|
||||
private function getCSVResource(InputInterface $input)
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
$filename = $input->getArgument('csv_file');
|
||||
|
||||
if (!$fs->exists($filename)) {
|
||||
throw new \RuntimeException("The file does not exists or you do not "
|
||||
. "have the right to read it.");
|
||||
}
|
||||
|
||||
$resource = fopen($filename, 'r');
|
||||
|
||||
if ($resource == FALSE) {
|
||||
throw new \RuntimeException("The file '$filename' could not be opened.");
|
||||
}
|
||||
|
||||
return $resource;
|
||||
$output->writeln('<info>' . $num . ' were added !</info>');
|
||||
}
|
||||
|
||||
private function addPostalCode($row, OutputInterface $output)
|
||||
{
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
|
||||
$output->writeln('handling row: '. $row[0].' | '. $row[1].' | '. $row[2]);
|
||||
$output->writeln('handling row: ' . $row[0] . ' | ' . $row[1] . ' | ' . $row[2]);
|
||||
}
|
||||
$em = $this->entityManager;
|
||||
$country = $em
|
||||
->getRepository(Country::class)
|
||||
->findOneBy(array('countryCode' => $row[2]));
|
||||
->getRepository(Country::class)
|
||||
->findOneBy(['countryCode' => $row[2]]);
|
||||
|
||||
if ($country === NULL) {
|
||||
throw new CountryCodeNotFoundException(sprintf("The country with code %s is not found. Aborting to insert postal code with %s - %s",
|
||||
$row[2], $row[0], $row[1]));
|
||||
if (null === $country) {
|
||||
throw new CountryCodeNotFoundException(sprintf(
|
||||
'The country with code %s is not found. Aborting to insert postal code with %s - %s',
|
||||
$row[2],
|
||||
$row[0],
|
||||
$row[1]
|
||||
));
|
||||
}
|
||||
|
||||
// try to find an existing postal code
|
||||
$existingPC = $em
|
||||
->getRepository(PostalCode::class)
|
||||
->findBy(array('code' => $row[0], 'name' => $row[1]));
|
||||
->getRepository(PostalCode::class)
|
||||
->findBy(['code' => $row[0], 'name' => $row[1]]);
|
||||
|
||||
if (count($existingPC) > 0) {
|
||||
throw new ExistingPostalCodeException(sprintf("A postal code with code : %s and name : %s already exists, skipping",
|
||||
$row[0], $row[1]));
|
||||
throw new ExistingPostalCodeException(sprintf(
|
||||
'A postal code with code : %s and name : %s already exists, skipping',
|
||||
$row[0],
|
||||
$row[1]
|
||||
));
|
||||
}
|
||||
|
||||
$postalCode = (new PostalCode())
|
||||
->setCode($row[0])
|
||||
->setName($row[1])
|
||||
->setCountry($country)
|
||||
;
|
||||
->setCode($row[0])
|
||||
->setName($row[1])
|
||||
->setCountry($country);
|
||||
|
||||
if (NULL != $row[3]){
|
||||
if (null != $row[3]) {
|
||||
$postalCode->setRefPostalCodeId($row[3]);
|
||||
}
|
||||
|
||||
if (NULL != $row[4] & NULL != $row[5]){
|
||||
if (null != $row[4] & null != $row[5]) {
|
||||
$postalCode->setCenter(Point::fromLonLat((float) $row[5], (float) $row[4]));
|
||||
}
|
||||
|
||||
if (NULL != $row[6]){
|
||||
if (null != $row[6]) {
|
||||
$postalCode->setPostalCodeSource($row[6]);
|
||||
}
|
||||
|
||||
@@ -171,35 +166,53 @@ class LoadPostalCodesCommand extends Command
|
||||
if ($errors->count() == 0) {
|
||||
$em->persist($postalCode);
|
||||
} else {
|
||||
$msg = "";
|
||||
$msg = '';
|
||||
|
||||
foreach ($errors as $error) {
|
||||
$msg .= " ".$error->getMessage();
|
||||
$msg .= ' ' . $error->getMessage();
|
||||
}
|
||||
|
||||
throw new PostalCodeNotValidException($msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
|
||||
$output->writeln(sprintf('Creating postal code with code: %s, name: %s, countryCode: %s',
|
||||
$postalCode->getCode(), $postalCode->getName(), $postalCode->getCountry()->getCountryCode()));
|
||||
$output->writeln(sprintf(
|
||||
'Creating postal code with code: %s, name: %s, countryCode: %s',
|
||||
$postalCode->getCode(),
|
||||
$postalCode->getName(),
|
||||
$postalCode->getCountry()->getCountryCode()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function getCSVResource(InputInterface $input)
|
||||
{
|
||||
$fs = new Filesystem();
|
||||
$filename = $input->getArgument('csv_file');
|
||||
|
||||
if (!$fs->exists($filename)) {
|
||||
throw new RuntimeException('The file does not exists or you do not '
|
||||
. 'have the right to read it.');
|
||||
}
|
||||
|
||||
$resource = fopen($filename, 'r');
|
||||
|
||||
if (false == $resource) {
|
||||
throw new RuntimeException("The file '{$filename}' could not be opened.");
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ExistingPostalCodeException extends \Exception
|
||||
class ExistingPostalCodeException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class CountryCodeNotFoundException extends \Exception
|
||||
class CountryCodeNotFoundException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class PostalCodeNotValidException extends \Exception
|
||||
class PostalCodeNotValidException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
@@ -1,101 +1,55 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2014 Champs-Libres Coopérative <info@champs-libres.coop>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* 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 Doctrine\ORM\EntityManager;
|
||||
use LogicException;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
|
||||
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
/**
|
||||
* Class SetPasswordCommand
|
||||
*
|
||||
* @package Chill\MainBundle\Command
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* Class SetPasswordCommand.
|
||||
*/
|
||||
class SetPasswordCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
|
||||
/**
|
||||
* SetPasswordCommand constructor.
|
||||
*
|
||||
* @param EntityManager $entityManager
|
||||
*/
|
||||
public function __construct(EntityManager $entityManager)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function configure()
|
||||
{
|
||||
$this->setName('chill:user:set_password')
|
||||
->setDescription('set a password to user')
|
||||
->addArgument('username', InputArgument::REQUIRED, 'the user\'s '
|
||||
. 'username you want to change password')
|
||||
->addArgument('password', InputArgument::OPTIONAL, 'the new password')
|
||||
;
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$user = $this->_getUser($input->getArgument('username'));
|
||||
|
||||
if ($user === NULL) {
|
||||
throw new \LogicException("The user with username '".
|
||||
$input->getArgument('username')."' is not found");
|
||||
}
|
||||
|
||||
$password = $input->getArgument('password');
|
||||
if ($password === NULL) {
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$password = $dialog->askHiddenResponse($output, "<question>the new password :"
|
||||
. "</question>");
|
||||
}
|
||||
|
||||
$this->_setPassword($user, $password);
|
||||
}
|
||||
|
||||
|
||||
public function _getUser($username)
|
||||
{
|
||||
return $this->entityManager
|
||||
->getRepository('ChillMainBundle:User')
|
||||
->findOneBy(array('username' => $username));
|
||||
->findOneBy(['username' => $username]);
|
||||
}
|
||||
|
||||
|
||||
public function _setPassword(User $user, $password)
|
||||
{
|
||||
$defaultEncoder = new MessageDigestPasswordEncoder('sha512', true, 5000);
|
||||
$encoders = [
|
||||
User::class => $defaultEncoder
|
||||
User::class => $defaultEncoder,
|
||||
];
|
||||
$encoderFactory = new EncoderFactory($encoders);
|
||||
$user->setPassword(
|
||||
@@ -103,4 +57,33 @@ class SetPasswordCommand extends Command
|
||||
);
|
||||
$this->entityManager->flush($user);
|
||||
}
|
||||
|
||||
public function configure()
|
||||
{
|
||||
$this->setName('chill:user:set_password')
|
||||
->setDescription('set a password to user')
|
||||
->addArgument('username', InputArgument::REQUIRED, 'the user\'s '
|
||||
. 'username you want to change password')
|
||||
->addArgument('password', InputArgument::OPTIONAL, 'the new password');
|
||||
}
|
||||
|
||||
public function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$user = $this->_getUser($input->getArgument('username'));
|
||||
|
||||
if (null === $user) {
|
||||
throw new LogicException("The user with username '" .
|
||||
$input->getArgument('username') . "' is not found");
|
||||
}
|
||||
|
||||
$password = $input->getArgument('password');
|
||||
|
||||
if (null === $password) {
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$password = $dialog->askHiddenResponse($output, '<question>the new password :'
|
||||
. '</question>');
|
||||
}
|
||||
|
||||
$this->_setPassword($user, $password);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user