Compare commits

..

3 Commits

Author SHA1 Message Date
3e7c79d6ce test app async working 2021-04-23 12:10:37 +02:00
bc1f624e14 fix dummy controller 2021-04-23 10:49:15 +02:00
f73d3bf320 test app 2021-04-22 20:42:48 +02:00
463 changed files with 29919 additions and 4372 deletions

64
.env
View File

@@ -1,64 +0,0 @@
##
## Manually dump .env files in .env.local.php with
## `$ composer symfony:dump-env prod`
##
## Project environment
APP_ENV=dev
## Enable debug
APP_DEBUG=true
## Locale
LOCALE=fr
## Framework secret
APP_SECRET=ThisTokenIsNotSoSecretChangeIt
## Symfony/swiftmailer
MAILER_TRANSPORT=smtp
MAILER_HOST=smtp
MAILER_PORT=1025
MAILER_CRYPT=
MAILER_AUTH=
MAILER_USER=
MAILER_PASSWORD=
MAILER_URL=${MAILER_TRANSPORT}://${MAILER_HOST}:${MAILER_PORT}?encryption=${MAILER_CRYPT}&auth_mode=${MAILER_AUTH}&username=${MAILER_USER}&password=${MAILER_PASSWORD}
## Notifications
NOTIFICATION_HOST=localhost:8001
NOTIFICATION_FROM_EMAIL=admin@chill.social
NOTIFICATION_FROM_NAME=Chill
## Gelf
GELF_HOST=gelf
GELF_PORT=12201
## OVH OpenStack Storage User/Role
OS_USERNAME=
OS_PASSWORD=
OS_TENANT_ID=
OS_REGION_NAME=GRA
OS_AUTH_URL=https://auth.cloud.ovh.net/v2.0/
## OVH OpenStack Storage Container
ASYNC_UPLOAD_TEMP_URL_KEY=
ASYNC_UPLOAD_TEMP_URL_BASE_PATH=
ASYNC_UPLOAD_TEMP_URL_CONTAINER=
## Redis Cache
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
## Twilio
TWILIO_SID=~
TWILIO_SECRET=~
## DOCKER IMAGES REGISTRY
#IMAGE_PHP=
#IMAGE_NGINX=
## DOCKER IMAGES VERSION
#VERSION=test
VERSION=prod

View File

@@ -1,6 +0,0 @@
# variables for .env environement
# those variables suits for gitlab-ci
# Run tests from root to adapt your own environment
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres?serverVersion=12&charset=utf8

17
.gitignore vendored
View File

@@ -1,21 +1,4 @@
.composer/*
composer.phar
composer.lock
docs/build/
###> symfony/framework-bundle ###
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
/bin/
###< symfony/framework-bundle ###
###> phpunit/phpunit ###
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###

View File

@@ -1,41 +0,0 @@
---
image: registry.gitlab.com/chill-projet/chill-app/php-base-image:7.4
# Select what we should cache between builds
cache:
paths:
- tests/app/vendor/
before_script:
# add extensions to postgres
- PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER -h db -c "CREATE EXTENSION IF NOT EXISTS unaccent; CREATE EXTENSION IF NOT EXISTS pg_trgm;"
# Install and run Composer
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install
- php tests/app/bin/console doctrine:migrations:migrate -n
- php tests/app/bin/console doctrine:fixtures:load -n
# Bring in any services we need http://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service
# See http://docs.gitlab.com/ee/ci/services/README.html for examples.
services:
- name: postgres:12
alias: db
- name: redis
alias: redis
# Set any variables we need
variables:
# Configure postgres environment variables (https://hub.docker.com/r/_/postgres/)
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
# fetch the chill-app using git submodules
GIT_SUBMODULE_STRATEGY: recursive
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_URL: redis://redis:6379
# Run our tests
test:
script:
- bin/phpunit --colors=never

3
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "_exts/sphinx-php"]
path = _exts/sphinx-php
url = https://github.com/fabpot/sphinx-php.git
[submodule "tests/app"]
path = tests/app
url = https://gitlab.com/Chill-projet/chill-app.git

View File

@@ -1,9 +0,0 @@
# Chill framework
Documentation of the Chill software.
The online documentation can be found at http://docs.chill.social
See the [`docs`][1] directory for more.
[1]: docs/README.md

View File

@@ -13,17 +13,12 @@
"Chill\\EventBundle\\": "src/Bundle/ChillEventBundle",
"Chill\\FamilyMemberBundle\\": "src/Bundle/ChillFamilyMemberBundle",
"Chill\\MainBundle\\": "src/Bundle/ChillMainBundle",
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle/src",
"Chill\\PersonBundle\\": "src/Bundle/ChillPersonBundle",
"Chill\\ReportBundle\\": "src/Bundle/ChillReportBundle",
"Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle",
"Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle"
}
},
"autoload-dev": {
"psr-4": {
"App\\": "tests/app/src/"
}
},
"require": {
"champs-libres/async-uploader-bundle": "dev-sf4",
"graylog2/gelf-php": "^1.5",
@@ -72,17 +67,6 @@
"symfony/stopwatch": "^5.1",
"symfony/web-profiler-bundle": "^5.0",
"symfony/var-dumper": "4.*",
"symfony/debug-bundle": "^5.1",
"symfony/phpunit-bridge": "^5.2"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
}
},
"config": {
"vendor-dir": "tests/app/vendor",
"bin-dir": "bin"
"symfony/debug-bundle": "^5.1"
}
}

View File

@@ -10,19 +10,10 @@ Compilation into HTML
To compile this documentation :
1. Install [sphinx-doc](http://sphinx-doc.org)
``` bash
$ virtualenv .venv # creation of the virtual env (only the first time)
$ source .venv/bin/activate # activate the virtual env
(.venv) $ pip install -r requirements.txt
```
1. Install [sphinx-doc](http://sphinx-doc.org) (eg. pip install sphinx & pip install sphinx_rtd_theme)
2. Install submodules : $ git submodule update --init;
3. run `make html` from the root directory
4. The base file is located on build/html/index.html
``` bash
$ cd build/html
$ python -m http.server 8888 # will serve the site on the port 8888
```
Contribute
===========

View File

@@ -29,7 +29,7 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
Timelines <timelines.rst>
Exports <exports.rst>
Embeddable comments <embeddable-comments.rst>
Run tests <run-tests.rst>
Testing <make-test-working.rst>
Useful snippets <useful-snippets.rst>
manual/index.rst
Assets <assets.rst>

View File

@@ -0,0 +1,231 @@
.. Copyright (C) 2014 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
Make tests working
******************
Unit and functional tests are important to ensure that bundle may be deployed securely.
In reason of the Chill architecture, test should be runnable from the bundle's directory and works correctly: this will allow continuous integration tools to run tests automatically.
.. note::
Integration tools (i.e. `travis-ci <https://travis-ci.org>`_) works like this :
* they clone the bundle repository in a virtual machine, using git
* they optionnaly run `composer` to download and install depedencies
* they optionnaly run other command to prepare a database, insert fixtures, ...
* they run test
On the developer's machine test should be runnable with two or three commands **runned from the bundle directory** :
.. code-block:: bash
$ composer install --dev
$ // command to insert fixtures, ...
$ phpunit
This chapter has been inspired by `this useful blog post <http://blog.kevingomez.fr/2013/01/09/functional-testing-standalone-symfony2-bundles/>`_.
Bootstrap phpunit for a standalone bundle
==========================================
Unit tests should run after achieving this step.
phpunit.xml
-----------
A `phpunit.xml.dist` file should be present at the bundle root.
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./Tests/bootstrap.php" colors="true">
<!-- the file "./Tests/boostrap.php" will be created on the next step -->
<testsuites>
<testsuite name="ChillMain test suite">
<directory suffix="Test.php">./Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>
bootstrap.php
--------------
A file `boostrap.php`, located in the `Tests` directory, will allow phpunit to resolve class autoloading :
.. code-block:: php
<?php
if (!is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
throw new \LogicException('Could not find autoload.php in vendor/. Did you run "composer install --dev"?');
}
require $autoloadFile;
composer.json
-------------
The `composer.json` file **located at the bundle's root** should contains all depencies needed to run test (and to execute bundle functions).
Ensure that all dependencies are included in the `require` and `require-dev` sections.
Functional tests
================
If you want to access services, database, and run functional tests, you will have to bootstrap a symfony app, with the minimal configuration. Three files are required :
* a `config_test.yml` file (eventually with a `config.yml`);
* a `routing.yml` file
* an `AppKernel.php` file
Adapt phpunit.xml
-----------------
You should add reference to the new application within `phpunit.xml.dist`. The directive `<php>` should be added like this, if your `AppKernel.php` file is located in `Tests/Fixtures/App` directory:
.. code-block:: xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./Tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="ChillMain test suite">
<directory suffix="Test.php">./Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
<!-- the lines we added -->
<php>
<server name="KERNEL_DIR" value="./Tests/Fixtures/App/" />
</php>
</phpunit>
AppKernel.php
-------------
This file boostrap the app. It contains three functions. This is the file used in the ChillMain bundle :
.. code-block:: php
<?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\MainBundle\ChillMainBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new \Symfony\Bundle\AsseticBundle\AsseticBundle(),
#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().'/ChillMainBundle/cache';
}
/**
* @return string
*/
public function getLogDir()
{
return sys_get_temp_dir().'/ChillMainBundle/logs';
}
}
config_test.yml
---------------
There are only few parameters required for the config file. This is a basic version for ChillMain :
.. code-block:: yaml
# 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
.. code-block:: yaml
# config/config.yml
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: #required for assetic. Remove if not needed
engines: ['twig']
.. note::
You must adapt config.yml file according to your required bundle. Some options will be missing, other may be removed...
.. note::
If you would like to tests different environments, with differents configuration, you could create differents config_XXX.yml files.
routing.yml
------------
You should add there all routing information needed for your bundle.
.. code-block: yaml
chill_main_bundle:
resource: "@CLChillMainBundle/Resources/config/routing.yml"
That's it. Tests should pass.

View File

@@ -1,68 +0,0 @@
.. Copyright (C) 2014 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
Run tests
*********
In reason of the Chill architecture, test should be runnable from the bundle's directory and works correctly: this will allow continuous integration tools to run tests automatically.
From chill app
==============
This is the most convenient method for developer: run test for chill bundle from the main app.
.. code-block:: bash
# run into a container
docker-compose exec --user $(id -u) php bash
# execute all tests suites
bin/phpunit
# .. or execute a single test
bin/phpunit vendor/chill-project/chill-bundles/src/Bundle/ChillMainBundle/Tests/path/to/FileTest.php
You can also run tests in a single command:
.. code-block:: bash
docker-compose exec --user $(id -u) php bin/phpunit
Tests from a bundle (chill-bundles)
-----------------------------------
Those tests needs the whole symfony app to execute Application Tests (which test html page).
For ease, the app is cloned using a :code:`git submodule`, which clone the main app into :code:`tests/app`, and tests are bootstrapped to this app. The dependencies are also installed into `tests/app/vendor` to ensure compliance with relative path from this symfony application.
You may boostrap the tests fro the chill bundle this way:
.. code-block:: bash
# ensure to be located into the environement (provided by docker suits well)
docker-compose exec --user $(id -u) php bash
# go to chill subdirectory
cd vendor/chill-project/chill-bundles
# install submodule
git submodule init
git submodule update
# install composer and dependencies
curl -sS https://getcomposer.org/installer | php
# run tests
bin/phpunit
.. note::
If you are on a fresh install, you will need to migrate database schema.
The path to console tool must be adapted to the app. To load migration and add fixtures, one can execute the following commands:
.. code-block:: bash
tests/app/bin/console doctrine:migrations:migrate
tests/app/bin/console doctrine:fixtures:load

View File

@@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/app/tests/bootstrap.php"
>
<php>
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
<server name="SHELL_VERBOSITY" value="-1" />
</php>
<testsuites>
<testsuite name="MainBundle">
<directory suffix="Test.php">src/Bundle/ChillMainBundle/Tests/</directory>
</testsuite>
<!--
<testsuite name="PersonBundle">
<directory suffix="Test.php">src/Bundle/ChillPersonBundle/Tests/</directory>
</testsuite>
-->
</testsuites>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
<!-- Run `composer require symfony/panther` before enabling this extension -->
<!--
<extensions>
<extension class="Symfony\Component\Panther\ServerExtension" />
</extensions>
-->
</phpunit>

View File

