diff --git a/Export/Aggregator/AgeAggregator.php b/Export/Aggregator/AgeAggregator.php index ba84bfa13..778a841ca 100644 --- a/Export/Aggregator/AgeAggregator.php +++ b/Export/Aggregator/AgeAggregator.php @@ -66,6 +66,10 @@ class AgeAggregator implements AggregatorInterface return "Age"; } + if ($value === NULL) { + return "no data"; + } + return $value; }; } diff --git a/Export/Aggregator/CountryOfBirthAggregator.php b/Export/Aggregator/CountryOfBirthAggregator.php new file mode 100644 index 000000000..43f62c336 --- /dev/null +++ b/Export/Aggregator/CountryOfBirthAggregator.php @@ -0,0 +1,190 @@ + + * + * 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 . + */ + +namespace Chill\PersonBundle\Export\Aggregator; + +use Chill\MainBundle\Export\AggregatorInterface; +use Symfony\Component\Form\FormBuilderInterface; +use Doctrine\ORM\QueryBuilder; +use Doctrine\ORM\EntityRepository; +use Chill\MainBundle\Templating\TranslatableStringHelper; +use Symfony\Component\Translation\TranslatorInterface; +use Chill\MainBundle\Util\CountriesInfo; +use Symfony\Component\Security\Core\Role\Role; +use Chill\PersonBundle\Security\Authorization\PersonVoter; + +/** + * + * + * @author Julien Fastré + */ +class CountryOfBirthAggregator implements AggregatorInterface +{ + /** + * + * @var EntityRepository + */ + protected $countriesRepository; + + /** + * + * @var TranslatableStringHelper + */ + protected $translatableStringHelper; + + /** + * + * @var TranslatorInterface + */ + protected $translator; + + public function __construct(EntityRepository $countriesRepository, + TranslatableStringHelper $translatableStringHelper, + TranslatorInterface $translator) + { + $this->countriesRepository = $countriesRepository; + $this->translatableStringHelper = $translatableStringHelper; + $this->translator = $translator; + } + + public function applyOn() + { + return 'person'; + } + + + public function buildForm(FormBuilderInterface $builder) + { + $builder->add('group_by_level', 'choice', array( + 'choices' => array( + 'Group by continents' => 'continent', + 'Group by country' => 'country' + ), + 'choices_as_values' => true, + 'expanded' => true, + 'multiple' => false + )); + + } + + public function alterQuery(QueryBuilder $qb, $data) + { + // add a clause in select part + if ($data['group_by_level'] === 'country') { + $qb->addSelect('countryOfBirth.countryCode as country_of_birth_aggregator'); + } elseif ($data['group_by_level'] === 'continent') { + $clause = 'CASE ' + . 'WHEN countryOfBirth.countryCode IN(:cob_africa_codes) THEN \'AF\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_asia_codes) THEN \'AS\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_europe_codes) THEN \'EU\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_north_america_codes) THEN \'NA\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_south_america_codes) THEN \'SA\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_oceania_codes) THEN \'OC\' ' + . 'WHEN countryOfBirth.countryCode IN(:cob_antartica_codes) THEN \'AN\' ' + . 'ELSE \'\' ' + . 'END as country_of_birth_aggregator '; + $qb->addSelect($clause); + $params = + array( + 'cob_africa_codes' => CountriesInfo::getCountriesCodeByContinent('AF'), + 'cob_asia_codes' => CountriesInfo::getCountriesCodeByContinent('AS'), + 'cob_europe_codes' => CountriesInfo::getCountriesCodeByContinent('EU'), + 'cob_north_america_codes' => CountriesInfo::getCountriesCodeByContinent('NA'), + 'cob_south_america_codes' => CountriesInfo::getCountriesCodeByContinent('SA'), + 'cob_oceania_codes' => CountriesInfo::getCountriesCodeByContinent('OC'), + 'cob_antartica_codes' => CountriesInfo::getCountriesCodeByContinent('AN') + ); + foreach ($params as $k => $v) { + $qb->setParameter($k, $v); + } + } else { + throw new \LogicException("The group_by_level '".$data['group_by_level'] + ." is not known."); + } + + + $qb->leftJoin('person.countryOfBirth', 'countryOfBirth'); + + // add group by + $groupBy = $qb->getDQLPart('groupBy'); + + if (!empty($groupBy)) { + $qb->addGroupBy('country_of_birth_aggregator'); + } else { + $qb->groupBy('country_of_birth_aggregator'); + } + + } + + public function getTitle() + { + return "Group people by country of birth"; + } + + public function getQueryKeys($data) + { + return array('country_of_birth_aggregator'); + } + + public function addRole() + { + return NULL; + } + + public function getLabels($key, array $values, $data) + { + if ($data['group_by_level'] === 'country') { + $qb = $this->countriesRepository->createQueryBuilder('c'); + + $countries = $qb + ->andWhere($qb->expr()->in('c.countryCode', ':countries')) + ->setParameter('countries', $values) + ->getQuery() + ->getResult(\Doctrine\ORM\Query::HYDRATE_SCALAR); + + // initialize array and add blank key for null values + $labels[''] = $this->translator->trans('without data'); + $labels['_header'] = $this->translator->trans('Nationality'); + foreach($countries as $row) { + $labels[$row['c_countryCode']] = $this->translatableStringHelper->localize($row['c_name']); + } + + + } elseif ($data['group_by_level'] === 'continent') { + + $labels = array( + 'EU' => $this->translator->trans('Europe'), + 'AS' => $this->translator->trans('Asia'), + 'AN' => $this->translator->trans('Antartica'), + 'AF' => $this->translator->trans('Africa'), + 'SA' => $this->translator->trans('South America'), + 'NA' => $this->translator->trans('North America'), + 'OC' => $this->translator->trans('Oceania'), + '' => $this->translator->trans('without data'), + '_header' => $this->translator->trans('Continent') + ); + } + + + return function($value) use ($labels) { + return $labels[$value]; + }; + + } +} diff --git a/Export/Declarations.php b/Export/Declarations.php index 6c0735d18..bbdf3e8e4 100644 --- a/Export/Declarations.php +++ b/Export/Declarations.php @@ -28,4 +28,5 @@ namespace Chill\PersonBundle\Export; abstract class Declarations { CONST PERSON_TYPE = 'person'; + CONST PERSON_IMPLIED_IN = 'person_implied_in'; } diff --git a/Export/Export/CountPerson.php b/Export/Export/CountPerson.php index bb688e030..dda2ce18b 100644 --- a/Export/Export/CountPerson.php +++ b/Export/Export/CountPerson.php @@ -130,7 +130,7 @@ class CountPerson implements ExportInterface public function supportsModifiers() { - return array(Declarations::PERSON_TYPE); + return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN); } } diff --git a/Export/Export/ListPerson.php b/Export/Export/ListPerson.php index 3cc9d3754..597ada954 100644 --- a/Export/Export/ListPerson.php +++ b/Export/Export/ListPerson.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Chill\MainBundle\Templating\TranslatableStringHelper; /** * Render a list of peoples @@ -35,18 +36,27 @@ class ListPerson implements ListInterface */ protected $translator; + /** + * + * @var TranslatableStringHelper + */ + protected $translatableStringHelper; + protected $fields = array( 'id', 'firstName', 'lastName', 'birthdate', - 'placeOfBirth', 'gender', 'memo', 'email', 'phonenumber' + 'placeOfBirth', 'gender', 'memo', 'email', 'phonenumber', + 'countryOfBirth', 'nationality' ); public function __construct( EntityManagerInterface $em, - TranslatorInterface $translator + TranslatorInterface $translator, + TranslatableStringHelper $translatableStringHelper ) { $this->entityManager = $em; $this->translator = $translator; + $this->translatableStringHelper = $translatableStringHelper; } /** @@ -133,7 +143,26 @@ class ListPerson implements ListInterface return $this->translator->trans($value); }; + case 'countryOfBirth': + case 'nationality': + $countryRepository = $this->entityManager + ->getRepository('ChillMainBundle:Country'); + // load all countries in a single query + $countryRepository->findBy(array('countryCode' => $values)); + + return function($value) use ($key, $countryRepository) { + if ($value === '_header') { return \strtolower($key); } + + if ($value === NULL) { + return $this->translator->trans('no data'); + } + + $country = $countryRepository->find($value); + + return $this->translatableStringHelper->localize( + $country->getName()); + }; default: return function($value) use ($key) { if ($value === '_header') { return \strtolower($key); } @@ -202,7 +231,14 @@ class ListPerson implements ListInterface foreach ($this->fields as $f) { if (in_array($f, $data['fields'])) { - $qb->addSelect(sprintf('person.%s as %s', $f, $f)); + switch ($f) { + case 'countryOfBirth': + case 'nationality': + $qb->addSelect(sprintf('IDENTITY(person.%s) as %s', $f, $f)); + break; + default: + $qb->addSelect(sprintf('person.%s as %s', $f, $f)); + } } } @@ -232,6 +268,6 @@ class ListPerson implements ListInterface */ public function supportsModifiers() { - return array(Declarations::PERSON_TYPE); + return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN); } } diff --git a/Resources/config/services/exports.yml b/Resources/config/services/exports.yml index 443ed7c3d..b2fed1274 100644 --- a/Resources/config/services/exports.yml +++ b/Resources/config/services/exports.yml @@ -11,6 +11,7 @@ services: arguments: - "@doctrine.orm.entity_manager" - "@translator" + - "@chill.main.helper.translatable_string" tags: - { name: chill.export, alias: list_person } @@ -40,6 +41,15 @@ services: tags: - { name: chill.export_aggregator, alias: person_nationality_aggregator } + chill.person.export.aggregator_country_of_birth: + class: Chill\PersonBundle\Export\Aggregator\CountryOfBirthAggregator + arguments: + - "@chill.main.countries_repository" + - "@chill.main.helper.translatable_string" + - "@translator" + tags: + - { name: chill.export_aggregator, alias: person_country_of_birth_aggregator } + chill.person.export.aggregator_gender: class: Chill\PersonBundle\Export\Aggregator\GenderAggregator arguments: diff --git a/Tests/Export/Export/ListPersonTest.php b/Tests/Export/Export/ListPersonTest.php index 3416014db..837d0da5f 100644 --- a/Tests/Export/Export/ListPersonTest.php +++ b/Tests/Export/Export/ListPersonTest.php @@ -35,10 +35,6 @@ class ListPersonTest extends AbstractExportTest */ private $export; - protected $fields = array( - 'id', 'firstName', 'lastName', 'birthdate', - 'placeOfBirth', 'gender', 'memo', 'email', 'phonenumber' - ); public function setUp() { @@ -64,7 +60,9 @@ class ListPersonTest extends AbstractExportTest return array( array('fields' => ['id', 'firstName', 'lastName']), array('fields' => ['id', 'birthdate', 'gender', 'memo', 'email', 'phonenumber']), - array('fields' => ['firstName', 'lastName', 'phonenumber']) + array('fields' => ['firstName', 'lastName', 'phonenumber']), + array('fields' => ['id', 'nationality']), + array('fields' => ['id', 'countryOfBirth']) ); }