apply rector rules

This commit is contained in:
2025-10-30 01:20:52 +01:00
parent 7a790d43ec
commit 14d65fa931
91 changed files with 306 additions and 571 deletions

View File

@@ -21,7 +21,6 @@ use League\Csv\Reader;
use League\Csv\Writer;
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;
@@ -30,8 +29,10 @@ use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name:'chill:main:import-users')]
class ChillImportUsersCommand extends Command
#[\Symfony\Component\Console\Attribute\AsCommand(name:'chill:main:import-users', help: <<<'TXT'
Import users from a csv file. Users are added to centers contained in the file. Headers are used to detect columns. Adding to multiple centers can be done by using a `grouping centers` file, which will group multiple centers into a signle alias, used in 'centers' column.
TXT)]
class ChillImportUsersCommand
{
protected static $defaultDescription = 'Import users from csv file';
/**
@@ -60,7 +61,6 @@ class ChillImportUsersCommand extends Command
protected ValidatorInterface $validator,
protected UserRepository $userRepository,
) {
parent::__construct('chill:main:import-users');
}
protected function appendUserToFile(User $user)
@@ -84,16 +84,6 @@ class ChillImportUsersCommand extends Command
return \implode(';', $str);
}
protected function configure()
{
$this
->setHelp("Import users from a csv file. Users are added to centers contained in the file. Headers are used to detect columns. Adding to multiple centers can be done by using a `grouping centers` file, which will group multiple centers into a signle alias, used in 'centers' column.")
->addArgument('csvfile', InputArgument::REQUIRED, 'Path to the csv file. Columns are: `username`, `email`, `center` (can contain alias), `permission group`')
->addOption('grouping-centers', null, InputOption::VALUE_OPTIONAL, 'Path to a csv file to aggregate multiple centers into a single alias')
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Do not commit the changes')
->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)) {
@@ -186,12 +176,16 @@ class ChillImportUsersCommand extends Command
return false;
}
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'csvfile', description: 'Path to the csv file. Columns are: `username`, `email`, `center` (can contain alias), `permission group`')]
string $csvfile, #[\Symfony\Component\Console\Attribute\Option(name: 'grouping-centers', mode: InputOption::VALUE_OPTIONAL, description: 'Path to a csv file to aggregate multiple centers into a single alias')]
$groupingCenters, #[\Symfony\Component\Console\Attribute\Option(name: 'dry-run', mode: InputOption::VALUE_NONE, description: 'Do not commit the changes')]
bool $dryRun = false, #[\Symfony\Component\Console\Attribute\Option(name: 'csv-dump', mode: InputOption::VALUE_REQUIRED, description: 'A path to dump a summary of the created file')]
$csvDump, OutputInterface $output): int
{
$this->tempOutput = $output;
$this->tempInput = $input;
if ($input->getOption('dry-run')) {
if ($dry_run) {
$this->doChanges = false;
}

View File

@@ -18,7 +18,6 @@ use Doctrine\ORM\EntityManagerInterface;
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;
@@ -28,7 +27,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
* Class ChillUserSendRenewPasswordCodeCommand.
*/
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:user:send-password-recover-code')]
class ChillUserSendRenewPasswordCodeCommand extends Command
class ChillUserSendRenewPasswordCodeCommand
{
protected static $defaultDescription = 'Send a message with code to recover password';
/**
@@ -77,19 +76,13 @@ class ChillUserSendRenewPasswordCodeCommand extends Command
$this->recoverPasswordHelper = $recoverPasswordHelper;
$this->eventDispatcher = $eventDispatcher;
parent::__construct();
}
protected function configure()
{
$this
->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): int
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'csvfile', description: 'CSV file with the list of users')]
string $csvfile, #[\Symfony\Component\Console\Attribute\Option(name: 'template', mode: InputOption::VALUE_REQUIRED, description: 'Template for email')]
$template, #[\Symfony\Component\Console\Attribute\Option(name: 'expiration', mode: InputOption::VALUE_REQUIRED, description: 'Expiration of the link, as an unix timestamp')]
$expiration, #[\Symfony\Component\Console\Attribute\Option(name: 'subject', mode: InputOption::VALUE_REQUIRED, description: 'Subject of the email')]
string $subject = 'Recover your password', OutputInterface $output): int
{
$this->input = $input;
$this->output = $output;

View File

@@ -14,18 +14,16 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Security\RoleDumper;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'chill:main:dump-list-permissions', description: 'Print a markdown reference of permissions (roles) grouped by title with dependencies).')]
final class DumpListPermissionsCommand extends Command
final class DumpListPermissionsCommand
{
public function __construct(private readonly RoleDumper $roleDumper)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(OutputInterface $output): int
{
$markdown = $this->roleDumper->dumpAsMarkdown();
$output->writeln($markdown);

View File

@@ -14,37 +14,37 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Cron\CronManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name:'chill:cron-job:execute')]
class ExecuteCronJobCommand extends Command
#[\Symfony\Component\Console\Attribute\AsCommand(name:'chill:cron-job:execute', help: <<<'TXT'
If no job is specified, the next available cronjob will be executed by system.
This command should be execute every 15 minutes (more or less)
TXT)]
class ExecuteCronJobCommand
{
protected static $defaultDescription = 'Execute the cronjob(s) given as argument, or one cronjob scheduled by system.';
public function __construct(
private readonly CronManagerInterface $cronManager,
) {
parent::__construct('chill:cron-job:execute');
}
protected function configure()
{
$this
->setHelp("If no job is specified, the next available cronjob will be executed by system.\nThis command should be execute every 15 minutes (more or less)")
->addArgument('job', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'one or more job to force execute (by default, all jobs are executed)', [])
->addUsage('');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ([] === $input->getArgument('job')) {
public function __invoke(
#[\Symfony\Component\Console\Attribute\Argument(name: 'job', description: 'one or more job to force execute (by default, all jobs are executed)')]
array $job = [],
): int {
if ([] === $job) {
$this->cronManager->run();
return Command::SUCCESS;
}
foreach ($input->getArgument('job') as $jobName) {
foreach ($job as $jobName) {
$this->cronManager->run($jobName);
}

View File

@@ -14,13 +14,10 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\Import\AddressReferenceBEFromBestAddress;
use Chill\MainBundle\Service\Import\PostalCodeBEFromBestAddress;
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;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:address-ref-from-best-addresses')]
class LoadAddressesBEFromBestAddressCommand extends Command
class LoadAddressesBEFromBestAddressCommand
{
protected static $defaultDescription = 'Import BE addresses from BeST Address (see https://osoc19.github.io/best/)';
@@ -28,25 +25,21 @@ class LoadAddressesBEFromBestAddressCommand extends Command
private readonly AddressReferenceBEFromBestAddress $addressImporter,
private readonly PostalCodeBEFromBestAddress $postalCodeBEFromBestAddressImporter,
) {
parent::__construct();
}
protected function configure()
{
$this
->addArgument('lang', InputArgument::REQUIRED, "Language code, for example 'fr'")
->addArgument('list', InputArgument::IS_ARRAY, "The list to add, for example 'full', or 'extract' (dev) or '1xxx' (brussel CP)")
->addOption('send-report-email', 's', InputOption::VALUE_REQUIRED, 'Email address where a list of unimported addresses can be send');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
public function __invoke(
#[\Symfony\Component\Console\Attribute\Argument(name: 'lang', description: "Language code, for example 'fr'")]
string $lang,
#[\Symfony\Component\Console\Attribute\Argument(name: 'list', description: "The list to add, for example 'full', or 'extract' (dev) or '1xxx' (brussel CP)")]
array $list,
#[\Symfony\Component\Console\Attribute\Option(name: 'send-report-email', shortcut: 's', mode: InputOption::VALUE_REQUIRED, description: 'Email address where a list of unimported addresses can be send')]
$sendReportEmail,
): int {
$this->postalCodeBEFromBestAddressImporter->import();
$this->addressImporter->import(
$input->getArgument('lang'),
$input->getArgument('list'),
$input->hasOption('send-report-email') ? $input->getOption('send-report-email') : null
$lang,
$list,
$input->hasOption('send-report-email') ? $send_report_email : null
);
return Command::SUCCESS;

View File

@@ -13,35 +13,27 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\Import\AddressReferenceFromBAN;
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;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:address-ref-from-ban')]
class LoadAddressesFRFromBANCommand extends Command
class LoadAddressesFRFromBANCommand
{
protected static $defaultDescription = 'Import FR addresses from BAN (see https://adresses.data.gouv.fr';
public function __construct(private readonly AddressReferenceFromBAN $addressReferenceFromBAN)
{
parent::__construct();
}
protected function configure()
{
$this
->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers')
->addOption('send-report-email', 's', InputOption::VALUE_REQUIRED, 'Email address where a list of unimported addresses can be send');
}
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'departementNo', description: 'a list of departement numbers')]
array $departementno, #[\Symfony\Component\Console\Attribute\Option(name: 'send-report-email', shortcut: 's', mode: InputOption::VALUE_REQUIRED, description: 'Email address where a list of unimported addresses can be send')]
$sendReportEmail, OutputInterface $output): int
{
dump(__METHOD__);
foreach ($input->getArgument('departementNo') as $departementNo) {
foreach ($departementNo as $departementNo) {
$output->writeln('Import addresses for '.$departementNo);
$this->addressReferenceFromBAN->import($departementNo, $input->hasOption('send-report-email') ? $input->getOption('send-report-email') : null);
$this->addressReferenceFromBAN->import($departementNo, $input->hasOption('send-report-email') ? $send_report_email : null);
}
return Command::SUCCESS;

View File

@@ -13,34 +13,26 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\Import\AddressReferenceFromBano;
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;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:address-ref-from-bano')]
class LoadAddressesFRFromBANOCommand extends Command
class LoadAddressesFRFromBANOCommand
{
protected static $defaultDescription = 'Import FR addresses from bano (see https://bano.openstreetmap.fr';
public function __construct(private readonly AddressReferenceFromBano $addressReferenceFromBano)
{
parent::__construct();
}
protected function configure()
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'departementNo', description: 'a list of departement numbers')]
array $departementno, #[\Symfony\Component\Console\Attribute\Option(name: 'send-report-email', shortcut: 's', mode: InputOption::VALUE_REQUIRED, description: 'Email address where a list of unimported addresses can be send')]
$sendReportEmail, OutputInterface $output): int
{
$this
->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers')
->addOption('send-report-email', 's', InputOption::VALUE_REQUIRED, 'Email address where a list of unimported addresses can be send');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
foreach ($input->getArgument('departementNo') as $departementNo) {
foreach ($departementNo as $departementNo) {
$output->writeln('Import addresses for '.$departementNo);
$this->addressReferenceFromBano->import($departementNo, $input->hasOption('send-report-email') ? $input->getOption('send-report-email') : null);
$this->addressReferenceFromBano->import($departementNo, $input->hasOption('send-report-email') ? $send_report_email : null);
}
return Command::SUCCESS;

View File

@@ -13,31 +13,24 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\Import\AddressReferenceLU;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:address-ref-lux')]
class LoadAddressesLUFromBDAddressCommand extends Command
class LoadAddressesLUFromBDAddressCommand
{
protected static $defaultDescription = 'Import LUX addresses from BD addresses (see https://data.public.lu/fr/datasets/adresses-georeferencees-bd-adresses/)';
public function __construct(
private readonly AddressReferenceLU $addressImporter,
) {
parent::__construct();
}
protected function configure()
{
$this
->addOption('send-report-email', 's', InputOption::VALUE_REQUIRED, 'Email address where a list of unimported addresses can be send');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
public function __invoke(
#[\Symfony\Component\Console\Attribute\Option(name: 'send-report-email', shortcut: 's', mode: InputOption::VALUE_REQUIRED, description: 'Email address where a list of unimported addresses can be send')]
$sendReportEmail,
): int {
$this->addressImporter->import(
$input->hasOption('send-report-email') ? $input->getOption('send-report-email') : null,
$input->hasOption('send-report-email') ? $send_report_email : null,
);
return Command::SUCCESS;

View File

@@ -14,9 +14,7 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Entity\Language;
use Doctrine\ORM\EntityManagerInterface;
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\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Intl\Languages;
@@ -24,7 +22,7 @@ use Symfony\Component\Intl\Languages;
* Load or update the languages entities command
*/
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:languages:populate')]
class LoadAndUpdateLanguagesCommand extends Command
class LoadAndUpdateLanguagesCommand
{
final public const INCLUDE_ANCIENT = 'include_ancient';
@@ -43,31 +41,6 @@ class LoadAndUpdateLanguagesCommand extends Command
*/
public function __construct(private readonly EntityManagerInterface $entityManager, private readonly ParameterBagInterface $parameterBag)
{
parent::__construct();
}
/**
* (non-PHPdoc).
*
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure()
{
$this
->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).'.'
)
->addOption(
self::INCLUDE_ANCIENT,
null,
InputOption::VALUE_NONE,
'Include the ancient languages that are languages with code '
.implode(', ', $this->ancientToExclude).'.'
);
}
/**
@@ -75,7 +48,11 @@ class LoadAndUpdateLanguagesCommand extends Command
*
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(
#[\Symfony\Component\Console\Attribute\Option(name: self::INCLUDE_REGIONAL_VERSION, mode: InputOption::VALUE_NONE, description: 'Include the regional languages. The regional languages are languages with code containing')]
bool $includeRegional = false,
#[\Symfony\Component\Console\Attribute\Option(name: self::INCLUDE_ANCIENT, mode: InputOption::VALUE_NONE, description: 'Include the ancient languages that are languages with code ')]
bool $includeAncient = false): int
{
$em = $this->entityManager;
$chillAvailableLanguages = $this->parameterBag->get('chill_main.available_languages');
@@ -88,11 +65,11 @@ class LoadAndUpdateLanguagesCommand extends Command
foreach (Languages::getNames() as $code => $lang) {
$excludeCode = (
(
null === $input->getOption(self::INCLUDE_REGIONAL_VERSION)
null === $include_regional
&& strpos($code, '_')
&& !\in_array($code, $this->regionalVersionToInclude, true)
) || (
null === $input->getOption(self::INCLUDE_ANCIENT)
null === $include_ancient
&& \in_array($code, $this->ancientToExclude, true)
)
);

View File

@@ -14,19 +14,16 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Entity\Country;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Intl\Countries;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:countries:populate')]
class LoadCountriesCommand extends Command
class LoadCountriesCommand
{
/**
* LoadCountriesCommand constructor.
*/
public function __construct(private readonly EntityManager $entityManager, private $availableLanguages)
{
parent::__construct();
}
public static function prepareCountryList($languages)
@@ -49,23 +46,15 @@ class LoadCountriesCommand extends Command
return $countryEntities;
}
/**
* (non-PHPdoc).
*
* @see \Symfony\Component\Console\Command\Command::configure()
*/
protected function configure() {}
/**
* (non-PHPdoc).
*
* @see \Symfony\Component\Console\Command\Command::execute()
*/
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(): int
{
$countries = static::prepareCountryList($this->availableLanguages);
$em = $this->entityManager;
foreach ($countries as $country) {
$countryStored = $em->getRepository(Country::class)
->findOneBy(['countryCode' => $country->getCountryCode()]);
@@ -76,7 +65,6 @@ class LoadCountriesCommand extends Command
$countryStored->setName($country->getName());
}
}
$em->flush();
return Command::SUCCESS;

View File

@@ -13,22 +13,17 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\Import\PostalCodeFRFromOpenData;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:postal-code:load:FR')]
class LoadPostalCodeFR extends Command
class LoadPostalCodeFR
{
protected static $defaultDescription = 'Load France\'s postal code from online open data';
public function __construct(private readonly PostalCodeFRFromOpenData $loader)
{
parent::__construct();
}
public function configure(): void {}
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(): int
{
$this->loader->import();

View File

@@ -16,7 +16,6 @@ use Chill\MainBundle\Entity\Country;
use Chill\MainBundle\Entity\PostalCode;
use Doctrine\ORM\EntityManagerInterface;
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;
@@ -24,58 +23,26 @@ use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Validator\Validator\ValidatorInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:main:postal-code:populate')]
class LoadPostalCodesCommand extends Command
class LoadPostalCodesCommand
{
protected static $defaultDescription = 'Add the postal code from a csv file.';
public function __construct(private readonly EntityManagerInterface $entityManager, private readonly ValidatorInterface $validator)
{
parent::__construct();
}
protected function configure()
{
$this
->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',
'\\'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'csv_file', description: 'the path to '
.'the csv file. See the help for specifications.')]
string $csvFile, #[\Symfony\Component\Console\Attribute\Option(name: 'delimiter', shortcut: 'd', mode: InputOption::VALUE_OPTIONAL, description: 'The delimiter character of the csv file')]
string $delimiter = ',', #[\Symfony\Component\Console\Attribute\Option(name: 'enclosure', mode: InputOption::VALUE_OPTIONAL, description: 'The enclosure character of the csv file')]
string $enclosure = '"', #[\Symfony\Component\Console\Attribute\Option(name: 'escape', mode: InputOption::VALUE_OPTIONAL, description: 'The escape character of the csv file')]
string $escape = '\\', OutputInterface $output): int
{
$csv = $this->getCSVResource($input);
if (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
$output->writeln('The content of the file is ...');
$output->write(file_get_contents($input->getArgument('csv_file')));
$output->write(file_get_contents($csv_file));
}
$num = 0;
@@ -85,9 +52,9 @@ class LoadPostalCodesCommand extends Command
false !== ($row = fgetcsv(
$csv,
0,
$input->getOption('delimiter'),
$input->getOption('enclosure'),
(string) $input->getOption('escape')
$delimiter,
$enclosure,
(string) $escape
))
) {
try {

View File

@@ -14,8 +14,6 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Entity\User;
use Doctrine\ORM\EntityManager;
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\Security\Core\Encoder\EncoderFactory;
@@ -23,7 +21,7 @@ use Symfony\Component\Security\Core\Encoder\EncoderFactory;
* Class SetPasswordCommand.
*/
#[\Symfony\Component\Console\Attribute\AsCommand(name: 'chill:user:set_password')]
class SetPasswordCommand extends Command
class SetPasswordCommand
{
protected static $defaultDescription = 'set a password to user';
@@ -32,7 +30,6 @@ class SetPasswordCommand extends Command
*/
public function __construct(private readonly EntityManager $entityManager)
{
parent::__construct();
}
public function _getUser($username): ?object
@@ -55,23 +52,18 @@ class SetPasswordCommand extends Command
$this->entityManager->flush();
}
public function configure(): void
public function __invoke(#[\Symfony\Component\Console\Attribute\Argument(name: 'username', description: 'the user\'s '
.'username you want to change password')]
string $username, #[\Symfony\Component\Console\Attribute\Argument(name: 'password', description: 'the new password')]
?string $password, OutputInterface $output): int
{
$this
->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): int
{
$user = $this->_getUser($input->getArgument('username'));
$user = $this->_getUser($username);
if (null === $user) {
throw new \LogicException("The user with username '".$input->getArgument('username')."' is not found");
throw new \LogicException("The user with username '".$username."' is not found");
}
$password = $input->getArgument('password');
$password = $password;
if (null === $password) {
$dialog = $this->getHelperSet()->get('dialog');

View File

@@ -13,23 +13,18 @@ namespace Chill\MainBundle\Command;
use Chill\MainBundle\Service\EntityInfo\ViewEntityInfoManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[\Symfony\Component\Console\Attribute\AsCommand(name:'chill:db:sync-views')]
class SynchronizeEntityInfoViewsCommand extends Command
class SynchronizeEntityInfoViewsCommand
{
protected static $defaultDescription = 'Update or create sql views which provide info for various entities';
public function __construct(
private readonly ViewEntityInfoManager $viewEntityInfoManager,
) {
parent::__construct('chill:db:sync-views');
}
protected function configure(): void {}
protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(): int
{
$this->viewEntityInfoManager->synchronizeOnDB();

View File

@@ -243,21 +243,19 @@ final class PasswordController extends AbstractController
->add('username_or_email', TextType::class, [
'label' => 'Username or email',
'constraints' => [
new Callback([
'callback' => function ($pattern, ExecutionContextInterface $context, $payload) {
$qb = $this->managerRegistry->getManager()
->createQueryBuilder();
$qb->select('COUNT(u)')
->from(User::class, 'u')
->where($qb->expr()->eq('u.usernameCanonical', 'UNACCENT(LOWER(:pattern))'))
->orWhere($qb->expr()->eq('u.emailCanonical', 'UNACCENT(LOWER(:pattern))'))
->setParameter('pattern', $pattern);
new Callback(callback: function ($pattern, ExecutionContextInterface $context, $payload) {
$qb = $this->managerRegistry->getManager()
->createQueryBuilder();
$qb->select('COUNT(u)')
->from(User::class, 'u')
->where($qb->expr()->eq('u.usernameCanonical', 'UNACCENT(LOWER(:pattern))'))
->orWhere($qb->expr()->eq('u.emailCanonical', 'UNACCENT(LOWER(:pattern))'))
->setParameter('pattern', $pattern);
if (1 !== (int) $qb->getQuery()->getSingleScalarResult()) {
$context->addViolation('This username or email does not exists');
}
},
]),
if (1 !== (int) $qb->getQuery()->getSingleScalarResult()) {
$context->addViolation('This username or email does not exists');
}
}),
],
])
->add('submit', SubmitType::class, [

View File

@@ -14,24 +14,17 @@ namespace Chill\MainBundle\Doctrine\Event;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Entity\User;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;
use Symfony\Bundle\SecurityBundle\Security;
class TrackCreateUpdateSubscriber implements EventSubscriber
#[\Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener(event: Events::prePersist)]
#[\Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener(event: Events::preUpdate)]
class TrackCreateUpdateSubscriber
{
public function __construct(private readonly Security $security) {}
public function getSubscribedEvents(): array
{
return [
Events::prePersist,
Events::preUpdate,
];
}
public function prePersist(PrePersistEventArgs $args): void
{
$object = $args->getObject();

View File

@@ -60,9 +60,7 @@ class DateIntervalType extends AbstractType
'step' => 1,
],
'constraints' => [
new GreaterThan([
'value' => 0,
]),
new GreaterThan(value: 0),
],
])
->add('unit', ChoiceType::class, [

View File

@@ -58,37 +58,29 @@ class UserPasswordType extends AbstractType
],
'invalid_message' => 'The password fields must match',
'constraints' => [
new Length([
'min' => 14,
'minMessage' => 'The password must be greater than {{ limit }} characters',
]),
new Length(min: 14, minMessage: 'The password must be greater than {{ limit }} characters'),
new NotBlank(),
new Regex([
'pattern' => "/((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\\/{}~=µ\\(\\)£]).{6,})/",
'message' => 'The password must contains one letter, one '
.'capitalized letter, one number and one special character '
."as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed.",
]),
new Regex(pattern: "/((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\\/{}~=µ\\(\\)£]).{6,})/", message: 'The password must contains one letter, one '
.'capitalized letter, one number and one special character '
."as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed."),
],
])
->add('actual_password', PasswordType::class, [
'label' => 'Your actual password',
'mapped' => false,
'constraints' => [
new Callback([
'callback' => function ($password, ExecutionContextInterface $context, $payload) use ($options) {
if (true === $this->passwordEncoder->isPasswordValid($options['user'], $password)) {
return;
}
new Callback(callback: function ($password, ExecutionContextInterface $context, $payload) use ($options) {
if (true === $this->passwordEncoder->isPasswordValid($options['user'], $password)) {
return;
}
// password problem :-)
$this->chillLogger
->notice('incorrect password when trying to change password', [
'username' => $options['user']->getUsername(),
]);
$context->addViolation('Incorrect password');
},
]),
// password problem :-)
$this->chillLogger
->notice('incorrect password when trying to change password', [
'username' => $options['user']->getUsername(),
]);
$context->addViolation('Incorrect password');
}),
],
]);
}

View File

@@ -127,17 +127,11 @@ class UserType extends AbstractType
],
'invalid_message' => 'The password fields must match',
'constraints' => [
new Length([
'min' => 9,
'minMessage' => 'The password must be greater than {{ limit }} characters',
]),
new Length(min: 9, minMessage: 'The password must be greater than {{ limit }} characters'),
new NotBlank(),
new Regex([
'pattern' => "/((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\\/{}~=µ\\(\\)£]).{6,})/",
'message' => 'The password must contains one letter, one '
.'capitalized letter, one number and one special character '
."as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed.",
]),
new Regex(pattern: "/((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\\/{}~=µ\\(\\)£]).{6,})/", message: 'The password must contains one letter, one '
.'capitalized letter, one number and one special character '
."as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed."),
],
]);
} else {

View File

@@ -11,22 +11,13 @@ declare(strict_types=1);
namespace Chill\MainBundle\Phonenumber;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class Templating extends AbstractExtension
class Templating
{
public function __construct(protected PhonenumberHelper $phonenumberHelper) {}
#[\Twig\Attribute\AsTwigFilter('chill_format_phonenumber')]
public function formatPhonenumber($phonenumber)
{
return $this->phonenumberHelper->format($phonenumber) ?? $phonenumber;
}
public function getFilters()
{
return [
new TwigFilter('chill_format_phonenumber', $this->formatPhonenumber(...)),
];
}
}

View File

@@ -20,6 +20,8 @@ use Doctrine\Persistence\ManagerRegistry;
* @method Location|null findOneBy(array $criteria, array $orderBy = null)
* @method Location[] findAll()
* @method Location[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*
* @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\Chill\MainBundle\Entity\Location>
*/
class LocationRepository extends ServiceEntityRepository
{

View File

@@ -20,6 +20,8 @@ use Doctrine\Persistence\ManagerRegistry;
* @method LocationType|null findOneBy(array $criteria, array $orderBy = null)
* @method LocationType[] findAll()
* @method LocationType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*
* @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\Chill\MainBundle\Entity\LocationType>
*/
class LocationTypeRepository extends ServiceEntityRepository
{

View File

@@ -21,6 +21,8 @@ use Doctrine\Persistence\ManagerRegistry;
/**
* @template-extends ServiceEntityRepository<EntityWorkflowStepHold>
*
* @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\Chill\MainBundle\Entity\Workflow\EntityWorkflowStepHold>
*/
class EntityWorkflowStepHoldRepository extends ServiceEntityRepository
{

View File

@@ -18,6 +18,8 @@ use Doctrine\Persistence\ManagerRegistry;
/**
* @template-extends ServiceEntityRepository<EntityWorkflowStepSignature>
*
* @extends \Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository<\Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature>
*/
class EntityWorkflowStepSignatureRepository extends ServiceEntityRepository
{

View File

@@ -42,7 +42,7 @@ class ChillExportVoter extends Voter implements ProvideRoleHierarchyInterface
return $this->helper->supports($attribute, $subject);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
return $this->helper->voteOnAttribute($attribute, $subject, $token);
}

View File

@@ -28,7 +28,7 @@ final class EntityWorkflowAttachmentVoter extends Voter
return $subject instanceof EntityWorkflow && self::EDIT === $attribute;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
if (!$subject instanceof EntityWorkflow) {
throw new \UnexpectedValueException('Subject must be an instance of EntityWorkflow');

View File

@@ -30,7 +30,7 @@ final class EntityWorkflowStepSignatureVoter extends Voter
&& in_array($attribute, [self::SIGN, self::CANCEL, self::REJECT], true);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
/** @var EntityWorkflowStepSignature $subject */
if ($subject->getSigner() instanceof Person) {

View File

@@ -59,7 +59,7 @@ final class EntityWorkflowTransitionVoter extends Voter implements ProvideRoleHi
return self::APPLY_ALL_TRANSITIONS === $attribute && ($subject instanceof EntityWorkflowStep || $subject instanceof EntityWorkflow);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
/** @var EntityWorkflowStep|EntityWorkflow $subject */
$entityWorkflow = $subject instanceof EntityWorkflowStep ? $subject->getEntityWorkflow() : $subject;

View File

@@ -44,7 +44,7 @@ class EntityWorkflowVoter extends Voter
/**
* @param EntityWorkflow $subject
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
switch ($attribute) {
case self::CREATE:

View File

@@ -24,7 +24,7 @@ class ExportGenerationVoter extends Voter
return self::VIEW === $attribute && $subject instanceof ExportGeneration;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
/* @var ExportGeneration $subject */
return $token->getUser()->getUserIdentifier() === $subject->getCreatedBy()->getUserIdentifier();

View File

@@ -42,7 +42,7 @@ final class NotificationVoter extends Voter
/**
* @param string $attribute
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
$user = $token->getUser();

View File

@@ -48,7 +48,7 @@ final class SavedExportVoter extends Voter
return $subject instanceof SavedExport && \in_array($attribute, self::ALL, true);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
/* @var SavedExport $subject */
$user = $token->getUser();

View File

@@ -28,7 +28,7 @@ final class UserGroupVoter extends Voter
return self::APPEND_TO_GROUP === $attribute && $subject instanceof UserGroup;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
/* @var UserGroup $subject */
if ($this->security->isGranted('ROLE_ADMIN')) {

View File

@@ -39,7 +39,7 @@ class WorkflowEntityDeletionVoter extends Voter
return false;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
foreach ($this->handlers as $handler) {
if ($handler->isObjectSupported($subject)) {

View File

@@ -52,7 +52,7 @@ class PasswordRecoverVoter extends Voter
return true;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
protected function voteOnAttribute($attribute, $subject, TokenInterface $token, ?\Symfony\Component\Security\Core\Authorization\Voter\Vote $vote = null): bool
{
switch ($attribute) {
case self::TRY_TOKEN:

View File

@@ -11,21 +11,11 @@ declare(strict_types=1);
namespace Chill\MainBundle\Security\Resolver;
use Twig\TwigFilter;
final class ResolverTwigExtension extends \Twig\Extension\AbstractExtension
final class ResolverTwigExtension
{
public function __construct(private readonly CenterResolverManagerInterface $centerResolverDispatcher, private readonly ScopeResolverDispatcher $scopeResolverDispatcher) {}
public function getFilters()
{
return [
new TwigFilter('chill_resolve_center', $this->resolveCenter(...)),
new TwigFilter('chill_resolve_scope', $this->resolveScope(...)),
new TwigFilter('chill_is_scope_concerned', $this->isScopeConcerned(...)),
];
}
#[\Twig\Attribute\AsTwigFilter('chill_is_scope_concerned')]
public function isScopeConcerned($entity, ?array $options = []): bool
{
return $this->scopeResolverDispatcher->isConcerned($entity, $options);
@@ -34,6 +24,7 @@ final class ResolverTwigExtension extends \Twig\Extension\AbstractExtension
/**
* @return Center|Center[]|null
*/
#[\Twig\Attribute\AsTwigFilter('chill_resolve_center')]
public function resolveCenter(mixed $entity, ?array $options = []): array
{
return $this->centerResolverDispatcher->resolveCenters($entity, $options);
@@ -42,6 +33,7 @@ final class ResolverTwigExtension extends \Twig\Extension\AbstractExtension
/**
* @return array|\Chill\MainBundle\Entity\Scope|\Chill\MainBundle\Entity\Scope[]
*/
#[\Twig\Attribute\AsTwigFilter('chill_resolve_scope')]
public function resolveScope($entity, ?array $options = []): array|\Chill\MainBundle\Entity\Scope
{
return $this->scopeResolverDispatcher->resolveScope();

View File

@@ -13,9 +13,7 @@ namespace Chill\MainBundle\Templating;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Component\HttpFoundation\RequestStack;
use Twig\Extension\AbstractExtension;
use Twig\Node\Node;
use Twig\TwigFilter;
use Twig\TwigFunction;
/**
@@ -23,7 +21,7 @@ use Twig\TwigFunction;
*
* The logic of the function is based on the original routing extension.
*/
class ChillTwigRoutingHelper extends AbstractExtension
class ChillTwigRoutingHelper
{
/**
* @var RoutingExtension
@@ -43,13 +41,6 @@ class ChillTwigRoutingHelper extends AbstractExtension
$this->originalExtension = $originalExtension;
}
public function getFilters()
{
return [
new TwigFilter('chill_return_path_label', $this->getLabelReturnPath(...)),
];
}
public function getFunctions()
{
return [
@@ -82,6 +73,7 @@ class ChillTwigRoutingHelper extends AbstractExtension
return $this->originalExtension->getPath($name, $params, $relative);
}
#[\Twig\Attribute\AsTwigFilter('chill_return_path_label')]
public function getLabelReturnPath($default)
{
$request = $this->requestStack->getCurrentRequest();

View File

@@ -12,31 +12,15 @@ declare(strict_types=1);
namespace Chill\MainBundle\Templating;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\Extension\ExtensionInterface;
class TranslatableStringTwig extends AbstractExtension
class TranslatableStringTwig
{
/**
* TranslatableStringTwig constructor.
*/
public function __construct(private readonly TranslatableStringHelper $helper) {}
/**
* Returns a list of filters to add to the existing list.
*
* (non-PHPdoc)
*
* @see Twig_Extension::getFilters()
*/
public function getFilters()
{
return [
new TwigFilter(
'localize_translatable_string',
$this->localize(...)
), ];
}
/**
* Returns the name of the extension.
*/
@@ -45,6 +29,7 @@ class TranslatableStringTwig extends AbstractExtension
return 'chill_main_localize';
}
#[\Twig\Attribute\AsTwigFilter('localize_translatable_string')]
public function localize(array $translatableStrings): ?string
{
return $this->helper