@@ -47,11 +47,11 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
{
/**
* widget factory
*
*
* @var WidgetFactoryInterface[]
*/
protected $widgetFactories = array();
/**
* @param WidgetFactoryInterface $factory
*/
@@ -59,7 +59,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
{
$this->widgetFactories[] = $factory;
}
/**
* @return WidgetFactoryInterface[]
*/
@@ -67,7 +67,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
{
return $this->widgetFactories;
}
/**
* {@inheritDoc}
* @param array $configs
@@ -79,31 +79,31 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
// configuration for main bundle
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('chill_main.installation_name',
$config['installation_name']);
$container->setParameter('chill_main.available_languages',
$config['available_languages']);
$container->setParameter('chill_main.routing.resources',
$config['routing']['resources']);
$container->setParameter('chill_main.routing.resources',
$config['routing']['resources']);
$container->setParameter('chill_main.pagination.item_per_page',
$config['pagination']['item_per_page']);
$container->setParameter('chill_main.notifications',
$container->setParameter('chill_main.notifications',
$config['notifications']);
$container->setParameter('chill_main.redis',
$container->setParameter('chill_main.redis',
$config['redis']);
$container->setParameter('chill_main.phone_helper',
$container->setParameter('chill_main.phone_helper',
$config['phone_helper'] ?? []);
// add the key 'widget' without the key 'enable'
$container->setParameter('chill_main.widgets',
isset($config['widgets']['homepage']) ?
$container->setParameter('chill_main.widgets',
isset($config['widgets']['homepage']) ?
array('homepage' => $config['widgets']['homepage']):
array()
);
@@ -131,11 +131,10 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
$loader->load('services/templating.yaml');
$loader->load('services/timeline.yaml');
$loader->load('services/search.yaml');
$loader->load('services/serializer.yaml');
$this->configureCruds($container, $config['cruds'], $loader);
}
/**
* @param array $config
* @param ContainerBuilder $container
@@ -145,11 +144,11 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
{
return new Configuration($this->widgetFactories, $container);
}
/**
* @param ContainerBuilder $container
*/
public function prepend(ContainerBuilder $container)
public function prepend(ContainerBuilder $container)
{
//add installation_name and date_format to globals
$chillMainConfig = $container->getExtensionConfig($this->getAlias());
@@ -164,7 +163,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
'form_themes' => array('@ChillMain/Form/fields.html.twig')
);
$container->prependExtensionConfig('twig', $twigConfig);
//add DQL function to ORM (default entity_manager)
$container->prependExtensionConfig('doctrine', array(
'orm' => array(
@@ -183,7 +182,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
)
)
));
//add dbal types (default entity_manager)
$container->prependExtensionConfig('doctrine', array(
'dbal' => [
@@ -192,23 +191,23 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
]
]
));
//add current route to chill main
$container->prependExtensionConfig('chill_main', array(
'routing' => array(
'resources' => array(
'@ChillMainBundle/config/routes.yaml'
)
)
));
//add a channel to log app events
$container->prependExtensionConfig('monolog', array(
'channels' => array('chill')
));
}
/**
* @param ContainerBuilder $container
* @param array $config the config under 'cruds' key
@@ -219,31 +218,31 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
if (count($config) === 0) {
return;
}
$loader->load('services/crud.yaml');
$container->setParameter('chill_main_crud_route_loader_config', $config);
$definition = new Definition();
$definition
->setClass(\Chill\MainBundle\CRUD\Routing\CRUDRoutesLoader::class)
->addArgument('%chill_main_crud_route_loader_config%')
;
$container->setDefinition('chill_main_crud_route_loader', $definition);
$alreadyExistingNames = [];
foreach ($config as $crudEntry) {
$controller = $crudEntry['controller'];
$controllerServiceName = 'cscrud_'.$crudEntry['name'].'_controller';
$name = $crudEntry['name'];
// check for existing crud names
if (\in_array($name, $alreadyExistingNames)) {
throw new LogicException(sprintf("the name %s is defined twice in CRUD", $name));
}
if (!$container->has($controllerServiceName)) {
$controllerDefinition = new Definition($controller);
$controllerDefinition->addTag('controller.service_arguments');
@@ -251,7 +250,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
$controllerDefinition->setClass($crudEntry['controller']);
$container->setDefinition($controllerServiceName, $controllerDefinition);
}
$container->setParameter('chill_main_crud_config_'.$name, $crudEntry);
$container->getDefinition($controllerServiceName)
->addMethodCall('setCrudConfig', ['%chill_main_crud_config_'.$name.'%']);

View File

@@ -27,7 +27,6 @@ use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Form\Type\DataTransformer\ObjectToIdTransformer;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Form\Type\Select2ChoiceType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
/**
* Extends choice to allow adding select2 library on widget
@@ -42,26 +41,15 @@ class Select2CountryType extends AbstractType
*/
private $requestStack;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
* @var ObjectManager
*/
private $em;
public function __construct(
RequestStack $requestStack,
ObjectManager $em,
TranslatableStringHelper $translatableStringHelper
)
public function __construct(RequestStack $requestStack,ObjectManager $em)
{
$this->requestStack = $requestStack;
$this->em = $em;
$this->translatableStringHelper = $translatableStringHelper;
}
public function getBlockPrefix()
@@ -87,7 +75,7 @@ class Select2CountryType extends AbstractType
$choices = array();
foreach ($countries as $c) {
$choices[$c->getId()] = $this->translatableStringHelper->localize($c->getName());
$choices[$c->getId()] = $c->getName()[$locale];
}
asort($choices, SORT_STRING | SORT_FLAG_CASE);

View File

@@ -27,7 +27,6 @@ use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Form\Type\DataTransformer\MultipleObjectsToIdTransformer;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Form\Type\Select2ChoiceType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
/**
* Extends choice to allow adding select2 library on widget for languages (multiple)
@@ -44,21 +43,10 @@ class Select2LanguageType extends AbstractType
*/
private $em;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
public function __construct(
RequestStack $requestStack,
ObjectManager $em,
TranslatableStringHelper $translatableStringHelper
)
public function __construct(RequestStack $requestStack,ObjectManager $em)
{
$this->requestStack = $requestStack;
$this->em = $em;
$this->translatableStringHelper = $translatableStringHelper;
}
public function getBlockPrefix()
@@ -84,7 +72,7 @@ class Select2LanguageType extends AbstractType
$choices = array();
foreach ($languages as $l) {
$choices[$l->getId()] = $this->translatableStringHelper->localize($l->getName());
$choices[$l->getId()] = $l->getName()[$locale];
}
asort($choices, SORT_STRING | SORT_FLAG_CASE);

View File

@@ -104,7 +104,7 @@ class Mailer
* @param \User $to
* @param array $subject Subject of the message [ 0 => $message (required), 1 => $parameters (optional), 3 => $domain (optional) ]
* @param array $bodies The bodies. An array where keys are the contentType and values the bodies
* @param callable $callback a callback to customize the message (add attachment, etc.)
* @param \callable $callback a callback to customize the message (add attachment, etc.)
*/
public function sendNotification(
$recipient,

View File

@@ -204,7 +204,7 @@ class SearchProvider
}
public function getResultByName($pattern, $name, $start = 0, $limit = 50,
array $options = array(), $format = 'html')
array $options = array(), $format)
{
$terms = $this->parse($pattern);
$search = $this->getByName($name);

View File

@@ -32,34 +32,34 @@ use Chill\MainBundle\Entity\GroupCenter;
use Chill\MainBundle\Entity\RoleScope;
/**
* Helper for authorizations.
*
* Helper for authorizations.
*
* Provides methods for user and entities information.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class AuthorizationHelper implements AuthorizationHelperInterface
class AuthorizationHelper
{
/**
*
* @var RoleHierarchyInterface
*/
protected $roleHierarchy;
/**
* The role in a hierarchy, given by the parameter
* The role in a hierarchy, given by the parameter
* `security.role_hierarchy.roles` from the container.
*
* @var string[]
*/
protected $hierarchy;
/**
*
* @var EntityManagerInterface
*/
protected $em;
public function __construct(
RoleHierarchyInterface $roleHierarchy,
$hierarchy,
@@ -69,10 +69,10 @@ class AuthorizationHelper implements AuthorizationHelperInterface
$this->hierarchy = $hierarchy;
$this->em = $em;
}
/**
* Determines if a user is active on this center
*
*
* @param User $user
* @param Center $center
* @return bool
@@ -81,21 +81,21 @@ class AuthorizationHelper implements AuthorizationHelperInterface
{
foreach ($user->getGroupCenters() as $groupCenter) {
if ($center->getId() === $groupCenter->getCenter()->getId()) {
return true;
}
}
return false;
}
/**
*
*
* Determines if the user has access to the given entity.
*
*
* if the entity implements Chill\MainBundle\Entity\HasScopeInterface,
* the scope is taken into account.
*
*
* @param User $user
* @param HasCenterInterface $entity the entity may also implement HasScopeInterface
* @param string|Role $attribute
@@ -103,15 +103,15 @@ class AuthorizationHelper implements AuthorizationHelperInterface
*/
public function userHasAccess(User $user, HasCenterInterface $entity, $attribute)
{
$center = $entity->getCenter();
if (!$this->userCanReachCenter($user, $center)) {
return false;
}
$role = ($attribute instanceof Role) ? $attribute : new Role($attribute);
foreach ($user->getGroupCenters() as $groupCenter){
//filter on center
if ($groupCenter->getCenter()->getId() === $entity->getCenter()->getId()) {
@@ -119,7 +119,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
//iterate on roleScopes
foreach($permissionGroup->getRoleScopes() as $roleScope) {
//check that the role allow to reach the required role
if ($this->isRoleReached($role,
if ($this->isRoleReached($role,
new Role($roleScope->getRole()))){
//if yes, we have a right on something...
// perform check on scope if necessary
@@ -137,17 +137,17 @@ class AuthorizationHelper implements AuthorizationHelperInterface
}
}
}
}
}
return false;
}
/**
* Get reachable Centers for the given user, role,
* and optionnaly Scope
*
*
* @param User $user
* @param Role $role
* @param null|Scope $scope
@@ -156,13 +156,13 @@ class AuthorizationHelper implements AuthorizationHelperInterface
public function getReachableCenters(User $user, Role $role, Scope $scope = null)
{
$centers = array();
foreach ($user->getGroupCenters() as $groupCenter){
$permissionGroup = $groupCenter->getPermissionsGroup();
//iterate on roleScopes
foreach($permissionGroup->getRoleScopes() as $roleScope) {
//check that the role is in the reachable roles
if ($this->isRoleReached($role,
if ($this->isRoleReached($role,
new Role($roleScope->getRole()))) {
if ($scope === null) {
$centers[] = $groupCenter->getCenter();
@@ -171,19 +171,19 @@ class AuthorizationHelper implements AuthorizationHelperInterface
if ($scope->getId() == $roleScope->getScope()->getId()){
$centers[] = $groupCenter->getCenter();
break 1;
}
}
}
}
}
}
return $centers;
}
/**
* Return all reachable scope for a given user, center and role
*
*
* @deprecated Use getReachableCircles
*
* @param User $user
@@ -195,10 +195,10 @@ class AuthorizationHelper implements AuthorizationHelperInterface
{
return $this->getReachableCircles($user, $role, $center);
}
/**
* Return all reachable circle for a given user, center and role
*
*
* @param User $user
* @param Role $role
* @param Center $center
@@ -207,7 +207,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
public function getReachableCircles(User $user, Role $role, Center $center)
{
$scopes = array();
foreach ($user->getGroupCenters() as $groupCenter){
if ($center->getId() === $groupCenter->getCenter()->getId()) {
//iterate on permissionGroup
@@ -215,7 +215,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
//iterate on roleScopes
foreach($permissionGroup->getRoleScopes() as $roleScope) {
//check that the role is in the reachable roles
if ($this->isRoleReached($role,
if ($this->isRoleReached($role,
new Role($roleScope->getRole()))) {
$scopes[] = $roleScope->getScope();
@@ -223,12 +223,12 @@ class AuthorizationHelper implements AuthorizationHelperInterface
}
}
}
return $scopes;
}
/**
*
*
* @param Role $role
* @param Center $center
* @param Scope $circle
@@ -239,7 +239,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
$parents = $this->getParentRoles($role);
$parents[] = $role;
$parentRolesString = \array_map(function(Role $r) { return $r->getRole(); }, $parents);
$qb = $this->em->createQueryBuilder();
$qb
->select('u')
@@ -250,21 +250,21 @@ class AuthorizationHelper implements AuthorizationHelperInterface
->where('gc.center = :center')
->andWhere($qb->expr()->in('rs.role', $parentRolesString))
;
$qb->setParameter('center', $center);
if ($circle !== null) {
$qb->andWhere('rs.scope = :circle')
->setParameter('circle', $circle)
;
}
return $qb->getQuery()->getResult();
}
/**
* Test if a parent role may give access to a given child role
*
*
* @param Role $childRole The role we want to test if he is reachable
* @param Role $parentRole The role which should give access to $childRole
* @return boolean true if the child role is granted by parent role
@@ -273,14 +273,14 @@ class AuthorizationHelper implements AuthorizationHelperInterface
{
$reachableRoles = $this->roleHierarchy
->getReachableRoles([$parentRole]);
return in_array($childRole, $reachableRoles);
}
/**
* Return all the role which give access to the given role. Only the role
* Return all the role which give access to the given role. Only the role
* which are registered into Chill are taken into account.
*
*
* @param Role $role
* @return Role[] the role which give access to the given $role
*/
@@ -291,18 +291,18 @@ class AuthorizationHelper implements AuthorizationHelperInterface
$roles = \array_map(
function($string) {
return new Role($string);
},
},
\array_keys($this->hierarchy)
);
foreach ($roles as $r) {
$childRoles = $this->roleHierarchy->getReachableRoleNames([$r->getRole()]);
if (\in_array($role, $childRoles)) {
$parentRoles[] = $r;
}
}
return $parentRoles;
}
}

View File

