mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'master' into privacyEvent
This commit is contained in:
commit
cdaf3af2d4
10
CHANGELOG.md
Normal file
10
CHANGELOG.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
Master branch
|
||||||
|
=============
|
||||||
|
|
||||||
|
- Improve import of person to allow multiple centers by file ;
|
||||||
|
- Launch an event on person import ;
|
||||||
|
- Allow person to have a `null` gender ;
|
||||||
|
- Allow filters and aggregator to handle null gender ;
|
||||||
|
- remove inexistant `person.css` file
|
||||||
|
|
@ -29,6 +29,13 @@ use Symfony\Component\Filesystem\Filesystem;
|
|||||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||||
use Symfony\Component\Console\Helper\Table;
|
use Symfony\Component\Console\Helper\Table;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\PostalCode;
|
||||||
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||||
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -67,6 +74,12 @@ class ImportPeopleFromCSVCommand extends ContainerAwareCommand
|
|||||||
*/
|
*/
|
||||||
protected $em;
|
protected $em;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var EventDispatcherInterface
|
||||||
|
*/
|
||||||
|
protected $eventDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the line currently read
|
* the line currently read
|
||||||
*
|
*
|
||||||
@ -80,6 +93,12 @@ class ImportPeopleFromCSVCommand extends ContainerAwareCommand
|
|||||||
*/
|
*/
|
||||||
protected $customFieldMapping = array();
|
protected $customFieldMapping = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var CustomFieldProvider
|
||||||
|
*/
|
||||||
|
protected $customFieldProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains an array of information searched in the file.
|
* Contains an array of information searched in the file.
|
||||||
*
|
*
|
||||||
@ -96,7 +115,11 @@ class ImportPeopleFromCSVCommand extends ContainerAwareCommand
|
|||||||
['opening_date', 'The column header for opening date', 'opening_date'],
|
['opening_date', 'The column header for opening date', 'opening_date'],
|
||||||
['closing_date', 'The column header for closing date', 'closing_date'],
|
['closing_date', 'The column header for closing date', 'closing_date'],
|
||||||
['memo', 'The column header for memo', 'memo'],
|
['memo', 'The column header for memo', 'memo'],
|
||||||
['phonenumber', 'The column header for phonenumber', 'phonenumber']
|
['phonenumber', 'The column header for phonenumber', 'phonenumber'],
|
||||||
|
['street1', 'The column header for street 1', 'street1'],
|
||||||
|
['postalcode', 'The column header for postal code', 'postalcode'],
|
||||||
|
['locality', 'The column header for locality', 'locality'],
|
||||||
|
['center', 'The column header for center', 'center']
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,11 +129,26 @@ class ImportPeopleFromCSVCommand extends ContainerAwareCommand
|
|||||||
*/
|
*/
|
||||||
protected static $defaultDateInterpreter = "%d/%m/%Y|%e/%m/%y|%d/%m/%Y|%e/%m/%Y";
|
protected static $defaultDateInterpreter = "%d/%m/%Y|%e/%m/%y|%d/%m/%Y|%e/%m/%Y";
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
\Psr\Log\LoggerInterface $logger,
|
||||||
|
\Chill\MainBundle\Templating\TranslatableStringHelper $helper,
|
||||||
|
\Doctrine\ORM\EntityManagerInterface $em,
|
||||||
|
CustomFieldProvider $customFieldProvider,
|
||||||
|
EventDispatcherInterface $eventDispatcher
|
||||||
|
) {
|
||||||
|
$this->logger = $logger;
|
||||||
|
$this->helper = $helper;
|
||||||
|
$this->em = $em;
|
||||||
|
$this->customFieldProvider = $customFieldProvider;
|
||||||
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
|
|
||||||
|
parent::__construct('chill:person:import');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this->setName('chill:person:import')
|
$this
|
||||||
->addArgument('csv_file', InputArgument::REQUIRED, "The CSV file to import")
|
->addArgument('csv_file', InputArgument::REQUIRED, "The CSV file to import")
|
||||||
->setDescription("Import people from a csv file")
|
->setDescription("Import people from a csv file")
|
||||||
->setHelp(<<<EOF
|
->setHelp(<<<EOF
|
||||||
@ -118,13 +156,21 @@ Import people from a csv file. The first row must contains the header column and
|
|||||||
|
|
||||||
Date format: the possible date format may be separatedby an |. The possible format will be tryed from the first to the last. The format should be explained as http://php.net/manual/en/function.strftime.php
|
Date format: the possible date format may be separatedby an |. The possible format will be tryed from the first to the last. The format should be explained as http://php.net/manual/en/function.strftime.php
|
||||||
|
|
||||||
php app/console chill:person:import /tmp/hepc.csv fr_FR.utf8 --firstname="Prénom" --lastname="Nom" --birthdate="D.N." --birthdate_format="%d/%m/%Y" --opening_date_format="%B %Y|%Y" --closing_date="der.contact" --closing_date_format="%Y" --custom-field="3=code" -vvv
|
php app/console chill:person:import /tmp/hepc.csv fr_FR.utf8 \
|
||||||
|
--firstname="Prénom" --lastname="Nom" \
|
||||||
|
--birthdate="D.N." --birthdate_format="%d/%m/%Y" \
|
||||||
|
--opening_date_format="%B %Y|%Y" --closing_date="der.contact" \
|
||||||
|
--closing_date_format="%Y" --custom-field="3=code" -vvv
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
->addArgument('locale', InputArgument::REQUIRED,
|
->addArgument('locale', InputArgument::REQUIRED,
|
||||||
"The locale to use in displaying translatable strings from entities")
|
"The locale to use in displaying translatable strings from entities")
|
||||||
->addArgument('center', InputArgument::REQUIRED,
|
->addOption(
|
||||||
"The id of the center")
|
'force-center',
|
||||||
|
null,
|
||||||
|
InputOption::VALUE_REQUIRED,
|
||||||
|
"The id of the center"
|
||||||
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
'force',
|
'force',
|
||||||
null,
|
null,
|
||||||
@ -161,7 +207,7 @@ EOF
|
|||||||
->addOption(
|
->addOption(
|
||||||
'dump-choice-matching',
|
'dump-choice-matching',
|
||||||
null,
|
null,
|
||||||
InputOption::VALUE_OPTIONAL,
|
InputOption::VALUE_REQUIRED,
|
||||||
"The path of the file to dump the matching between label in CSV and answers"
|
"The path of the file to dump the matching between label in CSV and answers"
|
||||||
)
|
)
|
||||||
->addOption(
|
->addOption(
|
||||||
@ -245,9 +291,7 @@ EOF
|
|||||||
|
|
||||||
$cfMappingsOptions = $this->input->getOption('custom-field');
|
$cfMappingsOptions = $this->input->getOption('custom-field');
|
||||||
/* @var $em \Doctrine\Common\Persistence\ObjectManager */
|
/* @var $em \Doctrine\Common\Persistence\ObjectManager */
|
||||||
$em = $this->getContainer()->get('doctrine.orm.entity_manager');
|
$em = $this->em;
|
||||||
/* @var $this->helper \Chill\MainBundle\Templating\TranslatableStringHelper */
|
|
||||||
$this->helper = $this->getContainer()->get('chill.main.helper.translatable_string');
|
|
||||||
|
|
||||||
foreach($cfMappingsOptions as $cfMappingStringOption) {
|
foreach($cfMappingsOptions as $cfMappingStringOption) {
|
||||||
list($rowNumber, $cfSlug) = preg_split('|=|', $cfMappingStringOption);
|
list($rowNumber, $cfSlug) = preg_split('|=|', $cfMappingStringOption);
|
||||||
@ -317,7 +361,7 @@ EOF
|
|||||||
|
|
||||||
protected function dumpAnswerMatching()
|
protected function dumpAnswerMatching()
|
||||||
{
|
{
|
||||||
if ($this->input->hasOption('dump-choice-matching')) {
|
if ($this->input->hasOption('dump-choice-matching') && !empty($this->input->getOption('dump-choice-matching'))) {
|
||||||
$this->logger->debug("Dump the matching between answer and choices");
|
$this->logger->debug("Dump the matching between answer and choices");
|
||||||
$str = json_encode($this->cacheAnswersMapping, JSON_PRETTY_PRINT);
|
$str = json_encode($this->cacheAnswersMapping, JSON_PRETTY_PRINT);
|
||||||
|
|
||||||
@ -330,7 +374,6 @@ EOF
|
|||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$this->logger = new ConsoleLogger($output);
|
|
||||||
$this->input = $input;
|
$this->input = $input;
|
||||||
$this->output = $output;
|
$this->output = $output;
|
||||||
|
|
||||||
@ -356,13 +399,30 @@ EOF
|
|||||||
$this->logger->debug("Processing line ".$this->line);
|
$this->logger->debug("Processing line ".$this->line);
|
||||||
if ($line === 1 ) {
|
if ($line === 1 ) {
|
||||||
$this->logger->debug('Processing line 1, headers');
|
$this->logger->debug('Processing line 1, headers');
|
||||||
|
$rawHeaders = $row;
|
||||||
$headers = $this->processingHeaders($row);
|
$headers = $this->processingHeaders($row);
|
||||||
} else {
|
} else {
|
||||||
$person = $this->createPerson($row, $headers);
|
$person = $this->createPerson($row, $headers);
|
||||||
$this->processingCustomFields($person, $row);
|
|
||||||
|
|
||||||
if ($this->input->getOption('force') === TRUE) {
|
if (count($this->customFieldMapping) > 0) {
|
||||||
|
$this->processingCustomFields($person, $row);
|
||||||
|
}
|
||||||
|
|
||||||
|
$event = new Event();
|
||||||
|
$event->person = $person;
|
||||||
|
$event->rawHeaders = $rawHeaders;
|
||||||
|
$event->row = $row;
|
||||||
|
$event->headers = $headers;
|
||||||
|
$event->skipPerson = false;
|
||||||
|
$event->force = $this->input->getOption('force');
|
||||||
|
$event->input = $this->input;
|
||||||
|
$event->output = $this->output;
|
||||||
|
$event->helperSet = $this->getHelperSet();
|
||||||
|
|
||||||
|
$this->eventDispatcher->dispatch('chill_person.person_import', $event);
|
||||||
|
|
||||||
|
if ($this->input->getOption('force') === TRUE
|
||||||
|
&& $event->skipPerson === false) {
|
||||||
$this->em->persist($person);
|
$this->em->persist($person);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,13 +511,13 @@ EOF
|
|||||||
$openingDate = $this->processDate($openingDateString, $this->input->getOption('opening_date_format'));
|
$openingDate = $this->processDate($openingDateString, $this->input->getOption('opening_date_format'));
|
||||||
|
|
||||||
$person = $openingDate instanceof \DateTime ? new Person($openingDate) : new Person();
|
$person = $openingDate instanceof \DateTime ? new Person($openingDate) : new Person();
|
||||||
|
|
||||||
// currently, import only men
|
|
||||||
$person->setGender(Person::MALE_GENDER);
|
|
||||||
|
|
||||||
// add the center
|
// add the center
|
||||||
$center = $this->em->getRepository('ChillMainBundle:Center')
|
$center = $this->getCenter($row, $headers);
|
||||||
->find($this->input->getArgument('center'));
|
|
||||||
|
if ($center === null) {
|
||||||
|
throw new \Exception("center not found");
|
||||||
|
}
|
||||||
|
|
||||||
$person->setCenter($center);
|
$person->setCenter($center);
|
||||||
|
|
||||||
foreach($headers as $column => $info) {
|
foreach($headers as $column => $info) {
|
||||||
@ -486,12 +546,198 @@ EOF
|
|||||||
case 'phonenumber':
|
case 'phonenumber':
|
||||||
$person->setPhonenumber($value);
|
$person->setPhonenumber($value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// we just keep the column number for those data
|
||||||
|
case 'postalcode':
|
||||||
|
$postalCodeValue = $value;
|
||||||
|
break;
|
||||||
|
case 'street1':
|
||||||
|
$street1Value = $value;
|
||||||
|
break;
|
||||||
|
case 'locality':
|
||||||
|
$localityValue = $value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle address
|
||||||
|
if (\in_array('postalcode', $headers)) {
|
||||||
|
|
||||||
|
$address = new Address();
|
||||||
|
$postalCode = $this->guessPostalCode($postalCodeValue, $localityValue ?? '');
|
||||||
|
|
||||||
|
if ($postalCode === null) {
|
||||||
|
throw new \Exception("The locality is not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setPostcode($postalCode);
|
||||||
|
|
||||||
|
if (\in_array('street1', $headers)) {
|
||||||
|
$address->setStreetAddress1($street1Value);
|
||||||
|
}
|
||||||
|
$address->setValidFrom(new \DateTime('today'));
|
||||||
|
|
||||||
|
$person->addAddress($address);
|
||||||
|
}
|
||||||
|
|
||||||
return $person;
|
return $person;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getCenter($row, $headers)
|
||||||
|
{
|
||||||
|
if ($this->input->hasOption('force-center') && !empty($this->input->getOption('force-center'))) {
|
||||||
|
return $this->em->getRepository('ChillMainBundle:Center')
|
||||||
|
->find($this->input->getOption('force-center'));
|
||||||
|
} else {
|
||||||
|
$columnCenter = \array_search('center', $headers);
|
||||||
|
$centerName = \trim($row[$columnCenter]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return $this->em->createQuery('SELECT c FROM ChillMainBundle:Center c '
|
||||||
|
. 'WHERE c.name = :center_name')
|
||||||
|
->setParameter('center_name', $centerName)
|
||||||
|
->getSingleResult()
|
||||||
|
;
|
||||||
|
} catch (\Doctrine\ORM\NonUniqueResultException $e) {
|
||||||
|
return $this->guessCenter($centerName);
|
||||||
|
} catch (\Doctrine\ORM\NoResultException $e) {
|
||||||
|
return $this->guessCenter($centerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function guessCenter($centerName)
|
||||||
|
{
|
||||||
|
if (!\array_key_exists('_center_picked', $this->cacheAnswersMapping)) {
|
||||||
|
$this->cacheAnswersMapping['_center_picked'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\array_key_exists($centerName, $this->cacheAnswersMapping['_center_picked'])) {
|
||||||
|
$id = $this->cacheAnswersMapping['_center_picked'][$centerName];
|
||||||
|
|
||||||
|
return $this->em->getRepository(Center::class)
|
||||||
|
->find($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$centers = $this->em->createQuery("SELECT c FROM ChillMainBundle:Center c "
|
||||||
|
. "ORDER BY SIMILARITY(c.name, :center_name) DESC")
|
||||||
|
->setParameter('center_name', $centerName)
|
||||||
|
->setMaxResults(10)
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
|
||||||
|
if (count($centers) > 1) {
|
||||||
|
if (\strtolower($centers[0]->getName()) === \strtolower($centerName)) {
|
||||||
|
return $centers[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$centersByName = [];
|
||||||
|
$names = \array_map(function(Center $c) use (&$centersByName) {
|
||||||
|
$n = $c->getName();
|
||||||
|
$centersByName[$n] = $c;
|
||||||
|
return $n;
|
||||||
|
|
||||||
|
}, $centers);
|
||||||
|
$names[] = "none of them";
|
||||||
|
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$question = new ChoiceQuestion(sprintf("Which center match the name \"%s\" ? (default to \"%s\")", $centerName, $names[0]),
|
||||||
|
$names,
|
||||||
|
0);
|
||||||
|
|
||||||
|
$answer = $helper->ask($this->input, $this->output, $question);
|
||||||
|
|
||||||
|
if ($answer === 'none of them') {
|
||||||
|
$questionCreate = new ConfirmationQuestion("Would you like to create it ?", false);
|
||||||
|
$create = $helper->ask($this->input, $this->output, $questionCreate);
|
||||||
|
|
||||||
|
if ($create) {
|
||||||
|
$center = (new Center())
|
||||||
|
->setName($centerName)
|
||||||
|
;
|
||||||
|
|
||||||
|
if ($this->input->getOption('force') === TRUE) {
|
||||||
|
$this->em->persist($center);
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$center = $centersByName[$answer];
|
||||||
|
|
||||||
|
$this->cacheAnswersMapping['_center_picked'][$centerName] = $center->getId();
|
||||||
|
|
||||||
|
return $center;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function guessPostalCode($postalCode, $locality)
|
||||||
|
{
|
||||||
|
if (!\array_key_exists('_postal_code_picked', $this->cacheAnswersMapping)) {
|
||||||
|
$this->cacheAnswersMapping['_postal_code_picked'] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\array_key_exists($postalCode, $this->cacheAnswersMapping['_postal_code_picked'])) {
|
||||||
|
if (\array_key_exists($locality, $this->cacheAnswersMapping['_postal_code_picked'][$postalCode])) {
|
||||||
|
$id = $this->cacheAnswersMapping['_postal_code_picked'][$postalCode][$locality];
|
||||||
|
|
||||||
|
return $this->em->getRepository(PostalCode::class)->find($id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$postalCodes = $this->em->createQuery("SELECT pc FROM ".PostalCode::class." pc "
|
||||||
|
. "WHERE pc.code = :postal_code "
|
||||||
|
. "ORDER BY SIMILARITY(pc.name, :locality) DESC "
|
||||||
|
)
|
||||||
|
->setMaxResults(10)
|
||||||
|
->setParameter('postal_code', $postalCode)
|
||||||
|
->setParameter('locality', $locality)
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
|
||||||
|
if (count($postalCodes) >= 1) {
|
||||||
|
if ($postalCodes[0]->getCode() === $postalCode
|
||||||
|
&& $postalCodes[0]->getName() === $locality) {
|
||||||
|
return $postalCodes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($postalCodes) === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$postalCodeByName = [];
|
||||||
|
$names = \array_map(function(PostalCode $pc) use (&$postalCodeByName) {
|
||||||
|
$n = $pc->getName();
|
||||||
|
$postalCodeByName[$n] = $pc;
|
||||||
|
|
||||||
|
return $n;
|
||||||
|
}, $postalCodes);
|
||||||
|
$names[] = 'none of them';
|
||||||
|
|
||||||
|
$helper = $this->getHelper('question');
|
||||||
|
$question = new ChoiceQuestion(sprintf("Which postal code match the "
|
||||||
|
. "name \"%s\" with postal code \"%s\" ? (default to \"%s\")",
|
||||||
|
$locality, $postalCode, $names[0]),
|
||||||
|
$names,
|
||||||
|
0);
|
||||||
|
|
||||||
|
$answer = $helper->ask($this->input, $this->output, $question);
|
||||||
|
|
||||||
|
if ($answer === 'none of them') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pc = $postalCodeByName[$answer];
|
||||||
|
|
||||||
|
$this->cacheAnswersMapping['_postal_code_picked'][$postalCode][$locality] =
|
||||||
|
$pc->getId();
|
||||||
|
|
||||||
|
return $pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function processBirthdate(Person $person, $value)
|
protected function processBirthdate(Person $person, $value)
|
||||||
{
|
{
|
||||||
@ -556,7 +802,7 @@ EOF
|
|||||||
/* @var $factory \Symfony\Component\Form\FormFactory */
|
/* @var $factory \Symfony\Component\Form\FormFactory */
|
||||||
$factory = $this->getContainer()->get('form.factory');
|
$factory = $this->getContainer()->get('form.factory');
|
||||||
/* @var $cfProvider \Chill\CustomFieldsBundle\Service\CustomFieldProvider */
|
/* @var $cfProvider \Chill\CustomFieldsBundle\Service\CustomFieldProvider */
|
||||||
$cfProvider = $this->getContainer()->get('chill.custom_field.provider');
|
$cfProvider = $this->customFieldProvider;
|
||||||
$cfData = array();
|
$cfData = array();
|
||||||
|
|
||||||
/* @var $$customField \Chill\CustomFieldsBundle\Entity\CustomField */
|
/* @var $$customField \Chill\CustomFieldsBundle\Entity\CustomField */
|
||||||
@ -722,7 +968,7 @@ EOF
|
|||||||
$value));
|
$value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var_dump($this->cacheAnswersMapping[$cf->getSlug()][$value]);
|
|
||||||
$form->submit(array($cf->getSlug() => $this->cacheAnswersMapping[$cf->getSlug()][$value]));
|
$form->submit(array($cf->getSlug() => $this->cacheAnswersMapping[$cf->getSlug()][$value]));
|
||||||
$value = $form->getData()[$cf->getSlug()];
|
$value = $form->getData()[$cf->getSlug()];
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
$loader->load('services/search.yml');
|
$loader->load('services/search.yml');
|
||||||
$loader->load('services/menu.yml');
|
$loader->load('services/menu.yml');
|
||||||
$loader->load('services/privacyEvent.yml');
|
$loader->load('services/privacyEvent.yml');
|
||||||
|
$loader->load('services/command.yml');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
|
private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
|
||||||
|
@ -83,6 +83,10 @@ class GenderAggregator implements AggregatorInterface
|
|||||||
return $this->translator->trans('woman');
|
return $this->translator->trans('woman');
|
||||||
case Person::MALE_GENDER :
|
case Person::MALE_GENDER :
|
||||||
return $this->translator->trans('man');
|
return $this->translator->trans('man');
|
||||||
|
case Person::BOTH_GENDER:
|
||||||
|
return $this->translator->trans('both');
|
||||||
|
case null:
|
||||||
|
return $this->translator->trans('Not given');
|
||||||
case '_header' :
|
case '_header' :
|
||||||
return $this->translator->trans('Gender');
|
return $this->translator->trans('Gender');
|
||||||
default:
|
default:
|
||||||
|
@ -51,17 +51,19 @@ class GenderFilter implements FilterInterface,
|
|||||||
$builder->add('accepted_genders', ChoiceType::class, array(
|
$builder->add('accepted_genders', ChoiceType::class, array(
|
||||||
'choices' => array(
|
'choices' => array(
|
||||||
'Woman' => Person::FEMALE_GENDER,
|
'Woman' => Person::FEMALE_GENDER,
|
||||||
'Man' => Person::MALE_GENDER
|
'Man' => Person::MALE_GENDER,
|
||||||
|
'Both' => Person::BOTH_GENDER,
|
||||||
|
'Not given' => 'null'
|
||||||
),
|
),
|
||||||
'choices_as_values' => true,
|
'choices_as_values' => true,
|
||||||
'multiple' => false,
|
'multiple' => true,
|
||||||
'expanded' => false
|
'expanded' => true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validateForm($data, ExecutionContextInterface $context)
|
public function validateForm($data, ExecutionContextInterface $context)
|
||||||
{
|
{
|
||||||
if ($data['accepted_genders'] === null) {
|
if (!is_array($data['accepted_genders']) || count($data['accepted_genders']) === 0 ) {
|
||||||
$context->buildViolation("You should select an option")
|
$context->buildViolation("You should select an option")
|
||||||
->addViolation();
|
->addViolation();
|
||||||
}
|
}
|
||||||
@ -70,8 +72,13 @@ class GenderFilter implements FilterInterface,
|
|||||||
public function alterQuery(QueryBuilder $qb, $data)
|
public function alterQuery(QueryBuilder $qb, $data)
|
||||||
{
|
{
|
||||||
$where = $qb->getDQLPart('where');
|
$where = $qb->getDQLPart('where');
|
||||||
$clause = $qb->expr()->in('person.gender', ':person_gender');
|
$isIn = $qb->expr()->in('person.gender', ':person_gender');
|
||||||
|
|
||||||
|
if (!\in_array('null', $data['accepted_genders'])) {
|
||||||
|
$clause = $isIn;
|
||||||
|
} else {
|
||||||
|
$clause = $qb->expr()->orX($isIn, $qb->expr()->isNull('person.gender'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($where instanceof Expr\Andx) {
|
if ($where instanceof Expr\Andx) {
|
||||||
$where->add($clause);
|
$where->add($clause);
|
||||||
@ -80,7 +87,11 @@ class GenderFilter implements FilterInterface,
|
|||||||
}
|
}
|
||||||
|
|
||||||
$qb->add('where', $where);
|
$qb->add('where', $where);
|
||||||
$qb->setParameter('person_gender', $data['accepted_genders']);
|
$qb->setParameter('person_gender', \array_filter(
|
||||||
|
$data['accepted_genders'],
|
||||||
|
function($el) {
|
||||||
|
return $el !== 'null';
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,7 @@ Chill\PersonBundle\Entity\Person:
|
|||||||
gender:
|
gender:
|
||||||
type: string
|
type: string
|
||||||
length: 9
|
length: 9
|
||||||
|
nullable: true
|
||||||
memo:
|
memo:
|
||||||
type: text
|
type: text
|
||||||
default: ''
|
default: ''
|
||||||
|
10
Resources/config/services/command.yml
Normal file
10
Resources/config/services/command.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
services:
|
||||||
|
Chill\PersonBundle\Command\ImportPeopleFromCSVCommand:
|
||||||
|
arguments:
|
||||||
|
$logger: '@logger'
|
||||||
|
$helper: '@Chill\MainBundle\Templating\TranslatableStringHelper'
|
||||||
|
$em: '@Doctrine\ORM\EntityManagerInterface'
|
||||||
|
$customFieldProvider: '@Chill\CustomFieldsBundle\Service\CustomFieldProvider'
|
||||||
|
$eventDispatcher: '@Symfony\Component\EventDispatcher\EventDispatcherInterface'
|
||||||
|
tags:
|
||||||
|
- { name: console.command }
|
26
Resources/migrations/Version20181005140249.php
Normal file
26
Resources/migrations/Version20181005140249.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Application\Migrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set person gender not null
|
||||||
|
*/
|
||||||
|
final class Version20181005140249 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function up(Schema $schema) : void
|
||||||
|
{
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE chill_person_person ALTER gender DROP NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema) : void
|
||||||
|
{
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE chill_person_person ALTER gender SET NOT NULL');
|
||||||
|
}
|
||||||
|
}
|
@ -24,13 +24,6 @@
|
|||||||
{% extends "ChillMainBundle::layoutWithVerticalMenu.html.twig" %}
|
{% extends "ChillMainBundle::layoutWithVerticalMenu.html.twig" %}
|
||||||
|
|
||||||
|
|
||||||
{% block css %}
|
|
||||||
{% stylesheets output="css/person.css" filter="cssrewrite"
|
|
||||||
"bundles/chillperson/css/person.css"
|
|
||||||
%}
|
|
||||||
<link rel="stylesheet" href="{{ asset_url }}"/>
|
|
||||||
{% endstylesheets %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block top_banner %}
|
{% block top_banner %}
|
||||||
<div class="grid-12 parent" id="header-person-name" >
|
<div class="grid-12 parent" id="header-person-name" >
|
||||||
|
Loading…
x
Reference in New Issue
Block a user