mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-01 06:26:15 +00:00
Merge remote-tracking branch 'ChillPerson/sf4' into sf4
This commit is contained in:
commit
a4246d4eeb
11
src/Bundle/ChillPerson/.gitignore
vendored
Normal file
11
src/Bundle/ChillPerson/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
composer.lock
|
||||
vendor/*
|
||||
parameters.yml
|
||||
*~
|
||||
*.DS_Store
|
||||
*.sass-cache
|
||||
Resources/node_modules/
|
||||
Tests/Fixtures/App/app/config/parameters.yml
|
||||
/nbproject/private/
|
||||
Resources/test/Fixtures/App/bootstrap.php.cache
|
||||
|
64
src/Bundle/ChillPerson/.gitlab-ci.yml
Normal file
64
src/Bundle/ChillPerson/.gitlab-ci.yml
Normal file
@ -0,0 +1,64 @@
|
||||
.test_definition: &test_definition
|
||||
services:
|
||||
- chill/database:latest
|
||||
before_script:
|
||||
- if [ -z ${GITHUB_TOKEN+x} ]; then composer config github-oauth.github.com $GITHUB_TOKEN; fi
|
||||
- php -d memory_limit=-1 /usr/local/bin/composer install --no-interaction
|
||||
- cp Resources/test/Fixtures/App/app/config/parameters.gitlab-ci.yml Resources/test/Fixtures/App/app/config/parameters.yml
|
||||
- php Resources/test/Fixtures/App/app/console --env=test cache:warmup
|
||||
- php Resources/test/Fixtures/App/app/console doctrine:migrations:migrate --env=test --no-interaction
|
||||
- php Resources/test/Fixtures/App/app/console doctrine:fixtures:load --env=test --no-interaction
|
||||
|
||||
stages:
|
||||
- deploy
|
||||
- test
|
||||
- build-doc
|
||||
- deploy-doc
|
||||
|
||||
test:php-7.2:
|
||||
image: chill/ci-image:php-7.2
|
||||
stage: test
|
||||
<<: *test_definition
|
||||
script: APP_ENV=test php vendor/bin/phpunit
|
||||
|
||||
deploy-packagist:
|
||||
stage: deploy
|
||||
image: chill/ci-image:php-7.2
|
||||
before_script:
|
||||
# test that PACKAGIST USERNAME and PACKAGIST_TOKEN variable are set
|
||||
- if [ -z ${PACKAGIST_USERNAME+x} ]; then echo "Please set PACKAGIST_USERNAME variable"; exit -1; fi
|
||||
- if [ -z ${PACKAGIST_TOKEN+x} ]; then echo "Please set PACKAGIST_TOKEN variable"; exit -1; fi
|
||||
script:
|
||||
- STATUSCODE=$(curl -XPOST -H'content-type:application/json' "https://packagist.org/api/update-package?username=$PACKAGIST_USERNAME&apiToken=$PACKAGIST_TOKEN" -d"{\"repository\":{\"url\":\"$CI_PROJECT_URL.git\"}}" --silent --output /dev/stderr --write-out "%{http_code}")
|
||||
- if [ $STATUSCODE = "202" ]; then exit 0; else exit $STATUSCODE; fi
|
||||
|
||||
# deploy documentation
|
||||
api-doc-build:
|
||||
stage: build-doc
|
||||
environment: api-doc
|
||||
image: chill/ci-image:php-7.2
|
||||
before_script:
|
||||
- mkdir api-doc
|
||||
script: apigen generate --destination api-doc/$CI_BUILD_REF_NAME/$CI_PROJECT_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- "api-doc/"
|
||||
name: api
|
||||
expire_in: '2h'
|
||||
only:
|
||||
- master
|
||||
- tags
|
||||
|
||||
api-doc-deploy:
|
||||
stage: deploy-doc
|
||||
image: pallet/swiftclient:latest
|
||||
before_script:
|
||||
# test that CONTAINER_API variable is set
|
||||
- if [ -z ${CONTAINER_API+x} ]; then echo "Please set CONTAINER_API variable"; exit -1; fi
|
||||
# go to api-doc to have and url with PROJECT/BUILD
|
||||
- cd api-doc
|
||||
# upload, and keep files during 1 year
|
||||
script: "swift upload --header \"X-Delete-After: 31536000\" $CONTAINER_API $CI_BUILD_REF_NAME/$CI_PROJECT_NAME"
|
||||
only:
|
||||
- master
|
||||
- tags
|
143
src/Bundle/ChillPerson/Actions/ActionEvent.php
Normal file
143
src/Bundle/ChillPerson/Actions/ActionEvent.php
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Actions;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Event triggered when an entity attached to a person is removed.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ActionEvent extends Event
|
||||
{
|
||||
const DELETE = 'CHILL_PERSON.DELETE_ASSOCIATED_ENTITY';
|
||||
const MOVE = 'CHILL_PERSON.MOVE_ASSOCIATED_ENTITY';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $personId;
|
||||
|
||||
/**
|
||||
* the FQDN class name as recorded in doctrine
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* an array of key value data to describe the movement
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $metadata;
|
||||
|
||||
/**
|
||||
* the sql statement
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sqlStatement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $preSql = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $postSql = [];
|
||||
|
||||
public function __construct($personId, $entity, $sqlStatement, $metadata = [])
|
||||
{
|
||||
$this->personId = $personId;
|
||||
$this->entity = $entity;
|
||||
$this->sqlStatement = $sqlStatement;
|
||||
$this->metadata = $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPreSql(): array
|
||||
{
|
||||
return $this->preSql;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPostSql(): array
|
||||
{
|
||||
return $this->postSql;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add Sql which will be executed **before** the delete statement
|
||||
*/
|
||||
public function addPreSql(string $preSql)
|
||||
{
|
||||
$this->preSql[] = $preSql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Sql which will be executed **after** the delete statement
|
||||
*
|
||||
* @param type $postSql
|
||||
* @return $this
|
||||
*/
|
||||
public function addPostSql(string $postSql)
|
||||
{
|
||||
$this->postSql[] = $postSql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPersonId(): int
|
||||
{
|
||||
return $this->personId;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the entity name, as recorded in doctrine
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntity(): string
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
public function getSqlStatement()
|
||||
{
|
||||
return $this->sqlStatement;
|
||||
}
|
||||
|
||||
public function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
}
|
184
src/Bundle/ChillPerson/Actions/Remove/PersonMove.php
Normal file
184
src/Bundle/ChillPerson/Actions/Remove/PersonMove.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Actions\Remove;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Chill\PersonBundle\Actions\ActionEvent;
|
||||
|
||||
/**
|
||||
* Move or delete entities associated to a person to a new one, and delete the
|
||||
* old person. The data associated to a person (birthdate, name, ...) are left
|
||||
* untouched on the "new one".
|
||||
*
|
||||
* See `getSql` for details.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PersonMove
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sql used to move or delete entities associated to a person to
|
||||
* a new one, and delete the old person. The data associated to a person
|
||||
* (birthdate, name, ...) are left untouched on the "new one".
|
||||
*
|
||||
* The accompanying periods associated to a person are always removed. The other
|
||||
* associated entity are updated: the new person id is associated to the entity.
|
||||
*
|
||||
* Optionnaly, you can ask for removing entity by passing them in $deleteEntities
|
||||
* parameters.
|
||||
*
|
||||
* The following events are triggered:
|
||||
* - `'CHILL_PERSON.DELETE_ASSOCIATED_ENTITY'` is triggered when an entity
|
||||
* will be removed ;
|
||||
* - `'CHILL_PERSON.MOVE_ASSOCIATED_ENTITY'` is triggered when an entity
|
||||
* will be moved ;
|
||||
*
|
||||
* Those events have the following metadata:
|
||||
*
|
||||
* - 'original_action' : always 'move' ;
|
||||
* - 'to': the person id to move ;
|
||||
*
|
||||
* @param Person $from
|
||||
* @param Person $to
|
||||
* @param array $deleteEntities
|
||||
* @return type
|
||||
*/
|
||||
public function getSQL(Person $from, Person $to, array $deleteEntities = [])
|
||||
{
|
||||
$sqls = [];
|
||||
$toDelete = \array_merge($deleteEntities, $this->getDeleteEntities());
|
||||
|
||||
foreach ($this->em->getMetadataFactory()->getAllMetadata() as $metadata) {
|
||||
if ($metadata->isMappedSuperclass) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($metadata->getAssociationMappings() as $field => $mapping) {
|
||||
if ($mapping['targetEntity'] === Person::class) {
|
||||
|
||||
if (\in_array($metadata->getName(), $toDelete)) {
|
||||
$sql = $this->createDeleteSQL($metadata, $from, $field);
|
||||
$event = new ActionEvent($from->getId(), $metadata->getName(), $sql,
|
||||
['to' => $to->getId(), 'original_action' => 'move']);
|
||||
$this->eventDispatcher->dispatch(ActionEvent::DELETE, $event);
|
||||
|
||||
} else {
|
||||
$sql = $this->createMoveSQL($metadata, $from, $to, $field);
|
||||
$event = new ActionEvent($from->getId(), $metadata->getName(), $sql,
|
||||
['to' => $to->getId(), 'original_action' => 'move']);
|
||||
$this->eventDispatcher->dispatch(ActionEvent::MOVE, $event);
|
||||
}
|
||||
|
||||
$sqls = \array_merge($sqls, $event->getPreSql(), [$event->getSqlStatement()], $event->getPostSql());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$personMetadata = $this->em->getClassMetadata(Person::class);
|
||||
$sqls[] = sprintf("DELETE FROM %s WHERE id = %d",
|
||||
$this->getTableName($personMetadata),
|
||||
$from->getId());
|
||||
|
||||
return $sqls ?? [];
|
||||
}
|
||||
|
||||
protected function createMoveSQL(ClassMetadata $metadata, Person $from, Person $to, $field): string
|
||||
{
|
||||
$mapping = $metadata->getAssociationMapping($field);
|
||||
|
||||
// Set part of the query, aka <here> in "UPDATE table SET <here> "
|
||||
$sets = [];
|
||||
foreach ($mapping["joinColumns"] as $columns) {
|
||||
$sets[] = sprintf("%s = %d", $columns["name"], $to->getId());
|
||||
}
|
||||
|
||||
$conditions = [];
|
||||
foreach ($mapping["joinColumns"] as $columns) {
|
||||
$conditions[] = sprintf("%s = %d", $columns["name"], $from->getId());
|
||||
}
|
||||
|
||||
return \sprintf("UPDATE %s SET %s WHERE %s",
|
||||
$this->getTableName($metadata),
|
||||
\implode(" ", $sets),
|
||||
\implode(" AND ", $conditions)
|
||||
);
|
||||
}
|
||||
|
||||
protected function createDeleteSQL(ClassMetadata $metadata, Person $from, $field): string
|
||||
{
|
||||
$mapping = $metadata->getAssociationMapping($field);
|
||||
|
||||
$conditions = [];
|
||||
foreach ($mapping["joinColumns"] as $columns) {
|
||||
$conditions[] = sprintf("%s = %d", $columns["name"], $from->getId());
|
||||
}
|
||||
|
||||
return \sprintf("DELETE FROM %s WHERE %s",
|
||||
$this->getTableName($metadata),
|
||||
\implode(" AND ", $conditions)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* return an array of classes where entities should be deleted
|
||||
* instead of moved
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDeleteEntities(): array
|
||||
{
|
||||
return [
|
||||
AccompanyingPeriod::class
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* get the full table name with schema if it does exists
|
||||
*/
|
||||
private function getTableName(ClassMetadata $metadata): string
|
||||
{
|
||||
return empty($metadata->getSchemaName()) ?
|
||||
$metadata->getTableName() :
|
||||
$metadata->getSchemaName().".".$metadata->getTableName();
|
||||
}
|
||||
|
||||
}
|
117
src/Bundle/ChillPerson/CHANGELOG.md
Normal file
117
src/Bundle/ChillPerson/CHANGELOG.md
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
Version 1.5.1
|
||||
=============
|
||||
|
||||
- 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
|
||||
- fix bug in accompanying person validation
|
||||
|
||||
Version 1.5.2
|
||||
==============
|
||||
|
||||
- Add an column with fullname canonical (lowercase and unaccent) to persons entity ;
|
||||
- Add a trigram index on fullname canonical ;
|
||||
- Add a "similar person matcher", which allow to detect person with similar names when adding a person ;
|
||||
- Add a research of persons by fuzzy name, returning result with a similarity of 0.15 ;
|
||||
|
||||
Thanks to @matla :-)
|
||||
|
||||
Version 1.5.3
|
||||
=============
|
||||
|
||||
- add filtering on accompanying period
|
||||
- fix problems in gender filter
|
||||
|
||||
Version 1.5.4
|
||||
=============
|
||||
|
||||
- add filenumber in person header
|
||||
|
||||
Version 1.5.5
|
||||
=============
|
||||
|
||||
- Fix bug in accompanying period filter
|
||||
|
||||
Version 1.5.6
|
||||
=============
|
||||
|
||||
- Update address validation
|
||||
- Add command to move person and all data of a person to a new one, and delete the old one.
|
||||
|
||||
Version 1.5.7
|
||||
=============
|
||||
|
||||
- fix error on macro renderPerson / withLink not taken into account
|
||||
- add a link between accompanying person and user
|
||||
- add an icon when the file is opened / closed in result list, and in person rendering macro
|
||||
- improve command to move person and all data: allow to delete some entities during move and add events
|
||||
|
||||
Version 1.5.8
|
||||
=============
|
||||
|
||||
- add search by phonenumber, with a custom SearchInterface
|
||||
|
||||
This can be activated or desactivated by config:
|
||||
|
||||
```
|
||||
chill_person:
|
||||
enabled: true
|
||||
search:
|
||||
enabled: true
|
||||
|
||||
# enable search by phone. 'always' show the result on every result. 'on-domain' will show the result only if the domain is given in the search box. 'never' disable this feature
|
||||
search_by_phone: on-domain # One of "always"; "on-domain"; "never"
|
||||
```
|
||||
- format phonenumber using twilio (if available) ;
|
||||
- add `record_actions` in person search result list: users can click on a little eye to open person page ;
|
||||
- add new fields (email, mobilenumber, gender) into importPeopleFromCSV command
|
||||
- configure asset using a function
|
||||
|
||||
|
||||
Version 1.5.9
|
||||
=============
|
||||
|
||||
- create CRUD
|
||||
- add the ability to add alt names to persons
|
||||
- [UI] set action button bottom of edit form according to crud template
|
||||
- [closing motive] add an hierarchy for closing motives ;
|
||||
- [closing motive] Add an admin section for closing motives ;
|
||||
|
||||
<<<<<<< HEAD
|
||||
Version 1.5.10
|
||||
==============
|
||||
|
||||
- [closing motive] display closing motive in remark
|
||||
|
||||
Version 1.5.11
|
||||
==============
|
||||
|
||||
- Fix versioning constraint to chill main
|
||||
|
||||
Version 1.5.12
|
||||
==============
|
||||
|
||||
- [addresses] add a homeless to person's addresses, and this information into
|
||||
person list
|
||||
|
||||
Version 1.5.13
|
||||
==============
|
||||
|
||||
- [CRUD] add step delete
|
||||
- [CRUD] improve index view in person CRUD
|
||||
- [CRUD] filter by basis on person by default in EntityPersonCRUDController
|
||||
- [CRUD] override relevant part of the main CRUD template
|
||||
- [CRUD] fix redirection on person view: add a `person_id` to every page redirected.
|
||||
|
||||
Version 1.5.14
|
||||
==============
|
||||
|
||||
- [Accompanying period list] Fix period label in list
|
||||
- [Accompanying period list] Fix label of closing motive
|
||||
- [Person details] Add an "empty" statement on place of birth
|
||||
- [Person list] Add a lock/unlock icon instead of open/closed folder in result list;
|
||||
- [Admin closing motive] Remove links to Closing motive View;
|
||||
- [Admin closing motive] Improve icons for active in list of closing motive;
|
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\CRUD\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
/**
|
||||
* Class EntityPersonCRUDController
|
||||
* CRUD Controller for entities attached to a Person
|
||||
*
|
||||
* @package Chill\PersonBundle\CRUD\Controller
|
||||
*/
|
||||
class EntityPersonCRUDController extends CRUDController
|
||||
{
|
||||
/**
|
||||
* Extract the person from the request
|
||||
*
|
||||
* the person parameter will be `person_id` and must be
|
||||
* present in the query
|
||||
*
|
||||
* If the parameter is not set, this method will return null.
|
||||
*
|
||||
* If the person id does not exists, the method will throw a
|
||||
* Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*
|
||||
* @param Request $request
|
||||
* @throws Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the person with given id is not found
|
||||
*/
|
||||
protected function getPerson(Request $request): ?Person
|
||||
{
|
||||
if (FALSE === $request->query->has('person_id')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$person = $this->getDoctrine()
|
||||
->getRepository(Person::class)
|
||||
->find($request->query->getInt('person_id'))
|
||||
;
|
||||
|
||||
if (NULL === $person) {
|
||||
throw $this->createNotFoundException('the person with this id is not found');
|
||||
}
|
||||
|
||||
return $person;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Chill\MainBundle\CRUD\Controller\string|string $action
|
||||
* @param Request $request
|
||||
* @return object
|
||||
*/
|
||||
protected function createEntity($action, Request $request): object
|
||||
{
|
||||
$entity = parent::createEntity($action, $request);
|
||||
|
||||
$person = $this->getPerson($request);
|
||||
|
||||
$entity->setPerson($person);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param mixed $entity
|
||||
* @param Request $request
|
||||
* @param array $defaultTemplateParameters
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function generateTemplateParameter(string $action, $entity, Request $request, array $defaultTemplateParameters = array()): array
|
||||
{
|
||||
$person = $this->getPerson($request);
|
||||
|
||||
if (NULL === $person) {
|
||||
throw new \Exception("the `person_id` parameter is not set in the query. "
|
||||
. "You should set it or override the current method to allow another "
|
||||
. "behaviour: ".__METHOD__);
|
||||
}
|
||||
|
||||
return parent::generateTemplateParameter(
|
||||
$action,
|
||||
$entity,
|
||||
$request,
|
||||
\array_merge([ 'person' => $person ], $defaultTemplateParameters)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param mixed $entity
|
||||
* @param Request $request
|
||||
* @return string
|
||||
*/
|
||||
protected function getTemplateFor($action, $entity, Request $request)
|
||||
{
|
||||
if ($this->hasCustomTemplate($action, $entity, $request)) {
|
||||
return $this->getActionConfig($action)['template'];
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'new':
|
||||
return '@ChillPerson/CRUD/new.html.twig';
|
||||
case 'edit':
|
||||
return '@ChillPerson/CRUD/edit.html.twig';
|
||||
case 'view':
|
||||
return '@ChillPerson/CRUD/view.html.twig';
|
||||
case 'delete':
|
||||
return '@ChillPerson/CRUD/delete.html.twig';
|
||||
case 'index':
|
||||
return '@ChillPerson/CRUD/index.html.twig';
|
||||
default:
|
||||
return parent::getTemplateFor($action, $entity, $request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param mixed $entity
|
||||
* @param \Symfony\Component\Form\FormInterface $form
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
protected function onBeforeRedirectAfterSubmission(string $action, $entity, \Symfony\Component\Form\FormInterface $form, Request $request)
|
||||
{
|
||||
$next = $request->request->get("submit", "save-and-close");
|
||||
|
||||
switch ($next) {
|
||||
case "save-and-close":
|
||||
return $this->redirectToRoute('chill_crud_'.$this->getCrudName().'_index', [
|
||||
'person_id' => $this->getPerson($request)->getId()
|
||||
]);
|
||||
case "save-and-new":
|
||||
return $this->redirectToRoute('chill_crud_'.$this->getCrudName().'_new', [
|
||||
'person_id' => $this->getPerson($request)->getId()
|
||||
]);
|
||||
case "new":
|
||||
return $this->redirectToRoute('chill_crud_'.$this->getCrudName().'_view', [
|
||||
'id' => $entity->getId(),
|
||||
'person_id' => $this->getPerson($request)->getId()
|
||||
]);
|
||||
default:
|
||||
return $this->redirectToRoute('chill_crud_'.$this->getCrudName().'_view', [
|
||||
'id' => $entity->getId(),
|
||||
'person_id' => $this->getPerson($request)->getId()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the base method to add a filtering step to a person.
|
||||
*
|
||||
* @param string $action
|
||||
* @param Request $request
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
protected function buildQueryEntities(string $action, Request $request)
|
||||
{
|
||||
$qb = parent::buildQueryEntities($action, $request);
|
||||
|
||||
return $this->filterQueryEntitiesByPerson($action, $qb, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a where clause to the buildQuery
|
||||
*
|
||||
* @param string $action
|
||||
* @param \Chill\PersonBundle\CRUD\Controller\QueryBuilder $qb
|
||||
* @param Request $request
|
||||
* @return \Chill\PersonBundle\CRUD\Controller\QueryBuilder
|
||||
*/
|
||||
protected function filterQueryEntitiesByPerson(string $action, QueryBuilder $qb, Request $request): QueryBuilder
|
||||
{
|
||||
$qb->andWhere($qb->expr()->eq('e.person', ':person'));
|
||||
$qb->setParameter('person', $this->getPerson($request));
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\CRUD\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Controller for entities attached as one-to-on to a person
|
||||
*
|
||||
*/
|
||||
class OneToOneEntityPersonCRUDController extends CRUDController
|
||||
{
|
||||
protected function getTemplateFor($action, $entity, Request $request)
|
||||
{
|
||||
if (!empty($this->crudConfig[$action]['template'])) {
|
||||
return $this->crudConfig[$action]['template'];
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'new':
|
||||
return '@ChillPerson/CRUD/new.html.twig';
|
||||
case 'edit':
|
||||
return '@ChillPerson/CRUD/edit.html.twig';
|
||||
case 'index':
|
||||
return '@ChillPerson/CRUD/index.html.twig';
|
||||
default:
|
||||
throw new \LogicException("the view for action $action is not "
|
||||
. "defined. You should override ".__METHOD__." to add this "
|
||||
. "action");
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEntity($action, $id, Request $request): ?object
|
||||
{
|
||||
$entity = parent::getEntity($action, $id, $request);
|
||||
|
||||
if (NULL === $entity) {
|
||||
$entity = $this->createEntity($action, $request);
|
||||
$person = $this->getDoctrine()
|
||||
->getManager()
|
||||
->getRepository(Person::class)
|
||||
->find($id);
|
||||
|
||||
$entity->setPerson($person);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
protected function onPreFlush(string $action, $entity, FormInterface $form, Request $request)
|
||||
{
|
||||
$this->getDoctrine()->getManager()->persist($entity);
|
||||
}
|
||||
|
||||
protected function onPostFetchEntity($action, Request $request, $entity): ?Response
|
||||
{
|
||||
if (FALSE === $this->getDoctrine()->getManager()->contains($entity)) {
|
||||
return new RedirectResponse($this->generateRedirectOnCreateRoute($action, $request, $entity));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function generateRedirectOnCreateRoute($action, Request $request, $entity)
|
||||
{
|
||||
throw new BadMethodCallException("not implemtented yet");
|
||||
}
|
||||
|
||||
}
|
21
src/Bundle/ChillPerson/ChillPersonBundle.php
Normal file
21
src/Bundle/ChillPerson/ChillPersonBundle.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\PersonBundle\Widget\PersonListWidgetFactory;
|
||||
use Chill\PersonBundle\DependencyInjection\CompilerPass\AccompanyingPeriodTimelineCompilerPass;
|
||||
|
||||
class ChillPersonBundle extends Bundle
|
||||
{
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->getExtension('chill_main')
|
||||
->addWidgetFactory(new PersonListWidgetFactory());
|
||||
|
||||
$container->addCompilerPass(new AccompanyingPeriodTimelineCompilerPass());
|
||||
}
|
||||
}
|
150
src/Bundle/ChillPerson/Command/ChillPersonMoveCommand.php
Normal file
150
src/Bundle/ChillPerson/Command/ChillPersonMoveCommand.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Command;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
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 Chill\PersonBundle\Actions\Remove\PersonMove;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class ChillPersonMoveCommand extends ContainerAwareCommand
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var PersonMove
|
||||
*/
|
||||
protected $mover;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $em;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $chillLogger;
|
||||
|
||||
public function __construct(
|
||||
PersonMove $mover,
|
||||
EntityManagerInterface $em,
|
||||
LoggerInterface $chillLogger
|
||||
) {
|
||||
parent::__construct('chill:person:move');
|
||||
|
||||
$this->mover = $mover;
|
||||
$this->em = $em;
|
||||
$this->chillLogger = $chillLogger;
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('chill:person:move')
|
||||
->setDescription('Move all the associated entities on a "from" person to a "to" person and remove the old person')
|
||||
->addOption('from', 'f', InputOption::VALUE_REQUIRED, "The person id to delete, all associated data will be moved before")
|
||||
->addOption('to', 't', InputOption::VALUE_REQUIRED, "The person id which will received data")
|
||||
->addOption('dump-sql', null, InputOption::VALUE_NONE, "dump sql to stdout")
|
||||
->addOption('force', null, InputOption::VALUE_NONE, "execute sql instead of dumping it")
|
||||
->addOption('delete-entity', null, InputOption::VALUE_REQUIRED|InputOption::VALUE_IS_ARRAY, "entity to delete", [])
|
||||
;
|
||||
}
|
||||
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if (FALSE === $input->hasOption('dump-sql') && FALSE === $input->hasOption('force')) {
|
||||
$msg = "You must use \"--dump-sql\" or \"--force\"";
|
||||
throw new RuntimeException($msg);
|
||||
}
|
||||
|
||||
foreach (["from", "to"] as $name) {
|
||||
if (empty($input->getOption($name))) {
|
||||
throw new RuntimeException("You must set a \"$name\" option");
|
||||
}
|
||||
$id = $input->getOption($name);
|
||||
if (\ctype_digit($id) === FALSE) {
|
||||
throw new RuntimeException("The id in \"$name\" field does not contains "
|
||||
. "only digits: $id");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$repository = $this->em->getRepository(Person::class);
|
||||
$from = $repository->find($input->getOption('from'));
|
||||
$to = $repository->find($input->getOption('to'));
|
||||
$deleteEntities = $input->getOption('delete-entity');
|
||||
|
||||
if ($from === NULL) {
|
||||
throw new RuntimeException(sprintf("Person \"from\" with id %d not found", $input->getOption('from')));
|
||||
}
|
||||
if ($to === NULL) {
|
||||
throw new RuntimeException(sprintf("Person \"to\" with id %d not found", $input->getOption('to')));
|
||||
}
|
||||
|
||||
$sqls = $this->mover->getSQL($from, $to, $deleteEntities);
|
||||
|
||||
if ($input->getOption('dump-sql')) {
|
||||
foreach($sqls as $sql) {
|
||||
$output->writeln($sql);
|
||||
}
|
||||
} else {
|
||||
$ctxt = $this->buildLoggingContext($from, $to, $deleteEntities, $sqls);
|
||||
$this->chillLogger->notice("Trying to move a person from command line", $ctxt);
|
||||
$connection = $this->em->getConnection();
|
||||
$connection->beginTransaction();
|
||||
foreach($sqls as $sql) {
|
||||
if ($output->isVerbose()) {
|
||||
$output->writeln($sql);
|
||||
}
|
||||
$connection->executeQuery($sql);
|
||||
}
|
||||
$connection->commit();
|
||||
|
||||
$this->chillLogger->notice("Move a person from command line succeeded", $ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildLoggingContext(Person $from, Person $to, $deleteEntities, $sqls)
|
||||
{
|
||||
$ctxt = [
|
||||
'from' => $from->getId(),
|
||||
'to' => $to->getId()
|
||||
];
|
||||
|
||||
foreach ($deleteEntities as $key => $de) {
|
||||
$ctxt['delete_entity_'.$key] = $de;
|
||||
}
|
||||
foreach ($sqls as $key => $sql) {
|
||||
$ctxt['sql_'.$key] = $sql;
|
||||
}
|
||||
|
||||
return $ctxt;
|
||||
}
|
||||
|
||||
}
|
1130
src/Bundle/ChillPerson/Command/ImportPeopleFromCSVCommand.php
Normal file
1130
src/Bundle/ChillPerson/Command/ImportPeopleFromCSVCommand.php
Normal file
File diff suppressed because it is too large
Load Diff
70
src/Bundle/ChillPerson/Config/ConfigPersonAltNamesHelper.php
Normal file
70
src/Bundle/ChillPerson/Config/ConfigPersonAltNamesHelper.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Config;
|
||||
|
||||
|
||||
/**
|
||||
* Give help to interact with the config for alt names
|
||||
*
|
||||
*
|
||||
*/
|
||||
class ConfigPersonAltNamesHelper
|
||||
{
|
||||
/**
|
||||
* the raw config, directly from the container parameter
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $config = [];
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if at least one alt name is configured
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAltNames(): bool
|
||||
{
|
||||
return count($this->config) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the choices as key => values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChoices(): array
|
||||
{
|
||||
$choices = [];
|
||||
foreach ($this->config as $entry) {
|
||||
|
||||
$labels = $entry['labels'];
|
||||
$lang = false;
|
||||
$label = false;
|
||||
$cur = reset($labels);
|
||||
while ($cur) {
|
||||
if (key($labels) === 'lang') {
|
||||
$lang = current($labels);
|
||||
}
|
||||
|
||||
if (key($labels) === 'label') {
|
||||
$label = current($labels);
|
||||
}
|
||||
|
||||
if ($lang !== FALSE && $label !== FALSE) {
|
||||
$choices[$entry['key']][$lang] = $label;
|
||||
$lang = false;
|
||||
$label = false;
|
||||
}
|
||||
$cur = next($labels);
|
||||
}
|
||||
}
|
||||
|
||||
return $choices;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Form\AccompanyingPeriodType;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Class AccompanyingPeriodController
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
*/
|
||||
class AccompanyingPeriodController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* ReportController constructor.
|
||||
*
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @return Response
|
||||
*/
|
||||
public function listAction($person_id){
|
||||
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
$event = new PrivacyEvent($person, array(
|
||||
'element_class' => AccompanyingPeriod::class,
|
||||
'action' => 'list'
|
||||
));
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:list.html.twig',
|
||||
array('accompanying_periods' => $person->getAccompanyingPeriodsOrdered(),
|
||||
'person' => $person));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function createAction($person_id, Request $request)
|
||||
{
|
||||
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
|
||||
'You are not allowed to update this person');
|
||||
|
||||
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime());
|
||||
$accompanyingPeriod->setClosingDate(new \DateTime());
|
||||
|
||||
$person->addAccompanyingPeriod(
|
||||
$accompanyingPeriod);
|
||||
|
||||
$form = $this->createForm(
|
||||
AccompanyingPeriodType::class,
|
||||
$accompanyingPeriod,
|
||||
[
|
||||
'period_action' => 'create',
|
||||
'center' => $person->getCenter()
|
||||
]);
|
||||
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$form->handleRequest($request);
|
||||
$errors = $this->_validatePerson($person);
|
||||
$flashBag = $this->get('session')->getFlashBag();
|
||||
|
||||
if ($form->isValid(array('Default', 'closed'))
|
||||
&& count($errors) === 0) {
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($accompanyingPeriod);
|
||||
$em->flush();
|
||||
$flashBag->add('success',
|
||||
$this->get('translator')->trans(
|
||||
'A period has been created.'));
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_person_accompanying_period_list',
|
||||
array('person_id' => $person->getId())));
|
||||
} else {
|
||||
$flashBag->add('error', $this->get('translator')
|
||||
->trans('Error! Period not created!'));
|
||||
|
||||
foreach($errors as $error) {
|
||||
$flashBag->add('info', $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'person' => $person,
|
||||
'accompanying_period' => $accompanyingPeriod
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @param $period_id
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response|\Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function updateAction($person_id, $period_id, Request $request){
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$accompanyingPeriod = $em->getRepository('ChillPersonBundle:AccompanyingPeriod')
|
||||
->find($period_id);
|
||||
|
||||
if ($accompanyingPeriod === null) {
|
||||
return $this->createNotFoundException("Period with id ".$period_id.
|
||||
" is not found");
|
||||
}
|
||||
|
||||
$person = $accompanyingPeriod->getPerson();
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
|
||||
'You are not allowed to update this person');
|
||||
|
||||
$form = $this->createForm(AccompanyingPeriodType::class,
|
||||
$accompanyingPeriod, array('period_action' => 'update',
|
||||
'center' => $person->getCenter()));
|
||||
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$form->handleRequest($request);
|
||||
$errors = $this->_validatePerson($person);
|
||||
$flashBag = $this->get('session')->getFlashBag();
|
||||
|
||||
if ($form->isValid(array('Default', 'closed'))
|
||||
&& count($errors) === 0) {
|
||||
$em->flush();
|
||||
|
||||
$flashBag->add('success',
|
||||
$this->get('translator')->trans(
|
||||
'An accompanying period has been updated.'));
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_person_accompanying_period_list',
|
||||
array('person_id' => $person->getId())));
|
||||
} else {
|
||||
$flashBag->add('error', $this->get('translator')
|
||||
->trans('Error when updating the period'));
|
||||
|
||||
foreach($errors as $error) {
|
||||
$flashBag->add('info', $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'person' => $person,
|
||||
'accompanying_period' => $accompanyingPeriod
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function closeAction($person_id, Request $request)
|
||||
{
|
||||
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
|
||||
'You are not allowed to update this person');
|
||||
|
||||
if ($person->isOpen() === false) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error', $this->get('translator')
|
||||
->trans('Beware period is closed',
|
||||
array('%name%' => $person->__toString())));
|
||||
|
||||
return $this->redirect(
|
||||
$this->generateUrl('chill_person_accompanying_period_list', array(
|
||||
'person_id' => $person->getId()
|
||||
)));
|
||||
}
|
||||
|
||||
$current = $person->getCurrentAccompanyingPeriod();
|
||||
|
||||
$form = $this->createForm(AccompanyingPeriodType::class, $current, array(
|
||||
'period_action' => 'close',
|
||||
'center' => $person->getCenter()
|
||||
));
|
||||
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()){
|
||||
$person->close($current);
|
||||
$errors = $this->_validatePerson($person);
|
||||
|
||||
if (count($errors) === 0) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('success', $this->get('translator')
|
||||
->trans('An accompanying period has been closed.',
|
||||
array('%name%' => $person->__toString())));
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->redirect(
|
||||
$this->generateUrl('chill_person_accompanying_period_list', array(
|
||||
'person_id' => $person->getId()
|
||||
))
|
||||
);
|
||||
} else {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error', $this->get('translator')
|
||||
->trans('Error! Period not closed!'));
|
||||
|
||||
foreach ($errors as $error) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('info', $error->getMessage());
|
||||
}
|
||||
}
|
||||
} else { //if form is not valid
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error',
|
||||
$this->get('translator')
|
||||
->trans('Pediod closing form is not valid')
|
||||
);
|
||||
|
||||
foreach ($form->getErrors() as $error) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('info', $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig',
|
||||
array(
|
||||
'form' => $form->createView(),
|
||||
'person' => $person,
|
||||
'accompanying_period' => $current
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
|
||||
*/
|
||||
private function _validatePerson(Person $person) {
|
||||
$errors = $this->get('validator')->validate($person, null,
|
||||
array('Default'));
|
||||
$errors_accompanying_period = $this->get('validator')->validate($person, null,
|
||||
array('accompanying_period_consistent'));
|
||||
|
||||
foreach($errors_accompanying_period as $error ) {
|
||||
$errors->add($error);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @param Request $request
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function openAction($person_id, Request $request) {
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::UPDATE, $person,
|
||||
'You are not allowed to update this person');
|
||||
|
||||
//in case the person is already open
|
||||
if ($person->isOpen()) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error', $this->get('translator')
|
||||
->trans('Error! Period %name% is not closed ; it can be open',
|
||||
array('%name%' => $person->__toString())));
|
||||
|
||||
return $this->redirect(
|
||||
$this->generateUrl('chill_person_accompanying_period_list', array(
|
||||
'person_id' => $person->getId()
|
||||
)));
|
||||
}
|
||||
|
||||
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime());
|
||||
|
||||
$form = $this->createForm(AccompanyingPeriodType::class,
|
||||
$accompanyingPeriod, array('period_action' => 'open',
|
||||
'center' => $person->getCenter()));
|
||||
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$person->open($accompanyingPeriod);
|
||||
|
||||
$errors = $this->_validatePerson($person);
|
||||
|
||||
if (count($errors) <= 0) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('success', $this->get('translator')
|
||||
->trans('An accompanying period has been opened.',
|
||||
array('%name%' => $person->__toString())));
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
return $this->redirect(
|
||||
$this->generateUrl('chill_person_accompanying_period_list', array(
|
||||
'person_id' => $person->getId()
|
||||
)));
|
||||
} else {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error', $this->get('translator')
|
||||
->trans('Period not opened'));
|
||||
|
||||
foreach ($errors as $error) {
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('info', $error->getMessage());
|
||||
}
|
||||
}
|
||||
} else { // if errors in forms
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('error', $this->get('translator')
|
||||
->trans('Period not opened : form is invalid'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:form.html.twig',
|
||||
array('form' => $form->createView(),
|
||||
'person' => $person,
|
||||
'accompanying_period' => $accompanyingPeriod));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $person_id
|
||||
* @param $period_id
|
||||
* @param Request $request
|
||||
* @return object|\Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function reOpenAction($person_id, $period_id, Request $request)
|
||||
{
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
$criteria = Criteria::create();
|
||||
$criteria->where($criteria->expr()->eq('id', $period_id));
|
||||
|
||||
/* @var $period AccompanyingPeriod */
|
||||
$period = $person->getAccompanyingPeriods()
|
||||
->matching($criteria)
|
||||
->first();
|
||||
|
||||
if ($period === NULL) {
|
||||
throw $this->createNotFoundException('period not found');
|
||||
}
|
||||
|
||||
$confirm = $request->query->getBoolean('confirm', false);
|
||||
|
||||
if ($confirm === true && $period->canBeReOpened()) {
|
||||
$period->reOpen();
|
||||
|
||||
$this->_validatePerson($person);
|
||||
|
||||
$this->getDoctrine()->getManager()->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans(
|
||||
'The period has been re-opened'));
|
||||
|
||||
return $this->redirectToRoute('chill_person_accompanying_period_list',
|
||||
array('person_id' => $person->getId()));
|
||||
} elseif ($confirm === false && $period->canBeReOpened()) {
|
||||
return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', array(
|
||||
'period' => $period,
|
||||
'person' => $person
|
||||
));
|
||||
} else {
|
||||
return (new Response())
|
||||
->setStatusCode(Response::HTTP_BAD_REQUEST)
|
||||
->setContent("You cannot re-open this period");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $id
|
||||
* @return Person
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the person is not found
|
||||
*/
|
||||
private function _getPerson($id) {
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')->find($id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException('Person not found');
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person,
|
||||
"You are not allowed to see this person");
|
||||
|
||||
return $person;
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||
|
||||
/**
|
||||
* Class AdminClosingMotiveController
|
||||
* Controller for closing motives
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
*/
|
||||
class AdminClosingMotiveController extends CRUDController
|
||||
{
|
||||
|
||||
/**
|
||||
* @param \Chill\MainBundle\CRUD\Controller\string|string $action
|
||||
* @param Request $request
|
||||
* @return object
|
||||
*/
|
||||
protected function createEntity($action, Request $request): object
|
||||
{
|
||||
$entity = parent::createEntity($action, $request);
|
||||
|
||||
if ($request->query->has('parent_id')) {
|
||||
$parentId = $request->query->getInt('parent_id');
|
||||
|
||||
$parent = $this->getDoctrine()->getManager()
|
||||
->getRepository($this->getEntityClass())
|
||||
->find($parentId);
|
||||
|
||||
if (NULL === $parent) {
|
||||
throw $this->createNotFoundException('parent id not found');
|
||||
}
|
||||
|
||||
$entity->setParent($parent);
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $action
|
||||
* @param \Doctrine\ORM\QueryBuilder|mixed $query
|
||||
* @param Request $request
|
||||
* @param PaginatorInterface $paginator
|
||||
* @return \Doctrine\ORM\QueryBuilder|mixed
|
||||
*/
|
||||
protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
|
||||
{
|
||||
/** @var \Doctrine\ORM\QueryBuilder $query */
|
||||
return $query->orderBy('e.ordering', 'ASC');
|
||||
}
|
||||
}
|
31
src/Bundle/ChillPerson/Controller/AdminController.php
Normal file
31
src/Bundle/ChillPerson/Controller/AdminController.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* Class AdminController
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
*/
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @param $_locale
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function indexAction($_locale)
|
||||
{
|
||||
return $this->render('ChillPersonBundle:Admin:layout.html.twig', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function redirectToAdminIndexAction()
|
||||
{
|
||||
return $this->redirectToRoute('chill_main_admin_central');
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
||||
|
||||
/**
|
||||
* Class AdminMaritalStatusController
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
*/
|
||||
class AdminMaritalStatusController extends CRUDController
|
||||
{
|
||||
// for minimal cases, nothing is required here !
|
||||
}
|
316
src/Bundle/ChillPerson/Controller/PersonAddressController.php
Normal file
316
src/Bundle/ChillPerson/Controller/PersonAddressController.php
Normal file
@ -0,0 +1,316 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2016, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\MainBundle\Form\Type\AddressType;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Class PersonAddressController
|
||||
* Controller for addresses associated with person
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class PersonAddressController extends AbstractController
|
||||
{
|
||||
|
||||
public function listAction($person_id)
|
||||
{
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found ");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(
|
||||
'CHILL_PERSON_SEE',
|
||||
$person,
|
||||
"You are not allowed to edit this person."
|
||||
);
|
||||
|
||||
return $this->render('ChillPersonBundle:Address:list.html.twig', array(
|
||||
'person' => $person
|
||||
));
|
||||
}
|
||||
|
||||
public function newAction($person_id)
|
||||
{
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found ");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(
|
||||
'CHILL_PERSON_UPDATE',
|
||||
$person,
|
||||
"You are not allowed to edit this person."
|
||||
);
|
||||
|
||||
$address = new Address();
|
||||
|
||||
$form = $this->createCreateForm($person, $address);
|
||||
|
||||
return $this->render('ChillPersonBundle:Address:new.html.twig', array(
|
||||
'person' => $person,
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
public function createAction($person_id, Request $request)
|
||||
{
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found ");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(
|
||||
'CHILL_PERSON_UPDATE',
|
||||
$person,
|
||||
"You are not allowed to edit this person."
|
||||
);
|
||||
|
||||
$address = new Address();
|
||||
|
||||
$form = $this->createCreateForm($person, $address);
|
||||
$form->handleRequest($request);
|
||||
|
||||
$person->addAddress($address);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$validatePersonErrors = $this->validatePerson($person);
|
||||
|
||||
if (count($validatePersonErrors) !== 0) {
|
||||
foreach ($validatePersonErrors as $error) {
|
||||
$this->addFlash('error', $error->getMessage());
|
||||
}
|
||||
} elseif ($form->isValid()) {
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash(
|
||||
'success',
|
||||
$this->get('translator')->trans('The new address was created successfully')
|
||||
);
|
||||
|
||||
return $this->redirectToRoute('chill_person_address_list', array(
|
||||
'person_id' => $person->getId()
|
||||
));
|
||||
} else {
|
||||
$this->addFlash('error', $this->get('translator')
|
||||
->trans('Error! Address not created!'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:Address:new.html.twig', array(
|
||||
'person' => $person,
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
public function editAction($person_id, $address_id)
|
||||
{
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found ");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(
|
||||
'CHILL_PERSON_UPDATE',
|
||||
$person,
|
||||
"You are not allowed to edit this person."
|
||||
);
|
||||
|
||||
$address = $this->findAddressById($person, $address_id);
|
||||
|
||||
$form = $this->createEditForm($person, $address);
|
||||
|
||||
return $this->render('ChillPersonBundle:Address:edit.html.twig', array(
|
||||
'person' => $person,
|
||||
'address' => $address,
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
public function updateAction($person_id, $address_id, Request $request)
|
||||
{
|
||||
$person = $this->getDoctrine()->getManager()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found ");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(
|
||||
'CHILL_PERSON_UPDATE',
|
||||
$person,
|
||||
"You are not allowed to edit this person."
|
||||
);
|
||||
|
||||
$address = $this->findAddressById($person, $address_id);
|
||||
|
||||
$form = $this->createEditForm($person, $address);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() and $form->isValid()) {
|
||||
$validatePersonErrors = $this->validatePerson($person);
|
||||
|
||||
if (count($validatePersonErrors) !== 0) {
|
||||
foreach ($validatePersonErrors as $error) {
|
||||
$this->addFlash('error', $error->getMessage());
|
||||
}
|
||||
} elseif ($form->isValid()) {
|
||||
$this->getDoctrine()->getManager()
|
||||
->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')->trans(
|
||||
"The address has been successfully updated"
|
||||
));
|
||||
|
||||
return $this->redirectToRoute('chill_person_address_list', array(
|
||||
'person_id' => $person->getId()
|
||||
));
|
||||
} else {
|
||||
$this->addFlash('error', $this->get('translator')
|
||||
->trans('Error when updating the period'));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillPersonBundle:Address:edit.html.twig', array(
|
||||
'person' => $person,
|
||||
'address' => $address,
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
* @param Address $address
|
||||
* @return \Symfony\Component\Form\Form
|
||||
*/
|
||||
protected function createEditForm(Person $person, Address $address)
|
||||
{
|
||||
$form = $this->createForm(AddressType::class, $address, array(
|
||||
'method' => 'POST',
|
||||
'action' => $this->generateUrl('chill_person_address_update', array(
|
||||
'person_id' => $person->getId(),
|
||||
'address_id' => $address->getId()
|
||||
)),
|
||||
'has_no_address' => true
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Submit'
|
||||
));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Person $person
|
||||
* @param Address $address
|
||||
* @return \Symfony\Component\Form\Form
|
||||
*/
|
||||
protected function createCreateForm(Person $person, Address $address)
|
||||
{
|
||||
$form = $this->createForm(AddressType::class, $address, array(
|
||||
'method' => 'POST',
|
||||
'action' => $this->generateUrl('chill_person_address_create', array(
|
||||
'person_id' => $person->getId()
|
||||
)),
|
||||
'has_no_address' => true
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array(
|
||||
'label' => 'Submit'
|
||||
));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Person $person
|
||||
* @param int $address_id
|
||||
* @return Address
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException if the address id does not exists or is not associated with given person
|
||||
*/
|
||||
protected function findAddressById(Person $person, $address_id)
|
||||
{
|
||||
// filtering address
|
||||
$criteria = Criteria::create()
|
||||
->where(Criteria::expr()->eq('id', $address_id))
|
||||
->setMaxResults(1);
|
||||
$addresses = $person->getAddresses()->matching($criteria);
|
||||
|
||||
if (count($addresses) === 0) {
|
||||
throw $this->createNotFoundException("Address with id $address_id "
|
||||
. "matching person $person_id not found ");
|
||||
}
|
||||
|
||||
return $addresses->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Chill\PersonBundle\Entity\Person $person
|
||||
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
|
||||
*/
|
||||
private function validatePerson(Person $person)
|
||||
{
|
||||
$errors = $this->get('validator')
|
||||
->validate($person, null, array('Default'));
|
||||
$errors_addresses_consistent = $this->get('validator')
|
||||
->validate($person, null, array('addresses_consistent'));
|
||||
|
||||
foreach($errors_addresses_consistent as $error) {
|
||||
$errors->add($error);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
416
src/Bundle/ChillPerson/Controller/PersonController.php
Normal file
416
src/Bundle/ChillPerson/Controller/PersonController.php
Normal file
@ -0,0 +1,416 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Form\PersonType;
|
||||
use Chill\PersonBundle\Form\CreationPersonType;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\PersonBundle\Search\SimilarPersonMatcher;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\MainBundle\Search\SearchProvider;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
|
||||
/**
|
||||
* Class PersonController
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
*/
|
||||
class PersonController extends AbstractController
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var SimilarPersonMatcher
|
||||
*/
|
||||
protected $similarPersonMatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var PersonRepository;
|
||||
*/
|
||||
protected $personRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ConfigPersonAltNamesHelper
|
||||
*/
|
||||
protected $configPersonAltNameHelper;
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(
|
||||
SimilarPersonMatcher $similarPersonMatcher,
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
PersonRepository $personRepository,
|
||||
ConfigPersonAltNamesHelper $configPersonAltNameHelper,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->similarPersonMatcher = $similarPersonMatcher;
|
||||
$this->translator = $translator;
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->configPersonAltNameHelper = $configPersonAltNameHelper;
|
||||
$this->personRepository = $personRepository;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function getCFGroup()
|
||||
{
|
||||
$cFGroup = null;
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$cFDefaultGroup = $em->getRepository("ChillCustomFieldsBundle:CustomFieldsDefaultGroup")
|
||||
->findOneByEntity("Chill\PersonBundle\Entity\Person");
|
||||
|
||||
if($cFDefaultGroup) {
|
||||
$cFGroup = $cFDefaultGroup->getCustomFieldsGroup();
|
||||
}
|
||||
|
||||
return $cFGroup;
|
||||
}
|
||||
|
||||
public function viewAction($person_id)
|
||||
{
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
throw $this->createNotFoundException("Person with id $person_id not"
|
||||
. " found on this server");
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person,
|
||||
"You are not allowed to see this person.");
|
||||
|
||||
$event = new PrivacyEvent($person);
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:view.html.twig',
|
||||
array(
|
||||
"person" => $person,
|
||||
"cFGroup" => $this->getCFGroup(),
|
||||
"alt_names" => $this->configPersonAltNameHelper->getChoices(),
|
||||
));
|
||||
}
|
||||
|
||||
public function editAction($person_id)
|
||||
{
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
return $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_UPDATE', $person,
|
||||
'You are not allowed to edit this person');
|
||||
|
||||
$form = $this->createForm(PersonType::class, $person,
|
||||
array(
|
||||
"action" => $this->generateUrl('chill_person_general_update',
|
||||
array("person_id" => $person_id)),
|
||||
"cFGroup" => $this->getCFGroup()
|
||||
)
|
||||
);
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:edit.html.twig',
|
||||
array('person' => $person, 'form' => $form->createView()));
|
||||
}
|
||||
|
||||
public function updateAction($person_id, Request $request)
|
||||
{
|
||||
$person = $this->_getPerson($person_id);
|
||||
|
||||
if ($person === null) {
|
||||
return $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_UPDATE', $person,
|
||||
'You are not allowed to edit this person');
|
||||
|
||||
$form = $this->createForm(PersonType::class, $person,
|
||||
array("cFGroup" => $this->getCFGroup()));
|
||||
|
||||
if ($request->getMethod() === 'POST') {
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ( ! $form->isValid() ) {
|
||||
$this->get('session')
|
||||
->getFlashBag()->add('error', $this->translator
|
||||
->trans('This form contains errors'));
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:edit.html.twig',
|
||||
array('person' => $person,
|
||||
'form' => $form->createView()));
|
||||
}
|
||||
|
||||
$this->get('session')->getFlashBag()
|
||||
->add('success',
|
||||
$this->get('translator')
|
||||
->trans('The person data has been updated')
|
||||
);
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->flush();
|
||||
|
||||
$url = $this->generateUrl('chill_person_view', array(
|
||||
'person_id' => $person->getId()
|
||||
));
|
||||
|
||||
return $this->redirect($url);
|
||||
}
|
||||
}
|
||||
|
||||
public function newAction()
|
||||
{
|
||||
// this is a dummy default center.
|
||||
$defaultCenter = $this->get('security.token_storage')
|
||||
->getToken()
|
||||
->getUser()
|
||||
->getGroupCenters()[0]
|
||||
->getCenter();
|
||||
|
||||
$person = (new Person(new \DateTime('now')))
|
||||
->setCenter($defaultCenter);
|
||||
|
||||
$form = $this->createForm(
|
||||
CreationPersonType::class,
|
||||
$person,
|
||||
array(
|
||||
'action' => $this->generateUrl('chill_person_review'),
|
||||
'form_status' => CreationPersonType::FORM_NOT_REVIEWED
|
||||
));
|
||||
|
||||
return $this->_renderNewForm($form);
|
||||
}
|
||||
|
||||
private function _renderNewForm($form)
|
||||
{
|
||||
return $this->render('ChillPersonBundle:Person:create.html.twig',
|
||||
array(
|
||||
'form' => $form->createView()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $form
|
||||
* @return \Chill\PersonBundle\Entity\Person
|
||||
*/
|
||||
private function _bindCreationForm($form)
|
||||
{
|
||||
/**
|
||||
* @var Person
|
||||
*/
|
||||
$person = $form->getData();
|
||||
|
||||
$periods = $person->getAccompanyingPeriodsOrdered();
|
||||
$period = $periods[0];
|
||||
$period->setOpeningDate($form['creation_date']->getData());
|
||||
// $person = new Person($form['creation_date']->getData());
|
||||
//
|
||||
// $person->setFirstName($form['firstName']->getData())
|
||||
// ->setLastName($form['lastName']->getData())
|
||||
// ->setGender($form['gender']->getData())
|
||||
// ->setBirthdate($form['birthdate']->getData())
|
||||
// ->setCenter($form['center']->getData())
|
||||
// ;
|
||||
|
||||
return $person;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Chill\PersonBundle\Entity\Person $person
|
||||
* @return \Symfony\Component\Validator\ConstraintViolationListInterface
|
||||
*/
|
||||
private function _validatePersonAndAccompanyingPeriod(Person $person)
|
||||
{
|
||||
$errors = $this->get('validator')
|
||||
->validate($person, null, array('creation'));
|
||||
|
||||
//validate accompanying periods
|
||||
$periods = $person->getAccompanyingPeriods();
|
||||
|
||||
foreach ($periods as $period) {
|
||||
$period_errors = $this->get('validator')
|
||||
->validate($period);
|
||||
|
||||
//group errors :
|
||||
foreach($period_errors as $error) {
|
||||
$errors->add($error);
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function reviewAction(Request $request)
|
||||
{
|
||||
if ($request->getMethod() !== 'POST') {
|
||||
$r = new Response("You must send something to review the creation of a new Person");
|
||||
$r->setStatusCode(400);
|
||||
return $r;
|
||||
}
|
||||
|
||||
$form = $this->createForm(
|
||||
//CreationPersonType::NAME,
|
||||
CreationPersonType::class,
|
||||
new Person(),
|
||||
array(
|
||||
'action' => $this->generateUrl('chill_person_create'),
|
||||
'form_status' => CreationPersonType::FORM_BEING_REVIEWED
|
||||
));
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
$person = $this->_bindCreationForm($form);
|
||||
|
||||
$errors = $this->_validatePersonAndAccompanyingPeriod($person);
|
||||
$this->logger->info(sprintf('Person created with %d errors ', count($errors)));
|
||||
|
||||
if ($errors->count() > 0) {
|
||||
$this->logger->info('The created person has errors');
|
||||
$flashBag = $this->get('session')->getFlashBag();
|
||||
$translator = $this->get('translator');
|
||||
|
||||
$flashBag->add('error', $translator->trans('The person data are not valid'));
|
||||
|
||||
foreach($errors as $error) {
|
||||
$flashBag->add('info', $error->getMessage());
|
||||
}
|
||||
|
||||
$form = $this->createForm(
|
||||
CreationPersonType::NAME,
|
||||
$person,
|
||||
array(
|
||||
'action' => $this->generateUrl('chill_person_review'),
|
||||
'form_status' => CreationPersonType::FORM_NOT_REVIEWED
|
||||
));
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
return $this->_renderNewForm($form);
|
||||
} else {
|
||||
$this->logger->info('Person created without errors');
|
||||
}
|
||||
|
||||
$alternatePersons = $this->similarPersonMatcher
|
||||
->matchPerson($person);
|
||||
|
||||
if (count($alternatePersons) === 0) {
|
||||
return $this->forward('ChillPersonBundle:Person:create');
|
||||
}
|
||||
|
||||
$this->get('session')->getFlashBag()->add('info',
|
||||
$this->get('translator')->trans(
|
||||
'%nb% person with similar name. Please verify that this is a new person',
|
||||
array('%nb%' => count($alternatePersons)))
|
||||
);
|
||||
|
||||
return $this->render('ChillPersonBundle:Person:create_review.html.twig',
|
||||
array(
|
||||
'person' => $person,
|
||||
'alternatePersons' => $alternatePersons,
|
||||
'firstName' => $form['firstName']->getData(),
|
||||
'lastName' => $form['lastName']->getData(),
|
||||
'birthdate' => $form['birthdate']->getData(),
|
||||
'gender' => $form['gender']->getData(),
|
||||
'creation_date' => $form['creation_date']->getData(),
|
||||
'form' => $form->createView()));
|
||||
}
|
||||
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
|
||||
if ($request->getMethod() !== 'POST') {
|
||||
$r = new Response('You must send something to create a person !');
|
||||
$r->setStatusCode(400);
|
||||
return $r;
|
||||
}
|
||||
|
||||
$form = $this->createForm(CreationPersonType::class, null, array(
|
||||
'form_status' => CreationPersonType::FORM_REVIEWED
|
||||
));
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
$person = $this->_bindCreationForm($form);
|
||||
|
||||
$errors = $this->_validatePersonAndAccompanyingPeriod($person);
|
||||
|
||||
$this->denyAccessUnlessGranted('CHILL_PERSON_CREATE', $person,
|
||||
'You are not allowed to create this person');
|
||||
|
||||
if ($errors->count() === 0) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$em->persist($person);
|
||||
|
||||
$em->flush();
|
||||
|
||||
return $this->redirect($this->generateUrl('chill_person_general_edit',
|
||||
array('person_id' => $person->getId())));
|
||||
} else {
|
||||
$text = "this should not happen if you reviewed your submission\n";
|
||||
foreach ($errors as $error) {
|
||||
$text .= $error->getMessage()."\n";
|
||||
}
|
||||
$r = new Response($text);
|
||||
$r->setStatusCode(400);
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* easy getting a person by his id
|
||||
* @return \Chill\PersonBundle\Entity\Person
|
||||
*/
|
||||
private function _getPerson($id)
|
||||
{
|
||||
$person = $this->personRepository->find($id);
|
||||
|
||||
return $person;
|
||||
}
|
||||
}
|
109
src/Bundle/ChillPerson/Controller/TimelinePersonController.php
Normal file
109
src/Bundle/ChillPerson/Controller/TimelinePersonController.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Controller;
|
||||
|
||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Chill\MainBundle\Timeline\TimelineBuilder;
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
|
||||
/**
|
||||
* Class TimelinePersonController
|
||||
*
|
||||
* @package Chill\PersonBundle\Controller
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class TimelinePersonController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TimelineBuilder
|
||||
*/
|
||||
protected $timelineBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var PaginatorFactory
|
||||
*/
|
||||
protected $paginatorFactory;
|
||||
|
||||
/**
|
||||
* TimelinePersonController constructor.
|
||||
*
|
||||
* @param EventDispatcherInterface $eventDispatcher
|
||||
*/
|
||||
public function __construct(
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
TimelineBuilder $timelineBuilder,
|
||||
PaginatorFactory $paginatorFactory
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->timelineBuilder = $timelineBuilder;
|
||||
$this->paginatorFactory = $paginatorFactory;
|
||||
}
|
||||
|
||||
|
||||
public function personAction(Request $request, $person_id)
|
||||
{
|
||||
$person = $this->getDoctrine()
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->find($person_id);
|
||||
|
||||
if ($person === NULL) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
|
||||
|
||||
$nbItems = $this->timelineBuilder->countItems('person',
|
||||
[ 'person' => $person ]
|
||||
);
|
||||
|
||||
$paginator = $this->paginatorFactory->create($nbItems);
|
||||
|
||||
$event = new PrivacyEvent($person, array('action' => 'timeline'));
|
||||
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
|
||||
|
||||
return $this->render('ChillPersonBundle:Timeline:index.html.twig', array
|
||||
(
|
||||
'timeline' => $this->timelineBuilder->getTimelineHTML(
|
||||
'person',
|
||||
array('person' => $person),
|
||||
$paginator->getCurrentPage()->getFirstItemNumber(),
|
||||
$paginator->getItemsPerPage()
|
||||
),
|
||||
'person' => $person,
|
||||
'nb_items' => $nbItems,
|
||||
'paginator' => $paginator
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
|
||||
/**
|
||||
* Load closing motives into database
|
||||
*
|
||||
* @author Julien Fastré <julien arobase fastre point info>
|
||||
*/
|
||||
class LoadAccompanyingPeriodClosingMotive extends AbstractFixture
|
||||
implements OrderedFixtureInterface
|
||||
{
|
||||
|
||||
public function getOrder() {
|
||||
return 9500;
|
||||
}
|
||||
|
||||
public static $closingMotives = array(
|
||||
'nothing_to_do' => array(
|
||||
'name' => array(
|
||||
'fr' => 'Plus rien à faire',
|
||||
'en' => 'Nothing to do',
|
||||
'nl' => 'nieks meer te doen'
|
||||
)
|
||||
),
|
||||
'did_not_come_back' => array(
|
||||
'name' => array(
|
||||
'fr' => "N'est plus revenu",
|
||||
'en' => "Did'nt come back",
|
||||
'nl' => "Niet teruggekomen"
|
||||
)
|
||||
),
|
||||
'no_more_money' => array(
|
||||
'active' => false,
|
||||
'name' => array(
|
||||
'fr' => "Plus d'argent",
|
||||
'en' => "No more money",
|
||||
'nl' => "Geen geld"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
public static $references = array();
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (static::$closingMotives as $ref => $new) {
|
||||
$motive = new ClosingMotive();
|
||||
$motive->setName($new['name'])
|
||||
->setActive((isset($new['active']) ? $new['active'] : true))
|
||||
;
|
||||
|
||||
$manager->persist($motive);
|
||||
$this->addReference($ref, $motive);
|
||||
echo "Adding ClosingMotive $ref\n";
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
229
src/Bundle/ChillPerson/DataFixtures/ORM/LoadCustomFields.php
Normal file
229
src/Bundle/ChillPerson/DataFixtures/ORM/LoadCustomFields.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldTitle;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldText;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsDefaultGroup;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadCustomFields extends AbstractFixture implements OrderedFixtureInterface,
|
||||
ContainerAwareInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomField
|
||||
*/
|
||||
private $customFieldText;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomField
|
||||
*/
|
||||
private $customFieldChoice;
|
||||
|
||||
/**
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* LoadCustomFields constructor.
|
||||
*
|
||||
* @param TranslatableStringHelper $translatableStringHelper
|
||||
* @param TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
//put your code here
|
||||
public function getOrder()
|
||||
{
|
||||
return 10003;
|
||||
}
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
if ($container === null) {
|
||||
throw new \RuntimeException("The given container should not be null");
|
||||
}
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$this->loadFields($manager);
|
||||
$this->loadData($manager);
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
private function loadData(ObjectManager $manager)
|
||||
{
|
||||
$personIds = $this->container->get('doctrine.orm.entity_manager')
|
||||
->createQuery("SELECT person.id FROM ChillPersonBundle:Person person")
|
||||
->getScalarResult();
|
||||
|
||||
// get possible values for cfGroup
|
||||
$choices = array_map(
|
||||
function($a) { return $a["slug"]; },
|
||||
$this->customFieldChoice->getOptions()["choices"]
|
||||
);
|
||||
// create faker
|
||||
$faker = \Faker\Factory::create('fr_FR');
|
||||
// select a set of people and add data
|
||||
foreach ($personIds as $id) {
|
||||
// add info on 1 person on 2
|
||||
if (rand(0,1) === 1) {
|
||||
/* @var $person Person */
|
||||
$person = $manager->getRepository(Person::class)->find($id);
|
||||
$person->setCFData(array(
|
||||
"remarques" => $this->createCustomFieldText()
|
||||
->serialize($faker->text(rand(150, 250)), $this->customFieldText),
|
||||
"document-d-identite" => $this->createCustomFieldChoice()
|
||||
->serialize(array($choices[array_rand($choices)]), $this->customFieldChoice)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function createCustomFieldText()
|
||||
{
|
||||
return new CustomFieldText(
|
||||
$this->container->get('request_stack'),
|
||||
$this->container->get('templating'),
|
||||
$this->translatableStringHelper
|
||||
);
|
||||
}
|
||||
|
||||
private function createCustomFieldChoice()
|
||||
{
|
||||
return new CustomFieldChoice(
|
||||
$this->translator,
|
||||
$this->container->get('templating'),
|
||||
$this->translatableStringHelper
|
||||
);
|
||||
}
|
||||
|
||||
private function loadFields(ObjectManager $manager)
|
||||
{
|
||||
$cfGroup = (new CustomFieldsGroup())
|
||||
->setEntity(Person::class)
|
||||
->setName(array("fr" => "Données"))
|
||||
;
|
||||
$manager->persist($cfGroup);
|
||||
|
||||
// make this group default for Person::class
|
||||
$manager->persist(
|
||||
(new CustomFieldsDefaultGroup())
|
||||
->setCustomFieldsGroup($cfGroup)
|
||||
->setEntity(Person::class)
|
||||
);
|
||||
|
||||
// create title field
|
||||
$customField0 = (new CustomField())
|
||||
->setActive(true)
|
||||
->setName(array("fr" => "Données personnalisées"))
|
||||
->setSlug("personal-data")
|
||||
->setOrdering(10)
|
||||
->setType('title')
|
||||
->setOptions(array(CustomFieldTitle::TYPE => CustomFieldTitle::TYPE_TITLE))
|
||||
->setCustomFieldsGroup($cfGroup)
|
||||
;
|
||||
$manager->persist($customField0);
|
||||
|
||||
// create text field
|
||||
$this->customFieldText = (new CustomField())
|
||||
->setActive(true)
|
||||
->setName(array("fr" => "Remarques"))
|
||||
->setSlug("remarques")
|
||||
->setOrdering(20)
|
||||
->setType('text')
|
||||
->setOptions(array('maxLength' => 5000))
|
||||
->setCustomFieldsGroup($cfGroup)
|
||||
;
|
||||
$manager->persist($this->customFieldText);
|
||||
|
||||
// create choice field
|
||||
$this->customFieldChoice = (new CustomField())
|
||||
->setActive(true)
|
||||
->setName(array("fr" => "Document d'identité"))
|
||||
->setSlug("document-d-identite")
|
||||
->setOrdering(30)
|
||||
->setType('choice')
|
||||
->setCustomFieldsGroup($cfGroup)
|
||||
->setOptions(array(
|
||||
"multiple" => true,
|
||||
"other" => false,
|
||||
"expanded" => true,
|
||||
"active" => true,
|
||||
"slug" => "document-d-identite",
|
||||
"choices" => array(
|
||||
array(
|
||||
"name" => array("fr" => "Carte d'identité"),
|
||||
"active" => true,
|
||||
"slug" => "carte-d-identite"
|
||||
),
|
||||
array(
|
||||
"name" => array("fr" => "Passeport"),
|
||||
"active" => true,
|
||||
"slug" => "passeport"
|
||||
),
|
||||
array(
|
||||
"name" => array("fr" => "Titre de séjour"),
|
||||
"active" => true,
|
||||
"slug" => "passeport"
|
||||
)
|
||||
)
|
||||
))
|
||||
;
|
||||
$manager->persist($this->customFieldChoice);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\PersonBundle\Entity\MaritalStatus;
|
||||
|
||||
/**
|
||||
* Load marital status into database
|
||||
*
|
||||
* @author Marc Ducobu <marc@champs-libres.coop>
|
||||
*/
|
||||
class LoadMaritalStatus extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
private $maritalStatuses = [
|
||||
['id' => 'single', 'name' =>['en' => 'single', 'fr' => 'célibataire']],
|
||||
['id' => 'married', 'name' =>['en' => 'married', 'fr' => 'marié(e)']],
|
||||
['id' => 'widow', 'name' =>['en' => 'widow', 'fr' => 'veuf – veuve ']],
|
||||
['id' => 'separat', 'name' =>['en' => 'separated', 'fr' => 'séparé(e)']],
|
||||
['id' => 'divorce', 'name' =>['en' => 'divorced', 'fr' => 'divorcé(e)']],
|
||||
['id' => 'legalco', 'name' =>['en' => 'legal cohabitant', 'fr' => 'cohabitant(e) légal(e)']],
|
||||
['id' => 'unknown', 'name' =>['en' => 'unknown', 'fr' => 'indéterminé']]
|
||||
];
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 9999;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
echo "loading maritalStatuses... \n";
|
||||
|
||||
foreach ($this->maritalStatuses as $ms) {
|
||||
echo $ms['name']['en'].' ';
|
||||
$new_ms = new MaritalStatus();
|
||||
$new_ms->setId($ms['id']);
|
||||
$new_ms->setName($ms['name']);
|
||||
$this->addReference('ms_'.$ms['id'], $new_ms);
|
||||
$manager->persist($new_ms);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
326
src/Bundle/ChillPerson/DataFixtures/ORM/LoadPeople.php
Normal file
326
src/Bundle/ChillPerson/DataFixtures/ORM/LoadPeople.php
Normal file
@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPostalCodes;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
|
||||
/**
|
||||
* Load people into database
|
||||
*
|
||||
* @author Julien Fastré <julien arobase fastre point info>
|
||||
* @author Marc Ducobu <marc@champs-libres.coop>
|
||||
*/
|
||||
class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
|
||||
{
|
||||
|
||||
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
|
||||
protected $faker;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->faker = \Faker\Factory::create('fr_FR');
|
||||
}
|
||||
|
||||
public function prepare()
|
||||
{
|
||||
//prepare days, month, years
|
||||
$y = 1950;
|
||||
do {
|
||||
$this->years[] = $y;
|
||||
$y = $y +1;
|
||||
} while ($y >= 1990);
|
||||
|
||||
$m = 1;
|
||||
do {
|
||||
$this->month[] = $m;
|
||||
$m = $m +1;
|
||||
} while ($m >= 12);
|
||||
|
||||
$d = 1;
|
||||
do {
|
||||
$this->day[] = $d;
|
||||
$d = $d + 1;
|
||||
} while ($d <= 28);
|
||||
}
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 10000;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$this->loadRandPeople($manager);
|
||||
$this->loadExpectedPeople($manager);
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
public function loadExpectedPeople(ObjectManager $manager)
|
||||
{
|
||||
echo "loading expected people...\n";
|
||||
|
||||
foreach ($this->peoples as $person) {
|
||||
$this->addAPerson($this->fillWithDefault($person), $manager);
|
||||
}
|
||||
}
|
||||
|
||||
public function loadRandPeople(ObjectManager $manager)
|
||||
{
|
||||
echo "loading rand people...\n";
|
||||
|
||||
$this->prepare();
|
||||
|
||||
$chooseLastNameOrTri = array('tri', 'tri', 'name', 'tri');
|
||||
|
||||
$i = 0;
|
||||
|
||||
do {
|
||||
$i++;
|
||||
|
||||
$sex = $this->genders[array_rand($this->genders)];
|
||||
|
||||
if ($chooseLastNameOrTri[array_rand($chooseLastNameOrTri)] === 'tri' ) {
|
||||
$length = rand(2, 3);
|
||||
$lastName = '';
|
||||
for ($j = 0; $j <= $length; $j++) {
|
||||
$lastName .= $this->lastNamesTrigrams[array_rand($this->lastNamesTrigrams)];
|
||||
}
|
||||
$lastName = ucfirst($lastName);
|
||||
} else {
|
||||
$lastName = $this->lastNames[array_rand($this->lastNames)];
|
||||
}
|
||||
|
||||
if ($sex === Person::MALE_GENDER) {
|
||||
$firstName = $this->firstNamesMale[array_rand($this->firstNamesMale)];
|
||||
} else {
|
||||
$firstName = $this->firstNamesFemale[array_rand($this->firstNamesFemale)];
|
||||
}
|
||||
|
||||
// add an address on 80% of the created people
|
||||
if (rand(0,100) < 80) {
|
||||
$address = $this->getRandomAddress();
|
||||
// on 30% of those person, add multiple addresses
|
||||
if (rand(0,10) < 4) {
|
||||
$address = array(
|
||||
$address,
|
||||
$this->getRandomAddress()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$address = null;
|
||||
}
|
||||
|
||||
$person = array(
|
||||
'FirstName' => $firstName,
|
||||
'LastName' => $lastName,
|
||||
'Gender' => $sex,
|
||||
'Nationality' => (rand(0,100) > 50) ? NULL: 'BE',
|
||||
'center' => (rand(0,1) == 0) ? 'centerA': 'centerB',
|
||||
'Address' => $address,
|
||||
'maritalStatus' => $this->maritalStatusRef[array_rand($this->maritalStatusRef)]
|
||||
);
|
||||
|
||||
$this->addAPerson($this->fillWithDefault($person), $manager);
|
||||
|
||||
} while ($i <= 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* fill a person array with default value
|
||||
*
|
||||
* @param string[] $specific
|
||||
*/
|
||||
private function fillWithDefault(array $specific)
|
||||
{
|
||||
return array_merge(array(
|
||||
'Birthdate' => "1960-10-12",
|
||||
'PlaceOfBirth' => "Ottignies Louvain-La-Neuve",
|
||||
'Gender' => Person::MALE_GENDER,
|
||||
'Email' => "Email d'un ami: roger@tt.com",
|
||||
'CountryOfBirth' => 'BE',
|
||||
'Nationality' => 'BE',
|
||||
'CFData' => array(),
|
||||
'Address' => null
|
||||
), $specific);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new person from array data
|
||||
*
|
||||
* @param array $person
|
||||
* @param ObjectManager $manager
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function addAPerson(array $person, ObjectManager $manager)
|
||||
{
|
||||
$p = new Person();
|
||||
|
||||
foreach ($person as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'CountryOfBirth':
|
||||
case 'Nationality':
|
||||
$value = $this->getCountry($value);
|
||||
break;
|
||||
case 'Birthdate':
|
||||
$value = new \DateTime($value);
|
||||
break;
|
||||
case 'center':
|
||||
case 'maritalStatus':
|
||||
$value = $this->getReference($value);
|
||||
break;
|
||||
}
|
||||
|
||||
//try to add the data using the setSomething function,
|
||||
// if not possible, fallback to addSomething function
|
||||
if (method_exists($p, 'set'.$key)) {
|
||||
call_user_func(array($p, 'set'.$key), $value);
|
||||
} elseif (method_exists($p, 'add'.$key)) {
|
||||
// if we have a "addSomething", we may have multiple items to add
|
||||
// so, we set the value in an array if it is not an array, and
|
||||
// will call the function addSomething multiple times
|
||||
if (!is_array($value)) {
|
||||
$value = array($value);
|
||||
}
|
||||
|
||||
foreach($value as $v) {
|
||||
if ($v !== NULL) {
|
||||
call_user_func(array($p, 'add'.$key), $v);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$manager->persist($p);
|
||||
echo "add person'".$p->__toString()."'\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creata a random address
|
||||
*
|
||||
* @return Address
|
||||
*/
|
||||
private function getRandomAddress()
|
||||
{
|
||||
return (new Address())
|
||||
->setStreetAddress1($this->faker->streetAddress)
|
||||
->setStreetAddress2(
|
||||
rand(0,9) > 5 ? $this->faker->streetAddress : ''
|
||||
)
|
||||
->setPostcode($this->getReference(
|
||||
LoadPostalCodes::$refs[array_rand(LoadPostalCodes::$refs)]
|
||||
))
|
||||
->setValidFrom($this->faker->dateTimeBetween('-5 years'))
|
||||
;
|
||||
}
|
||||
|
||||
private function getCountry($countryCode)
|
||||
{
|
||||
if ($countryCode === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return $this->container->get('doctrine.orm.entity_manager')
|
||||
->getRepository('ChillMainBundle:Country')
|
||||
->findOneByCountryCode($countryCode);
|
||||
}
|
||||
|
||||
private $maritalStatusRef = ['ms_single', 'ms_married', 'ms_widow', 'ms_separat',
|
||||
'ms_divorce', 'ms_legalco', 'ms_unknown'];
|
||||
|
||||
private $firstNamesMale = array("Jean", "Mohamed", "Alfred", "Robert",
|
||||
"Compère", "Jean-de-Dieu",
|
||||
"Charles", "Pierre", "Luc", "Mathieu", "Alain", "Etienne", "Eric",
|
||||
"Corentin", "Gaston", "Spirou", "Fantasio", "Mahmadou", "Mohamidou",
|
||||
"Vursuv" );
|
||||
private $firstNamesFemale = array("Svedana", "Sevlatina","Irène", "Marcelle",
|
||||
"Corentine", "Alfonsine","Caroline","Solange","Gostine", "Fatoumata",
|
||||
"Groseille", "Chana", "Oxana", "Ivana");
|
||||
|
||||
private $lastNames = array("Diallo", "Bah", "Gaillot");
|
||||
private $lastNamesTrigrams = array("fas", "tré", "hu", 'blart', 'van', 'der', 'lin', 'den',
|
||||
'ta', 'mi', 'gna', 'bol', 'sac', 'ré', 'jo', 'du', 'pont', 'cas', 'tor', 'rob', 'al',
|
||||
'ma', 'gone', 'car',"fu", "ka", "lot", "no", "va", "du", "bu", "su",
|
||||
"lo", 'to', "cho", "car", 'mo','zu', 'qi', 'mu');
|
||||
|
||||
private $genders = array(Person::MALE_GENDER, Person::FEMALE_GENDER);
|
||||
|
||||
private $years = array();
|
||||
|
||||
private $month = array();
|
||||
|
||||
private $day = array();
|
||||
|
||||
private $peoples = array(
|
||||
array(
|
||||
'FirstName' => "Depardieu",
|
||||
'LastName' => "Gérard",
|
||||
'Birthdate' => "1948-12-27",
|
||||
'PlaceOfBirth' => "Châteauroux",
|
||||
'Gender' => Person::MALE_GENDER,
|
||||
'CountryOfBirth' => 'FR',
|
||||
'Nationality' => 'RU',
|
||||
'center' => 'centerA',
|
||||
'maritalStatus' => 'ms_divorce'
|
||||
),
|
||||
array(
|
||||
//to have a person with same firstname as Gérard Depardieu
|
||||
'FirstName' => "Depardieu",
|
||||
'LastName' => "Jean",
|
||||
'Birthdate' => "1960-10-12",
|
||||
'CountryOfBirth' => 'FR',
|
||||
'Nationality' => 'FR',
|
||||
'center' => 'centerA',
|
||||
'maritalStatus' => 'ms_divorce'
|
||||
),
|
||||
array(
|
||||
//to have a person with same birthdate of Gérard Depardieu
|
||||
'FirstName' => 'Van Snick',
|
||||
'LastName' => 'Bart',
|
||||
'Birthdate' => '1948-12-27',
|
||||
'center' => 'centerA',
|
||||
'maritalStatus' => 'ms_legalco'
|
||||
),
|
||||
array(
|
||||
//to have a woman with Depardieu as FirstName
|
||||
'FirstName' => 'Depardieu',
|
||||
'LastName' => 'Charline',
|
||||
'Gender' => Person::FEMALE_GENDER,
|
||||
'center' => 'centerA',
|
||||
'maritalStatus' => 'ms_legalco'
|
||||
),
|
||||
array(
|
||||
//to have a special character in lastName
|
||||
'FirstName' => 'Manço',
|
||||
'LastName' => 'Étienne',
|
||||
'center' => 'centerA',
|
||||
'maritalStatus' => 'ms_unknown'
|
||||
)
|
||||
);
|
||||
}
|
87
src/Bundle/ChillPerson/DataFixtures/ORM/LoadPersonACL.php
Normal file
87
src/Bundle/ChillPerson/DataFixtures/ORM/LoadPersonACL.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Julien Fastré <julien.fastre@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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
|
||||
use Chill\MainBundle\Entity\RoleScope;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
|
||||
/**
|
||||
* Add a role CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE for all groups except administrative,
|
||||
* and a role CHILL_PERSON_SEE for administrative
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadPersonACL extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
public function getOrder()
|
||||
{
|
||||
return 9600;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
|
||||
$permissionsGroup = $this->getReference($permissionsGroupRef);
|
||||
|
||||
//create permission group
|
||||
switch ($permissionsGroup->getName()) {
|
||||
case 'social':
|
||||
case 'direction':
|
||||
printf("Adding CHILL_PERSON_UPDATE & CHILL_PERSON_CREATE to %s permission group \n", $permissionsGroup->getName());
|
||||
$roleScopeUpdate = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_UPDATE')
|
||||
->setScope(null);
|
||||
$permissionsGroup->addRoleScope($roleScopeUpdate);
|
||||
$roleScopeCreate = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_CREATE')
|
||||
->setScope(null);
|
||||
$permissionsGroup->addRoleScope($roleScopeCreate);
|
||||
$roleScopeList = (new RoleScope())
|
||||
->setRole(PersonVoter::LISTS)
|
||||
->setScope(null);
|
||||
$permissionsGroup->addRoleScope($roleScopeList);
|
||||
$roleScopeStats = (new RoleScope())
|
||||
->setRole(PersonVoter::STATS)
|
||||
->setScope(null);
|
||||
$permissionsGroup->addRoleScope($roleScopeStats);
|
||||
$manager->persist($roleScopeUpdate);
|
||||
$manager->persist($roleScopeCreate);
|
||||
break;
|
||||
case 'administrative':
|
||||
printf("Adding CHILL_PERSON_SEE to %s permission group \n", $permissionsGroup->getName());
|
||||
$roleScopeSee = (new RoleScope())
|
||||
->setRole('CHILL_PERSON_SEE')
|
||||
->setScope(null);
|
||||
$permissionsGroup->addRoleScope($roleScopeSee);
|
||||
$manager->persist($roleScopeSee);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Julien Fastré <julien.fastre@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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
* Class ChillPersonExtension
|
||||
* Loads and manages your bundle configuration
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
|
||||
* @package Chill\PersonBundle\DependencyInjection
|
||||
*/
|
||||
class ChillPersonExtension extends Extension implements PrependExtensionInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @param array $configs
|
||||
* @param ContainerBuilder $container
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$config = $this->processConfiguration($configuration, $configs);
|
||||
|
||||
// set configuration for validation
|
||||
$container->setParameter('chill_person.validation.birtdate_not_before',
|
||||
$config['validation']['birthdate_not_after']);
|
||||
|
||||
$this->handlePersonFieldsParameters($container, $config['person_fields']);
|
||||
$this->handleAccompanyingPeriodsFieldsParameters($container, $config['accompanying_periods_fields']);
|
||||
|
||||
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
|
||||
$loader->load('services.yaml');
|
||||
$loader->load('services/widgets.yaml');
|
||||
$loader->load('services/exports.yaml');
|
||||
$loader->load('services/fixtures.yaml');
|
||||
$loader->load('services/controller.yaml');
|
||||
$loader->load('services/search.yaml');
|
||||
$loader->load('services/menu.yaml');
|
||||
$loader->load('services/privacyEvent.yaml');
|
||||
$loader->load('services/command.yaml');
|
||||
$loader->load('services/actions.yaml');
|
||||
$loader->load('services/form.yaml');
|
||||
$loader->load('services/repository.yaml');
|
||||
$loader->load('services/templating.yaml');
|
||||
$loader->load('services/alt_names.yaml');
|
||||
|
||||
// load service advanced search only if configure
|
||||
if ($config['search']['search_by_phone'] != 'never') {
|
||||
$loader->load('services/search_by_phone.yaml');
|
||||
$container->setParameter('chill_person.search.search_by_phone',
|
||||
$config['search']['search_by_phone']);
|
||||
}
|
||||
|
||||
if ($container->getParameter('chill_person.accompanying_period') !== 'hidden') {
|
||||
$loader->load('services/exports_accompanying_period.yaml');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
* @param $config
|
||||
*/
|
||||
private function handlePersonFieldsParameters(ContainerBuilder $container, $config)
|
||||
{
|
||||
if (array_key_exists('enabled', $config)) {
|
||||
unset($config['enabled']);
|
||||
}
|
||||
|
||||
$container->setParameter('chill_person.person_fields', $config);
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
switch($key) {
|
||||
case 'accompanying_period':
|
||||
$container->setParameter('chill_person.accompanying_period', $value);
|
||||
break;
|
||||
default:
|
||||
$container->setParameter('chill_person.person_fields.'.$key, $value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
* @param $config
|
||||
*/
|
||||
private function handleAccompanyingPeriodsFieldsParameters(ContainerBuilder $container, $config)
|
||||
{
|
||||
$container->setParameter('chill_person.accompanying_period_fields', $config);
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
switch($key) {
|
||||
case 'enabled':
|
||||
break;
|
||||
default:
|
||||
$container->setParameter('chill_person.accompanying_period_fields.'.$key, $value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
* @throws MissingBundleException
|
||||
*/
|
||||
private function declarePersonAsCustomizable (ContainerBuilder $container)
|
||||
{
|
||||
$bundles = $container->getParameter('kernel.bundles');
|
||||
if (!isset($bundles['ChillCustomFieldsBundle'])) {
|
||||
throw new MissingBundleException('ChillCustomFieldsBundle');
|
||||
}
|
||||
|
||||
$container->prependExtensionConfig('chill_custom_fields',
|
||||
array('customizables_entities' =>
|
||||
array(
|
||||
array('class' => 'Chill\PersonBundle\Entity\Person', 'name' => 'PersonEntity')
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
* @throws MissingBundleException
|
||||
*/
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
$this->prependRoleHierarchy($container);
|
||||
$this->prependHomepageWidget($container);
|
||||
$this->prependDoctrineDQL($container);
|
||||
$this->prependCruds($container);
|
||||
|
||||
//add person_fields parameter as global
|
||||
$chillPersonConfig = $container->getExtensionConfig($this->getAlias());
|
||||
$config = $this->processConfiguration(new Configuration(), $chillPersonConfig);
|
||||
$twigConfig = array(
|
||||
'globals' => array(
|
||||
'chill_person' => array(
|
||||
'fields' => $config['person_fields']
|
||||
),
|
||||
'chill_accompanying_periods' => [
|
||||
'fields' => $config['accompanying_periods_fields']
|
||||
]
|
||||
),
|
||||
'form_themes' => array('ChillPersonBundle:Export:ListPersonFormFields.html.twig')
|
||||
);
|
||||
$container->prependExtensionConfig('twig', $twigConfig);
|
||||
|
||||
$this-> declarePersonAsCustomizable($container);
|
||||
|
||||
//declare routes for person bundle
|
||||
$container->prependExtensionConfig('chill_main', array(
|
||||
'routing' => array(
|
||||
'resources' => array(
|
||||
'@ChillPersonBundle/config/routes.yaml'
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a widget "add a person" on the homepage, automatically
|
||||
*
|
||||
* @param \Chill\PersonBundle\DependencyInjection\containerBuilder $container
|
||||
*/
|
||||
protected function prependHomepageWidget(containerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('chill_main', array(
|
||||
'widgets' => array(
|
||||
'homepage' => array(
|
||||
array(
|
||||
'widget_alias' => 'add_person',
|
||||
'order' => 2
|
||||
)
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role hierarchy.
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
*/
|
||||
protected function prependRoleHierarchy(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('security', array(
|
||||
'role_hierarchy' => array(
|
||||
'CHILL_PERSON_UPDATE' => array('CHILL_PERSON_SEE'),
|
||||
'CHILL_PERSON_CREATE' => array('CHILL_PERSON_SEE'),
|
||||
PersonVoter::LISTS => [ ChillExportVoter::EXPORT ],
|
||||
PersonVoter::STATS => [ ChillExportVoter::EXPORT ]
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add DQL function linked with person
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
*/
|
||||
protected function prependDoctrineDQL(ContainerBuilder $container)
|
||||
{
|
||||
//add DQL function to ORM (default entity_manager)
|
||||
|
||||
$container->prependExtensionConfig('doctrine', array(
|
||||
'orm' => array(
|
||||
'dql' => array(
|
||||
'string_functions' => array(
|
||||
'GET_PERSON_ADDRESS_ADDRESS_ID' => AddressPart\AddressPartAddressId::class,
|
||||
'GET_PERSON_ADDRESS_STREET_ADDRESS_1' => AddressPart\AddressPartStreetAddress1::class,
|
||||
'GET_PERSON_ADDRESS_STREET_ADDRESS_2' => AddressPart\AddressPartStreetAddress2::class,
|
||||
'GET_PERSON_ADDRESS_VALID_FROM' => AddressPart\AddressPartValidFrom::class,
|
||||
'GET_PERSON_ADDRESS_POSTCODE_LABEL' => AddressPart\AddressPartPostCodeLabel::class,
|
||||
'GET_PERSON_ADDRESS_POSTCODE_CODE' => AddressPart\AddressPartPostCodeCode::class,
|
||||
'GET_PERSON_ADDRESS_POSTCODE_ID' => AddressPart\AddressPartPostCodeId::class,
|
||||
'GET_PERSON_ADDRESS_COUNTRY_NAME' => AddressPart\AddressPartCountryName::class,
|
||||
'GET_PERSON_ADDRESS_COUNTRY_CODE' => AddressPart\AddressPartCountryCode::class,
|
||||
'GET_PERSON_ADDRESS_COUNTRY_ID' => AddressPart\AddressPartCountryId::class,
|
||||
),
|
||||
'numeric_functions' => [
|
||||
'GET_PERSON_ADDRESS_ISNOADDRESS' => AddressPart\AddressPartIsNoAddress::class,
|
||||
]
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $container
|
||||
*/
|
||||
protected function prependCruds(ContainerBuilder $container)
|
||||
{
|
||||
$container->prependExtensionConfig('chill_main', [
|
||||
'cruds' => [
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive::class,
|
||||
'name' => 'closing_motive',
|
||||
'base_path' => '/admin/closing-motive',
|
||||
'form_class' => \Chill\PersonBundle\Form\ClosingMotiveType::class,
|
||||
'controller' => \Chill\PersonBundle\Controller\AdminClosingMotiveController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'template' => '@ChillPerson/ClosingMotive/index.html.twig',
|
||||
'role' => 'ROLE_ADMIN'
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/ClosingMotive/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/ClosingMotive/edit.html.twig',
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\MaritalStatus::class,
|
||||
'name' => 'marital_status',
|
||||
'base_path' => '/admin/marital-status',
|
||||
'form_class' => \Chill\PersonBundle\Form\MaritalStatusType::class,
|
||||
'controller' => \Chill\PersonBundle\Controller\AdminMaritalStatusController::class,
|
||||
'actions' => [
|
||||
'index' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/MaritalStatus/index.html.twig',
|
||||
],
|
||||
'new' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/MaritalStatus/new.html.twig',
|
||||
],
|
||||
'edit' => [
|
||||
'role' => 'ROLE_ADMIN',
|
||||
'template' => '@ChillPerson/MaritalStatus/edit.html.twig',
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\DependencyInjection\CompilerPass;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
|
||||
/**
|
||||
* Remove services which add AccompanyingPeriod to timeline if
|
||||
* accompanying_periods are set to `hidden`
|
||||
*
|
||||
*/
|
||||
class AccompanyingPeriodTimelineCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// remove services when accompanying period are hidden
|
||||
if ($container->getParameter('chill_person.accompanying_period') !== 'hidden') {
|
||||
return;
|
||||
}
|
||||
|
||||
$definitions = [
|
||||
'chill.person.timeline.accompanying_period_opening',
|
||||
'chill.person.timeline.accompanying_period_closing'
|
||||
];
|
||||
|
||||
foreach($definitions as $definition) {
|
||||
$container
|
||||
->removeDefinition($definition)
|
||||
;
|
||||
}
|
||||
|
||||
$definition = $container->getDefinition('chill.main.timeline_builder');
|
||||
|
||||
// we have to remove all methods call, and re-add them if not linked
|
||||
// to this service
|
||||
$calls = $definition->getMethodCalls();
|
||||
|
||||
foreach($calls as list($method, $arguments)) {
|
||||
if ($method !== 'addProvider') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$definition->removeMethodCall('addProvider');
|
||||
|
||||
if (FALSE === \in_array($arguments[1], $definitions)) {
|
||||
$definition->addMethodCall($method, $arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
138
src/Bundle/ChillPerson/DependencyInjection/Configuration.php
Normal file
138
src/Bundle/ChillPerson/DependencyInjection/Configuration.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* This is the class that validates and merges configuration from your app/config files
|
||||
*
|
||||
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
|
||||
private $validationBirthdateNotAfterInfos = "The period before today during which"
|
||||
. " any birthdate is not allowed. The birthdate is expressed as ISO8601 : "
|
||||
. "https://en.wikipedia.org/wiki/ISO_8601#Durations";
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder('cl_chill_person');
|
||||
$rootNode = $treeBuilder->getRootNode('cl_chill_person');
|
||||
|
||||
$rootNode
|
||||
->canBeDisabled()
|
||||
->children()
|
||||
->arrayNode('search')
|
||||
->canBeDisabled()
|
||||
->children()
|
||||
->enumNode('search_by_phone')
|
||||
->values(['always', 'on-domain', 'never'])
|
||||
->defaultValue('on-domain')
|
||||
->info('enable search by phone. \'always\' show the result '
|
||||
. 'on every result. \'on-domain\' will show the result '
|
||||
. 'only if the domain is given in the search box. '
|
||||
. '\'never\' disable this feature')
|
||||
->end()
|
||||
->end() //children for 'search', parent = array node 'search'
|
||||
->end() // array 'search', parent = children of root
|
||||
->arrayNode('validation')
|
||||
->canBeDisabled()
|
||||
->children()
|
||||
->scalarNode('birthdate_not_after')
|
||||
->info($this->validationBirthdateNotAfterInfos)
|
||||
->defaultValue('P1D')
|
||||
->validate()
|
||||
->ifTrue(function($period) {
|
||||
try {
|
||||
$interval = new \DateInterval($period);
|
||||
} catch (\Exception $ex) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
->thenInvalid('Invalid period for birthdate validation : "%s" '
|
||||
. 'The parameter should match duration as defined by ISO8601 : '
|
||||
. 'https://en.wikipedia.org/wiki/ISO_8601#Durations')
|
||||
->end() // birthdate_not_after, parent = children of validation
|
||||
|
||||
->end() // children for 'validation', parent = validation
|
||||
->end() //validation, parent = children of root
|
||||
->end() // children of root, parent = root
|
||||
->arrayNode('person_fields')
|
||||
->canBeDisabled()
|
||||
->children()
|
||||
->append($this->addFieldNode('place_of_birth'))
|
||||
->append($this->addFieldNode('email'))
|
||||
->append($this->addFieldNode('phonenumber'))
|
||||
->append($this->addFieldNode('mobilenumber'))
|
||||
->append($this->addFieldNode('contact_info'))
|
||||
->append($this->addFieldNode('nationality'))
|
||||
->append($this->addFieldNode('country_of_birth'))
|
||||
->append($this->addFieldNode('marital_status'))
|
||||
->append($this->addFieldNode('spoken_languages'))
|
||||
->append($this->addFieldNode('address'))
|
||||
->append($this->addFieldNode('accompanying_period'))
|
||||
->append($this->addFieldNode('memo'))
|
||||
->arrayNode('alt_names')
|
||||
->defaultValue([])
|
||||
->arrayPrototype()
|
||||
->children()
|
||||
->scalarNode('key')
|
||||
->isRequired()->cannotBeEmpty()
|
||||
->end()
|
||||
->arrayNode('labels')
|
||||
->children()
|
||||
->scalarNode('lang')->isRequired()->cannotBeEmpty()
|
||||
->example('fr')
|
||||
->end()
|
||||
->scalarNode('label')->isRequired()->cannotBeEmpty()
|
||||
->example('Nom de jeune fille')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end() //children for 'person_fields', parent = array 'person_fields'
|
||||
->end() // person_fields, parent = children of root
|
||||
->arrayNode('accompanying_periods_fields')
|
||||
->canBeDisabled()
|
||||
->children()
|
||||
->append($this->addFieldNode('user'))
|
||||
->end() //children for 'accompanying_person_fields', parent = array 'person_fields'
|
||||
->end() // paccompanying_person_fields, parent = children of root
|
||||
->end() // children of 'root', parent = root
|
||||
;
|
||||
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
|
||||
private function addFieldNode($key)
|
||||
{
|
||||
$tree = new TreeBuilder($key,'enum');
|
||||
$node = $tree->getRootNode($key);
|
||||
|
||||
switch($key) {
|
||||
case 'accompanying_period':
|
||||
$info = "If the accompanying periods are shown";
|
||||
break;
|
||||
default:
|
||||
$info = "If the field $key must be shown";
|
||||
break;
|
||||
}
|
||||
|
||||
$node
|
||||
->values(array('hidden', 'visible'))
|
||||
->defaultValue('visible')
|
||||
->info($info)
|
||||
->end();
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
103
src/Bundle/ChillPerson/Doctrine/DQL/AddressPart.php
Normal file
103
src/Bundle/ChillPerson/Doctrine/DQL/AddressPart.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
/**
|
||||
*
|
||||
* USAGE GET_ADDRESS_<part>(person.id, :date, 'postcode') where part
|
||||
* should be replace by the part of the address.
|
||||
*
|
||||
* This function return the current address part at the given date, for the
|
||||
* given person (identified by his id)
|
||||
*
|
||||
* The aim of this function is to be used within reports
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
abstract class AddressPart extends FunctionNode
|
||||
{
|
||||
public $fields = array(
|
||||
'address_id',
|
||||
'streetaddress1',
|
||||
'streetaddress2',
|
||||
'validfrom',
|
||||
'postcode_label',
|
||||
'postcode_code',
|
||||
'postcode_id',
|
||||
'country_name',
|
||||
'country_code',
|
||||
'country_id'
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Doctrine\ORM\Query\AST\Node
|
||||
*/
|
||||
private $pid;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Doctrine\ORM\Query\AST\Node
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Doctrine\ORM\Query\AST\Node
|
||||
*/
|
||||
private $part;
|
||||
|
||||
/**
|
||||
* return the part of the address
|
||||
*
|
||||
* Should be one value of the "public" amongst
|
||||
* 'address_id', 'streetaddress1',
|
||||
* 'streetaddress2', 'validfrom', 'postcode_label', 'postcode_code',
|
||||
* 'postcode_id', 'country_name', 'country_code', 'country_id', 'isnoaddress'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getPart();
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker)
|
||||
{
|
||||
return sprintf(
|
||||
'get_last_address_%s(%s, %s)',
|
||||
$this->getPart(),
|
||||
$this->pid->dispatch($sqlWalker),
|
||||
$this->date->dispatch($sqlWalker)
|
||||
);
|
||||
}
|
||||
|
||||
public function parse(Parser $parser)
|
||||
{
|
||||
$a = $parser->match(Lexer::T_IDENTIFIER);
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
// person id
|
||||
$this->pid = $parser->SingleValuedPathExpression();
|
||||
$parser->match(Lexer::T_COMMA);
|
||||
// date
|
||||
$this->date = $parser->ArithmeticPrimary();
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartAddressId extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'address_id';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartCountryCode extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'country_code';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartCountryId extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'country_id';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartCountryName extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'country_name';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartIsNoAddress extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'isnoaddress';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartPostCodeCode extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'postcode_code';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartPostCodeId extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'postcode_id';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartPostCodeLabel extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'postcode_label';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartStreetAddress1 extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'streetaddress1';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartStreetAddress2 extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'streetaddress2';
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AddressPartValidFrom extends AddressPart
|
||||
{
|
||||
public function getPart()
|
||||
{
|
||||
return 'validfrom';
|
||||
}
|
||||
}
|
330
src/Bundle/ChillPerson/Entity/AccompanyingPeriod.php
Normal file
330
src/Bundle/ChillPerson/Entity/AccompanyingPeriod.php
Normal file
@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
|
||||
/**
|
||||
* AccompanyingPeriod
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="chill_person_accompanying_period")
|
||||
*/
|
||||
class AccompanyingPeriod
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="date")
|
||||
*/
|
||||
private $openingDate;
|
||||
|
||||
/**
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(type="date", nullable=true)
|
||||
*/
|
||||
private $closingDate = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="text")
|
||||
*/
|
||||
private $remark = '';
|
||||
|
||||
/**
|
||||
* @var Person
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\PersonBundle\Entity\Person",
|
||||
* inversedBy="accompanyingPeriods",
|
||||
* cascade={"refresh"})
|
||||
*/
|
||||
private $person;
|
||||
|
||||
/**
|
||||
* @var AccompanyingPeriod\ClosingMotive
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $closingMotive = null;
|
||||
|
||||
/**
|
||||
* The user making the accompanying
|
||||
* @var User
|
||||
*
|
||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $user;
|
||||
|
||||
|
||||
/**
|
||||
* AccompanyingPeriod constructor.
|
||||
*
|
||||
* @param \DateTime $dateOpening
|
||||
* @uses AccompanyingPeriod::setClosingDate()
|
||||
*/
|
||||
public function __construct(\DateTime $dateOpening) {
|
||||
$this->setOpeningDate($dateOpening);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set openingDate
|
||||
*
|
||||
* @param \DateTime $dateOpening
|
||||
* @return AccompanyingPeriod
|
||||
*/
|
||||
public function setOpeningDate($openingDate)
|
||||
{
|
||||
$this->openingDate = $openingDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get openingDate
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getOpeningDate()
|
||||
{
|
||||
return $this->openingDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set closingDate
|
||||
*
|
||||
* For closing a Person file, you should use Person::setClosed instead.
|
||||
*
|
||||
* @param \DateTime $dateClosing
|
||||
* @return AccompanyingPeriod
|
||||
*
|
||||
*/
|
||||
public function setClosingDate($closingDate)
|
||||
{
|
||||
$this->closingDate = $closingDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get closingDate
|
||||
*
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getClosingDate()
|
||||
{
|
||||
return $this->closingDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOpen(): bool
|
||||
{
|
||||
if ($this->getOpeningDate() > new \DateTime('now')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->getClosingDate() === null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set remark
|
||||
*
|
||||
* @param string $remark
|
||||
* @return AccompanyingPeriod
|
||||
*/
|
||||
public function setRemark($remark)
|
||||
{
|
||||
if ($remark === null) {
|
||||
$remark = '';
|
||||
}
|
||||
|
||||
$this->remark = $remark;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remark
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRemark()
|
||||
{
|
||||
return $this->remark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set person.
|
||||
*
|
||||
* For consistency, you should use Person::addAccompanyingPeriod instead.
|
||||
*
|
||||
* @param Person $person
|
||||
* @return AccompanyingPeriod
|
||||
* @see Person::addAccompanyingPeriod
|
||||
*/
|
||||
public function setPerson(Person $person = null)
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get person
|
||||
*
|
||||
* @return Person
|
||||
*/
|
||||
public function getPerson()
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AccompanyingPeriod\ClosingMotive
|
||||
*/
|
||||
public function getClosingMotive()
|
||||
{
|
||||
return $this->closingMotive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriod\ClosingMotive|null $closingMotive
|
||||
* @return $this
|
||||
*/
|
||||
public function setClosingMotive(AccompanyingPeriod\ClosingMotive $closingMotive = null)
|
||||
{
|
||||
$this->closingMotive = $closingMotive;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the period can be reopened.
|
||||
*
|
||||
* This function test if the period is closed and if the period is the last
|
||||
* for the associated person
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function canBeReOpened()
|
||||
{
|
||||
if ($this->isOpen() === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$periods = $this->getPerson()->getAccompanyingPeriodsOrdered();
|
||||
|
||||
return end($periods) === $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function reOpen()
|
||||
{
|
||||
$this->setClosingDate(null);
|
||||
$this->setClosingMotive(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation function
|
||||
*/
|
||||
public function isDateConsistent(ExecutionContextInterface $context)
|
||||
{
|
||||
if ($this->isOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->isClosingAfterOpening()) {
|
||||
$context->buildViolation('The date of closing is before the date of opening')
|
||||
->atPath('dateClosing')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the closing date is after the opening date.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isClosingAfterOpening()
|
||||
{
|
||||
$diff = $this->getOpeningDate()->diff($this->getClosingDate());
|
||||
|
||||
if ($diff->invert === 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User|null
|
||||
*/
|
||||
function getUser(): ?User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return AccompanyingPeriod
|
||||
*/
|
||||
function setUser(User $user): self
|
||||
{
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
* ClosingMotive give an explanation why we closed the Accompanying period
|
||||
*
|
||||
* @ORM\Entity(
|
||||
* repositoryClass="Chill\PersonBundle\Repository\ClosingMotiveRepository")
|
||||
* @ORM\Table(name="chill_person_closingmotive")
|
||||
*/
|
||||
class ClosingMotive
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
|
||||
/**
|
||||
* @var self
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive",
|
||||
* inversedBy="children")
|
||||
*/
|
||||
private $parent = null;
|
||||
|
||||
/**
|
||||
* Child Accompanying periods
|
||||
* @var Collection
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive",
|
||||
* mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @ORM\Column(type="float")
|
||||
*/
|
||||
private $ordering = 0.0;
|
||||
|
||||
|
||||
/**
|
||||
* ClosingMotive constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->children = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param array $name
|
||||
*
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $active
|
||||
* @return $this
|
||||
*/
|
||||
public function setActive(bool $active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
if ($this->active === FALSE) {
|
||||
foreach ($this->getChildren() as $child) {
|
||||
$child->setActive(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getChildren(): Collection
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClosingMotive|null $parent
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function setParent(?ClosingMotive $parent): ClosingMotive
|
||||
{
|
||||
$this->parent = $parent;
|
||||
|
||||
if (NULL !== $parent) {
|
||||
//$parent->addChildren($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $children
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function setChildren(Collection $children): ClosingMotive
|
||||
{
|
||||
$this->children = $children;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClosingMotive $child
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function addChildren(ClosingMotive $child): ClosingMotive
|
||||
{
|
||||
if ($this->children->contains($child)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->children->add($child);
|
||||
$child->setParent($this);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClosingMotive $child
|
||||
* @return ClosingMotive
|
||||
*/
|
||||
public function removeChildren(ClosingMotive $child): ClosingMotive
|
||||
{
|
||||
if ($this->children->removeElement($child)) {
|
||||
$child->setParent(null);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getOrdering(): float
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $ordering
|
||||
* @return $this
|
||||
*/
|
||||
public function setOrdering(float $ordering)
|
||||
{
|
||||
$this->ordering = $ordering;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isChild(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isParent(): bool
|
||||
{
|
||||
return $this->children->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLeaf(): bool
|
||||
{
|
||||
return $this->children->count() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasParent(): bool
|
||||
{
|
||||
return $this->parent !== null;
|
||||
}
|
||||
|
||||
}
|
||||
|
34
src/Bundle/ChillPerson/Entity/HasPerson.php
Normal file
34
src/Bundle/ChillPerson/Entity/HasPerson.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2019, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Entity;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
* Interface which applies to entities which are associated to a single person
|
||||
*
|
||||
*/
|
||||
interface HasPerson
|
||||
{
|
||||
public function setPerson(Person $person = null): HasPerson;
|
||||
|
||||
public function getPerson(): ?Person;
|
||||
}
|
92
src/Bundle/ChillPerson/Entity/MaritalStatus.php
Normal file
92
src/Bundle/ChillPerson/Entity/MaritalStatus.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* MaritalStatus
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="chill_person_marital_status")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*/
|
||||
class MaritalStatus
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Id()
|
||||
* @ORM\Column(type="string", length=7)
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string array
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set id
|
||||
*
|
||||
* @param string $id
|
||||
* @return MaritalStatus
|
||||
*/
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param string array $name
|
||||
* @return MaritalStatus
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return string array
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
1054
src/Bundle/ChillPerson/Entity/Person.php
Normal file
1054
src/Bundle/ChillPerson/Entity/Person.php
Normal file
File diff suppressed because it is too large
Load Diff
125
src/Bundle/ChillPerson/Entity/PersonAltName.php
Normal file
125
src/Bundle/ChillPerson/Entity/PersonAltName.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* PersonAltName
|
||||
*
|
||||
* @ORM\Table(name="chill_person_alt_name")
|
||||
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\PersonAltNameRepository")
|
||||
*/
|
||||
class PersonAltName
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="key", type="string", length=255)
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="label", type="text")
|
||||
*/
|
||||
private $label;
|
||||
|
||||
/**
|
||||
* @var Person
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\PersonBundle\Entity\Person",
|
||||
* inversedBy="altNames"
|
||||
* )
|
||||
*/
|
||||
private $person;
|
||||
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set key.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return PersonAltName
|
||||
*/
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set label.
|
||||
*
|
||||
* @param string $label
|
||||
*
|
||||
* @return PersonAltName
|
||||
*/
|
||||
public function setLabel($label)
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get label.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Person
|
||||
*/
|
||||
public function getPerson(): Person
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person|null $person
|
||||
* @return $this
|
||||
*/
|
||||
public function setPerson(?Person $person = null)
|
||||
{
|
||||
$this->person = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Export;
|
||||
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AbstractAccompanyingPeriodExportElement
|
||||
{
|
||||
/**
|
||||
* Return true if "accompanying_period" alias is present in the query alises.
|
||||
*
|
||||
* @param QueryBuilder $query
|
||||
* @return bool
|
||||
*/
|
||||
protected function havingAccompanyingPeriodInJoin(QueryBuilder $query): bool
|
||||
{
|
||||
$joins = $query->getDQLPart('join') ?? [];
|
||||
|
||||
return (\in_array('accompanying_period', $query->getAllAliases()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the accompanying period alias to the query
|
||||
*
|
||||
* @param QueryBuilder $query
|
||||
* @return void
|
||||
* @throws \LogicException if the "person" alias is not present and attaching accompanying period is not possible
|
||||
*/
|
||||
protected function addJoinAccompanyingPeriod(QueryBuilder $query): void
|
||||
{
|
||||
if (FALSE === $this->havingAccompanyingPeriodInJoin($query)) {
|
||||
if (FALSE === \in_array('person', $query->getAllAliases())) {
|
||||
throw new \LogicException("the alias 'person' does not exists in "
|
||||
. "query builder");
|
||||
}
|
||||
|
||||
$query->join('person.accompanyingPeriods', 'accompanying_period');
|
||||
}
|
||||
}
|
||||
}
|
112
src/Bundle/ChillPerson/Export/Aggregator/AgeAggregator.php
Normal file
112
src/Bundle/ChillPerson/Export/Aggregator/AgeAggregator.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Aggregator;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class AgeAggregator implements AggregatorInterface,
|
||||
ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct($translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb->addSelect('DATE_DIFF(:date_age_calculation, person.birthdate)/365 as person_age');
|
||||
$qb->setParameter('date_age_calculation', $data['date_age_calculation']);
|
||||
$qb->addGroupBy('person_age');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_age_calculation', DateType::class, array(
|
||||
'label' => "Calculate age in relation to this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy'
|
||||
));
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['date_age_calculation'] === null) {
|
||||
$context->buildViolation("The date should not be empty")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function($value) {
|
||||
if ($value === '_header') {
|
||||
return "Age";
|
||||
}
|
||||
|
||||
if ($value === NULL) {
|
||||
return $this->translator->trans("without data");
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array(
|
||||
'person_age'
|
||||
);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Aggregate by age";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CountryOfBirthAggregator implements AggregatorInterface,
|
||||
ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @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', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Group by continents' => 'continent',
|
||||
'Group by country' => 'country'
|
||||
),
|
||||
'expanded' => true,
|
||||
'multiple' => false
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['group_by_level'] === null) {
|
||||
$context->buildViolation("You should select an option")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
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('Country of birth');
|
||||
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 of birth')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return function($value) use ($labels) {
|
||||
return $labels[$value];
|
||||
};
|
||||
|
||||
}
|
||||
}
|
103
src/Bundle/ChillPerson/Export/Aggregator/GenderAggregator.php
Normal file
103
src/Bundle/ChillPerson/Export/Aggregator/GenderAggregator.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Aggregator;
|
||||
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class GenderAggregator implements AggregatorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
|
||||
$qb->addSelect('person.gender as gender');
|
||||
|
||||
$qb->addGroupBy('gender');
|
||||
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Group people by gender";
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array('gender');
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function($value) {
|
||||
switch ($value) {
|
||||
case Person::FEMALE_GENDER :
|
||||
return $this->translator->trans('woman');
|
||||
case Person::MALE_GENDER :
|
||||
return $this->translator->trans('man');
|
||||
case Person::BOTH_GENDER:
|
||||
return $this->translator->trans('both');
|
||||
case null:
|
||||
return $this->translator->trans('Not given');
|
||||
case '_header' :
|
||||
return $this->translator->trans('Gender');
|
||||
default:
|
||||
throw new \LogicException(sprintf("The value %s is not valid", $value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class NationalityAggregator implements AggregatorInterface,
|
||||
ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @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', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Group by continents' => 'continent',
|
||||
'Group by country' => 'country'
|
||||
),
|
||||
'expanded' => true,
|
||||
'multiple' => false
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['group_by_level'] === null) {
|
||||
$context->buildViolation("You should select an option")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// add a clause in select part
|
||||
if ($data['group_by_level'] === 'country') {
|
||||
$qb->addSelect('nationality.countryCode as nationality_aggregator');
|
||||
} elseif ($data['group_by_level'] === 'continent') {
|
||||
$clause = 'CASE '
|
||||
. 'WHEN nationality.countryCode IN(:africa_codes) THEN \'AF\' '
|
||||
. 'WHEN nationality.countryCode IN(:asia_codes) THEN \'AS\' '
|
||||
. 'WHEN nationality.countryCode IN(:europe_codes) THEN \'EU\' '
|
||||
. 'WHEN nationality.countryCode IN(:north_america_codes) THEN \'NA\' '
|
||||
. 'WHEN nationality.countryCode IN(:south_america_codes) THEN \'SA\' '
|
||||
. 'WHEN nationality.countryCode IN(:oceania_codes) THEN \'OC\' '
|
||||
. 'WHEN nationality.countryCode IN(:antartica_codes) THEN \'AN\' '
|
||||
. 'ELSE \'\' '
|
||||
. 'END as nationality_aggregator ';
|
||||
$qb->addSelect($clause);
|
||||
$params =
|
||||
array(
|
||||
'africa_codes' => CountriesInfo::getCountriesCodeByContinent('AF'),
|
||||
'asia_codes' => CountriesInfo::getCountriesCodeByContinent('AS'),
|
||||
'europe_codes' => CountriesInfo::getCountriesCodeByContinent('EU'),
|
||||
'north_america_codes' => CountriesInfo::getCountriesCodeByContinent('NA'),
|
||||
'south_america_codes' => CountriesInfo::getCountriesCodeByContinent('SA'),
|
||||
'oceania_codes' => CountriesInfo::getCountriesCodeByContinent('OC'),
|
||||
'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.nationality', 'nationality');
|
||||
|
||||
// add group by
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('nationality_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('nationality_aggregator');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Group people by nationality";
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array('nationality_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];
|
||||
};
|
||||
|
||||
}
|
||||
}
|
32
src/Bundle/ChillPerson/Export/Declarations.php
Normal file
32
src/Bundle/ChillPerson/Export/Declarations.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export;
|
||||
|
||||
/**
|
||||
* This class declare constants used for the export framework.
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
abstract class Declarations
|
||||
{
|
||||
CONST PERSON_TYPE = 'person';
|
||||
CONST PERSON_IMPLIED_IN = 'person_implied_in';
|
||||
}
|
136
src/Bundle/ChillPerson/Export/Export/CountPerson.php
Normal file
136
src/Bundle/ChillPerson/Export/Export/CountPerson.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Export;
|
||||
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CountPerson implements ExportInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em
|
||||
)
|
||||
{
|
||||
$this->entityManager = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return "Count peoples by various parameters.";
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Count peoples";
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
{
|
||||
return new Role(PersonVoter::STATS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the query
|
||||
*
|
||||
* @param QueryBuilder $qb
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
|
||||
{
|
||||
$centers = array_map(function($el) { return $el['center']; }, $acl);
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$qb->select('COUNT(person.id) AS export_result')
|
||||
->from('ChillPersonBundle:Person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
;
|
||||
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return array('export_result');
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
if ($key !== 'export_result') {
|
||||
throw new \LogicException("the key $key is not used by this export");
|
||||
}
|
||||
|
||||
$labels = array_combine($values, $values);
|
||||
$labels['_header'] = $this->getTitle();
|
||||
|
||||
return function($value) use ($labels) {
|
||||
return $labels[$value];
|
||||
};
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return array(FormatterInterface::TYPE_TABULAR);
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder) {
|
||||
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN);
|
||||
}
|
||||
|
||||
}
|
503
src/Bundle/ChillPerson/Export/Export/ListPerson.php
Normal file
503
src/Bundle/ChillPerson/Export/Export/ListPerson.php
Normal file
@ -0,0 +1,503 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Export\Export;
|
||||
|
||||
use Chill\MainBundle\Export\ListInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
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\PersonBundle\Entity\Person;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
|
||||
|
||||
/**
|
||||
* Render a list of peoples
|
||||
*
|
||||
* @author julien
|
||||
*/
|
||||
class ListPerson implements ListInterface, ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
protected $customFieldProvider;
|
||||
|
||||
protected $fields = array(
|
||||
'id', 'firstName', 'lastName', 'birthdate',
|
||||
'placeOfBirth', 'gender', 'memo', 'email', 'phonenumber',
|
||||
'mobilenumber', 'contactInfo', 'countryOfBirth', 'nationality',
|
||||
'address_street_address_1', 'address_street_address_2',
|
||||
'address_valid_from', 'address_postcode_label', 'address_postcode_code',
|
||||
'address_country_name', 'address_country_code', 'address_isnoaddress'
|
||||
);
|
||||
|
||||
private $slugs = [];
|
||||
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
CustomFieldProvider $customFieldProvider
|
||||
) {
|
||||
$this->entityManager = $em;
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->customFieldProvider = $customFieldProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param FormBuilderInterface $builder
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$choices = array_combine($this->fields, $this->fields);
|
||||
|
||||
foreach ($this->getCustomFields() as $cf) {
|
||||
$choices
|
||||
[$this->translatableStringHelper->localize($cf->getName())]
|
||||
=
|
||||
$cf->getSlug();
|
||||
}
|
||||
|
||||
// Add a checkbox to select fields
|
||||
$builder->add('fields', ChoiceType::class, array(
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'choices' => $choices,
|
||||
'label' => 'Fields to include in export',
|
||||
'choice_attr' => function($val, $key, $index) {
|
||||
// add a 'data-display-target' for address fields
|
||||
if (substr($val, 0, 8) === 'address_') {
|
||||
return ['data-display-target' => 'address_date'];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
'constraints' => [new Callback(array(
|
||||
'callback' => function($selected, ExecutionContextInterface $context) {
|
||||
if (count($selected) === 0) {
|
||||
$context->buildViolation('You must select at least one element')
|
||||
->atPath('fields')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
))]
|
||||
));
|
||||
|
||||
// add a date field for addresses
|
||||
$builder->add('address_date', DateType::class, array(
|
||||
'label' => "Address valid at this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array( 'class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
'required' => false,
|
||||
'block_name' => 'list_export_form_address_date'
|
||||
));
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
// get the field starting with address_
|
||||
$addressFields = array_filter(function($el) {
|
||||
return substr($el, 0, 8) === 'address_';
|
||||
}, $this->fields);
|
||||
|
||||
// check if there is one field starting with address in data
|
||||
if (count(array_intersect($data['fields'], $addressFields)) > 0) {
|
||||
// if a field address is checked, the date must not be empty
|
||||
if (empty($data['address_date'])) {
|
||||
$context
|
||||
->buildViolation("You must set this date if an address is checked")
|
||||
->atPath('address_date')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom fields associated with person
|
||||
*
|
||||
* @return CustomField[]
|
||||
*/
|
||||
private function getCustomFields()
|
||||
{
|
||||
return $this->entityManager
|
||||
->createQuery("SELECT cf "
|
||||
. "FROM ChillCustomFieldsBundle:CustomField cf "
|
||||
. "JOIN cf.customFieldGroup g "
|
||||
. "WHERE cf.type != :title AND g.entity LIKE :entity")
|
||||
->setParameters(array(
|
||||
'title' => 'title',
|
||||
'entity' => \addcslashes(Person::class, "\\")
|
||||
))
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return array(FormatterInterface::TYPE_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return "Create a list of people according to various filters.";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param type $key
|
||||
* @param array $values
|
||||
* @param type $data
|
||||
* @return type
|
||||
*/
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'birthdate':
|
||||
// for birthdate, we have to transform the string into a date
|
||||
// to format the date correctly.
|
||||
return function($value) {
|
||||
if ($value === '_header') { return 'birthdate'; }
|
||||
|
||||
if (empty($value))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
$date = \DateTime::createFromFormat('Y-m-d', $value);
|
||||
// check that the creation could occurs.
|
||||
if ($date === false) {
|
||||
throw new \Exception(sprintf("The value %s could "
|
||||
. "not be converted to %s", $value, \DateTime::class));
|
||||
}
|
||||
|
||||
return $date->format('d-m-Y');
|
||||
};
|
||||
case 'gender' :
|
||||
// for gender, we have to translate men/women statement
|
||||
return function($value) {
|
||||
if ($value === '_header') { return 'gender'; }
|
||||
|
||||
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());
|
||||
};
|
||||
case 'address_country_name':
|
||||
return function($value) use ($key) {
|
||||
if ($value === '_header') { return \strtolower($key); }
|
||||
|
||||
if ($value === NULL) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize(json_decode($value, true));
|
||||
};
|
||||
case 'address_isnoaddress':
|
||||
return function($value) use ($key) {
|
||||
if ($value === '_header') { return 'address.address_homeless'; }
|
||||
|
||||
if ($value) {
|
||||
return 'X';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
default:
|
||||
// for fields which are associated with person
|
||||
if (in_array($key, $this->fields)) {
|
||||
return function($value) use ($key) {
|
||||
if ($value === '_header') { return \strtolower($key); }
|
||||
|
||||
return $value;
|
||||
|
||||
};
|
||||
} else {
|
||||
return $this->getLabelForCustomField($key, $values, $data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getLabelForCustomField($key, array $values, $data)
|
||||
{
|
||||
// for fields which are custom fields
|
||||
/* @var $cf CustomField */
|
||||
$cf = $this->entityManager
|
||||
->getRepository(CustomField::class)
|
||||
->findOneBy(array('slug' => $this->DQLToSlug($key)));
|
||||
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
|
||||
$defaultFunction = function($value) use ($cf) {
|
||||
if ($value === '_header') {
|
||||
return $this->translatableStringHelper->localize($cf->getName());
|
||||
}
|
||||
|
||||
return $this->customFieldProvider
|
||||
->getCustomFieldByType($cf->getType())
|
||||
->render(json_decode($value, true), $cf, 'csv');
|
||||
};
|
||||
|
||||
if ($cfType instanceof CustomFieldChoice and $cfType->isMultiple($cf)) {
|
||||
return function($value) use ($cf, $cfType, $key) {
|
||||
$slugChoice = $this->extractInfosFromSlug($key)['additionnalInfos']['choiceSlug'];
|
||||
$decoded = \json_decode($value, true);
|
||||
|
||||
if ($value === '_header') {
|
||||
|
||||
$label = $cfType->getChoices($cf)[$slugChoice];
|
||||
|
||||
return $this->translatableStringHelper->localize($cf->getName())
|
||||
.' | '.$label;
|
||||
}
|
||||
|
||||
if ($slugChoice === '_other' and $cfType->isChecked($cf, $choiceSlug, $decoded)) {
|
||||
return $cfType->extractOtherValue($cf, $decoded);
|
||||
} else {
|
||||
return $cfType->isChecked($cf, $slugChoice, $decoded);
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
return $defaultFunction;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param type $data
|
||||
* @return type
|
||||
*/
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
$fields = array();
|
||||
|
||||
foreach ($data['fields'] as $key) {
|
||||
if (in_array($key, $this->fields)) {
|
||||
$fields[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
// add the key from slugs and return
|
||||
return \array_merge($fields, \array_keys($this->slugs));
|
||||
}
|
||||
|
||||
/**
|
||||
* clean a slug to be usable by DQL
|
||||
*
|
||||
* @param string $slugsanitize
|
||||
* @param string $type the type of the customfield, if required (currently only for choices)
|
||||
* @return string
|
||||
*/
|
||||
private function slugToDQL($slug, $type = "default", array $additionalInfos = [])
|
||||
{
|
||||
$uid = 'slug_'.\uniqid();
|
||||
|
||||
$this->slugs[$uid] = [
|
||||
'slug' => $slug,
|
||||
'type' => $type,
|
||||
'additionnalInfos' => $additionalInfos
|
||||
];
|
||||
|
||||
return $uid;
|
||||
}
|
||||
|
||||
private function DQLToSlug($cleanedSlug)
|
||||
{
|
||||
return $this->slugs[$cleanedSlug]['slug'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $cleanedSlug
|
||||
* @return an array with keys = 'slug', 'type', 'additionnalInfo'
|
||||
*/
|
||||
private function extractInfosFromSlug($slug)
|
||||
{
|
||||
return $this->slugs[$slug];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return "List peoples";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return Declarations::PERSON_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = array())
|
||||
{
|
||||
$centers = array_map(function($el) { return $el['center']; }, $acl);
|
||||
|
||||
// throw an error if any fields are present
|
||||
if (!\array_key_exists('fields', $data)) {
|
||||
throw new \Doctrine\DBAL\Exception\InvalidArgumentException("any fields "
|
||||
. "have been checked");
|
||||
}
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
foreach ($this->fields as $f) {
|
||||
if (in_array($f, $data['fields'])) {
|
||||
switch ($f) {
|
||||
case 'countryOfBirth':
|
||||
case 'nationality':
|
||||
$qb->addSelect(sprintf('IDENTITY(person.%s) as %s', $f, $f));
|
||||
break;
|
||||
case 'address_street_address_1':
|
||||
case 'address_street_address_2':
|
||||
case 'address_valid_from':
|
||||
case 'address_postcode_label':
|
||||
case 'address_postcode_code':
|
||||
case 'address_country_name':
|
||||
case 'address_country_code':
|
||||
case 'address_isnoaddress':
|
||||
|
||||
$qb->addSelect(sprintf(
|
||||
'GET_PERSON_ADDRESS_%s(person.id, :address_date) AS %s',
|
||||
// get the part after address_
|
||||
strtoupper(substr($f, 8)),
|
||||
$f));
|
||||
$qb->setParameter('address_date', $data['address_date']);
|
||||
break;
|
||||
default:
|
||||
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getCustomFields() as $cf) {
|
||||
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
|
||||
if ($cfType instanceof CustomFieldChoice and $cfType->isMultiple($cf)) {
|
||||
foreach($cfType->getChoices($cf) as $choiceSlug => $label) {
|
||||
$slug = $this->slugToDQL($cf->getSlug(), 'choice', [ 'choiceSlug' => $choiceSlug ]);
|
||||
$qb->addSelect(
|
||||
sprintf('GET_JSON_FIELD_BY_KEY(person.cFData, :slug%s) AS %s',
|
||||
$slug, $slug));
|
||||
$qb->setParameter(sprintf('slug%s', $slug), $cf->getSlug());
|
||||
}
|
||||
} else {
|
||||
$slug = $this->slugToDQL($cf->getSlug());
|
||||
$qb->addSelect(
|
||||
sprintf('GET_JSON_FIELD_BY_KEY(person.cFData, :slug%s) AS %s',
|
||||
$slug, $slug));
|
||||
$qb->setParameter(sprintf('slug%s', $slug), $cf->getSlug());
|
||||
}
|
||||
}
|
||||
|
||||
$qb
|
||||
->from('ChillPersonBundle:Person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
;
|
||||
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function requiredRole()
|
||||
{
|
||||
return new Role(PersonVoter::LISTS);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array(Declarations::PERSON_TYPE, Declarations::PERSON_IMPLIED_IN);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Chill\PersonBundle\Export\AbstractAccompanyingPeriodExportElement;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AccompanyingPeriodClosingFilter extends AbstractAccompanyingPeriodExportElement implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$this->addJoinAccompanyingPeriod($qb);
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('accompanying_period.closingDate', ':date_to'),
|
||||
$qb->expr()->gte('accompanying_period.closingDate', ':date_from'));
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('date_from', $data['date_from'], Type::DATE);
|
||||
$qb->setParameter('date_to', $data['date_to'], Type::DATE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period closed after this date",
|
||||
'data' => new \DateTime("-1 month"),
|
||||
));
|
||||
|
||||
$builder->add('date_to', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period closed before this date",
|
||||
'data' => new \DateTime(),
|
||||
));
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
"Filtered by accompanying period: persons having an accompanying period"
|
||||
. " closed between the %date_from% and %date_to%",
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return "Filter by accompanying period: closed between two dates";
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Chill\PersonBundle\Export\AbstractAccompanyingPeriodExportElement;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AccompanyingPeriodFilter extends AbstractAccompanyingPeriodExportElement implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$this->addJoinAccompanyingPeriod($qb);
|
||||
|
||||
$clause = $qb->expr()->andX();
|
||||
|
||||
$clause->add(
|
||||
$qb->expr()->lte('accompanying_period.openingDate', ':date_to')
|
||||
);
|
||||
$clause->add(
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->gte('accompanying_period.closingDate', ':date_from'),
|
||||
$qb->expr()->isNull('accompanying_period.closingDate')
|
||||
)
|
||||
);
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('date_from', $data['date_from'], Type::DATE);
|
||||
$qb->setParameter('date_to', $data['date_to'], Type::DATE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period opened after this date",
|
||||
'data' => new \DateTime("-1 month"),
|
||||
));
|
||||
|
||||
$builder->add('date_to', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period ending before this date, or "
|
||||
. "still opened at this date",
|
||||
'data' => new \DateTime(),
|
||||
));
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
"Filtered by accompanying period: persons having an accompanying period"
|
||||
. " opened after the %date_from% and closed before the %date_to% (or still opened "
|
||||
. "at the %date_to%)",
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return "Filter by accompanying period: active period";
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Champs Libres Cooperative <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Chill\PersonBundle\Export\AbstractAccompanyingPeriodExportElement;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AccompanyingPeriodOpeningFilter extends AbstractAccompanyingPeriodExportElement implements FilterInterface
|
||||
{
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$this->addJoinAccompanyingPeriod($qb);
|
||||
|
||||
$clause = $qb->expr()->andX(
|
||||
$qb->expr()->lte('accompanying_period.openingDate', ':date_to'),
|
||||
$qb->expr()->gte('accompanying_period.openingDate', ':date_from'));
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('date_from', $data['date_from'], Type::DATE);
|
||||
$qb->setParameter('date_to', $data['date_to'], Type::DATE);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period opened after this date",
|
||||
'data' => new \DateTime("-1 month"),
|
||||
));
|
||||
|
||||
$builder->add('date_to', ChillDateType::class, array(
|
||||
'label' => "Having an accompanying period opened before this date",
|
||||
'data' => new \DateTime(),
|
||||
));
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return [
|
||||
"Filtered by accompanying period: persons having an accompanying period"
|
||||
. " opened between the %date_from% and %date_to%",
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return "Filter by accompanying period: starting between two dates";
|
||||
}
|
||||
}
|
130
src/Bundle/ChillPerson/Export/Filter/BirthdateFilter.php
Normal file
130
src/Bundle/ChillPerson/Export/Filter/BirthdateFilter.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Validator\Constraints;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Chill\MainBundle\Form\Type\Export\FilterType;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class BirthdateFilter implements FilterInterface, ExportElementValidatedInterface
|
||||
{
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->between('person.birthdate', ':date_from',
|
||||
':date_to');
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('date_from', $data['date_from']);
|
||||
$qb->setParameter('date_to', $data['date_to']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('date_from', DateType::class, array(
|
||||
'label' => "Born after this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
$builder->add('date_to', DateType::class, array(
|
||||
'label' => "Born before this date",
|
||||
'data' => new \DateTime(),
|
||||
'attr' => array('class' => 'datepicker'),
|
||||
'widget'=> 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
$date_from = $data['date_from'];
|
||||
$date_to = $data['date_to'];
|
||||
|
||||
if ($date_from === null) {
|
||||
$context->buildViolation('The "date from" should not be empty')
|
||||
//->atPath('date_from')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if ($date_to === null) {
|
||||
$context->buildViolation('The "date to" should not be empty')
|
||||
//->atPath('date_to')
|
||||
->addViolation();
|
||||
}
|
||||
|
||||
if (
|
||||
($date_from !== null && $date_to !== null)
|
||||
&&
|
||||
$date_from >= $date_to
|
||||
) {
|
||||
$context->buildViolation('The date "date to" should be after the '
|
||||
. 'date given in "date from" field')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return array('Filtered by person\'s birtdate: '
|
||||
. 'between %date_from% and %date_to%', array(
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y')
|
||||
));
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by person\'s birthdate';
|
||||
}
|
||||
|
||||
}
|
139
src/Bundle/ChillPerson/Export/Filter/GenderFilter.php
Normal file
139
src/Bundle/ChillPerson/Export/Filter/GenderFilter.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class GenderFilter implements FilterInterface,
|
||||
ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_genders', ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Woman' => Person::FEMALE_GENDER,
|
||||
'Man' => Person::MALE_GENDER,
|
||||
'Both' => Person::BOTH_GENDER,
|
||||
'Not given' => 'null'
|
||||
),
|
||||
'multiple' => true,
|
||||
'expanded' => true
|
||||
));
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if (!is_array($data['accepted_genders']) || count($data['accepted_genders']) === 0 ) {
|
||||
$context->buildViolation("You should select an option")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$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) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('person_gender', \array_filter(
|
||||
$data['accepted_genders'],
|
||||
function($el) {
|
||||
return $el !== 'null';
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* A title which will be used in the label for the form
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filter by person gender';
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
$genders = [];
|
||||
|
||||
foreach ($data['accepted_genders'] as $g) {
|
||||
if ('null' === $g) {
|
||||
$genders[] = $this->translator->trans('Not given');
|
||||
} else {
|
||||
$genders[] = $this->translator->trans($g);
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
"Filtering by genders: only %genders%",
|
||||
[ "%genders%" => \implode(", ", $genders)]
|
||||
];
|
||||
}
|
||||
}
|
111
src/Bundle/ChillPerson/Export/Filter/NationalityFilter.php
Normal file
111
src/Bundle/ChillPerson/Export/Filter/NationalityFilter.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter;
|
||||
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\MainBundle\Entity\Country;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Form\Type\Select2CountryType;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class NationalityFilter implements FilterInterface,
|
||||
ExportElementValidatedInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelper $helper)
|
||||
{
|
||||
$this->translatableStringHelper = $helper;
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return 'person';
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('nationalities', Select2CountryType::class, array(
|
||||
'placeholder' => 'Choose countries'
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
{
|
||||
if ($data['nationalities'] === null) {
|
||||
$context->buildViolation("A nationality must be selected")
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('person.nationality', ':person_nationality');
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('person_nationality', array($data['nationalities']));
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return "Filter by person's nationality";
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
$countries = $data['nationalities'];
|
||||
|
||||
$names = array_map(function(Country $c) {
|
||||
return $this->translatableStringHelper->localize($c->getName());
|
||||
}, array($countries));
|
||||
|
||||
return array(
|
||||
"Filtered by nationality : %nationalities%",
|
||||
array('%nationalities%' => implode(", ", $names))
|
||||
);
|
||||
}
|
||||
}
|
132
src/Bundle/ChillPerson/Form/AccompanyingPeriodType.php
Normal file
132
src/Bundle/ChillPerson/Form/AccompanyingPeriodType.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Chill\MainBundle\Form\Type\UserPickerType;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Chill\PersonBundle\Form\Type\ClosingMotivePickerType;
|
||||
|
||||
/**
|
||||
* Class AccompanyingPeriodType
|
||||
*
|
||||
* @package Chill\PersonBundle\Form
|
||||
*/
|
||||
class AccompanyingPeriodType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* array of configuration for accompanying_periods.
|
||||
*
|
||||
* Contains whether we should add fields some optional fields (optional per
|
||||
* instance)
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $config = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string[] $config configuration of visibility of some fields
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
//if the period_action is close, date opening should not be seen
|
||||
if ($options['period_action'] !== 'close') {
|
||||
$builder
|
||||
->add('openingDate', DateType::class, [
|
||||
"required" => true,
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy'
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
// closingDate should be seen only if
|
||||
// period_action = close
|
||||
// OR ( period_action = update AND accompanying period is already closed )
|
||||
$accompanyingPeriod = $options['data'];
|
||||
|
||||
if (
|
||||
($options['period_action'] === 'close')
|
||||
OR
|
||||
($options['period_action'] === 'create')
|
||||
OR
|
||||
($options['period_action'] === 'update' AND !$accompanyingPeriod->isOpen())
|
||||
) {
|
||||
|
||||
$builder->add('closingDate', DateType::class, [
|
||||
'required' => true,
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy'
|
||||
]);
|
||||
|
||||
$builder->add('closingMotive', ClosingMotivePickerType::class);
|
||||
}
|
||||
|
||||
if ($this->config['user'] === 'visible') {
|
||||
$builder->add('user', UserPickerType::class, [
|
||||
'center' => $options['center'],
|
||||
'role' => new Role(PersonVoter::SEE),
|
||||
]);
|
||||
}
|
||||
|
||||
$builder->add('remark', TextareaType::class, [
|
||||
'required' => false
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => 'Chill\PersonBundle\Entity\AccompanyingPeriod'
|
||||
]);
|
||||
|
||||
$resolver
|
||||
->setRequired(['period_action'])
|
||||
->addAllowedTypes('period_action', 'string')
|
||||
->addAllowedValues('period_action', ['update', 'open', 'close', 'create'])
|
||||
->setRequired('center')
|
||||
->setAllowedTypes('center', Center::class)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormView $view
|
||||
* @param FormInterface $form
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
$view->vars['action'] = $options['period_action'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'chill_personbundle_accompanyingperiod';
|
||||
}
|
||||
}
|
138
src/Bundle/ChillPerson/Form/ChoiceLoader/PersonChoiceLoader.php
Normal file
138
src/Bundle/ChillPerson/Form/ChoiceLoader/PersonChoiceLoader.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Form\ChoiceLoader;
|
||||
|
||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
* Class PersonChoiceLoader
|
||||
*
|
||||
* @package Chill\PersonBundle\Form\ChoiceLoader
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PersonChoiceLoader implements ChoiceLoaderInterface
|
||||
{
|
||||
/**
|
||||
* @var EntityRepository
|
||||
*/
|
||||
protected $personRepository;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $lazyLoadedPersons = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $centers = [];
|
||||
|
||||
/**
|
||||
* PersonChoiceLoader constructor.
|
||||
*
|
||||
* @param EntityRepository $personRepository
|
||||
* @param array|null $centers
|
||||
*/
|
||||
public function __construct(
|
||||
EntityRepository $personRepository,
|
||||
array $centers = null
|
||||
) {
|
||||
$this->personRepository = $personRepository;
|
||||
if (NULL !== $centers) {
|
||||
$this->centers = $centers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasCenterFilter()
|
||||
{
|
||||
return count($this->centers) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $value
|
||||
* @return ChoiceListInterface
|
||||
*/
|
||||
public function loadChoiceList($value = null): ChoiceListInterface
|
||||
{
|
||||
$list = new \Symfony\Component\Form\ChoiceList\ArrayChoiceList(
|
||||
$this->lazyLoadedPersons,
|
||||
function(Person $p) use ($value) {
|
||||
return \call_user_func($value, $p);
|
||||
});
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @param null $value
|
||||
* @return array
|
||||
*/
|
||||
public function loadChoicesForValues(array $values, $value = null)
|
||||
{
|
||||
$choices = [];
|
||||
|
||||
foreach($values as $value) {
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$person = $this->personRepository->find($value);
|
||||
|
||||
if ($this->hasCenterFilter() &&
|
||||
!\in_array($person->getCenter(), $this->centers)) {
|
||||
throw new \RuntimeException("chosen a person not in correct center");
|
||||
}
|
||||
|
||||
$choices[] = $person;
|
||||
}
|
||||
|
||||
return $choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $choices
|
||||
* @param null $value
|
||||
* @return array|string[]
|
||||
*/
|
||||
public function loadValuesForChoices(array $choices, $value = null)
|
||||
{
|
||||
$values = [];
|
||||
|
||||
foreach ($choices as $choice) {
|
||||
if (NULL === $choice) {
|
||||
$values[] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = \call_user_func($value, $choice);
|
||||
$values[] = $id;
|
||||
$this->lazyLoadedPersons[$id] = $choice;
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
76
src/Bundle/ChillPerson/Form/ClosingMotiveType.php
Normal file
76
src/Bundle/ChillPerson/Form/ClosingMotiveType.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2014-2020, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
use Chill\PersonBundle\Form\Type\ClosingMotivePickerType;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
|
||||
/**
|
||||
* Class ClosingMotiveType
|
||||
*
|
||||
* @package Chill\PersonBundle\Form
|
||||
*/
|
||||
class ClosingMotiveType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('name', TranslatableStringFormType::class, [
|
||||
'label' => 'Nom'
|
||||
])
|
||||
->add('active', CheckboxType::class, [
|
||||
'label' => 'Actif ?',
|
||||
'required' => false
|
||||
])
|
||||
->add('ordering', NumberType::class, [
|
||||
'label' => 'Ordre d\'apparition',
|
||||
'required' => true,
|
||||
'scale' => 5
|
||||
])
|
||||
->add('parent', ClosingMotivePickerType::class, [
|
||||
'label' => 'Parent',
|
||||
'required' => false,
|
||||
'placeholder' => 'closing_motive.any parent',
|
||||
'multiple' => false,
|
||||
'only_leaf' => false
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setDefault('class', ClosingMotive::class)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
159
src/Bundle/ChillPerson/Form/CreationPersonType.php
Normal file
159
src/Bundle/ChillPerson/Form/CreationPersonType.php
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Chill\MainBundle\Form\Type\CenterType;
|
||||
use Chill\PersonBundle\Form\Type\GenderType;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
||||
|
||||
class CreationPersonType extends AbstractType
|
||||
{
|
||||
|
||||
const NAME = 'chill_personbundle_person_creation';
|
||||
|
||||
const FORM_NOT_REVIEWED = 'not_reviewed';
|
||||
const FORM_REVIEWED = 'reviewed' ;
|
||||
const FORM_BEING_REVIEWED = 'being_reviewed';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CenterTransformer
|
||||
*/
|
||||
private $centerTransformer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ConfigPersonAltNamesHelper
|
||||
*/
|
||||
protected $configPersonAltNamesHelper;
|
||||
|
||||
public function __construct(
|
||||
CenterTransformer $centerTransformer,
|
||||
ConfigPersonAltNamesHelper $configPersonAltNamesHelper
|
||||
) {
|
||||
$this->centerTransformer = $centerTransformer;
|
||||
$this->configPersonAltNamesHelper = $configPersonAltNamesHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($options['form_status'] === self::FORM_BEING_REVIEWED) {
|
||||
|
||||
$dateToStringTransformer = new DateTimeToStringTransformer(
|
||||
null, null, 'd-m-Y', false);
|
||||
|
||||
$builder->add('firstName', HiddenType::class)
|
||||
->add('lastName', HiddenType::class)
|
||||
->add('birthdate', HiddenType::class, array(
|
||||
'property_path' => 'birthdate'
|
||||
))
|
||||
->add('gender', HiddenType::class)
|
||||
->add('creation_date', HiddenType::class, array(
|
||||
'mapped' => false
|
||||
))
|
||||
->add('form_status', HiddenType::class, array(
|
||||
'mapped' => false,
|
||||
'data' => $options['form_status']
|
||||
))
|
||||
->add('center', HiddenType::class)
|
||||
;
|
||||
|
||||
if ($this->configPersonAltNamesHelper->hasAltNames()) {
|
||||
$builder->add('altNames', PersonAltNameType::class, [
|
||||
'by_reference' => false,
|
||||
'force_hidden' => true
|
||||
]);
|
||||
}
|
||||
|
||||
$builder->get('birthdate')
|
||||
->addModelTransformer($dateToStringTransformer);
|
||||
$builder->get('creation_date')
|
||||
->addModelTransformer($dateToStringTransformer);
|
||||
$builder->get('center')
|
||||
->addModelTransformer($this->centerTransformer);
|
||||
} else {
|
||||
$builder
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('birthdate', DateType::class, array('required' => false,
|
||||
'widget' => 'single_text', 'format' => 'dd-MM-yyyy'))
|
||||
->add('gender', GenderType::class, array(
|
||||
'required' => true, 'placeholder' => null
|
||||
))
|
||||
->add('creation_date', DateType::class, array(
|
||||
'required' => true,
|
||||
'widget' => 'single_text',
|
||||
'format' => 'dd-MM-yyyy',
|
||||
'mapped' => false,
|
||||
'data' => new \DateTime()))
|
||||
->add('form_status', HiddenType::class, array(
|
||||
'data' => $options['form_status'],
|
||||
'mapped' => false
|
||||
))
|
||||
->add('center', CenterType::class)
|
||||
;
|
||||
|
||||
if ($this->configPersonAltNamesHelper->hasAltNames()) {
|
||||
$builder->add('altNames', PersonAltNameType::class, [
|
||||
'by_reference' => false
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\PersonBundle\Entity\Person'
|
||||
));
|
||||
|
||||
$resolver->setRequired('form_status')
|
||||
->setAllowedValues('form_status', array(
|
||||
self::FORM_BEING_REVIEWED,
|
||||
self::FORM_NOT_REVIEWED,
|
||||
self::FORM_REVIEWED
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return self::NAME;
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form\DataMapper;
|
||||
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Chill\PersonBundle\Entity\PersonAltName;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PersonAltNameDataMapper implements DataMapperInterface
|
||||
{
|
||||
public function mapDataToForms($viewData, $forms)
|
||||
{
|
||||
if (null === $viewData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$viewData instanceof Collection) {
|
||||
throw new UnexpectedTypeException($viewData, Collection::class);
|
||||
}
|
||||
|
||||
$mapIndexToKey = [];
|
||||
foreach ($viewData->getIterator() as $key => $altName) {
|
||||
/** @var PersonAltName $altName */
|
||||
$mapIndexToKey[$altName->getKey()] = $key;
|
||||
}
|
||||
|
||||
foreach ($forms as $key => $form) {
|
||||
if (\array_key_exists($key, $mapIndexToKey)) {
|
||||
$form->setData($viewData->get($mapIndexToKey[$key])->getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param FormInterface[] $forms
|
||||
* @param Collection $viewData
|
||||
*/
|
||||
public function mapFormsToData($forms, &$viewData)
|
||||
{
|
||||
$mapIndexToKey = [];
|
||||
|
||||
if (is_array($viewData)) {
|
||||
$dataIterator = $viewData;
|
||||
} else {
|
||||
$dataIterator = $viewData instanceof ArrayCollection ?
|
||||
$viewData->toArray() : $viewData->getIterator();
|
||||
}
|
||||
|
||||
foreach ($dataIterator as $key => $altName) {
|
||||
/** @var PersonAltName $altName */
|
||||
$mapIndexToKey[$altName->getKey()] = $key;
|
||||
}
|
||||
|
||||
foreach ($forms as $key => $form) {
|
||||
$isEmpty = empty($form->getData());
|
||||
|
||||
if (\array_key_exists($key, $mapIndexToKey)) {
|
||||
if ($isEmpty) {
|
||||
$viewData->remove($mapIndexToKey[$key]);
|
||||
} else {
|
||||
$viewData->get($mapIndexToKey[$key])->setLabel($form->getData());
|
||||
}
|
||||
} else {
|
||||
if (!$isEmpty) {
|
||||
$altName = (new PersonAltName())
|
||||
->setKey($key)
|
||||
->setLabel($form->getData())
|
||||
;
|
||||
|
||||
if (is_array($viewData)) {
|
||||
$viewData[] = $altName;
|
||||
} else {
|
||||
$viewData->add($altName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
class PersonToIdTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $om
|
||||
*/
|
||||
public function __construct(ObjectManager $om)
|
||||
{
|
||||
$this->om = $om;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an object (issue) to a string (id).
|
||||
*
|
||||
* @param Person|null $issue
|
||||
* @return string
|
||||
*/
|
||||
public function transform($issue)
|
||||
{
|
||||
if (null === $issue) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return $issue->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a string (id) to an object (issue).
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return Person|null
|
||||
*
|
||||
* @throws TransformationFailedException if object (issue) is not found.
|
||||
*/
|
||||
public function reverseTransform($id)
|
||||
{
|
||||
if (!$id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$issue = $this->om
|
||||
->getRepository('ChillPersonBundle:Person')
|
||||
->findOneBy(array('id' => $id))
|
||||
;
|
||||
|
||||
if (null === $issue) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'An issue with id "%s" does not exist!',
|
||||
$id
|
||||
));
|
||||
}
|
||||
|
||||
return $issue;
|
||||
}
|
||||
}
|
||||
?>
|
45
src/Bundle/ChillPerson/Form/MaritalStatusType.php
Normal file
45
src/Bundle/ChillPerson/Form/MaritalStatusType.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Chill\PersonBundle\Entity\MaritalStatus;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* Class MaritalStatusType
|
||||
*
|
||||
* @package Chill\PersonBundle\Form
|
||||
*/
|
||||
class MaritalStatusType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('id', TextType::class, [
|
||||
'label' => 'Identifiant'
|
||||
])
|
||||
->add('name', TranslatableStringFormType::class, [
|
||||
'label' => 'Nom'
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setDefault('class', MaritalStatus::class)
|
||||
;
|
||||
}
|
||||
}
|
175
src/Bundle/ChillPerson/Form/PersonType.php
Normal file
175
src/Bundle/ChillPerson/Form/PersonType.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TelType;
|
||||
use Chill\PersonBundle\Form\Type\GenderType;
|
||||
use Chill\MainBundle\Form\Type\Select2CountryType;
|
||||
use Chill\MainBundle\Form\Type\Select2LanguageType;
|
||||
use Chill\CustomFieldsBundle\Form\Type\CustomFieldType;
|
||||
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
use Chill\PersonBundle\Form\Type\PersonAltNameType;
|
||||
|
||||
class PersonType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* array of configuration for person_fields.
|
||||
*
|
||||
* Contains whether we should add fields some optional fields (optional per
|
||||
* instance)
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $config = array();
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ConfigPersonAltNamesHelper
|
||||
*/
|
||||
protected $configAltNamesHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string[] $personFieldsConfiguration configuration of visibility of some fields
|
||||
*/
|
||||
public function __construct(
|
||||
array $personFieldsConfiguration,
|
||||
ConfigPersonAltNamesHelper $configAltNamesHelper
|
||||
) {
|
||||
$this->config = $personFieldsConfiguration;
|
||||
$this->configAltNamesHelper = $configAltNamesHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('firstName')
|
||||
->add('lastName')
|
||||
->add('birthdate', DateType::class, array('required' => false, 'widget' => 'single_text', 'format' => 'dd-MM-yyyy'))
|
||||
->add('gender', GenderType::class, array(
|
||||
'required' => true
|
||||
));
|
||||
|
||||
if ($this->configAltNamesHelper->hasAltNames()) {
|
||||
$builder->add('altNames', PersonAltNameType::class, [
|
||||
'by_reference' => false
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->config['memo'] === 'visible') {
|
||||
$builder
|
||||
->add('memo', TextareaType::class, array('required' => false))
|
||||
;
|
||||
}
|
||||
|
||||
if ($this->config['place_of_birth'] === 'visible') {
|
||||
$builder->add('placeOfBirth', TextType::class, array('required' => false));
|
||||
}
|
||||
|
||||
if ($this->config['contact_info'] === 'visible') {
|
||||
$builder->add('contactInfo', TextareaType::class, array('required' => false));
|
||||
}
|
||||
|
||||
if ($this->config['phonenumber'] === 'visible') {
|
||||
$builder->add('phonenumber', TelType::class, array('required' => false));
|
||||
}
|
||||
|
||||
if ($this->config['mobilenumber'] === 'visible') {
|
||||
$builder->add('mobilenumber', TelType::class, array('required' => false));
|
||||
}
|
||||
|
||||
if ($this->config['email'] === 'visible') {
|
||||
$builder->add('email', EmailType::class, array('required' => false));
|
||||
}
|
||||
|
||||
if ($this->config['country_of_birth'] === 'visible') {
|
||||
$builder->add('countryOfBirth', Select2CountryType::class, array(
|
||||
'required' => false
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->config['nationality'] === 'visible') {
|
||||
$builder->add('nationality', Select2CountryType::class, array(
|
||||
'required' => false
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->config['spoken_languages'] === 'visible') {
|
||||
$builder->add('spokenLanguages', Select2LanguageType::class, array(
|
||||
'required' => false,
|
||||
'multiple' => true
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->config['marital_status'] === 'visible'){
|
||||
$builder->add('maritalStatus', Select2MaritalStatusType::class, array(
|
||||
'required' => false
|
||||
));
|
||||
}
|
||||
|
||||
if($options['cFGroup']) {
|
||||
$builder
|
||||
->add('cFData', CustomFieldType::class,
|
||||
array('attr' => array('class' => 'cf-fields'), 'group' => $options['cFGroup']))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolverInterface $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\PersonBundle\Entity\Person',
|
||||
'validation_groups' => array('general', 'creation')
|
||||
));
|
||||
|
||||
$resolver->setRequired(array(
|
||||
'cFGroup'
|
||||
));
|
||||
|
||||
$resolver->setAllowedTypes(
|
||||
'cFGroup', array('null', 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'chill_personbundle_person';
|
||||
}
|
||||
}
|
98
src/Bundle/ChillPerson/Form/Type/ClosingMotivePickerType.php
Normal file
98
src/Bundle/ChillPerson/Form/Type/ClosingMotivePickerType.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\ClosingMotive;
|
||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Chill\PersonBundle\Repository\ClosingMotiveRepository;
|
||||
|
||||
/**
|
||||
* Class ClosingMotivePickerType
|
||||
* A type to add a closing motive
|
||||
*
|
||||
* @package Chill\PersonBundle\Form\Type
|
||||
*/
|
||||
class ClosingMotivePickerType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
protected $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* @var ChillEntityRenderExtension
|
||||
*/
|
||||
protected $entityRenderExtension;
|
||||
|
||||
/**
|
||||
* @var ClosingMotiveRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* ClosingMotivePickerType constructor.
|
||||
*
|
||||
* @param TranslatableStringHelper $translatableStringHelper
|
||||
* @param ChillEntityRenderExtension $chillEntityRenderExtension
|
||||
* @param ClosingMotiveRepository $closingMotiveRepository
|
||||
*/
|
||||
public function __construct(
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
ChillEntityRenderExtension $chillEntityRenderExtension,
|
||||
ClosingMotiveRepository $closingMotiveRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->entityRenderExtension = $chillEntityRenderExtension;
|
||||
$this->repository = $closingMotiveRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'closing_motive';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return EntityType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolver $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
|
||||
$resolver->setDefaults([
|
||||
'class' => ClosingMotive::class,
|
||||
'empty_data' => null,
|
||||
'placeholder' => 'Choose a motive',
|
||||
'choice_label' => function(ClosingMotive $cm) {
|
||||
return $this->entityRenderExtension->renderString($cm);
|
||||
},
|
||||
'only_leaf' => true
|
||||
]);
|
||||
|
||||
$resolver
|
||||
->setAllowedTypes('only_leaf', 'bool')
|
||||
->setNormalizer('choices', function (Options $options) {
|
||||
return $this->repository
|
||||
->getActiveClosingMotive($options['only_leaf']);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
}
|
38
src/Bundle/ChillPerson/Form/Type/GenderType.php
Normal file
38
src/Bundle/ChillPerson/Form/Type/GenderType.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
* A type to select the civil union state
|
||||
*
|
||||
* @author julien
|
||||
*/
|
||||
class GenderType extends AbstractType {
|
||||
|
||||
public function getParent() {
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver) {
|
||||
|
||||
$a = array(
|
||||
Person::MALE_GENDER => Person::MALE_GENDER,
|
||||
Person::FEMALE_GENDER => Person::FEMALE_GENDER,
|
||||
Person::BOTH_GENDER => Person::BOTH_GENDER
|
||||
);
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
'choices' => $a,
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'placeholder' => null
|
||||
));
|
||||
}
|
||||
|
||||
}
|
76
src/Bundle/ChillPerson/Form/Type/PersonAltNameType.php
Normal file
76
src/Bundle/ChillPerson/Form/Type/PersonAltNameType.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class PersonAltNameType extends AbstractType
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var ConfigPersonAltNamesHelper
|
||||
*/
|
||||
private $configHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ConfigPersonAltNamesHelper $configHelper,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->configHelper = $configHelper;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
foreach ($this->getKeyChoices() as $label => $key) {
|
||||
$builder->add(
|
||||
$key,
|
||||
$options['force_hidden'] ? HiddenType::class : TextType::class, [
|
||||
'label' => $label,
|
||||
'required' => false
|
||||
]);
|
||||
}
|
||||
|
||||
$builder->setDataMapper(new \Chill\PersonBundle\Form\DataMapper\PersonAltNameDataMapper());
|
||||
}
|
||||
|
||||
protected function getKeyChoices()
|
||||
{
|
||||
$choices = $this->configHelper->getChoices();
|
||||
$translatedChoices = [];
|
||||
|
||||
foreach ($choices as $key => $labels) {
|
||||
$label = $this->translatableStringHelper->localize($labels);
|
||||
$translatedChoices[$label] = $key;
|
||||
}
|
||||
|
||||
return $translatedChoices;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setDefault('class', \Chill\PersonBundle\Entity\PersonAltName::class)
|
||||
->setDefined('force_hidden')
|
||||
->setAllowedTypes('force_hidden', 'bool')
|
||||
->setDefault('force_hidden', false)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
191
src/Bundle/ChillPerson/Form/Type/PickPersonType.php
Normal file
191
src/Bundle/ChillPerson/Form/Type/PickPersonType.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use Chill\PersonBundle\Search\PersonSearch;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Chill\PersonBundle\Form\ChoiceLoader\PersonChoiceLoader;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
|
||||
/**
|
||||
* This type allow to pick a person.
|
||||
*
|
||||
* The form is embedded in a select2 input.
|
||||
*
|
||||
* The people may be filtered :
|
||||
*
|
||||
* - with the `centers` option, only the people associated with the given center(s)
|
||||
* are seen. May be an instance of `Chill\MainBundle\Entity\Center`, or an array of
|
||||
* `Chill\MainBundle\Entity\Center`. By default, all the reachable centers as selected.
|
||||
* - with the `role` option, only the people belonging to the reachable center for the
|
||||
* given role are displayed.
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PickPersonType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var PersonRepository
|
||||
*/
|
||||
protected $personRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\MainBundle\Entity\User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $authorizationHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(
|
||||
PersonRepository $personRepository,
|
||||
TokenStorageInterface $tokenStorage,
|
||||
AuthorizationHelper $authorizationHelper,
|
||||
UrlGeneratorInterface $urlGenerator,
|
||||
TranslatorInterface $translator
|
||||
)
|
||||
{
|
||||
$this->personRepository = $personRepository;
|
||||
$this->user = $tokenStorage->getToken()->getUser();
|
||||
$this->authorizationHelper = $authorizationHelper;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
protected function filterCentersfom(Options $options)
|
||||
{
|
||||
if ($options['role'] === NULL) {
|
||||
$centers = array_map(function (GroupCenter $g) {
|
||||
|
||||
return $g->getCenter();
|
||||
}, $this->user->getGroupCenters()->toArray());
|
||||
} else {
|
||||
$centers = $this->authorizationHelper
|
||||
->getReachableCenters($this->user, $options['role']);
|
||||
}
|
||||
|
||||
if ($options['centers'] === NULL) {
|
||||
// we select all selected centers
|
||||
$selectedCenters = $centers;
|
||||
} else {
|
||||
$selectedCenters = array();
|
||||
$optionsCenters = is_array($options['centers']) ?
|
||||
$options['centers'] : array($options['centers']);
|
||||
|
||||
foreach ($optionsCenters as $c) {
|
||||
// check that every member of the array is a center
|
||||
if (!$c instanceof Center) {
|
||||
throw new \RuntimeException('Every member of the "centers" '
|
||||
. 'option must be an instance of '.Center::class);
|
||||
}
|
||||
if (!in_array($c->getId(), array_map(
|
||||
function(Center $c) { return $c->getId();},
|
||||
$centers))) {
|
||||
throw new AccessDeniedException('The given center is not reachable');
|
||||
}
|
||||
$selectedCenters[] = $c;
|
||||
}
|
||||
}
|
||||
|
||||
return $selectedCenters;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
parent::configureOptions($resolver);
|
||||
|
||||
// add the possibles options for this type
|
||||
$resolver->setDefined('centers')
|
||||
->addAllowedTypes('centers', array('array', Center::class, 'null'))
|
||||
->setDefault('centers', null)
|
||||
->setDefined('role')
|
||||
->addAllowedTypes('role', array(Role::class, 'null'))
|
||||
->setDefault('role', null)
|
||||
;
|
||||
|
||||
// add the default options
|
||||
$resolver->setDefaults(array(
|
||||
'class' => Person::class,
|
||||
'choice_label' => function(Person $p) {
|
||||
return $p->getFirstname().' '.$p->getLastname();
|
||||
},
|
||||
'placeholder' => 'Pick a person',
|
||||
'choice_attr' => function(Person $p) {
|
||||
return array(
|
||||
'data-center' => $p->getCenter()->getId()
|
||||
);
|
||||
},
|
||||
'attr' => array('class' => 'select2 '),
|
||||
'choice_loader' => function(Options $options) {
|
||||
$centers = $this->filterCentersfom($options);
|
||||
|
||||
return new PersonChoiceLoader($this->personRepository, $centers);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return EntityType::class;
|
||||
}
|
||||
|
||||
public function buildView(\Symfony\Component\Form\FormView $view, \Symfony\Component\Form\FormInterface $form, array $options)
|
||||
{
|
||||
$view->vars['attr']['data-person-picker'] = true;
|
||||
$view->vars['attr']['data-select-interactive-loading'] = true;
|
||||
$view->vars['attr']['data-search-url'] = $this->urlGenerator
|
||||
->generate('chill_main_search', [ 'name' => PersonSearch::NAME, '_format' => 'json' ]);
|
||||
$view->vars['attr']['data-placeholder'] = $this->translator->trans($options['placeholder']);
|
||||
$view->vars['attr']['data-no-results-label'] = $this->translator->trans('select2.no_results');
|
||||
$view->vars['attr']['data-error-load-label'] = $this->translator->trans('select2.error_loading');
|
||||
$view->vars['attr']['data-searching-label'] = $this->translator->trans('select2.searching');
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, <http://www.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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Chill\MainBundle\Form\Type\DataTransformer\ObjectToIdTransformer;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\MainBundle\Form\Type\Select2ChoiceType;
|
||||
|
||||
/**
|
||||
* A type to select the marital status
|
||||
*
|
||||
* @author Champs-Libres COOP
|
||||
*/
|
||||
class Select2MaritalStatusType extends AbstractType
|
||||
{
|
||||
/** @var RequestStack */
|
||||
private $requestStack;
|
||||
|
||||
/** @var ObjectManager */
|
||||
private $em;
|
||||
|
||||
public function __construct(RequestStack $requestStack,ObjectManager $em)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function getBlockPrefix() {
|
||||
return 'select2_chill_marital_status';
|
||||
}
|
||||
|
||||
public function getParent() {
|
||||
return Select2ChoiceType::class;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$transformer = new ObjectToIdTransformer($this->em,'Chill\PersonBundle\Entity\MaritalStatus');
|
||||
$builder->addModelTransformer($transformer);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$locale = $this->requestStack->getCurrentRequest()->getLocale();
|
||||
$maritalStatuses = $this->em->getRepository('Chill\PersonBundle\Entity\MaritalStatus')->findAll();
|
||||
$choices = array();
|
||||
|
||||
foreach ($maritalStatuses as $ms) {
|
||||
$choices[$ms->getId()] = $ms->getName()[$locale];
|
||||
}
|
||||
|
||||
asort($choices, SORT_STRING | SORT_FLAG_CASE);
|
||||
|
||||
$resolver->setDefaults(array(
|
||||
'class' => 'Chill\PersonBundle\Entity\MaritalStatus',
|
||||
'choices' => array_combine(array_values($choices),array_keys($choices))
|
||||
));
|
||||
}
|
||||
}
|
661
src/Bundle/ChillPerson/LICENSE
Normal file
661
src/Bundle/ChillPerson/LICENSE
Normal file
@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
61
src/Bundle/ChillPerson/Menu/AdminMenuBuilder.php
Normal file
61
src/Bundle/ChillPerson/Menu/AdminMenuBuilder.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AdminMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
protected $authorizationChecker;
|
||||
|
||||
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
|
||||
{
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
}
|
||||
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$menu->addChild('Person', [
|
||||
'route' => 'chill_person_admin'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 20
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'admin_section' ];
|
||||
}
|
||||
}
|
84
src/Bundle/ChillPerson/Menu/PersonMenuBuilder.php
Normal file
84
src/Bundle/ChillPerson/Menu/PersonMenuBuilder.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Add menu entrie to person menu.
|
||||
*
|
||||
* Menu entries added :
|
||||
*
|
||||
* - person details ;
|
||||
* - accompanying period (if `visible`)
|
||||
*
|
||||
*/
|
||||
class PersonMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string 'visible' or 'hidden'
|
||||
*/
|
||||
protected $showAccompanyingPeriod;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(
|
||||
$showAccompanyingPeriod,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->showAccompanyingPeriod = $showAccompanyingPeriod;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
$menu->addChild($this->translator->trans('Person details'), [
|
||||
'route' => 'chill_person_view',
|
||||
'routeParameters' => [
|
||||
'person_id' => $parameters['person']->getId()
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 50
|
||||
]);
|
||||
|
||||
if ($this->showAccompanyingPeriod === 'visible') {
|
||||
$menu->addChild($this->translator->trans('Accompanying period list'), [
|
||||
'route' => 'chill_person_accompanying_period_list',
|
||||
'routeParameters' => [
|
||||
'person_id' => $parameters['person']->getId()
|
||||
]
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 100
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'person' ];
|
||||
}
|
||||
}
|
83
src/Bundle/ChillPerson/Menu/SectionMenuBuilder.php
Normal file
83
src/Bundle/ChillPerson/Menu/SectionMenuBuilder.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Champs-Libres <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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Menu;
|
||||
|
||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||
use Knp\Menu\MenuItem;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Class SectionMenuBuilder
|
||||
*
|
||||
* @package Chill\PersonBundle\Menu
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class SectionMenuBuilder implements LocalMenuBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
protected $authorizationChecker;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* SectionMenuBuilder constructor.
|
||||
*
|
||||
* @param AuthorizationCheckerInterface $authorizationChecker
|
||||
* @param TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(AuthorizationCheckerInterface $authorizationChecker, TranslatorInterface $translator)
|
||||
{
|
||||
$this->authorizationChecker = $authorizationChecker;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $menuId
|
||||
* @param MenuItem $menu
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters)
|
||||
{
|
||||
if ($this->authorizationChecker->isGranted(PersonVoter::CREATE)) {
|
||||
$menu->addChild($this->translator->trans('Add a person'), [
|
||||
'route' => 'chill_person_new'
|
||||
])
|
||||
->setExtras([
|
||||
'order' => 10,
|
||||
'icons' => [ 'plus' ]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getMenuIds(): array
|
||||
{
|
||||
return [ 'section' ];
|
||||
}
|
||||
}
|
110
src/Bundle/ChillPerson/Privacy/PrivacyEvent.php
Normal file
110
src/Bundle/ChillPerson/Privacy/PrivacyEvent.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Privacy;
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
/**
|
||||
* Class PrivacyEvent
|
||||
*
|
||||
* Array $args expects arguments with the following keys: 'element_class', 'element_id', 'action'
|
||||
* By default, action is set to 'show'
|
||||
*
|
||||
* @package Chill\PersonBundle\Privacy
|
||||
*/
|
||||
class PrivacyEvent extends Event
|
||||
{
|
||||
const PERSON_PRIVACY_EVENT = 'chill_person.privacy_event';
|
||||
|
||||
/**
|
||||
* @var Person
|
||||
*/
|
||||
private $person;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $args;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $persons;
|
||||
|
||||
/**
|
||||
* PrivacyEvent constructor.
|
||||
*
|
||||
* @param Person $person
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct(Person $person, array $args = array('action' => 'show'))
|
||||
{
|
||||
$this->person = $person;
|
||||
$this->args = $args;
|
||||
$this->persons = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Person
|
||||
*/
|
||||
public function getPerson()
|
||||
{
|
||||
return $this->person;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Person $person
|
||||
*/
|
||||
public function addPerson(Person $person)
|
||||
{
|
||||
$this->persons[] = $person;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array $persons
|
||||
*/
|
||||
public function getPersons()
|
||||
{
|
||||
return $this->persons;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPersons()
|
||||
{
|
||||
return count($this->persons) >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArgs()
|
||||
{
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
}
|
89
src/Bundle/ChillPerson/Privacy/PrivacyEventSubscriber.php
Normal file
89
src/Bundle/ChillPerson/Privacy/PrivacyEventSubscriber.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Privacy;
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
* <http://www.champs-libres.coop>, <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/>.
|
||||
*/
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
|
||||
class PrivacyEventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var TokenStorageInterface
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* PrivacyEventSubscriber constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger, TokenStorageInterface $token)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(PrivacyEvent::PERSON_PRIVACY_EVENT => array(
|
||||
array('onPrivacyEvent')
|
||||
));
|
||||
}
|
||||
|
||||
public function onPrivacyEvent(PrivacyEvent $event)
|
||||
{
|
||||
$persons = array();
|
||||
|
||||
if ($event->hasPersons() === true) {
|
||||
foreach ($event->getPersons() as $person) {
|
||||
$persons[] = $person->getId();
|
||||
}
|
||||
}
|
||||
|
||||
$involved = array(
|
||||
'by_user' => $this->token->getToken()->getUser()->getUsername(),
|
||||
'by_user_id' => $this->token->getToken()->getUser()->getId(),
|
||||
'person_id' => $event->getPerson()->getId(),
|
||||
);
|
||||
|
||||
if ($event->hasPersons()) {
|
||||
$involved['persons'] = \array_map(
|
||||
function(Person $p) { return $p->getId(); },
|
||||
$event->getPersons()
|
||||
);
|
||||
}
|
||||
|
||||
$this->logger->notice(
|
||||
"[Privacy Event] A Person Folder has been viewed",
|
||||
array_merge($involved, $event->getArgs())
|
||||
);
|
||||
}
|
||||
}
|
9
src/Bundle/ChillPerson/README.md
Normal file
9
src/Bundle/ChillPerson/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
ChillPersonBundle
|
||||
=================
|
||||
|
||||
The chill bundle for dealing with persons
|
||||
|
||||
Documentation & installation
|
||||
----------------------------
|
||||
|
||||
Read documentation here : http://chill.readthedocs.org
|
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2020 Champs-Libres <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/>.
|
||||
*/
|
||||
namespace Chill\PersonBundle\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||
|
||||
/**
|
||||
* Class ClosingMotiveRepository
|
||||
* Entity repository for closing motives
|
||||
*
|
||||
* @package Chill\PersonBundle\Repository
|
||||
*/
|
||||
class ClosingMotiveRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
* @param bool $onlyLeaf
|
||||
* @return mixed
|
||||
*/
|
||||
public function getActiveClosingMotive(bool $onlyLeaf = true)
|
||||
{
|
||||
$rsm = new ResultSetMappingBuilder($this->getEntityManager());
|
||||
$rsm->addRootEntityFromClassMetadata($this->getClassName(), 'cm');
|
||||
|
||||
$sql = "SELECT ".(string) $rsm."
|
||||
FROM chill_person_closingmotive AS cm
|
||||
WHERE
|
||||
active IS TRUE ";
|
||||
|
||||
if ($onlyLeaf) {
|
||||
$sql .= "AND cm.id NOT IN (
|
||||
SELECT DISTINCT parent_id FROM chill_person_closingmotive WHERE parent_id IS NOT NULL
|
||||
)";
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY cm.ordering ASC";
|
||||
|
||||
return $this->_em
|
||||
->createNativeQuery($sql, $rsm)
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\PersonBundle\Repository;
|
||||
|
||||
/**
|
||||
* PersonAltNameRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class PersonAltNameRepository extends \Doctrine\ORM\EntityRepository
|
||||
{
|
||||
}
|
131
src/Bundle/ChillPerson/Repository/PersonRepository.php
Normal file
131
src/Bundle/ChillPerson/Repository/PersonRepository.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (C) 2019 Julien Fastré <julien.fastre@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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
/**
|
||||
* Class PersonRepository
|
||||
*
|
||||
* @package Chill\PersonBundle\Repository
|
||||
*/
|
||||
class PersonRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
* @param string $phonenumber
|
||||
* @param $centers
|
||||
* @param $firstResult
|
||||
* @param $maxResults
|
||||
* @param array $only
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function findByPhone(
|
||||
string $phonenumber,
|
||||
$centers,
|
||||
$firstResult,
|
||||
$maxResults,
|
||||
array $only = ['mobile', 'phone']
|
||||
) {
|
||||
$qb = $this->createQueryBuilder('p');
|
||||
$qb->select('p');
|
||||
|
||||
$this->addByCenters($qb, $centers);
|
||||
$this->addPhoneNumber($qb, $phonenumber, $only);
|
||||
|
||||
$qb->setFirstResult($firstResult)
|
||||
->setMaxResults($maxResults)
|
||||
;
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $phonenumber
|
||||
* @param $centers
|
||||
* @param array $only
|
||||
* @return int
|
||||
* @throws \Doctrine\ORM\NoResultException
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function countByPhone(
|
||||
string $phonenumber,
|
||||
$centers,
|
||||
array $only = ['mobile', 'phone']
|
||||
): int
|
||||
{
|
||||
$qb = $this->createQueryBuilder('p');
|
||||
$qb->select('COUNT(p)');
|
||||
|
||||
$this->addByCenters($qb, $centers);
|
||||
$this->addPhoneNumber($qb, $phonenumber, $only);
|
||||
|
||||
return $qb->getQuery()->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryBuilder $qb
|
||||
* @param string $phonenumber
|
||||
* @param array $only
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function addPhoneNumber(QueryBuilder $qb, string $phonenumber, array $only)
|
||||
{
|
||||
if (count($only) === 0) {
|
||||
throw new \Exception("No array field to search");
|
||||
}
|
||||
|
||||
$phonenumber = $this->parsePhoneNumber($phonenumber);
|
||||
|
||||
$orX = $qb->expr()->orX();
|
||||
|
||||
if (\in_array('mobile', $only)) {
|
||||
$orX->add($qb->expr()->like("REPLACE(p.mobilenumber, ' ', '')", ':phonenumber'));
|
||||
}
|
||||
if (\in_array('phone', $only)) {
|
||||
$orX->add($qb->expr()->like("REPLACE(p.phonenumber, ' ', '')", ':phonenumber'));
|
||||
}
|
||||
|
||||
$qb->andWhere($orX);
|
||||
|
||||
$qb->setParameter('phonenumber', '%'.$phonenumber.'%');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $phonenumber
|
||||
* @return string
|
||||
*/
|
||||
protected function parsePhoneNumber($phonenumber): string
|
||||
{
|
||||
return \str_replace(' ', '', $phonenumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QueryBuilder $qb
|
||||
* @param array $centers
|
||||
*/
|
||||
protected function addByCenters(QueryBuilder $qb, array $centers)
|
||||
{
|
||||
if (count($centers) > 0) {
|
||||
$qb->andWhere($qb->expr()->in('p.center', ':centers'));
|
||||
$qb->setParameter('centers', $centers);
|
||||
}
|
||||
}
|
||||
}
|
46
src/Bundle/ChillPerson/Resources/Gruntfile.js
Normal file
46
src/Bundle/ChillPerson/Resources/Gruntfile.js
Normal file
@ -0,0 +1,46 @@
|
||||
module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
chillperson: {
|
||||
folders: {
|
||||
pub: './public',
|
||||
css: '<%= chillperson.folders.pub %>/css/',
|
||||
sass: '<%= chillperson.folders.pub %>/sass/',
|
||||
}
|
||||
},
|
||||
sass: {
|
||||
dist: {
|
||||
options: {
|
||||
debugInfo: false,
|
||||
},
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: '<%= chillperson.folders.sass.src %>',
|
||||
src: ['*.scss'],
|
||||
dest: '<%= chillperson.folders.css %>',
|
||||
ext: '.css'
|
||||
}]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
css: {
|
||||
files: [ '<%= chillperson.folders.sass %>/*.scss', '<%= chillperson.folders.sass %>/**/*.scss' ],
|
||||
tasks: ['generatecss'],
|
||||
/*
|
||||
options: {
|
||||
spawn: false,
|
||||
interrupt: true,
|
||||
}
|
||||
*/
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-sass');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
|
||||
grunt.registerTask('generatecss', 'sass');
|
||||
|
||||
grunt.registerTask('default', ['generatecss']);
|
||||
};
|
0
src/Bundle/ChillPerson/Resources/doc/index.rst
Normal file
0
src/Bundle/ChillPerson/Resources/doc/index.rst
Normal file
16
src/Bundle/ChillPerson/Resources/package.json
Normal file
16
src/Bundle/ChillPerson/Resources/package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "chill-person-js-css",
|
||||
"version": "0.0.0",
|
||||
"description": "JS-CSS files for ChillPerson Bundle, a software for social workers",
|
||||
"directories": {
|
||||
},
|
||||
"author": "Champs-Libres <info@champs-libres.coop>",
|
||||
"devDependencies": {
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-contrib-copy": "^0.7.0",
|
||||
"grunt-contrib-sass": "^0.8.1",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-contrib-clean": "^0.6.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
78
src/Bundle/ChillPerson/Resources/public/css/person.css
Normal file
78
src/Bundle/ChillPerson/Resources/public/css/person.css
Normal file
@ -0,0 +1,78 @@
|
||||
.chill-blue, div.person-view div.custom-fields figure.person-details div.cf_title_box:nth-child(4n+4) h2 {
|
||||
color: #334d5c; }
|
||||
|
||||
.chill-green, div.person-view div.custom-fields figure.person-details div.cf_title_box:nth-child(4n+2) h2 {
|
||||
color: #43b29d; }
|
||||
|
||||
.chill-green-dark {
|
||||
color: #328474; }
|
||||
|
||||
.chill-yellow {
|
||||
color: #eec84a; }
|
||||
|
||||
.chill-orange, div.person-view div.custom-fields figure.person-details div.cf_title_box:nth-child(4n+3) h2 {
|
||||
color: #e2793d; }
|
||||
|
||||
.chill-red, div.person-view div.custom-fields figure.person-details div.cf_title_box:nth-child(4n+1) h2 {
|
||||
color: #df4949; }
|
||||
|
||||
.chill-gray {
|
||||
color: #ececec; }
|
||||
|
||||
.chill-beige {
|
||||
color: #cabb9f; }
|
||||
|
||||
.chill-pink {
|
||||
color: #dd506d; }
|
||||
|
||||
.chill-dark-gray {
|
||||
color: #333333; }
|
||||
|
||||
.chill-light-gray {
|
||||
color: #b2b2b2; }
|
||||
|
||||
div#header-person-name {
|
||||
background: none repeat scroll 0 0 #328474;
|
||||
color: #FFF;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em; }
|
||||
|
||||
div#header-person-details {
|
||||
background: none repeat scroll 0 0 #43b29d;
|
||||
color: #FFF;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em; }
|
||||
|
||||
div#person_details_container {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px; }
|
||||
|
||||
div.person-view {
|
||||
/* custom fields on the home page */ }
|
||||
div.person-view figure.person-details {
|
||||
/* background-color: $black;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
}*/ }
|
||||
div.person-view figure.person-details h2 {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.3em;
|
||||
font-variant: small-caps; }
|
||||
div.person-view figure.person-details dl {
|
||||
margin-top: 0.3em; }
|
||||
div.person-view figure.person-details dt {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 600; }
|
||||
div.person-view figure.person-details dd {
|
||||
margin-left: 0; }
|
||||
div.person-view div.custom-fields figure.person-details {
|
||||
display: flex;
|
||||
flex-flow: row wrap; }
|
||||
div.person-view div.custom-fields figure.person-details div.cf_title_box:nth-child(2n+1) {
|
||||
width: 50%;
|
||||
margin-right: 40px; }
|
||||
div.person-view div.custom-fields figure.person-details iv.cf_title_box:nth-child(2n+2) {
|
||||
width: calc(50% - 40px); }
|
||||
|
||||
/*# sourceMappingURL=person.css.map */
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"mappings": "AAkBE,wGAA+B;EAC7B,KAAK,EAJI,OAAO;;AAGlB,yGAA+B;EAC7B,KAAK,EAJY,OAAO;;AAG1B,iBAA+B;EAC7B,KAAK,EAJoB,OAAO;;AAGlC,aAA+B;EAC7B,KAAK,EAJ4B,OAAO;;AAG1C,0GAA+B;EAC7B,KAAK,EAJoC,OAAO;;AAGlD,uGAA+B;EAC7B,KAAK,EAJ4C,OAAO;;AAG1D,WAA+B;EAC7B,KAAK,EAJoD,OAAO;;AAGlE,YAA+B;EAC7B,KAAK,EAJ4D,OAAO;;AAG1E,WAA+B;EAC7B,KAAK,EAJoE,OAAO;;AAGlF,gBAA+B;EAC7B,KAAK,EAJ4E,OAAO;;AAG1F,iBAA+B;EAC7B,KAAK,EAJoF,OAAO;;ACZpG,sBAAuB;EACnB,UAAU,EAAE,8BAAwC;EACpD,KAAK,EAAE,IAAI;EACX,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,GAAG;;AAGvB,yBAA0B;EACtB,UAAU,EAAE,8BAAmC;EAC/C,KAAK,EAAE,IAAI;EACX,WAAW,EAAE,GAAG;EAChB,cAAc,EAAE,GAAG;;AAGvB,4BAA6B;EAC5B,WAAW,EAAE,IAAI;EACjB,cAAc,EAAE,IAAI;;AAGrB,eAAgB;EA6BZ,oCAAoC;EA5BpC,qCAAsB;IAsB1B;;;mBAGe;IAxBH,wCAAG;MACC,WAAW,EAAE,WAAW;MACxB,WAAW,EAAE,GAAG;MAChB,aAAa,EAAE,KAAK;MACpB,YAAY,EAAE,UAAU;IAG5B,wCAAG;MACK,UAAU,EAAE,KAAK;IAGzB,wCAAG;MACH,WAAW,EAAE,WAAW;MACxB,WAAW,EAAE,GAAG;IAGhB,wCAAG;MACK,WAAW,EAAE,CAAC;EAY1B,uDAAsB;IAClB,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,QAAQ;IAkBnB,wFAAgC;MAC5B,KAAK,EAAE,GAAG;MACV,YAAY,EAAE,IAAI;IAGtB,uFAAgC;MAC5B,KAAK,EAAE,gBAAgB",
|
||||
"sources": ["../../../../main/Resources/public/sass/custom/config/_colors.scss","../sass/person.scss"],
|
||||
"names": [],
|
||||
"file": "person.css"
|
||||
}
|
1
src/Bundle/ChillPerson/Resources/public/index.js
Normal file
1
src/Bundle/ChillPerson/Resources/public/index.js
Normal file
@ -0,0 +1 @@
|
||||
require('./sass/person.scss');
|
5
src/Bundle/ChillPerson/Resources/public/sass/index.js
Normal file
5
src/Bundle/ChillPerson/Resources/public/sass/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
require('./phone-alt-solid.svg');
|
||||
require('./mobile-alt-solid.svg');
|
||||
require('./person_by_phonenumber.scss');
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="mobile-alt" class="svg-inline--fa fa-mobile-alt fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M272 0H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h224c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM160 480c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm112-108c0 6.6-5.4 12-12 12H60c-6.6 0-12-5.4-12-12V60c0-6.6 5.4-12 12-12h200c6.6 0 12 5.4 12 12v312z"></path></svg>
|
After Width: | Height: | Size: 516 B |
88
src/Bundle/ChillPerson/Resources/public/sass/person.scss
Normal file
88
src/Bundle/ChillPerson/Resources/public/sass/person.scss
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
@import '../../../../main/Resources/public/sass/custom/config/colors';
|
||||
|
||||
div#header-person-name {
|
||||
background: none repeat scroll 0 0 $chill-green-dark;
|
||||
color: #FFF;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
div#header-person-details {
|
||||
background: none repeat scroll 0 0 $chill-green;
|
||||
color: #FFF;
|
||||
padding-top: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
div#person_details_container {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
div.person-view {
|
||||
figure.person-details {
|
||||
h2 {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.3em;
|
||||
font-variant: small-caps;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-family: 'Open Sans';
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
// a.sc-button {
|
||||
/* background-color: $black;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
}*/
|
||||
}
|
||||
|
||||
/* custom fields on the home page */
|
||||
div.custom-fields {
|
||||
figure.person-details {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
|
||||
div.cf_title_box:nth-child(4n+1) h2 {
|
||||
@extend .chill-red;
|
||||
}
|
||||
|
||||
div.cf_title_box:nth-child(4n+2) h2 {
|
||||
@extend .chill-green;
|
||||
}
|
||||
|
||||
div.cf_title_box:nth-child(4n+3) h2 {
|
||||
@extend .chill-orange;
|
||||
}
|
||||
|
||||
div.cf_title_box:nth-child(4n+4) h2 {
|
||||
@extend .chill-blue;
|
||||
}
|
||||
|
||||
div.cf_title_box:nth-child(2n+1){
|
||||
width: 50%;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
iv.cf_title_box:nth-child(2n+2) {
|
||||
width: calc(50% - 40px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
.person-list__--by-phonenumber {
|
||||
.person-list__--by-phonenumber__phones {
|
||||
ul {
|
||||
list-style: none inside;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
margin: 0.80rem;
|
||||
|
||||
img {
|
||||
vertical-align: baseline;
|
||||
height: 0.90rem;
|
||||
margin-right: 0.20rem;
|
||||
}
|
||||
pre {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
;
|
@ -0,0 +1 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="phone-alt" class="svg-inline--fa fa-phone-alt fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M497.39 361.8l-112-48a24 24 0 0 0-28 6.9l-49.6 60.6A370.66 370.66 0 0 1 130.6 204.11l60.6-49.6a23.94 23.94 0 0 0 6.9-28l-48-112A24.16 24.16 0 0 0 122.6.61l-104 24A24 24 0 0 0 0 48c0 256.5 207.9 464 464 464a24 24 0 0 0 23.4-18.6l24-104a24.29 24.29 0 0 0-14.01-27.6z"></path></svg>
|
After Width: | Height: | Size: 502 B |
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
|
||||
class AppKernel extends Kernel
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
return array(
|
||||
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
|
||||
new Chill\CustomFieldsBundle\ChillCustomFieldsBundle(),
|
||||
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
|
||||
new Symfony\Bundle\TwigBundle\TwigBundle(),
|
||||
new \Symfony\Bundle\AsseticBundle\AsseticBundle(),
|
||||
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
|
||||
new Chill\PersonBundle\ChillPersonBundle(),
|
||||
new Chill\MainBundle\ChillMainBundle(),
|
||||
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
|
||||
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
|
||||
new Symfony\Bundle\MonologBundle\MonologBundle(),
|
||||
#add here all the required bundle (some bundle are not required)
|
||||
);
|
||||
}
|
||||
|
||||
public function registerContainerConfiguration(LoaderInterface $loader)
|
||||
{
|
||||
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheDir()
|
||||
{
|
||||
return sys_get_temp_dir().'/PersonBundle/cache';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLogDir()
|
||||
{
|
||||
return sys_get_temp_dir().'/PersonBundle/logs';
|
||||
}
|
||||
}
|
||||
|
2
src/Bundle/ChillPerson/Resources/test/Fixtures/App/app/DoctrineMigrations/.gitignore
vendored
Normal file
2
src/Bundle/ChillPerson/Resources/test/Fixtures/App/app/DoctrineMigrations/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
{% block stylesheets %}{% endblock %}
|
||||
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
{% block javascripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
/** @var ClassLoader $loader */
|
||||
$loader = require __DIR__.'/../../../../../vendor/autoload.php';
|
||||
|
||||
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
|
||||
|
||||
return $loader;
|
@ -0,0 +1,76 @@
|
||||
imports:
|
||||
- { resource: parameters.yml }
|
||||
|
||||
parameters:
|
||||
locale: en
|
||||
|
||||
framework:
|
||||
secret: Not very secret
|
||||
router: { resource: "%kernel.root_dir%/config/routing.yml" }
|
||||
form: true
|
||||
csrf_protection: true
|
||||
session: ~
|
||||
default_locale: fr
|
||||
translator: { fallback: fr }
|
||||
profiler: { only_exceptions: false }
|
||||
templating:
|
||||
engines: ['twig']
|
||||
|
||||
# Assetic Configuration
|
||||
assetic:
|
||||
debug: "%kernel.debug%"
|
||||
use_controller: false
|
||||
bundles: [ ]
|
||||
#java: /usr/bin/java
|
||||
filters:
|
||||
cssrewrite: ~
|
||||
|
||||
doctrine:
|
||||
dbal:
|
||||
driver: pdo_pgsql
|
||||
host: "%database_host%"
|
||||
port: "%database_port%"
|
||||
dbname: "%database_name%"
|
||||
user: "%database_user%"
|
||||
password: "%database_password%"
|
||||
charset: UTF8
|
||||
orm:
|
||||
auto_generate_proxy_classes: "%kernel.debug%"
|
||||
auto_mapping: true
|
||||
|
||||
chill_main:
|
||||
available_languages: [ fr, nl, en ]
|
||||
|
||||
security:
|
||||
providers:
|
||||
users:
|
||||
entity:
|
||||
class: Chill\MainBundle\Entity\User
|
||||
property: username
|
||||
|
||||
encoders:
|
||||
Chill\MainBundle\Entity\User:
|
||||
algorithm: bcrypt
|
||||
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
|
||||
|
||||
|
||||
default:
|
||||
anonymous: ~
|
||||
http_basic: ~
|
||||
form_login:
|
||||
csrf_parameter: _csrf_token
|
||||
csrf_token_id: authenticate
|
||||
csrf_provider: form.csrf_provider
|
||||
|
||||
logout: ~
|
||||
|
||||
|
||||
access_control:
|
||||
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/admin, roles: ROLE_ADMIN }
|
||||
- { path: ^/, roles: ROLE_USER }
|
@ -0,0 +1,7 @@
|
||||
imports:
|
||||
- { resource: config.yml } #here we import a config.yml file, this is not required
|
||||
|
||||
framework:
|
||||
test: ~
|
||||
session:
|
||||
storage_id: session.storage.filesystem
|
@ -0,0 +1,8 @@
|
||||
# config/config_test.yml
|
||||
imports:
|
||||
- { resource: config.yml } #here we import a config.yml file, this is not required
|
||||
|
||||
framework:
|
||||
test: ~
|
||||
session:
|
||||
storage_id: session.storage.filesystem
|
@ -0,0 +1,18 @@
|
||||
# config/config_test.yml
|
||||
imports:
|
||||
- { resource: config.yml } #here we import a config.yml file, this is not required
|
||||
|
||||
framework:
|
||||
test: ~
|
||||
session:
|
||||
storage_id: session.storage.filesystem
|
||||
|
||||
chill_person:
|
||||
person_fields:
|
||||
nationality: hidden
|
||||
email: hidden
|
||||
place_of_birth: hidden
|
||||
phonenumber: hidden
|
||||
country_of_birth: hidden
|
||||
marital_status: hidden
|
||||
spoken_languages: hidden
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user