@@ -1,87 +0,0 @@
<?php
namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\HasCenterInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\MainBundle\Entity\Scope;
interface AuthorizationHelperInterface
{
/**
* Determines if a user is active on this center
*
* @param User $user
* @param Center $center
* @return bool
*/
public function userCanReachCenter(User $user, Center $center);
/**
*
* Determines if the user has access to the given entity.
*
* if the entity implements Chill\MainBundle\Entity\HasScopeInterface,
* the scope is taken into account.
*
* @param User $user
* @param HasCenterInterface $entity the entity may also implement HasScopeInterface
* @param string|Role $attribute
* @return boolean true if the user has access
*/
public function userHasAccess(User $user, HasCenterInterface $entity, $attribute);
/**
* Get reachable Centers for the given user, role,
* and optionnaly Scope
*
* @param User $user
* @param Role $role
* @param null|Scope $scope
* @return Center[]
*/
public function getReachableCenters(User $user, Role $role, Scope $scope = null);
/**
* Return all reachable scope for a given user, center and role
*
* @deprecated Use getReachableCircles
*
* @param User $user
* @param Role $role
* @param Center $center
* @return Scope[]
*/
public function getReachableScopes(User $user, Role $role, Center $center);
/**
* Return all reachable circle for a given user, center and role
*
* @param User $user
* @param Role $role
* @param Center $center
* @return Scope[]
*/
public function getReachableCircles(User $user, Role $role, Center $center);
/**
*
* @param Role $role
* @param Center $center
* @param Scope $circle
* @return Users
*/
public function findUsersReaching(Role $role, Center $center, Scope $circle = null);
/**
* Return all the role which give access to the given role. Only the role
* which are registered into Chill are taken into account.
*
* @param Role $role
* @return Role[] the role which give access to the given $role
*/
public function getParentRoles(Role $role);
}

View File

@@ -1,44 +0,0 @@
<?php
/*
*
* Copyright (C) 2014-2021, 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\MainBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\Center;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
*
*
*/
class CenterNormalizer implements NormalizerInterface
{
public function normalize($center, string $format = null, array $context = array())
{
/** @var Center $center */
return [
'id' => $center->getId(),
'name' => $center->getName()
];
}
public function supportsNormalization($data, string $format = null): bool
{
return $data instanceof Center;
}
}

View File

@@ -1,39 +0,0 @@
<?php
/*
*
* Copyright (C) 2014-2021, 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\MainBundle\Serializer\Normalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
class DateNormalizer implements NormalizerInterface
{
public function normalize($date, string $format = null, array $context = array())
{
/** @var \DateTimeInterface $date */
return [
'datetime' => $date->format(\DateTimeInterface::ISO8601),
'u' => $date->getTimestamp()
];
}
public function supportsNormalization($data, string $format = null): bool
{
return $data instanceof \DateTimeInterface;
}
}

View File

@@ -1,44 +0,0 @@
<?php
/*
*
* Copyright (C) 2014-2021, 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\MainBundle\Serializer\Normalizer;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
/**
*
*
*/
class UserNormalizer implements NormalizerInterface
{
public function normalize($user, string $format = null, array $context = array())
{
/** @var User $user */
return [
'id' => $user->getId(),
'username' => $user->getUsername()
];
}
public function supportsNormalization($data, string $format = null): bool
{
return $data instanceof User;
}
}

View File

@@ -2,7 +2,7 @@
/*
* Chill is a software for social workers
*
* Copyright (C) 2014-2019, Champs Libres Cooperative SCRLFS,
* Copyright (C) 2014-2019, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
@@ -28,18 +28,18 @@ use Twig\TwigFilter;
*
* @package Chill\MainBundle\Templating\Entity
*/
class ChillEntityRenderExtension extends AbstractExtension implements ChillEntityRenderExtensionInterface
class ChillEntityRenderExtension extends AbstractExtension
{
/**
* @var ChillEntityRenderInterface
* @var ChillEntityRenderInterface
*/
protected $renders = [];
/**
* @var ChillEntityRender
*/
protected $defaultRender;
/**
* ChillEntityRenderExtension constructor.
*/
@@ -47,7 +47,7 @@ class ChillEntityRenderExtension extends AbstractExtension implements ChillEntit
{
$this->defaultRender = new ChillEntityRender();
}
/**
* @return array|TwigFilter[]
*/
@@ -62,7 +62,7 @@ class ChillEntityRenderExtension extends AbstractExtension implements ChillEntit
])
];
}
/**
* @param $entity
* @param array $options
@@ -76,7 +76,7 @@ class ChillEntityRenderExtension extends AbstractExtension implements ChillEntit
return $this->getRender($entity, $options)
->renderString($entity, $options);
}
/**
* @param $entity
* @param array $options
@@ -90,7 +90,7 @@ class ChillEntityRenderExtension extends AbstractExtension implements ChillEntit
return $this->getRender($entity, $options)
->renderBox($entity, $options);
}
/**
* @param ChillEntityRenderInterface $render
*/
@@ -98,7 +98,7 @@ class ChillEntityRenderExtension extends AbstractExtension implements ChillEntit
{
$this->renders[] = $render;
}
/**
* @param $entity
* @param $options

View File

@@ -1,33 +0,0 @@
<?php
namespace Chill\MainBundle\Templating\Entity;
use Twig\Extension\ExtensionInterface;
use Twig\TwigFilter;
interface ChillEntityRenderExtensionInterface extends ExtensionInterface
{
/**
* @return array|TwigFilter[]
*/
public function getFilters();
/**
* @param $entity
* @param array $options
* @return string
*/
public function renderString($entity, array $options = []): string;
/**
* @param $entity
* @param array $options
* @return string
*/
public function renderBox($entity, array $options = []): string;
/**
* @param ChillEntityRenderInterface $render
*/
public function addRender(ChillEntityRenderInterface $render);
}

View File

@@ -23,36 +23,36 @@ use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Translation\Translator;
/**
*
*
* This helper helps to find the string in current locale from translatable_strings
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*
*/
class TranslatableStringHelper implements TranslatableStringHelperInterface
class TranslatableStringHelper
{
/**
*
*
* @var RequestStack
*/
private $requestStack;
private $fallbackLocales;
public function __construct(RequestStack $requestStack, Translator $translator)
{
$this->requestStack = $requestStack;
$this->fallbackLocales = $translator->getFallbackLocales();
}
/**
* return the string in current locale if it exists.
*
*
* If it does not exists; return the name in the first language available.
*
*
* Return a blank string if any strings are available.
* Return NULL if $translatableString is NULL
*
*
* @param array $translatableStrings
* @return string
*/
@@ -61,32 +61,32 @@ class TranslatableStringHelper implements TranslatableStringHelperInterface
if (NULL === $translatableStrings) {
return NULL;
}
$language = $this->requestStack->getCurrentRequest()->getLocale();
if (isset($translatableStrings[$language])) {
return $translatableStrings[$language];
} else {
foreach ($this->fallbackLocales as $locale) {
if (array_key_exists($locale, $translatableStrings)) {
return $translatableStrings[$locale];
}
}
}
// no fallback translation... trying the first available
$langs = array_keys($translatableStrings);
if (count($langs) === 0) {
return '';
}
return $translatableStrings[$langs[0]];
}
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Chill\MainBundle\Templating;
interface TranslatableStringHelperInterface
{
/**
* return the string in current locale if it exists.
*
* If it does not exists; return the name in the first language available.
*
* Return a blank string if any strings are available.
* Return NULL if $translatableString is NULL
*
* @param array $translatableStrings
* @return string
*/
public function localize(array $translatableStrings);
}

View File

@@ -34,7 +34,7 @@ trait PrepareClientTrait
* @return \Symfony\Component\BrowserKit\Client
* @throws \LogicException
*/
public function getClientAuthenticated(
public function getClient(
$username = 'center a_social',
$password = 'password'
) {

View File

@@ -0,0 +1,13 @@
<?php
namespace Chill\MainBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
}
}

View File

@@ -9,7 +9,15 @@ class LoginControllerTest extends WebTestCase
{
public function testLogin()
{
$client = static::createClient();
$client = static::createClient(array(
'framework' => array(
'default_locale' => 'en',
'translator' => array(
'fallback' => 'en'
)
),
));
//load login page and submit form
$crawler = $client->request('GET', '/login');
@@ -34,17 +42,17 @@ class LoginControllerTest extends WebTestCase
//on the home page, there must be a logout link
$client->followRedirects(true);
$crawler = $client->request('GET', '/');
$this->assertRegExp('/center a_social/', $client->getResponse()
->getContent());
$logoutLinkFilter = $crawler->filter('a:contains("Se déconnecter")');
$logoutLinkFilter = $crawler->filter('a:contains("Logout")');
//check there is > 0 logout link
$this->assertGreaterThan(0, $logoutLinkFilter->count(), 'check that a logout link is present');
//click on logout link
$client->followRedirects(false);
$client->click($crawler->selectLink('Se déconnecter')->link());
$client->click($crawler->selectLink('Logout')->link());
$this->assertTrue($client->getResponse()->isRedirect());
$client->followRedirect(); #redirect to login page

View File

@@ -32,7 +32,21 @@ use Chill\MainBundle\Search\SearchInterface;
*/
class SearchControllerTest extends WebTestCase
{
/*
public function setUp()
{
static::bootKernel();
//add a default service
$this->addSearchService(
$this->createDefaultSearchService('<p>I am default</p>', 10), 'default'
);
//add a domain service
$this->addSearchService(
$this->createDefaultSearchService('<p>I am domain bar</p>', 20), 'bar'
);
}
/**
* Test the behaviour when no domain is provided in the search pattern :
* the default search should be enabled
@@ -91,6 +105,29 @@ class SearchControllerTest extends WebTestCase
$this->assertTrue($client->getResponse()->isNotFound());
}
public function testSearchWithinSpecificSearchName()
{
/*
//add a search service which will be supported
$this->addSearchService(
$this->createNonDefaultDomainSearchService("<p>I am domain foo</p>", 100, TRUE), 'foo'
);
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search',
array('q' => '@foo default search', 'name' => 'foo'));
//$this->markTestSkipped();
$this->assertEquals(0, $crawler->filter('p:contains("I am default")')->count(),
"The mocked default results are not shown");
$this->assertEquals(0, $crawler->filter('p:contains("I am domain bar")')->count(),
"The mocked non-default results are not shown");
$this->assertEquals(1, $crawler->filter('p:contains("I am domain foo")')->count(),
"The mocked nnon default results for foo are shown");
*/
}
private function getAuthenticatedClient()
{
return static::createClient(array(), array(

View File

@@ -37,12 +37,11 @@ class UserControllerTest extends WebTestCase
$username = 'Test_user'. uniqid();
$password = 'Password1234!';
dump($crawler->text());
// Fill in the form and submit it
$form = $crawler->selectButton('Créer')->form(array(
'chill_mainbundle_user[username]' => $username,
'chill_mainbundle_user[plainPassword][first]' => $password,
'chill_mainbundle_user[plainPassword][second]' => $password
'chill_mainbundle_user[plainPassword][password][first]' => $password,
'chill_mainbundle_user[plainPassword][password][second]' => $password
));
$this->client->submit($form);
@@ -120,8 +119,8 @@ class UserControllerTest extends WebTestCase
$crawler = $this->client->click($link);
$form = $crawler->selectButton('Changer le mot de passe')->form(array(
'chill_mainbundle_user_password[new_password][first]' => $newPassword,
'chill_mainbundle_user_password[new_password][second]' => $newPassword,
'chill_mainbundle_user_password[password][first]' => $newPassword,
'chill_mainbundle_user_password[password][second]' => $newPassword,
));
$this->client->submit($form);

View File

@@ -0,0 +1,179 @@
<?php
/*
* Chill is a software for social workers
* 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\MainBundle\Tests\DependencyInjection;
use Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilderInterface;
/**
* Description of ConfigConsistencyCompilerPassTest
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ConfigConsistencyCompilerPassTest extends \PHPUnit\Framework\TestCase
{
/**
*
*
* @var \Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass
*/
private $configConsistencyCompilerPass;
public function setUp()
{
$this->configConsistencyCompilerPass = new ConfigConsistencyCompilerPass();
}
/**
* Test that everything is fine is configuration is correct
*
*/
public function testLanguagesArePresent()
{
try {
$this ->configConsistencyCompilerPass
->process(
$this->mockContainer(
$this->mockTranslatorDefinition(array('fr')),
array('fr', 'nl')
)
);
$this->assertTrue(TRUE, 'the config consistency can process');
} catch (\Exception $ex) {
$this->assertTrue(FALSE,
'the config consistency can process');
}
}
/**
* Test that everything is fine is configuration is correct
* if multiple fallback languages are present
*
*/
public function testMultiplesLanguagesArePresent()
{
try {
$this ->configConsistencyCompilerPass
->process(
$this->mockContainer(
$this->mockTranslatorDefinition(array('fr', 'nl')),
array('fr', 'nl', 'en')
)
);
$this->assertTrue(TRUE, 'the config consistency can process');
} catch (\Exception $ex) {
$this->assertTrue(FALSE,
'the config consistency can process');
}
}
/**
* Test that a runtime exception is throw if the available language does
* not contains the fallback locale
*
* @expectedException \RuntimeException
* @expectedExceptionMessageRegExp /The chill_main.available_languages parameter does not contains fallback locales./
*/
public function testLanguageNotPresent()
{
$container = $this->mockContainer(
$this->mockTranslatorDefinition(array('en')), array('fr')
);
$this->configConsistencyCompilerPass->process($container);
}
/**
* Test that a logic exception is thrown if the setFallbackLocale
* method is not defined in translator definition
*
* @expectedException \LogicException
*/
public function testSetFallbackNotDefined()
{
$container = $this->mockContainer(
$this->mockTranslatorDefinition(NULL), array('fr')
);
$this->configConsistencyCompilerPass->process($container);
}
/**
* @return ContainerBuilder
*/
private function mockContainer($definition, $availableLanguages)
{
$container = $this
->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
->getMock();
$container->method('getParameter')
->will($this->returnCallback(
function($parameter) use ($availableLanguages) {
if ($parameter === 'chill_main.available_languages') {
return $availableLanguages;
} else {
throw new \LogicException("the parameter '$parameter' "
. "is not defined in stub test");
}
}
));
$container->method('findDefinition')
->will($this->returnCallback(
function($id) use ($definition) {
if (in_array($id, array('translator', 'translator.default'))) {
return $definition;
} else {
throw new \LogicException("the id $id is not defined in test");
}
}));
return $container;
}
/**
*
* @param type $languages
* @return 'Symfony\Component\DependencyInjection\Definition'
*/
private function mockTranslatorDefinition(array $languages = NULL)
{
$definition = $this
->getMockBuilder('Symfony\Component\DependencyInjection\Definition')
->getMock();
if (NULL !== $languages) {
$definition->method('getMethodCalls')
->willReturn(array(
['setFallbackLocales', array($languages)]
));
} else {
$definition->method('getMethodCalls')
->willReturn(array(['nothing', array()]));
}
return $definition;
}
}

View File

@@ -45,6 +45,11 @@ class ExportManagerTest extends KernelTestCase
use \Chill\MainBundle\Test\PrepareUserTrait;
use \Chill\MainBundle\Test\PrepareScopeTrait;
/**
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
*
@@ -60,6 +65,8 @@ class ExportManagerTest extends KernelTestCase
{
self::bootKernel();
$this->container = self::$kernel->getContainer();
$this->prophet = new \Prophecy\Prophet;
}
@@ -90,7 +97,7 @@ class ExportManagerTest extends KernelTestCase
\Symfony\Component\Security\Core\User\UserInterface $user = null
)
{
$localUser = $user === NULL ? self::$container->get('doctrine.orm.entity_manager')
$localUser = $user === NULL ? $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneBy(array('username' => 'center a_social')) :
$user;
@@ -99,10 +106,10 @@ class ExportManagerTest extends KernelTestCase
$tokenStorage->setToken($token);
return new ExportManager(
$logger === NULL ? self::$container->get('logger') : $logger,
$em === NULL ? self::$container->get('doctrine.orm.entity_manager') : $em,
$authorizationChecker === NULL ? self::$container->get('security.authorization_checker') : $authorizationChecker,
$authorizationHelper === NULL ? self::$container->get('chill.main.security.authorization.helper') : $authorizationHelper,
$logger === NULL ? $this->container->get('logger') : $logger,
$em === NULL ? $this->container->get('doctrine.orm.entity_manager') : $em,
$authorizationChecker === NULL ? $this->container->get('security.authorization_checker') : $authorizationChecker,
$authorizationHelper === NULL ? $this->container->get('chill.main.security.authorization.helper') : $authorizationHelper,
$tokenStorage)
;
}
@@ -537,7 +544,7 @@ class ExportManagerTest extends KernelTestCase
$export = $this->prophet->prophesize();
$export->willImplement(ExportInterface::class);
$em = self::$container->get('doctrine.orm.entity_manager');
$em = $this->container->get('doctrine.orm.entity_manager');
$export->initiateQuery(
Argument::is(array('foo')),
Argument::Type('array'),
@@ -620,13 +627,12 @@ class ExportManagerTest extends KernelTestCase
//add formatter interface
$formatter = new \Chill\MainBundle\Export\Formatter\SpreadSheetFormatter(
self::$container->get('translator'), $exportManager);
$this->container->get('translator'), $exportManager);
$exportManager->addFormatter($formatter, 'spreadsheet');
//ob_start();
$response = $exportManager->generate(
'dummy',
array($center),
$response = $exportManager->generate('dummy',
array(PickCenterType::CENTERS_IDENTIFIERS => array($center)),
array(
ExportType::FILTER_KEY => array(
'filter_foo' => array(

View File

@@ -54,20 +54,13 @@ class PageTest extends KernelTestCase
$number = 1,
$itemPerPage = 10,
$route = 'route',
array $routeParameters = array(),
$totalItems = 100
array $routeParameters = array()
) {
$urlGenerator = $this->prophet->prophesize();
$urlGenerator->willImplement(UrlGeneratorInterface::class);
return new Page(
$number,
$itemPerPage,
$urlGenerator->reveal(),
$route,
$routeParameters,
$totalItems
);
return new Page($number, $itemPerPage, $urlGenerator->reveal(), $route,
$routeParameters);
}
public function testPageNumber() {

View File

@@ -21,10 +21,9 @@ namespace Chill\MainBundle\Test\Search;
use Chill\MainBundle\Search\SearchProvider;
use Chill\MainBundle\Search\SearchInterface;
use PHPUnit\Framework\TestCase;
class SearchProviderTest extends TestCase
class SearchProviderTest extends \PHPUnit\Framework\TestCase
{
/**
@@ -312,4 +311,4 @@ class SearchProviderTest extends TestCase
return $mock;
}
}
}

View File

@@ -50,7 +50,7 @@ class AuthorizationHelperTest extends KernelTestCase
*/
private function getAuthorizationHelper()
{
return static::$container
return static::$kernel->getContainer()
->get('chill.main.security.authorization.helper')
;
}

View File

@@ -39,7 +39,8 @@ class TokenManagerTest extends KernelTestCase
{
self::bootKernel();
$logger = self::$container
$logger = self::$kernel
->getContainer()
->get('logger');
$this->tokenManager = new TokenManager('secret', $logger);

View File

@@ -36,19 +36,53 @@ class ChillMenuTwigFunctionTest extends KernelTestCase
public static function setUpBeforeClass()
{
self::bootKernel(array('environment' => 'test'));
static::$templating = static::$container
->get('templating');
$pathToBundle = static::$container->getParameter('kernel.bundles_metadata')['ChillMainBundle']['path'];
static::$templating = static::$kernel
->getContainer()->get('templating');
//load templates in Tests/Resources/views
static::$container->get('twig.loader')
->addPath($pathToBundle.'/Resources/test/views/', $namespace = 'tests');
static::$kernel->getContainer()->get('twig.loader')
->addPath(static::$kernel->getContainer()->getParameter('kernel.root_dir')
.'/Resources/views/', $namespace = 'tests');
}
public function testNormalMenu()
{
$content = static::$templating->render('@tests/menus/normalMenu.html.twig');
$this->assertContains('ul', $content,
"test that the file contains an ul tag"
);
$crawler = new Crawler($content);
$ul = $crawler->filter('ul')->getNode(0);
$this->assertEquals( 'ul', $ul->tagName);
$lis = $crawler->filter('ul')->children();
$this->assertEquals(3, count($lis));
$lis->each(function(Crawler $node, $i) {
$this->assertEquals('li', $node->getNode(0)->tagName);
$a = $node->children()->getNode(0);
$this->assertEquals('a', $a->tagName);
switch($i) {
case 0:
$this->assertEquals('/dummy?param=fake', $a->getAttribute('href'));
$this->assertEquals('active', $a->getAttribute('class'));
$this->assertEquals('test0', $a->nodeValue);
break;
case 1:
$this->assertEquals('/dummy1?param=fake', $a->getAttribute('href'));
$this->assertEmpty($a->getAttribute('class'));
$this->assertEquals('test1', $a->nodeValue);
break;
case 3:
$this->assertEquals('/dummy2/fake', $a->getAttribute('href'));
$this->assertEmpty($a->getAttribute('class'));
$this->assertEquals('test2', $a->nodeValue);
}
});
}
public function testMenuOverrideTemplate()
{
$this->markTestSkipped("this hacks seems not working now");
$content = static::$templating->render('@tests/menus/overrideTemplate.html.twig');
$this->assertEquals('fake template', $content);
}
}

View File

@@ -28,7 +28,7 @@ class MenuComposerTest extends KernelTestCase
public function setUp()
{
self::bootKernel(array('environment' => 'test'));
$this->menuComposer = static::$container
$this->menuComposer = static::$kernel->getContainer()
->get('chill.main.menu_composer');
}
@@ -42,5 +42,50 @@ class MenuComposerTest extends KernelTestCase
$routes = $this->menuComposer->getRoutesFor('dummy0');
$this->assertInternalType('array', $routes);
$this->assertCount(3, $routes);
//check that the keys are sorted
$orders = array_keys($routes);
foreach ($orders as $key => $order){
if (array_key_exists($key + 1, $orders)) {
$this->assertGreaterThan($order, $orders[$key + 1],
'Failing to assert that routes are ordered');
}
}
//check that the array are identical, order is not important :
$expected = array(
50 => array(
'key' => 'chill_main_dummy_0',
'label' => 'test0',
'otherkey' => 'othervalue'
),
51 => array(
'key' => 'chill_main_dummy_1',
'label' => 'test1',
'helper'=> 'great helper'
),
52 => array(
'key' => 'chill_main_dummy_2',
'label' => 'test2'
));
foreach ($expected as $order => $route ){
}
//compare arrays
foreach($expected as $order => $route) {
//check the key are the one expected
$this->assertTrue(isset($routes[$order]));
if (isset($routes[$order])){ #avoid an exception if routes with order does not exists
//sort arrays. Order matters for phpunit::assertSame
ksort($route);
ksort($routes[$order]);
$this->assertSame($route, $routes[$order]);
}
}
}
}

View File

@@ -29,40 +29,40 @@ use Symfony\Component\DependencyInjection\ContainerAwareInterface;
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterface
class TimelineBuilder implements ContainerAwareInterface
{
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
/**
*
* @var \Doctrine\ORM\EntityManagerInterface
*/
private $em;
/**
* Record provider
*
*
* This array has the structure `[ 'service id' => $service ]`
*
* @var TimelineProviderInterface[]
*/
private $providers = [];
/**
* Record provider and their context
*
*
* This array has the structure `[ 'context' => [ 'service id' ] ]`
*
* @var array
*/
private $providersByContext = [];
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* return an HTML string with timeline
*
@@ -79,18 +79,18 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
public function getTimelineHTML($context, array $args, $firstItem = 0, $number = 20)
{
$union = $this->buildUnionQuery($context, $args);
//add ORDER BY clause and LIMIT
$query = $union . sprintf(' ORDER BY date DESC LIMIT %d OFFSET %d',
$number, $firstItem);
// run query and handle results
$fetched = $this->runUnionQuery($query);
$entitiesByKey = $this->getEntities($fetched, $context);
return $this->render($fetched, $entitiesByKey, $context, $args);
}
/**
* Return the number of items for the given context and args
*
@@ -101,17 +101,17 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
public function countItems($context, array $args)
{
$union = $this->buildUnionQuery($context, $args);
// embed the union query inside a count query
$count = sprintf('SELECT COUNT(sq.id) AS total FROM (%s) as sq', $union);
$rsm = (new ResultSetMapping())
->addScalarResult('total', 'total', Type::INTEGER);
return $this->em->createNativeQuery($count, $rsm)
->getSingleScalarResult();
}
/**
* add a provider id
*
@@ -125,7 +125,7 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
$this->providersByContext[$context][] = $id;
$this->providers[$id] = $provider;
}
/**
* Get providers by context
*
@@ -139,16 +139,16 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
throw new \LogicException(sprintf('No builders have been defined for "%s"'
. ' context', $context));
}
$providers = [];
foreach($this->providersByContext[$context] as $providerId) {
$providers[] = $this->providers[$providerId];
}
return $providers;
}
/**
* build the UNION query with all providers
*
@@ -170,10 +170,10 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
$append = ($union === '') ? $select : ' UNION '.$select;
$union .= $append;
}
return $union;
}
/**
* return the SQL SELECT query as a string,
*
@@ -186,7 +186,7 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
private function buildSelectQuery(TimelineProviderInterface $provider, $context, array $args)
{
$data = $provider->fetchQuery($context, $args);
return sprintf(
'SELECT %s AS id, '
. '%s AS "date", '
@@ -199,7 +199,7 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
$data['FROM'],
$data['WHERE']);
}
/**
* run the UNION query and return result as an array
*
@@ -212,11 +212,11 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
->addScalarResult('id', 'id')
->addScalarResult('type', 'type')
->addScalarResult('date', 'date');
return $this->em->createNativeQuery($query, $resultSetMapping)
->getArrayResult();
}
/**
*
* @param array $queriedIds
@@ -227,11 +227,11 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
{
//gather entities by type to pass all id with same type to the TimelineProvider.
$idsByType = array();
foreach($queriedIds as $result) {
$idsByType[$result['type']][] = $result['id'];
}
//fetch entities from providers
$entitiesByType = array();
foreach ($idsByType as $type => $ids) {
@@ -243,10 +243,10 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
}
}
}
return $entitiesByType;
}
/**
* render the timeline as HTML
*
@@ -269,17 +269,17 @@ class TimelineBuilder implements ContainerAwareInterface, TimelineBuilderInterfa
$timelineEntry['date'] = new \DateTime($result['date']);
$timelineEntry['template'] = $data['template'];
$timelineEntry['template_data'] = $data['template_data'];
$timelineEntries[] = $timelineEntry;
}
return $this->container->get('templating')
->render('@ChillMain/Timeline/index.html.twig', array(
'results' => $timelineEntries
));
}
/**
* get the template data from the provider for the given entity, by type.
*

View File

@@ -1,24 +0,0 @@
<?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\MainBundle\Timeline;
interface TimelineBuilderInterface
{
}

View File

@@ -86,3 +86,7 @@ login_check:
logout:
path: /logout
chill_main_test:
path: /{_locale}/main/test
controller: Chill\MainBundle\Controller\DefaultController::testAction

View File

@@ -10,7 +10,6 @@ services:
- "@translator.default"
Chill\MainBundle\Templating\TranslatableStringHelper: '@chill.main.helper.translatable_string'
Chill\MainBundle\Templating\TranslatableStringHelperInterface: Chill\MainBundle\Templating\TranslatableStringHelper
chill.main.twig.translatable_string:
class: Chill\MainBundle\Templating\TranslatableStringTwig
@@ -20,14 +19,14 @@ services:
- [ setContainer, ["@service_container"]]
tags:
- { name: twig.extension }
chill.main.twig.widget:
class: Chill\MainBundle\Templating\Widget\WidgetRenderingTwig
arguments:
- "@event_dispatcher"
tags:
- { name: twig.extension }
chill.main.twig.csv_cell:
class: Chill\MainBundle\Templating\CSVCellTwig
tags:

View File

@@ -23,7 +23,6 @@ services:
arguments:
- "@request_stack"
- "@doctrine.orm.entity_manager"
- "@chill.main.helper.translatable_string"
tags:
- { name: form.type, alias: select2_chill_country }
@@ -32,7 +31,6 @@ services:
arguments:
- "@request_stack"
- "@doctrine.orm.entity_manager"
- "@chill.main.helper.translatable_string"
tags:
- { name: form.type, alias: select2_chill_language }

View File

@@ -1,4 +1,4 @@
services:
services:
chill.main.security.authorization.helper:
class: Chill\MainBundle\Security\Authorization\AuthorizationHelper
arguments:
@@ -6,48 +6,47 @@ services:
$hierarchy: "%security.role_hierarchy.roles%"
$em: '@Doctrine\ORM\EntityManagerInterface'
Chill\MainBundle\Security\Authorization\AuthorizationHelper: '@chill.main.security.authorization.helper'
Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface: Chill\MainBundle\Security\Authorization\AuthorizationHelper
chill.main.role_provider:
class: Chill\MainBundle\Security\RoleProvider
chill.main.user_provider:
class: Chill\MainBundle\Security\UserProvider\UserProvider
arguments:
$em: '@Doctrine\ORM\EntityManagerInterface'
Chill\MainBundle\Security\Authorization\ChillExportVoter:
arguments:
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper'
tags:
- { name: security.voter }
Chill\MainBundle\Security\PasswordRecover\TokenManager:
Chill\MainBundle\Security\PasswordRecover\TokenManager:
arguments:
$secret: '%kernel.secret%'
$logger: '@Psr\Log\LoggerInterface'
Chill\MainBundle\Security\PasswordRecover\RecoverPasswordHelper:
arguments:
$tokenManager: '@Chill\MainBundle\Security\PasswordRecover\TokenManager'
$urlGenerator: '@Symfony\Component\Routing\Generator\UrlGeneratorInterface'
$mailer: '@Chill\MainBundle\Notification\Mailer'
$routeParameters: "%chill_main.notifications%"
Chill\MainBundle\Security\PasswordRecover\PasswordRecoverEventSubscriber:
arguments:
$locker: '@Chill\MainBundle\Security\PasswordRecover\PasswordRecoverLocker'
tags:
- { name: kernel.event_subscriber }
Chill\MainBundle\Security\PasswordRecover\PasswordRecoverLocker:
arguments:
$chillRedis: '@Chill\MainBundle\Redis\ChillRedis'
$logger: '@Psr\Log\LoggerInterface'
Chill\MainBundle\Security\PasswordRecover\PasswordRecoverVoter:
arguments:
$locker: '@Chill\MainBundle\Security\PasswordRecover\PasswordRecoverLocker'
$requestStack: '@Symfony\Component\HttpFoundation\RequestStack'
tags:
- { name: security.voter }
- { name: security.voter }

View File

@@ -1,13 +0,0 @@
---
services:
Chill\MainBundle\Serializer\Normalizer\CenterNormalizer:
tags:
- { name: 'serializer.normalizer', priority: 64 }
Chill\MainBundle\Serializer\Normalizer\DateNormalizer:
tags:
- { name: 'serializer.normalizer', priority: 64 }
Chill\MainBundle\Serializer\Normalizer\UserNormalizer:
tags:
- { name: 'serializer.normalizer', priority: 64 }

View File

@@ -30,7 +30,6 @@ services:
Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension:
tags:
- { name: twig.extension }
Chill\MainBundle\Templating\Entity\ChillEntityRenderExtensionInterface: Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension
Chill\MainBundle\Templating\Entity\CommentRender:
arguments:
@@ -38,7 +37,7 @@ services:
- '@Symfony\Component\Templating\EngineInterface'
tags:
- { name: 'chill.render_entity' }
Chill\MainBundle\Templating\ChillMarkdownRenderExtension:
tags:
- { name: twig.extension }

View File

@@ -4,6 +4,4 @@ services:
arguments:
- "@doctrine.orm.entity_manager"
calls:
- [ setContainer, ["@service_container"]]
Chill\MainBundle\Timeline\TimelineBuilderInterface: "@chill_main.timeline_builder"
- [ setContainer, ["@service_container"]]

View File

@@ -17,57 +17,57 @@
*/
namespace Chill\PersonBundle\Actions;
use Symfony\Contracts\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\Event;
/**
* Event triggered when an entity attached to a person is removed.
*
*
*
*/
class ActionEvent implements Event
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
* @var string
*/
protected $sqlStatement;
/**
*
* @var string[]
*/
protected $preSql = [];
/**
*
* @var string[]
*/
protected $postSql = [];
public function __construct($personId, $entity, $sqlStatement, $metadata = [])
{
$this->personId = $personId;
@@ -77,7 +77,7 @@ class ActionEvent implements Event
}
/**
*
*
* @return string[]
*/
public function getPreSql(): array
@@ -86,7 +86,7 @@ class ActionEvent implements Event
}
/**
*
*
* @return string[]
*/
public function getPostSql(): array
@@ -105,7 +105,7 @@ class ActionEvent implements Event
/**
* Add Sql which will be executed **after** the delete statement
*
*
* @param type $postSql
* @return $this
*/
@@ -122,22 +122,22 @@ class ActionEvent implements Event
/**
* 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;
}
}

View File

@@ -5,10 +5,10 @@ namespace Chill\PersonBundle\Config;
/**
* Give help to interact with the config for alt names
*
*
*
*/
class ConfigPersonAltNamesHelper implements ConfigPersonAltNamesHelperInterface
class ConfigPersonAltNamesHelper
{
/**
* the raw config, directly from the container parameter
@@ -16,32 +16,32 @@ class ConfigPersonAltNamesHelper implements ConfigPersonAltNamesHelperInterface
* @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;
@@ -50,11 +50,11 @@ class ConfigPersonAltNamesHelper implements ConfigPersonAltNamesHelperInterface
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;
@@ -63,7 +63,7 @@ class ConfigPersonAltNamesHelper implements ConfigPersonAltNamesHelperInterface
$cur = next($labels);
}
}
return $choices;
}

View File

@@ -4,21 +4,17 @@ namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Privacy\AccompanyingPeriodPrivacyEvent;
use Chill\PersonBundle\Entity\Person;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* Class AccompanyingCourseController
@@ -27,21 +23,6 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
*/
class AccompanyingCourseController extends Controller
{
protected SerializerInterface $serializer;
protected EventDispatcherInterface $dispatcher;
protected ValidatorInterface $validator;
public function __construct(
SerializerInterface $serializer,
EventDispatcherInterface $dispatcher,
ValidatorInterface $validator
) {
$this->serializer = $serializer;
$this->dispatcher = $dispatcher;
$this->validator = $validator;
}
/**
* Homepage of Accompanying Course section
*
@@ -87,75 +68,54 @@ class AccompanyingCourseController extends Controller
}
/**
* Get API Data for showing endpoint
*
* Sérialise temporairement quelques données pour donner à manger au composant vuejs
* @Route(
* "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/show.{_format}",
* name="chill_person_accompanying_course_api_show"
* )
* "/{_locale}/api/parcours/{accompanying_period_id}/show",
* name="chill_person_accompanying_course_api_show")
* @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"})
* @param SerializerInterface $serializer
*/
public function showAPI(AccompanyingPeriod $accompanyingCourse, $_format): Response
public function showAPI(AccompanyingPeriod $accompanyingCourse): Response
{
// TODO check ACL on AccompanyingPeriod
$this->dispatcher->dispatch(
AccompanyingPeriodPrivacyEvent::ACCOMPANYING_PERIOD_PRIVACY_EVENT,
new AccompanyingPeriodPrivacyEvent($accompanyingCourse, [
'action' => 'showApi'
])
);
switch ($_format) {
case 'json':
return $this->json($accompanyingCourse);
default:
throw new BadRequestException('Unsupported format');
$persons = [];
foreach ($accompanyingCourse->getParticipations() as $k => $participation ) {
/**
* @var AccompanyingPeriodParticipation $participation
* @var Person $person
*/
$person = $participation->getPerson();
$persons[$k] = [
'firstname' => $person->getFirstName(),
'lastname' => $person->getLastName(),
'email' => $person->getEmail(),
'phone' => $person->getPhonenumber(),
'startdate' => ($participation->getStartDate()) ? $participation->getStartDate()->format('Y-m-d') : null,
'enddate' => ($participation->getEndDate()) ? $participation->getEndDate()->format('Y-m-d') : null
];
}
$data = [
'id' => $accompanyingCourse->getId(),
'remark' => $accompanyingCourse->getRemark(),
'closing_motive' => $accompanyingCourse->getClosingMotive() ? $accompanyingCourse->getClosingMotive()->getName()['fr'] : null,
'opening_date' => ($accompanyingCourse->getOpeningDate()) ? $accompanyingCourse->getOpeningDate()->format('Y-m-d') : null,
'closing_date' => ($accompanyingCourse->getClosingDate()) ? $accompanyingCourse->getClosingDate()->format('Y-m-d') : null,
'persons' => $persons
];
/**
$normalizer = [new ObjectNormalizer()];
$encoder = [new JsonEncoder()];
$serializer = new Serializer($normalizer, $encoder);
$serialized = $serializer->serialize($data,'json', []);
*
*/
$serialized = \json_encode($data);
$response = new Response($serialized);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
/**
* Get API Data for showing endpoint
*
* @Route(
* "/{_locale}/person/api/1.0/accompanying-course/{accompanying_period_id}/participation.{_format}",
* name="chill_person_accompanying_course_api_add_participation",
* methods={"POST"},
* format="json",
* requirements={
* "_format": "json",
* }
* )
* @ParamConverter("accompanyingCourse", options={"id": "accompanying_period_id"})
*/
public function addParticipationAPI(Request $request, AccompanyingPeriod $accompanyingCourse, $_format): Response
{
switch ($_format) {
case 'json':
$person = $this->serializer->deserialize($request->getContent(), Person::class, $_format, [
]);
break;
default:
throw new BadRequestException('Unsupported format');
}
if (NULL === $person) {
throw new BadRequestException('person id not found');
}
// TODO add acl
$accompanyingCourse->addPerson($person);
$errors = $this->validator->validate($accompanyingCourse);
if ($errors->count() > 0) {
// only format accepted
return $this->json($errors);
}
$this->getDoctrine()->getManager()->flush();
return new JsonResponse();
}
}

View File

@@ -26,7 +26,7 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
use Doctrine\DBAL\Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Form\Type\AccompanyingPeriodType;
use Chill\PersonBundle\Form\AccompanyingPeriodType;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\Common\Collections\Criteria;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
@@ -47,12 +47,12 @@ class AccompanyingPeriodController extends AbstractController
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @var ValidatorInterface
*/
protected $validator;
/**
* AccompanyingPeriodController constructor.
*
@@ -64,17 +64,11 @@ class AccompanyingPeriodController extends AbstractController
$this->eventDispatcher = $eventDispatcher;
$this->validator = $validator;
}
/**
* @Route(
* name="chill_person_accompanying_period_list",
* path="/{_locale}/person/{person_id}/accompanying-period"
* )
*/
public function listAction(int $person_id): Response
{
$person = $this->_getPerson($person_id);
$event = new PrivacyEvent($person, [
'element_class' => AccompanyingPeriod::class,
'action' => 'list'
@@ -86,13 +80,7 @@ class AccompanyingPeriodController extends AbstractController
'person' => $person
]);
}
/**
* @Route(
* name="chill_person_accompanying_period_create",
* path="/{_locale}/person/{person_id}/accompanying-period/create"
* )
*/
public function createAction(int $person_id, Request $request): Response
{
$person = $this->_getPerson($person_id);
@@ -102,17 +90,17 @@ class AccompanyingPeriodController extends AbstractController
$accompanyingPeriod = new AccompanyingPeriod(new \DateTime('now'));
$accompanyingPeriod->setClosingDate(new \DateTime('now'));
$accompanyingPeriod->addPerson($person);
//or $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);
@@ -132,7 +120,7 @@ class AccompanyingPeriodController extends AbstractController
$this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId()
]));
} else {
$flashBag->add('error', $this->get('translator')
->trans('Error! Period not created!'));
@@ -149,12 +137,9 @@ class AccompanyingPeriodController extends AbstractController
'accompanying_period' => $accompanyingPeriod
]);
}
/**
* @Route(
* name="chill_person_accompanying_period_update",
* path="/{_locale}/person/{person_id}/accompanying-period/{period_id}/update"
* )
* @throws Exception
*/
public function updateAction(int $person_id, int $period_id, Request $request): Response
{
@@ -169,7 +154,7 @@ class AccompanyingPeriodController extends AbstractController
/** @var Person $person */
$person = $this->_getPerson($person_id);
// CHECK
if (! $accompanyingPeriod->containsPerson($person)) {
throw new Exception("Accompanying period " . $period_id . " does not contain person " . $person_id);
@@ -191,7 +176,7 @@ class AccompanyingPeriodController extends AbstractController
if ($form->isValid(['Default', 'closed'])
&& count($errors) === 0) {
$em->flush();
$flashBag->add('success',
@@ -201,9 +186,9 @@ class AccompanyingPeriodController extends AbstractController
$this->generateUrl('chill_person_accompanying_period_list', [
'person_id' => $person->getId()
]));
} else {
$flashBag->add('error', $this->get('translator')
->trans('Error when updating the period'));
@@ -219,22 +204,19 @@ class AccompanyingPeriodController extends AbstractController
'accompanying_period' => $accompanyingPeriod
]);
}
/**
* @Route(
* name="chill_person_accompanying_period_close",
* path="/{_locale}/person/{person_id}/accompanying-period/close"
* )
* @throws \Exception
*/
public function closeAction(int $person_id, Request $request): Response
{
$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', ['%name%' => $person->__toString()]
@@ -247,7 +229,7 @@ class AccompanyingPeriodController extends AbstractController
}
$current = $person->getCurrentAccompanyingPeriod();
$form = $this->createForm(AccompanyingPeriodType::class, $current, [
'period_action' => 'close',
'center' => $person->getCenter()
@@ -274,7 +256,7 @@ class AccompanyingPeriodController extends AbstractController
'person_id' => $person->getId()
])
);
} else {
$this->get('session')->getFlashBag()
->add('error', $this->get('translator')
@@ -285,7 +267,7 @@ class AccompanyingPeriodController extends AbstractController
->add('info', $error->getMessage());
}
}
} else { //if form is not valid
$this->get('session')->getFlashBag()
->add('error',
@@ -306,7 +288,7 @@ class AccompanyingPeriodController extends AbstractController
'accompanying_period' => $current
]);
}
private function _validatePerson(Person $person): ConstraintViolationListInterface
{
$errors = $this->validator->validate($person, null,
@@ -314,10 +296,10 @@ class AccompanyingPeriodController extends AbstractController
// Can be disabled with config
if (false === $this->container->getParameter('chill_person.allow_multiple_simultaneous_accompanying_periods')) {
$errors_accompanying_period = $this->validator->validate($person, null,
['accompanying_period_consistent']);
foreach($errors_accompanying_period as $error ) {
$errors->add($error);
}
@@ -325,13 +307,7 @@ class AccompanyingPeriodController extends AbstractController
return $errors;
}
/**
* @Route(
* name="chill_person_accompanying_period_open",
* path="/{_locale}/person/{person_id}/accompanying-period/open"
* )
*/
public function openAction(int $person_id, Request $request): Response
{
$person = $this->_getPerson($person_id);
@@ -408,13 +384,7 @@ class AccompanyingPeriodController extends AbstractController
'accompanying_period' => $accompanyingPeriod
]);
}
/**
* @Route(
* name="chill_person_accompanying_period_re_open",
* path="/{_locale}/person/{person_id}/accompanying-period/re-open"
* )
*/
public function reOpenAction(int $person_id, int $period_id, Request $request): Response
{
/** @var Person $person */
@@ -447,13 +417,13 @@ class AccompanyingPeriodController extends AbstractController
return $this->redirectToRoute('chill_person_accompanying_period_list', [
'person_id' => $person->getId()
]);
} elseif ($confirm === false && $period->canBeReOpened($person)) {
return $this->render('ChillPersonBundle:AccompanyingPeriod:re_open.html.twig', [
'period' => $period,
'person' => $person
]);
} else {
return (new Response())
->setStatusCode(Response::HTTP_BAD_REQUEST)

View File

@@ -13,29 +13,16 @@ use Symfony\Component\Routing\Annotation\Route;
class AdminController extends AbstractController
{
/**
* @Route(
* name="chill_person_admin",
* path="/{_locale}/admin/person"
* )
* @param $_locale
* @return \Symfony\Component\HttpFoundation\Response
*/
public function indexAction($_locale)
{
return $this->render('ChillPersonBundle:Admin:layout.html.twig', []);
}
/**
* @Route(
* name="chill_person_admin_redirect_to_admin_index",
* path="/{_locale}/admin/person_redirect_to_main",
* options={
* menus={
* admin_person={
* order="0",
* label="Main admin menu"
* }
* }
* }
* )
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function redirectToAdminIndexAction()
{

View File

@@ -30,7 +30,6 @@ use Chill\MainBundle\Entity\Address;
use Doctrine\Common\Collections\Criteria;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class PersonAddressController
@@ -46,7 +45,7 @@ class PersonAddressController extends AbstractController
* @var ValidatorInterface
*/
protected $validator;
/**
* PersonAddressController constructor.
*
@@ -56,13 +55,7 @@ class PersonAddressController extends AbstractController
{
$this->validator = $validator;
}
/**
* @Route(
* name="chill_person_address_list",
* path="/{_locale}/person/{person_id}/address/list"
* )
*/
public function listAction($person_id)
{
$person = $this->getDoctrine()->getManager()
@@ -85,13 +78,6 @@ class PersonAddressController extends AbstractController
));
}
/**
* @Route(
* name="chill_person_address_create",
* path="/{_locale}/person/{person_id}/address/create",
* methods={"POST"}
* )
*/
public function newAction($person_id)
{
$person = $this->getDoctrine()->getManager()
@@ -119,12 +105,6 @@ class PersonAddressController extends AbstractController
));
}
/**
* @Route(
* name="chill_person_address_new",
* path="/{_locale}/person/{person_id}/address/new"
* )
*/
public function createAction($person_id, Request $request)
{
$person = $this->getDoctrine()->getManager()
@@ -181,12 +161,6 @@ class PersonAddressController extends AbstractController
));
}
/**
* @Route(
* name="chill_person_address_edit",
* path="/{_locale}/person/{person_id}/address/{address_id}/edit"
* )
*/
public function editAction($person_id, $address_id)
{
$person = $this->getDoctrine()->getManager()
@@ -215,12 +189,6 @@ class PersonAddressController extends AbstractController
));
}
/**
* @Route(
* name="chill_person_address_update",
* path="/{_locale}/person/{person_id}/address/{address_id}/update"
* )
*/
public function updateAction($person_id, $address_id, Request $request)
{
$person = $this->getDoctrine()->getManager()

View File

@@ -34,23 +34,27 @@ 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;
use Chill\PersonBundle\Repository\PersonNotDuplicateRepository;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
final class PersonController extends AbstractController
/**
* Class PersonController
*
* @package Chill\PersonBundle\Controller
*/
class PersonController extends AbstractController
{
/**
*
* @var SimilarPersonMatcher
*/
protected $similarPersonMatcher;
/**
*
* @var TranslatorInterface
*/
protected $translator;
@@ -61,39 +65,35 @@ final class PersonController extends AbstractController
protected $eventDispatcher;
/**
*
* @var PersonRepository;
*/
protected $personRepository;
/**
*
* @var ConfigPersonAltNamesHelper
*/
protected $configPersonAltNameHelper;
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* @var ValidatorInterface
*/
private $validator;
public function __construct(
public function __construct(
SimilarPersonMatcher $similarPersonMatcher,
TranslatorInterface $translator,
EventDispatcherInterface $eventDispatcher,
PersonRepository $personRepository,
ConfigPersonAltNamesHelper $configPersonAltNameHelper,
LoggerInterface $logger,
ValidatorInterface $validator,
EntityManagerInterface $em
ValidatorInterface $validator
) {
$this->similarPersonMatcher = $similarPersonMatcher;
$this->translator = $translator;
@@ -102,14 +102,14 @@ final class PersonController extends AbstractController
$this->personRepository = $personRepository;
$this->logger = $logger;
$this->validator = $validator;
$this->em = $em;
}
public function getCFGroup()
{
$cFGroup = null;
$cFDefaultGroup = $this->em->getRepository("ChillCustomFieldsBundle:CustomFieldsDefaultGroup")
$em = $this->getDoctrine()->getManager();
$cFDefaultGroup = $em->getRepository("ChillCustomFieldsBundle:CustomFieldsDefaultGroup")
->findOneByEntity("Chill\PersonBundle\Entity\Person");
if($cFDefaultGroup) {
@@ -119,12 +119,6 @@ final class PersonController extends AbstractController
return $cFGroup;
}
/**
* @Route(
* name="chill_person_view",
* path="/{_locale}/person/{person_id}/general"
* )
*/
public function viewAction($person_id)
{
$person = $this->_getPerson($person_id);
@@ -148,12 +142,6 @@ final class PersonController extends AbstractController
));
}
/**
* @Route(
* name="chill_person_general_edit",
* path="/{_locale}/person/{person_id}/general/edit"
* )
*/
public function editAction($person_id)
{
$person = $this->_getPerson($person_id);
@@ -177,13 +165,7 @@ final class PersonController extends AbstractController
array('person' => $person, 'form' => $form->createView()));
}
/**
* @Route(
* name="chill_person_general_update",
* path="/{_locale}/person/{person_id}/general/update"
* )
*/
public function updateAction($person_id, Request $request, TranslatorInterface $translator)
public function updateAction($person_id, Request $request)
{
$person = $this->_getPerson($person_id);
@@ -212,11 +194,12 @@ final class PersonController extends AbstractController
$this->get('session')->getFlashBag()
->add('success',
$translator
$this->get('translator')
->trans('The person data has been updated')
);
$this->em->flush();
$em = $this->getDoctrine()->getManager();
$em->flush();
$url = $this->generateUrl('chill_person_view', array(
'person_id' => $person->getId()
@@ -226,12 +209,6 @@ final class PersonController extends AbstractController
}
}
/**
* @Route(
* name="chill_person_new",
* path="/{_locale}/person/new"
* )
*/
public function newAction()
{
// this is a dummy default center.
@@ -316,13 +293,7 @@ final class PersonController extends AbstractController
return $errors;
}
/**
* @Route(
* name="chill_person_review",
* path="/{_locale}/person/review"
* )
*/
public function reviewAction(Request $request, PersonNotDuplicateRepository $personNotDuplicateRepository)
public function reviewAction(Request $request)
{
if ($request->getMethod() !== 'POST') {
$r = new Response("You must send something to review the creation of a new Person");
@@ -372,9 +343,8 @@ final class PersonController extends AbstractController
$this->logger->info('Person created without errors');
}
$this->em->persist($person);
$alternatePersons = $this->similarPersonMatcher->matchPerson($person, $personNotDuplicateRepository);
$alternatePersons = $this->similarPersonMatcher
->matchPerson($person);
if (count($alternatePersons) === 0) {
return $this->forward('ChillPersonBundle:Person:create');
@@ -398,12 +368,6 @@ final class PersonController extends AbstractController
'form' => $form->createView()));
}
/**
* @Route(
* name="chill_person_create",
* path="/{_locale}/person/create"
* )
*/
public function createAction(Request $request)
{
@@ -427,9 +391,11 @@ final class PersonController extends AbstractController
'You are not allowed to create this person');
if ($errors->count() === 0) {
$this->em->persist($person);
$em = $this->getDoctrine()->getManager();
$this->em->flush();
$em->persist($person);
$em->flush();
return $this->redirect($this->generateUrl('chill_person_general_edit',
array('person_id' => $person->getId())));

View File

@@ -12,17 +12,16 @@ use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Search\SimilarPersonMatcher;
use http\Exception\InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Translation\TranslatorInterface;
use Chill\ActivityBundle\Entity\Activity;
use Chill\DocStoreBundle\Entity\PersonDocument;
use Chill\EventBundle\Entity\Participation;
use Chill\PersonBundle\Repository\PersonNotDuplicateRepository;
use Chill\TaskBundle\Entity\SingleTask;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class PersonDuplicateController extends AbstractController
class PersonDuplicateController extends Controller
{
/**
* @var \Chill\PersonBundle\Search\SimilarPersonMatcher
@@ -63,13 +62,7 @@ class PersonDuplicateController extends AbstractController
$this->eventDispatcher = $eventDispatcher;
}
/**
* @Route(
* name="chill_person_duplicate_view",
* path="/{_locale}/person/{person_id}/duplicate/view"
* )
*/
public function viewAction($person_id, PersonNotDuplicateRepository $personNotDuplicateRepository)
public function viewAction($person_id)
{
$person = $this->_getPerson($person_id);
if ($person === null) {
@@ -83,7 +76,8 @@ class PersonDuplicateController extends AbstractController
$duplicatePersons = $this->similarPersonMatcher->
matchPerson($person, 0.5, SimilarPersonMatcher::SIMILAR_SEARCH_ORDER_BY_ALPHABETICAL);
$notDuplicatePersons = $personNotDuplicateRepository->findNotDuplicatePerson($person);
$notDuplicatePersons = $this->getDoctrine()->getRepository(PersonNotDuplicate::class)
->findNotDuplicatePerson($person);
return $this->render('ChillPersonBundle:PersonDuplicate:view.html.twig', [
'person' => $person,
@@ -92,12 +86,6 @@ class PersonDuplicateController extends AbstractController
]);
}
/**
* @Route(
* name="chill_person_duplicate_confirm",
* path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/confirm"
* )
*/
public function confirmAction($person1_id, $person2_id, Request $request)
{
if ($person1_id === $person2_id) {
@@ -109,7 +97,7 @@ class PersonDuplicateController extends AbstractController
$person1->counters = $this->_getCounters($person1_id);
$person2->counters = $this->_getCounters($person2_id);
if ($person1 === null) {
throw $this->createNotFoundException("Person with id $person1_id not"
. " found on this server");
@@ -155,12 +143,6 @@ class PersonDuplicateController extends AbstractController
]);
}
/**
* @Route(
* name="chill_person_duplicate_not_duplicate",
* path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/not-duplicate"
* )
*/
public function notDuplicateAction($person1_id, $person2_id)
{
[$person1, $person2] = $this->_getPersonsByPriority($person1_id, $person2_id);
@@ -184,12 +166,6 @@ class PersonDuplicateController extends AbstractController
return $this->redirectToRoute('chill_person_duplicate_view', ['person_id' => $person1->getId()]);
}
/**
* @Route(
* name="chill_person_remove_duplicate_not_duplicate",
* path="/{_locale}/person/{person1_id}/duplicate/{person2_id}/remove-not-duplicate"
* )
*/
public function removeNotDuplicateAction($person1_id, $person2_id)
{
[$person1, $person2] = $this->_getPersonsByPriority($person1_id, $person2_id);
@@ -208,12 +184,6 @@ class PersonDuplicateController extends AbstractController
return $this->redirectToRoute('chill_person_duplicate_view', ['person_id' => $person1->getId()]);
}
/**
* @Route(
* name="chill_person_find_manually_duplicate",
* path="/{_locale}/person/{person_id}/find-manually"
* )
*/
public function findManuallyDuplicateAction($person_id, Request $request)
{
$person = $this->_getPerson($person_id);
@@ -294,17 +264,17 @@ class PersonDuplicateController extends AbstractController
return [$person1, $person2];
}
private function _getCounters($id): ?array
{
$em = $this->getDoctrine()->getManager();
$nb_activity = $em->getRepository(Activity::class)->findBy(['person'=>$id]);
$nb_document = $em->getRepository(PersonDocument::class)->findBy(['person'=>$id]);
$nb_event = $em->getRepository(Participation::class)->findBy(['person'=>$id]);
$nb_task = $em->getRepository(SingleTask::class)->countByParameters(['person'=>$id]);
$person = $em->getRepository(Person::class)->findOneBy(['id'=>$id]);
return [
'nb_activity' => count($nb_activity),
'nb_document' => count($nb_document),

View File

@@ -26,9 +26,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Chill\MainBundle\Timeline\TimelineBuilder;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Timeline\TimelineBuilderInterface;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class TimelinePersonController
@@ -38,24 +36,24 @@ use Symfony\Component\Routing\Annotation\Route;
*/
class TimelinePersonController extends AbstractController
{
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
*
* @var TimelineBuilderInterface
* @var TimelineBuilder
*/
protected $timelineBuilder;
/**
*
* @var PaginatorFactory
*/
protected $paginatorFactory;
/**
* TimelinePersonController constructor.
*
@@ -63,28 +61,15 @@ class TimelinePersonController extends AbstractController
*/
public function __construct(
EventDispatcherInterface $eventDispatcher,
TimelineBuilderInterface $timelineBuilder,
TimelineBuilder $timelineBuilder,
PaginatorFactory $paginatorFactory
) {
$this->eventDispatcher = $eventDispatcher;
$this->timelineBuilder = $timelineBuilder;
$this->paginatorFactory = $paginatorFactory;
}
/**
* @Route(
* name="chill_person_timeline",
* path="/{_locale}/person/{person_id}/timeline",
* options={
* menus={
* person={
* order="60",
* label="Timeline"
* }
* }
* }
* )
*/
public function personAction(Request $request, $person_id)
{
$person = $this->getDoctrine()
@@ -94,22 +79,22 @@ class TimelinePersonController extends AbstractController
if ($person === NULL) {
throw $this->createNotFoundException();
}
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person);
$nbItems = $this->timelineBuilder->countItems('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',
'person',
array('person' => $person),
$paginator->getCurrentPage()->getFirstItemNumber(),
$paginator->getItemsPerPage()

View File

@@ -38,7 +38,7 @@ use Chill\PersonBundle\Doctrine\DQL\AddressPart;
*/
class ChillPersonExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritDoc}
* @param array $configs
@@ -49,40 +49,45 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
{
$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']);
$container->setParameter('chill_person.allow_multiple_simultaneous_accompanying_periods',
$config['allow_multiple_simultaneous_accompanying_periods']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(dirname(__DIR__, 2).'/config'));
$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');
$loader->load('services/serializer.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
@@ -92,9 +97,9 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
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':
@@ -106,7 +111,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
}
}
}
/**
* @param ContainerBuilder $container
* @param $config
@@ -114,7 +119,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
private function handleAccompanyingPeriodsFieldsParameters(ContainerBuilder $container, $config)
{
$container->setParameter('chill_person.accompanying_period_fields', $config);
foreach ($config as $key => $value) {
switch($key) {
case 'enabled':
@@ -125,7 +130,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
}
}
}
/**
* @param ContainerBuilder $container
* @throws MissingBundleException
@@ -145,7 +150,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
)
);
}
/**
* @param ContainerBuilder $container
* @throws MissingBundleException
@@ -156,7 +161,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
$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);
@@ -174,17 +179,17 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
$container->prependExtensionConfig('twig', $twigConfig);
$this-> declarePersonAsCustomizable($container);
//declare routes for person bundle
$container->prependExtensionConfig('chill_main', array(
'routing' => array(
'resources' => array(
dirname(__DIR__, 2) . '/config/routes.yaml'
'@ChillPersonBundle/config/routes.yaml'
)
)
));
}
/**
* Add a widget "add a person" on the homepage, automatically
*
@@ -203,7 +208,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
)
));
}
/**
* Add role hierarchy.
*
@@ -220,7 +225,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
)
));
}
/**
* Add DQL function linked with person
*
@@ -229,7 +234,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
protected function prependDoctrineDQL(ContainerBuilder $container)
{
//add DQL function to ORM (default entity_manager)
$container->prependExtensionConfig('doctrine', array(
'orm' => array(
'dql' => array(
@@ -252,7 +257,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
)
));
}
/**
* @param ContainerBuilder $container
*/

View File

@@ -37,43 +37,13 @@ use Chill\MainBundle\Entity\User;
/**
* AccompanyingPeriod Class
*
* @ORM\Entity
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriodRepository")
* @ORM\Table(name="chill_person_accompanying_period")
*/
class AccompanyingPeriod
{
/**
* Mark an accompanying period as "occasional"
*
* used in INTENSITY
*/
public const INTENSITY_OCCASIONAL = 'occasional';
/**
* Mark an accompanying period as "regular"
*
* used in INTENSITY
*/
public const INTENSITY_REGULAR = 'regular';
public const INTENSITIES = [self::INTENSITY_OCCASIONAL, self::INTENSITY_REGULAR];
/**
* Mark an accompanying period as "draft".
*
* This means that the accompanying period is not yet
* confirmed by the creator
*/
public const STEP_DRAFT = 'DRAFT';
/**
* Mark an accompanying period as "confirmed".
*
* This means that the accompanying period **is**
* confirmed by the creator
*/
public const STEP_CONFIRMED = 'CONFIRMED';
const INTENSITY = ['occasional', 'regular'];
/**
* @var integer
*
@@ -103,7 +73,7 @@ class AccompanyingPeriod
* @ORM\Column(type="text")
*/
private $remark = '';
/**
* @var Collection
*
@@ -112,7 +82,7 @@ class AccompanyingPeriod
* )
*/
private $comments;
/**
* @var Collection
*
@@ -121,7 +91,7 @@ class AccompanyingPeriod
* cascade={"persist", "remove", "merge", "detach"})
*/
private $participations;
/**
* @var AccompanyingPeriod\ClosingMotive
*
@@ -130,31 +100,31 @@ class AccompanyingPeriod
* @ORM\JoinColumn(nullable=true)
*/
private $closingMotive = null;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=true)
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=true)
*/
private $createdBy;
/**
* @var string
* @ORM\Column(type="string", length=32, nullable=true)
*/
private $step = self::STEP_DRAFT;
private $step = 'DRAFT';
/**
* @ORM\ManyToOne(targetEntity=Origin::class)
* @ORM\JoinColumn(nullable=true)
*/
private $origin;
/**
* @var string
* @ORM\Column(type="string", nullable=true)
@@ -214,7 +184,7 @@ class AccompanyingPeriod
* )
*/
private $resources;
/**
* AccompanyingPeriod constructor.
*
@@ -246,7 +216,7 @@ class AccompanyingPeriod
public function setOpeningDate($openingDate)
{
$this->openingDate = $openingDate;
return $this;
}
@@ -272,7 +242,7 @@ class AccompanyingPeriod
public function setClosingDate($closingDate)
{
$this->closingDate = $closingDate;
return $this;
}
@@ -285,7 +255,7 @@ class AccompanyingPeriod
{
return $this->closingDate;
}
/**
* @return boolean
*/
@@ -298,43 +268,43 @@ class AccompanyingPeriod
if ($this->getClosingDate() === null) {
return true;
}
return false;
}
public function setRemark(string $remark): self
{
if ($remark === null) {
$remark = '';
}
$this->remark = $remark;
return $this;
}
public function getRemark(): string
{
return $this->remark;
}
public function getComments(): Collection
{
return $this->comments;
}
public function addComment(Comment $comment): self
{
$this->comments[] = $comment;
return $this;
}
public function removeComment(Comment $comment): void
{
$this->comments->removeElement($comment);
}
/**
* Get Participations Collection
*/
@@ -342,7 +312,7 @@ class AccompanyingPeriod
{
return $this->participations;
}
/**
* This private function scan Participations Collection,
* searching for a given Person
@@ -357,7 +327,7 @@ class AccompanyingPeriod
return null;
}
/**
* This public function is the same but return only true or false
*/
@@ -365,7 +335,7 @@ class AccompanyingPeriod
{
return ($this->participationsContainsPerson($person) === null) ? false : true;
}
/**
* Add Person
*/
@@ -373,36 +343,36 @@ class AccompanyingPeriod
{
$participation = new AccompanyingPeriodParticipation($this, $person);
$this->participations[] = $participation;
return $this;
}
/**
* Remove Person
*/
public function removePerson(Person $person): void
{
$participation = $this->participationsContainsPerson($person);
if (! null === $participation) {
$participation->setEndDate(new \DateTimeImmutable('now'));
$this->participations->removeElement($participation);
}
}
public function getClosingMotive(): ?ClosingMotive
{
return $this->closingMotive;
}
public function setClosingMotive(ClosingMotive $closingMotive = null): self
{
$this->closingMotive = $closingMotive;
return $this;
}
/**
* If the period can be reopened.
*
@@ -414,7 +384,7 @@ class AccompanyingPeriod
if ($this->isOpen() === true) {
return false;
}
$participation = $this->participationsContainsPerson($person);
if (!null === $participation)
{
@@ -422,10 +392,10 @@ class AccompanyingPeriod
$periods = $person->getAccompanyingPeriodsOrdered();
return end($periods) === $this;
}
return false;
}
/**
*/
public function reOpen(): void
@@ -442,14 +412,14 @@ class AccompanyingPeriod
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.
*
@@ -467,16 +437,16 @@ class AccompanyingPeriod
}
return false;
}
function getUser(): ?User
{
return $this->user;
}
function setUser(User $user): self
{
$this->user = $user;
return $this;
}
@@ -484,38 +454,38 @@ class AccompanyingPeriod
{
return $this->origin;
}
public function setOrigin(Origin $origin): self
{
$this->origin = $origin;
return $this;
}
public function getRequestorPerson(): ?Person
{
return $this->requestorPerson;
}
public function setRequestorPerson(Person $requestorPerson): self
{
$this->requestorPerson = ($this->requestorThirdParty === null) ? $requestorPerson : null;
return $this;
}
public function getRequestorThirdParty(): ?ThirdParty
{
return $this->requestorThirdParty;
}
public function setRequestorThirdParty(ThirdParty $requestorThirdParty): self
{
$this->requestorThirdParty = ($this->requestorPerson === null) ? $requestorThirdParty : null;
return $this;
}
/**
* @return Person|ThirdParty
*/
@@ -523,48 +493,48 @@ class AccompanyingPeriod
{
return $this->requestorPerson ?? $this->requestorThirdParty;
}
public function isRequestorAnonymous(): bool
{
return $this->requestorAnonymous;
}
public function setRequestorAnonymous(bool $requestorAnonymous): self
{
$this->requestorAnonymous = $requestorAnonymous;
return $this;
}
public function isEmergency(): bool
{
return $this->emergency;
}
public function setEmergency(bool $emergency): self
{
$this->emergency = $emergency;
return $this;
}
public function isConfidential(): bool
{
return $this->confidential;
}
public function setConfidential(bool $confidential): self
{
$this->confidential = $confidential;
return $this;
}
public function getCreatedBy(): ?User
{
return $this->createdBy;
}
public function setCreatedBy(User $createdBy): self
{
$this->createdBy = $createdBy;
@@ -576,11 +546,11 @@ class AccompanyingPeriod
{
return $this->step;
}
public function setStep(string $step): self
{
$this->step = $step;
return $this;
}
@@ -588,57 +558,45 @@ class AccompanyingPeriod
{
return $this->intensity;
}
public function setIntensity(string $intensity): self
{
$this->intensity = $intensity;
return $this;
}
public function getScopes(): Collection
{
return $this->scopes;
}
public function addScope(Scope $scope): self
{
$this->scopes[] = $scope;
return $this;
}
public function removeScope(Scope $scope): void
{
$this->scopes->removeElement($scope);
}
public function getResources(): Collection
{
return $this->resources;
}
public function addResource(Resource $resource): self
{
$this->resources[] = $resource;
return $this;
}
public function removeResource(Resource $resource): void
{
$this->resources->removeElement($resource);
}
/**
* Get a list of all persons which are participating to this course
*/
public function getPersons(): Collection
{
return $this->participations->map(
function(AccompanyingPeriodParticipation $participation) {
return $participation->getPerson();
}
);
}
}

View File

@@ -29,7 +29,8 @@ use Doctrine\Common\Collections\ArrayCollection;
/**
* ClosingMotive give an explanation why we closed the Accompanying period
*
* @ORM\Entity
* @ORM\Entity(
* repositoryClass="Chill\PersonBundle\Repository\AccompanyingPeriod\ClosingMotiveRepository")
* @ORM\Table(name="chill_person_accompanying_period_closingmotive")
*/
class ClosingMotive
@@ -46,17 +47,17 @@ class ClosingMotive
/**
* @var array
*
* @ORM\Column(type="json")
* @ORM\Column(type="json_array")
*/
private $name;
/**
* @var boolean
*
* @ORM\Column(type="boolean")
*/
private $active = true;
/**
* @var self
*
@@ -65,7 +66,7 @@ class ClosingMotive
* inversedBy="children")
*/
private $parent = null;
/**
* Child Accompanying periods
* @var Collection
@@ -75,15 +76,15 @@ class ClosingMotive
* mappedBy="parent")
*/
private $children;
/**
* @var float
*
* @ORM\Column(type="float")
*/
private $ordering = 0.0;
/**
* ClosingMotive constructor.
*/
@@ -91,7 +92,7 @@ class ClosingMotive
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
@@ -125,7 +126,7 @@ class ClosingMotive
{
return $this->name;
}
/**
* @return bool
*/
@@ -133,7 +134,7 @@ class ClosingMotive
{
return $this->active;
}
/**
* @param bool $active
* @return $this
@@ -141,16 +142,16 @@ class ClosingMotive
public function setActive(bool $active)
{
$this->active = $active;
if ($this->active === FALSE) {
foreach ($this->getChildren() as $child) {
$child->setActive(FALSE);
}
}
return $this;
}
/**
* @return ClosingMotive
*/
@@ -158,7 +159,7 @@ class ClosingMotive
{
return $this->parent;
}
/**
* @return Collection
*/
@@ -166,7 +167,7 @@ class ClosingMotive
{
return $this->children;
}
/**
* @param ClosingMotive|null $parent
* @return ClosingMotive
@@ -174,14 +175,14 @@ class ClosingMotive
public function setParent(?ClosingMotive $parent): ClosingMotive
{
$this->parent = $parent;
if (NULL !== $parent) {
//$parent->addChildren($this);
}
return $this;
}
/**
* @param Collection $children
* @return ClosingMotive
@@ -189,10 +190,10 @@ class ClosingMotive
public function setChildren(Collection $children): ClosingMotive
{
$this->children = $children;
return $this;
}
/**
* @param ClosingMotive $child
* @return ClosingMotive
@@ -202,13 +203,13 @@ class ClosingMotive
if ($this->children->contains($child)) {
return $this;
}
$this->children->add($child);
$child->setParent($this);
return $this;
}
/**
* @param ClosingMotive $child
* @return ClosingMotive
@@ -218,10 +219,10 @@ class ClosingMotive
if ($this->children->removeElement($child)) {
$child->setParent(null);
}
return $this;
}
/**
* @return float
*/
@@ -229,7 +230,7 @@ class ClosingMotive
{
return $this->ordering;
}
/**
* @param float $ordering
* @return $this
@@ -237,10 +238,10 @@ class ClosingMotive
public function setOrdering(float $ordering)
{
$this->ordering = $ordering;
return $this;
}
/**
* @return bool
*/
@@ -248,7 +249,7 @@ class ClosingMotive
{
return $this->parent !== null;
}
/**
* @return bool
*/
@@ -256,7 +257,7 @@ class ClosingMotive
{
return $this->children->count() > 0;
}
/**
* @return bool
*/
@@ -264,7 +265,7 @@ class ClosingMotive
{
return $this->children->count() === 0;
}
/**
* @return bool
*/

View File

@@ -22,12 +22,13 @@
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Repository\AccompanyingPeriod\CommentRepository;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Entity(repositoryClass=CommentRepository::class)
* @ORM\Table(name="chill_person_accompanying_period_comment")
*/
class Comment

View File

@@ -22,10 +22,11 @@
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\OriginRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Entity(repositoryClass=OriginRepository::class)
* @ORM\Table(name="chill_person_accompanying_period_origin")
*/
class Origin
@@ -38,7 +39,7 @@ class Origin
private $id;
/**
* @ORM\Column(type="json")
* @ORM\Column(type="string", length=255)
*/
private $label;

View File

@@ -22,6 +22,7 @@
namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Repository\AccompanyingPeriod\ResourceRepository;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriod\Comment;
use Chill\PersonBundle\Entity\Person;
@@ -29,7 +30,7 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Entity(repositoryClass=ResourceRepository::class)
* @ORM\Table(name="chill_person_accompanying_period_resource")
*/
class Resource
@@ -120,7 +121,7 @@ class Resource
return $this;
}
/**
* @return Person|ThirdParty
*/

View File

@@ -22,6 +22,7 @@
namespace Chill\PersonBundle\Entity;
use Chill\PersonBundle\Repository\AccompanyingPeriodParticipationRepository;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Doctrine\ORM\Mapping as ORM;
@@ -30,7 +31,7 @@ use Doctrine\ORM\Mapping as ORM;
* AccompanyingPeriodParticipation Class
*
* @package Chill\PersonBundle\Entity
* @ORM\Entity
* @ORM\Entity(repositoryClass=AccompanyingPeriodParticipationRepository::class)
* @ORM\Table(name="chill_person_accompanying_period_participation")
*/
class AccompanyingPeriodParticipation
@@ -41,83 +42,83 @@ class AccompanyingPeriodParticipation
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=Person::class, inversedBy="accompanyingPeriodParticipations")
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
*/
private $person;
/**
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="participations", cascade={"persist"})
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class, inversedBy="participations")
* @ORM\JoinColumn(name="accompanyingperiod_id", referencedColumnName="id", nullable=false)
*/
private $accompanyingPeriod;
/**
* @ORM\Column(type="date", nullable=false)
*/
private $startDate;
/**
* @ORM\Column(type="date", nullable=true)
*/
private $endDate = null;
public function __construct(AccompanyingPeriod $accompanyingPeriod, Person $person)
{
$this->startDate = new \DateTimeImmutable('now');
$this->accompanyingPeriod = $accompanyingPeriod;
$this->person = $person;
}
public function getId(): ?int
{
return $this->id;
}
public function getPerson(): ?Person
{
return $this->person;
}
public function setPerson(?Person $person): self
{
$this->person = $person;
return $this;
}
public function getAccompanyingPeriod(): ?AccompanyingPeriod
{
return $this->accompanyingPeriod;
}
public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self
{
$this->accompanyingPeriod = $accompanyingPeriod;
return $this;
}
public function getStartDate(): ?\DateTimeInterface
{
return $this->startDate;
}
/*
* public function setStartDate(\DateTimeInterface $startDate): self { $this->startDate = $startDate; return $this; }
*/
public function getEndDate(): ?\DateTimeInterface
{
return $this->endDate;
}
public function setEndDate(?\DateTimeInterface $endDate): self
{
$this->endDate = $endDate;
return $this;
}
}

View File

@@ -25,7 +25,7 @@ use Doctrine\ORM\Mapping as ORM;
/**
* MaritalStatus
*
* @ORM\Entity
* @ORM\Entity()
* @ORM\Table(name="chill_person_marital_status")
* @ORM\HasLifecycleCallbacks()
*/
@@ -48,7 +48,7 @@ class MaritalStatus
/**
* Get id
*
* @return string
* @return string
*/
public function getId()
{
@@ -57,7 +57,7 @@ class MaritalStatus
/**
* Set id
*
*
* @param string $id
* @return MaritalStatus
*/
@@ -76,17 +76,17 @@ class MaritalStatus
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string array
* @return string array
*/
public function getName()
{
return $this->name;
}
}
}

View File

@@ -22,23 +22,21 @@ namespace Chill\PersonBundle\Entity;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
use ArrayIterator;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Country;
use Chill\PersonBundle\Entity\MaritalStatus;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\Address;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* Person Class
*
* @ORM\Entity
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\PersonRepository")
* @ORM\Table(name="chill_person_person",
* indexes={@ORM\Index(
* name="person_names",
@@ -287,7 +285,7 @@ class Person implements HasCenterInterface
$this->open(new AccompanyingPeriod($opening));
}
/**
* This private function scan accompanyingPeriodParticipations Collection,
* searching for a given AccompanyingPeriod
@@ -299,10 +297,10 @@ class Person implements HasCenterInterface
if ($accompanyingPeriod === $participation->getAccompanyingPeriod()) {
return $participation;
}}
return null;
}
/**
* This public function is the same but return only true or false
*/
@@ -310,7 +308,7 @@ class Person implements HasCenterInterface
{
return ($this->participationsContainAccompanyingPeriod($accompanyingPeriod)) ? false : true;
}
/**
* Add AccompanyingPeriodParticipation
*
@@ -320,7 +318,7 @@ class Person implements HasCenterInterface
{
$participation = new AccompanyingPeriodParticipation($accompanyingPeriod, $this);
$this->accompanyingPeriodParticipations->add($participation);
return $this;
}
@@ -330,7 +328,7 @@ class Person implements HasCenterInterface
public function removeAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod) : void
{
$participation = $this->participationsContainAccompanyingPeriod($accompanyingPeriod);
if (! null === $participation) {
$participation->setEndDate(\DateTimeImmutable::class);
$this->accompanyingPeriodParticipations->removeElement($participation);
@@ -408,7 +406,7 @@ class Person implements HasCenterInterface
}
return $accompanyingPeriods;
}
/**
* Get AccompanyingPeriodParticipations Collection
*/
@@ -1010,28 +1008,32 @@ class Person implements HasCenterInterface
/**
* By default, the addresses are ordered by date, descending (the most
* recent first)
*
* @return \Chill\MainBundle\Entity\Address[]
*/
public function getAddresses(): Collection
public function getAddresses()
{
return $this->addresses;
}
public function getLastAddress(DateTime $from = null)
/**
* @param \DateTime|null $date
* @return null
*/
public function getLastAddress(\DateTime $date = null)
{
$from ??= new DateTime('now');
if ($date === null) {
$date = new \DateTime('now');
}
/** @var ArrayIterator $addressesIterator */
$addressesIterator = $this->getAddresses()
->filter(static fn (Address $address): bool => $address->getValidFrom() <= $from)
->getIterator();
$addresses = $this->getAddresses();
$addressesIterator->uasort(
static fn (Address $left, Address $right): int => $right->getValidFrom() <=> $left->getValidFrom()
);
if ($addresses == null) {
return [] === ($addresses = iterator_to_array($addressesIterator)) ?
null :
current($addresses);
return null;
}
return $addresses->first();
}
/**
@@ -1140,12 +1142,12 @@ class Person implements HasCenterInterface
return true;
}
public function getFullnameCanonical() : string
{
return $this->fullnameCanonical;
}
public function setFullnameCanonical($fullnameCanonical) : Person
{
$this->fullnameCanonical = $fullnameCanonical;

View File

@@ -8,7 +8,7 @@ use Doctrine\ORM\Mapping as ORM;
* PersonAltName
*
* @ORM\Table(name="chill_person_alt_name")
* @ORM\Entity
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\PersonAltNameRepository")
*/
class PersonAltName
{
@@ -34,7 +34,7 @@ class PersonAltName
* @ORM\Column(name="label", type="text")
*/
private $label;
/**
* @var Person
*
@@ -45,7 +45,7 @@ class PersonAltName
*/
private $person;
/**
* Get id.
*
@@ -103,7 +103,7 @@ class PersonAltName
{
return $this->label;
}
/**
* @return Person
*/
@@ -111,7 +111,7 @@ class PersonAltName
{
return $this->person;
}
/**
* @param Person|null $person
* @return $this
@@ -119,7 +119,7 @@ class PersonAltName
public function setPerson(?Person $person = null)
{
$this->person = $person;
return $this;
}
}

View File

@@ -9,7 +9,7 @@ use Chill\MainBundle\Entity\User;
* PersonNotDuplicate
*
* @ORM\Table(name="chill_person_not_duplicate")
* @ORM\Entity
* @ORM\Entity(repositoryClass="Chill\PersonBundle\Repository\PersonNotDuplicateRepository")
*/
class PersonNotDuplicate
{

Some files were not shown because too many files have changed in this diff Show More