Merge remote-tracking branch 'origin/master' into cire16
@ -18,10 +18,8 @@ max_line_length = 80
|
||||
|
||||
[COMMIT_EDITMSG]
|
||||
max_line_length = 0
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
|
||||
[*.{js, vue, ts}]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
|
2
.gitignore
vendored
@ -24,3 +24,5 @@ docs/build/
|
||||
/.php-cs-fixer.cache
|
||||
/.idea/
|
||||
/.psalm/
|
||||
|
||||
node_modules/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -11,6 +11,11 @@ and this project adheres to
|
||||
## Unreleased
|
||||
|
||||
<!-- write down unreleased development here -->
|
||||
* [person][export] Fixed: rename the alias for `accompanying_period` to `acp` in filter associated with person
|
||||
* [activity][export] Feature: improve label for aliases in "Filter by activity type"
|
||||
* [activity][export] DX/Feature: use of an `ActivityTypeRepositoryInterface` instead of the old-style EntityRepository
|
||||
* [person][export] Fixed: some inconsistency with date filter on accompanying courses
|
||||
* [person][export] Fixed: use left join for related entities in accompanying course aggregators
|
||||
* [workflow] Feature: allow user to copy and send manually the access link for the workflow
|
||||
* [workflow] Feature: show the email addresses that received an access link for the workflow
|
||||
|
||||
@ -32,6 +37,9 @@ and this project adheres to
|
||||
* [social_action]: only show active objectives (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/625)
|
||||
* [household]: Reposition and cut button for enfant hors menage have been deleted (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/620)
|
||||
* [admin]: Add crud for composition type in admin (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/611)
|
||||
* [social_action]: only show active objectives (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/625)
|
||||
|
||||
## Test releases
|
||||
|
||||
### 2022-05-30
|
||||
|
||||
|
@ -19,10 +19,12 @@
|
||||
"graylog2/gelf-php": "^1.5",
|
||||
"knplabs/knp-menu-bundle": "^3.0",
|
||||
"knplabs/knp-time-bundle": "^1.12",
|
||||
"knpuniversity/oauth2-client-bundle": "^2.10",
|
||||
"league/csv": "^9.7.1",
|
||||
"nyholm/psr7": "^1.4",
|
||||
"ocramius/package-versions": "^1.10 || ^2",
|
||||
"odolbeau/phone-number-bundle": "^3.6",
|
||||
"ovh/ovh": "^3.0",
|
||||
"phpoffice/phpspreadsheet": "^1.16",
|
||||
"ramsey/uuid-doctrine": "^1.7",
|
||||
"sensio/framework-extra-bundle": "^5.5",
|
||||
@ -36,6 +38,7 @@
|
||||
"symfony/http-foundation": "^4.4",
|
||||
"symfony/intl": "^4.4",
|
||||
"symfony/mailer": "^5.4",
|
||||
"symfony/messenger": "^5.4",
|
||||
"symfony/mime": "^5.4",
|
||||
"symfony/monolog-bundle": "^3.5",
|
||||
"symfony/security-bundle": "^4.4",
|
||||
@ -49,6 +52,7 @@
|
||||
"symfony/webpack-encore-bundle": "^1.11",
|
||||
"symfony/workflow": "^4.4",
|
||||
"symfony/yaml": "^4.4",
|
||||
"thenetworg/oauth2-azure": "^2.0",
|
||||
"twig/extra-bundle": "^3.0",
|
||||
"twig/intl-extra": "^3.0",
|
||||
"twig/markdown-extra": "^3.3",
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
@ -25,7 +18,6 @@ use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountPerson implements ExportInterface
|
||||
{
|
||||
@ -80,9 +72,9 @@ class CountPerson implements ExportInterface
|
||||
return ['export_result'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
@ -113,9 +105,9 @@ class CountPerson implements ExportInterface
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(PersonVoter::STATS);
|
||||
return PersonVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
|
93
docs/source/development/cronjob.rst
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
.. Copyright (C) 2014-2023 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".
|
||||
|
||||
.. _cronjob:
|
||||
|
||||
Cron jobs
|
||||
*********
|
||||
|
||||
Some tasks must be executed regularly: refresh some materialized views, remove old data, ...
|
||||
|
||||
For this purpose, one can programmatically implements a "cron job", which will be scheduled by a specific command.
|
||||
|
||||
The command :code:`chill:cron-job:execute`
|
||||
==========================================
|
||||
|
||||
The command :code:`chill:cron-job:execute` will schedule a task, one by one. In a classical implementation, it should
|
||||
be executed every 15 minutes (more or less), to ensure that every task can be executed.
|
||||
|
||||
.. warning::
|
||||
|
||||
This command should not be executed in parallel. The installer should ensure that two job are executed concurrently.
|
||||
|
||||
How to implements a cron job ?
|
||||
==============================
|
||||
|
||||
Implements a :code:`Chill\MainBundle\Cron\CronJobInterface`. Here is an example:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace Chill\MainBundle\Service\Something;
|
||||
|
||||
use Chill\MainBundle\Cron\CronJobInterface;
|
||||
use Chill\MainBundle\Entity\CronJobExecution;
|
||||
use DateInterval;
|
||||
use DateTimeImmutable;
|
||||
|
||||
class MyCronJob implements CronJobInterface
|
||||
{
|
||||
public function canRun(?CronJobExecution $cronJobExecution): bool
|
||||
{
|
||||
// the parameter $cronJobExecution contains data about the last execution of the cronjob
|
||||
// if it is null, it should be executed immediatly
|
||||
if (null === $cronJobExecution) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($cronJobExecution->getKey() !== $this->getKey()) {
|
||||
throw new UnexpectedValueException();
|
||||
}
|
||||
|
||||
// this cron job should be executed if the last execution is greater than one day, but only during the night
|
||||
|
||||
$now = new DateTimeImmutable('now');
|
||||
|
||||
return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
|
||||
&& in_array($now->format('H'), self::ACCEPTED_HOURS, true)
|
||||
// introduce a random component to ensure a roll of task execution when multiple instances are hosted on same machines
|
||||
&& mt_rand(0, 5) === 0;
|
||||
}
|
||||
|
||||
public function getKey(): string
|
||||
{
|
||||
return 'arbitrary-and-unique-key';
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
// here, we execute the command
|
||||
}
|
||||
}
|
||||
|
||||
How are cron job scheduled ?
|
||||
============================
|
||||
|
||||
If the command :code:`chill:cron-job:execute` is run with one or more :code:`job` argument, those jobs are run, **without checking that the job can run** (the method :code:`canRun` is not executed).
|
||||
|
||||
If any :code:`job` argument is given, the :code:`CronManager` schedule job with those steps:
|
||||
|
||||
* the tasks are ordered, with:
|
||||
* a priority is given for tasks that weren't never executed;
|
||||
* then, the tasks are ordered, the last executed are the first in the list
|
||||
* then, for each tasks, and in the given order, the first task where :code:`canRun` return :code:`TRUE` will be executed.
|
||||
|
||||
The command :code:`chill:cron-job:execute` execute **only one** task.
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
|
||||
Useful snippets <useful-snippets.rst>
|
||||
manual/index.rst
|
||||
Assets <assets.rst>
|
||||
Cron Jobs <cronjob.rst>
|
||||
|
||||
Layout and UI
|
||||
**************
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -1,12 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers.
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
|
@ -18,6 +18,7 @@ Installation & Usage
|
||||
:maxdepth: 2
|
||||
|
||||
prod.rst
|
||||
load-addresses.rst
|
||||
prod-calendar-sms-sending.rst
|
||||
msgraph-configure.rst
|
||||
|
||||
@ -170,7 +171,7 @@ There are several users available:
|
||||
|
||||
The password is always ``password``.
|
||||
|
||||
Now, read `Operations` below.
|
||||
Now, read `Operations` below. For running in production, read `prod_`.
|
||||
|
||||
|
||||
Operations
|
||||
|
50
docs/source/installation/load-addresses.rst
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
.. _addresses:
|
||||
|
||||
Addresses
|
||||
*********
|
||||
|
||||
Chill can store a list of geolocated address references, which are used to suggest address and ensure that the data is correctly stored.
|
||||
|
||||
Those addresses may be load from a dedicated source.
|
||||
|
||||
In France
|
||||
=========
|
||||
|
||||
The address are loaded from the `BANO <https://bano.openstreetmap.fr/>`_. The postal codes are loaded from `the official list of
|
||||
postal codes <https://datanova.laposte.fr/explore/dataset/laposte_hexasmal/information/>`_
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# first, load postal codes
|
||||
bin/console chill:main:postal-code:load:FR
|
||||
# then, load all addresses, by departement (multiple departement can be loaded by repeating the departement code
|
||||
bin/console chill:main:address-ref-from-bano 57 54 51
|
||||
|
||||
In Belgium
|
||||
==========
|
||||
|
||||
Addresses are prepared from the `BeST Address data <https://www.geo.be/catalog/details/ca0fd5c0-8146-11e9-9012-482ae30f98d9>`_.
|
||||
|
||||
Postal code are loaded from this database. There is no need to load postal codes from another source (actually, this is strongly discouraged).
|
||||
|
||||
The data are prepared for Chill (`See this repository <https://gitea.champs-libres.be/Chill-project/belgian-bestaddresses-transform/releases>`_).
|
||||
One can select postal code by his first number (:code:`1xxx` for postal codes from 1000 to 1999), or a limited list for development purpose.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# load postal code from 1000 to 3999:
|
||||
bin/console chill:main:address-ref-from-best-addresse 1xxx 2xxx 3xxx
|
||||
|
||||
# load only an extract (for dev purposes)
|
||||
bin/console chill:main:address-ref-from-best-addresse extract
|
||||
|
||||
# load full addresses (discouraged)
|
||||
bin/console chill:main:address-ref-from-best-addresse full
|
||||
|
||||
.. note::
|
||||
|
||||
There is a possibility to load the full list of addresses is discouraged: the loading is optimized with smaller extracts.
|
||||
|
||||
Once you load the full list, it is not possible to load smaller extract: each extract loaded **after** will not
|
||||
delete the addresses loaded with the full extract (and some addresses will be present twice).
|
320
docs/source/installation/msgraph-configure.rst
Normal file
@ -0,0 +1,320 @@
|
||||
|
||||
Configure Chill for calendar sync and SSO with Microsoft Graph (Outlook)
|
||||
========================================================================
|
||||
|
||||
Chill offers the possibility to:
|
||||
|
||||
* authenticate users using Microsoft Graph, with relatively small adaptations;
|
||||
* synchronize calendar in both ways (`see the user manual for a large description of the feature <https://gitea.champs-libres.be/Chill-project/manuals>`_).
|
||||
|
||||
Both can be configured separately (synchronising calendars without SSO, or SSO without calendar). When calendar sync is configured without SSL, the user's email address is the key to associate Chill's users with Microsoft's ones.
|
||||
|
||||
Configure SSO
|
||||
-------------
|
||||
|
||||
On Azure side
|
||||
*************
|
||||
|
||||
Configure an app with the Azure interface, and give it the name of your choice.
|
||||
|
||||
Grab the tenant's ID for your app, which is visible on the main tab "Vue d'ensemble":
|
||||
|
||||
.. figure:: ./saml_login_id_general.png
|
||||
|
||||
This the variable which will be named :code:`SAML_IDP_APP_UUID`.
|
||||
|
||||
Go to the "Single sign-on" ("Authentication unique") section. Choose "SAML" as protocol, and fill those values:
|
||||
|
||||
.. figure:: ./saml_login_1.png
|
||||
|
||||
1. The :code:`entityId` seems to be arbitrary. This will be your variable :code:`SAML_ENTITY_ID`;
|
||||
2. The url response must be your Chill's URL appended by :code:`/saml/acs`
|
||||
3. The only used attributes is :code:`emailaddress`, which must match the user's email one.
|
||||
|
||||
.. figure:: ./saml_login_2.png
|
||||
|
||||
You must download the certificate, as base64. The format for the download is :code:`cer`: you will remove the first and last line (the ones with :code:`-----BEGIN CERTIFICATE-----` and :code:`-----END CERTIFICATE-----`), and remove all the return line. The final result should be something as :code:`MIIAbcdef...XyZA=`.
|
||||
|
||||
This certificat will be your :code:`SAML_IDP_X509_CERT` variable.
|
||||
|
||||
The url login will be filled automatically with your tenant id.
|
||||
|
||||
Do not forget to provider user's accesses to your app, using the "Utilisateurs et groupes" tab:
|
||||
|
||||
.. figure:: ./saml_login_appro.png
|
||||
|
||||
|
||||
You must know have gathered all the required variables for SSO:
|
||||
|
||||
.. code-block::
|
||||
|
||||
SAML_BASE_URL=https://test.chill.be # must be
|
||||
SAML_ENTITY_ID=https://test.chill.be # must match the one entered
|
||||
SAML_IDP_APP_UUID=42XXXXXX-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
SAML_IDP_X509_CERT: MIIC...E8u3bk # truncated
|
||||
|
||||
Configure chill app
|
||||
*******************
|
||||
|
||||
* add the bundle :code:`hslavich/oneloginsaml-bundle`
|
||||
* add the configuration file (see example above)
|
||||
* configure the security part (see example above)
|
||||
* add a user SAML factory into your src, and register it
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# config/packages/hslavich_onelogin.yaml
|
||||
|
||||
parameters:
|
||||
saml_base_url: '%env(resolve:SAML_BASE_URL)%'
|
||||
saml_entity_id: '%env(resolve:SAML_ENTITY_ID)%'
|
||||
saml_idp_x509cert: '%env(resolve:SAML_IDP_X509_CERT)%'
|
||||
saml_idp_app_uuid: '%env(resolve:SAML_IDP_APP_UUID)%'
|
||||
|
||||
|
||||
hslavich_onelogin_saml:
|
||||
# Basic settings
|
||||
idp:
|
||||
entityId: 'https://sts.windows.net/%saml_idp_app_uuid%/'
|
||||
singleSignOnService:
|
||||
url: 'https://login.microsoftonline.com/%saml_idp_app_uuid%/saml2'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
singleLogoutService:
|
||||
url: 'https://login.microsoftonline.com/%saml_idp_app_uuid%/saml2'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
x509cert: '%saml_idp_x509cert%'
|
||||
sp:
|
||||
entityId: '%saml_entity_id%'
|
||||
assertionConsumerService:
|
||||
url: '%saml_base_url%/saml/acs'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
||||
singleLogoutService:
|
||||
url: '%saml_base_url%/saml/'
|
||||
binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
|
||||
privateKey: ''
|
||||
# Optional settings.
|
||||
baseurl: '%saml_base_url%/saml'
|
||||
strict: true
|
||||
debug: true
|
||||
security:
|
||||
nameIdEncrypted: false
|
||||
authnRequestsSigned: false
|
||||
logoutRequestSigned: false
|
||||
logoutResponseSigned: false
|
||||
wantMessagesSigned: false
|
||||
wantAssertionsSigned: false
|
||||
wantNameIdEncrypted: false
|
||||
requestedAuthnContext: true
|
||||
signMetadata: false
|
||||
wantXMLValidation: true
|
||||
signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
|
||||
digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256'
|
||||
contactPerson:
|
||||
technical:
|
||||
givenName: 'Tech User'
|
||||
emailAddress: 'techuser@example.com'
|
||||
support:
|
||||
givenName: 'Support User'
|
||||
emailAddress: 'supportuser@example.com'
|
||||
organization:
|
||||
en:
|
||||
name: 'Example'
|
||||
displayname: 'Example'
|
||||
url: 'http://example.com'
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# config/security.yaml
|
||||
# merge this with other existing configurations
|
||||
|
||||
security:
|
||||
|
||||
|
||||
providers:
|
||||
saml_provider:
|
||||
# Loads user from user repository
|
||||
entity:
|
||||
class: Chill\MainBundle\Entity\User
|
||||
property: username
|
||||
|
||||
firewalls:
|
||||
|
||||
|
||||
default:
|
||||
# saml part:
|
||||
saml:
|
||||
username_attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
|
||||
# weird behaviour in dev environment... configuration seems different
|
||||
# username_attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
|
||||
# Use the attribute's friendlyName instead of the name
|
||||
use_attribute_friendly_name: false
|
||||
user_factory: user_from_saml_factory
|
||||
persist_user: true
|
||||
check_path: saml_acs
|
||||
login_path: saml_login
|
||||
logout:
|
||||
path: /saml/logout
|
||||
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// src/Security/SamlFactory.php
|
||||
|
||||
namespace App\Security;
|
||||
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Hslavich\OneloginSamlBundle\Security\Authentication\Token\SamlTokenInterface;
|
||||
use Hslavich\OneloginSamlBundle\Security\User\SamlUserFactoryInterface;
|
||||
|
||||
class UserSamlFactory implements SamlUserFactoryInterface
|
||||
{
|
||||
public function createUser(SamlTokenInterface $token)
|
||||
{
|
||||
$attributes = $token->getAttributes();
|
||||
$user = new User();
|
||||
$user->setUsername($attributes['http://schemas.microsoft.com/identity/claims/displayname'][0]);
|
||||
$user->setLabel($attributes['http://schemas.microsoft.com/identity/claims/displayname'][0]);
|
||||
$user->setPassword('');
|
||||
$user->setEmail($attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'][0]);
|
||||
$user->setAttributes($attributes);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Configure sync
|
||||
--------------
|
||||
|
||||
The sync processe might be configured in the same app, or into a different app.
|
||||
|
||||
The synchronization processes use Oauth2.0 for authentication and authorization.
|
||||
|
||||
.. note::
|
||||
|
||||
Two flows are in use:
|
||||
|
||||
* we authenticate "on behalf of a user", to allow users to see their own calendar or other user's calendar into the web interface.
|
||||
|
||||
Typically, when the page is loaded, Chill first check that an authorization token exists. If not, the user is redirected to Microsoft Azure for authentification and a new token is grabbed (most of the times, this is transparent for users).
|
||||
|
||||
* Chill also acts "as a machine", to synchronize calendars with a daemon background.
|
||||
|
||||
One can access the configuration using this screen (it is quite well hidden into the multiple of tabs):
|
||||
|
||||
.. figure:: ./oauth_app_registration.png
|
||||
|
||||
You can find the oauth configuration on the "Securité > Autorisations" tab, and click on "application registration" (not translated).
|
||||
|
||||
Add a redirection URI for you authentification:
|
||||
|
||||
.. figure:: ./oauth_api_authentification.png
|
||||
|
||||
The URI must be "your chill public url" with :code:`/connect/azure/check` at the end.
|
||||
|
||||
Allow some authorizations for your app:
|
||||
|
||||
.. figure:: ./oauth_api_autorisees.png
|
||||
|
||||
Take care of the separation between autorization "on behalf of a user" (déléguée), or "for a machine" (application).
|
||||
|
||||
Some explanation:
|
||||
|
||||
* Users must be allowed to read their user profile (:code:`User.Read`), and the profile of other users (:code:`User.ReadBasicAll`);
|
||||
* They must be allowed to read their calendar (:code:`Calendars.Read`), and the calendars shared with them (:code:`Calendars.Read.Shared`);
|
||||
|
||||
The sync daemon must have write access:
|
||||
|
||||
* the daemon must be allowed to read all users and their profile, to establish a link between them and the Chill's users: (:code:`Users.Read.All`);
|
||||
* it must also be allowed to read and write into the calendars (:code:`Calendars.ReadWrite.All`)
|
||||
* for sending invitation to other users, the permission (:code:`Mail.Send`) must be granted.
|
||||
|
||||
At this step, you might choose to accept those permissions for all users, or let them do it by yourself.
|
||||
|
||||
Grab your client id:
|
||||
|
||||
.. figure:: ./oauth_api_client_id.png
|
||||
|
||||
This will be your :code:`OAUTH_AZURE_CLIENT_ID` variable.
|
||||
|
||||
|
||||
Generate a secret:
|
||||
|
||||
.. figure:: ./oauth_api_secret.png
|
||||
|
||||
This will be your :code:`OAUTH_AZURE_CLIENT_SECRET` variable.
|
||||
|
||||
And get you azure's tenant id, which is the same as the :code:`SAML_IDP_APP_UUID` (see above).
|
||||
|
||||
Your variables will be:
|
||||
|
||||
.. code-block::
|
||||
|
||||
OAUTH_AZURE_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
OAUTH_AZURE_CLIENT_TENANT=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||
OAUTH_AZURE_CLIENT_SECRET: 3-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
Then, configure chill:
|
||||
|
||||
Enable the calendar sync with microsoft azure:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# config/packages/chill_calendar.yaml
|
||||
|
||||
chill_calendar:
|
||||
remote_calendars_sync:
|
||||
microsoft_graph:
|
||||
enabled: true
|
||||
|
||||
and configure the oauth client:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# config/packages/knp_oauth2_client.yaml
|
||||
knpu_oauth2_client:
|
||||
clients:
|
||||
azure:
|
||||
type: azure
|
||||
client_id: '%env(OAUTH_AZURE_CLIENT_ID)%'
|
||||
client_secret: '%env(OAUTH_AZURE_CLIENT_SECRET)%'
|
||||
redirect_route: chill_calendar_remote_connect_azure_check
|
||||
redirect_params: { }
|
||||
tenant: '%env(OAUTH_AZURE_CLIENT_TENANT)%'
|
||||
url_api: 'https://graph.microsoft.com/'
|
||||
default_end_point_version: '2.0'
|
||||
|
||||
|
||||
You can now process for the first api authorization on the application side, (unless you did it in the Azure interface), and get a first token, by using :
|
||||
|
||||
:code:`bin/console chill:calendar:msgraph-grant-admin-consent`
|
||||
|
||||
This will generate a url that you can use to grant your app for your tenant. The redirection may fails in the browser, but this is not relevant: if you get an authorization token in the CLI, the authentication works.
|
||||
|
||||
Run the processes to synchronize
|
||||
--------------------------------
|
||||
|
||||
The calendar synchronization is processed using symfony messenger. It seems to be intersting to configure a queue (in the postgresql database it is the most simple way), and to run a worker for synchronization, at least in production.
|
||||
|
||||
The association between chill's users and Microsoft's users is done by this cli command:
|
||||
|
||||
.. code-block::
|
||||
|
||||
bin/console chill:calendar:msgraph-user-map-subscribe
|
||||
|
||||
This command:
|
||||
|
||||
* will associate the Microsoft's user metadata in our database;
|
||||
* and, most important, create a subscription to get notification when the user alter his calendar, to sync chill's event and ranges in sync.
|
||||
|
||||
The subscription least at most 3 days. This command should be runned:
|
||||
|
||||
* at least each time a user is added;
|
||||
* and, at least, every three days.
|
||||
|
||||
In production, we advise to run it at least every day to get the sync working.
|
||||
|
||||
|
BIN
docs/source/installation/oauth_api_authentification.png
Normal file
After Width: | Height: | Size: 61 KiB |
BIN
docs/source/installation/oauth_api_autorisees.png
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
docs/source/installation/oauth_api_client_id.png
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
docs/source/installation/oauth_api_secret.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
docs/source/installation/oauth_app_registration.png
Normal file
After Width: | Height: | Size: 116 KiB |
27
docs/source/installation/prod-calendar-sms-sending.rst
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
Send short messages (SMS) with calendar bundle
|
||||
==============================================
|
||||
|
||||
To activate the sending of messages, you should run this command on a regularly basis (using, for instance, a cronjob):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
bin/console chill:calendar:send-short-messages
|
||||
|
||||
A transporter must be configured for the message to be effectively sent.
|
||||
|
||||
Configure OVH Transporter
|
||||
-------------------------
|
||||
|
||||
Currently, this is the only one transporter available.
|
||||
|
||||
For configuring this, simply add this config variable in your environment:
|
||||
|
||||
```env
|
||||
SHORT_MESSAGE_DSN=ovh://applicationKey:applicationSecret@endpoint?consumerKey=xxxx&sender=yyyy&service_name=zzzz
|
||||
```
|
||||
|
||||
In order to generate the application key, secret, and consumerKey, refers to their `documentation <https://docs.ovh.com/gb/en/api/first-steps-with-ovh-api/>`_.
|
||||
|
||||
Before to be able to send your first sms, you must enable your account, grab some credits, and configure a sender. The service_name is an internal configuration generated by OVH.
|
||||
|
63
docs/source/installation/prod.rst
Normal file
@ -0,0 +1,63 @@
|
||||
.. Copyright (C) 2014-2019 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".
|
||||
|
||||
.. _prod:
|
||||
|
||||
Installation for production
|
||||
###########################
|
||||
|
||||
An installation use these services, which are deployed using docker containers:
|
||||
|
||||
* a php-fpm image, which run the Php and Symfony code for Chill;
|
||||
* a nginx image, which serves the assets, and usually proxy the php requests to the fpm image;
|
||||
* a redis server, which stores the cache, sessions (this is currently hardcoded in the php image), and some useful keys (like wopi locks);
|
||||
* a postgresql database. The use of postgresql is mandatory;
|
||||
* a relatorio service, which transform odt templates to full documents (replacing the placeholders);
|
||||
|
||||
Some external services:
|
||||
|
||||
* (required) an openstack object store, configured with `temporary url <https://docs.openstack.org/swift/latest/api/temporary_url_middleware.html>` configured (no openstack users is required). This is currently the only way to store documents from chill;
|
||||
* a mailer service (SMTP)
|
||||
* (optional) a service for verifying phone number. Currently, only Twilio is possible;
|
||||
* (optional) a service for sending Short Messages (SMS). Currently, only Ovh is possible;
|
||||
|
||||
The `docker-compose.yaml` file of chill app is a basis for a production install. The environment variable in the ```.env``` and ```.env.prod``` should be overriden by environment variables, or ```.env.local``` files.
|
||||
|
||||
This should be adapted to your needs:
|
||||
|
||||
* The image for php and nginx apps are pre-compiled images, with the default configuration and bundle. If they do not fullfill your needs, you should compile your own images.
|
||||
|
||||
.. TODO:
|
||||
|
||||
As the time of writing (2022-07-03) those images are not published yet.
|
||||
|
||||
* Think about how you will backup your database. Some adminsys find easier to store database outside of docker, which might be easier to administrate or replicate.
|
||||
|
||||
Cron jobs
|
||||
=========
|
||||
|
||||
The command :code:`chill:cron-job:execute` should be executed every 15 minutes (more or less).
|
||||
|
||||
This command should never be executed concurrently. It should be not have more than one process for a single instance.
|
||||
|
||||
Post-install tasks
|
||||
==================
|
||||
|
||||
- import addresses. See :ref:`addresses`.
|
||||
|
||||
|
||||
Tweak symfony messenger
|
||||
=======================
|
||||
|
||||
Calendar sync is processed using symfony messenger.
|
||||
|
||||
You can tweak the configuration
|
||||
|
||||
Going further:
|
||||
|
||||
* Configure the saml login and synchronisation with Outlook api
|
BIN
docs/source/installation/saml_login_1.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
docs/source/installation/saml_login_2.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
docs/source/installation/saml_login_appro.png
Normal file
After Width: | Height: | Size: 92 KiB |
BIN
docs/source/installation/saml_login_id_general.png
Normal file
After Width: | Height: | Size: 87 KiB |
63
exports_alias_conventions.csv
Normal file
@ -0,0 +1,63 @@
|
||||
Entity,Join,Attribute,Alias
|
||||
AccompanyingPeriod::class,,,acp
|
||||
,AccompanyingPeriodWork::class,acp.works,acpw
|
||||
,AccompanyingPeriodParticipation::class,acp.participations,acppart
|
||||
,Location::class,acp.administrativeLocation,acploc
|
||||
,ClosingMotive::class,acp.closingMotive,acpmotive
|
||||
,UserJob::class,acp.job,acpjob
|
||||
,Origin::class,acp.origin,acporigin
|
||||
,Scope::class,acp.scopes,acpscope
|
||||
,SocialIssue::class,acp.socialIssues,acpsocialissue
|
||||
,User::class,acp.user,acpuser
|
||||
AccompanyingPeriodWork::class,,,acpw
|
||||
,AccompanyingPeriodWorkEvaluation::class,acpw.accompanyingPeriodWorkEvaluations,workeval
|
||||
,User::class,acpw.referrers,acpwuser
|
||||
,SocialAction::class,acpw.socialAction,acpwsocialaction
|
||||
,Goal::class,acpw.goals,goal
|
||||
,Result::class,acpw.results,result
|
||||
AccompanyingPeriodParticipation::class,,,acppart
|
||||
,Person::class,acppart.person,partperson
|
||||
AccompanyingPeriodWorkEvaluation::class,,,workeval
|
||||
,Evaluation::class,workeval.evaluation,eval
|
||||
Goal::class,,,goal
|
||||
,Result::class,goal.results,goalresult
|
||||
Person::class,,,person
|
||||
,Center::class,person.center,center
|
||||
,HouseholdMember::class,partperson.householdParticipations,householdmember
|
||||
,MaritalStatus::class,person.maritalStatus,personmarital
|
||||
,VendeePerson::class,,vp
|
||||
,VendeePersonMineur::class,,vpm
|
||||
ResidentialAddress::class,,,resaddr
|
||||
,ThirdParty::class,resaddr.hostThirdParty,tparty
|
||||
ThirdParty::class,,,tparty
|
||||
,ThirdPartyCategory::class,tparty.categories,tpartycat
|
||||
HouseholdMember::class,,,householdmember
|
||||
,Household::class,householdmember.household,household
|
||||
,Person::class,householdmember.person,memberperson
|
||||
,,memberperson.center,membercenter
|
||||
Household::class,,,household
|
||||
,HouseholdComposition::class,household.compositions,composition
|
||||
Activity::class,,,activity
|
||||
,Person::class,activity.person,actperson
|
||||
,AccompanyingPeriod::class,activity.accompanyingPeriod,acp
|
||||
,Person::class,activity_person_having_activity.person,person_person_having_activity
|
||||
,ActivityReason::class,activity_person_having_activity.reasons,reasons_person_having_activity
|
||||
,ActivityType::class,activity.activityType,acttype
|
||||
,Location::class,activity.location,actloc
|
||||
,SocialAction::class,activity.socialActions,actsocialaction
|
||||
,SocialIssue::class,activity.socialIssues,actsocialssue
|
||||
,ThirdParty::class,activity.thirdParties,acttparty
|
||||
,User::class,activity.user,actuser
|
||||
,User::class,activity.users,actusers
|
||||
,ActivityReason::class,activity.reasons,actreasons
|
||||
,Center::class,actperson.center,actcenter
|
||||
ActivityReason::class,,,actreasons
|
||||
,ActivityReasonCategory::class,actreason.category,actreasoncat
|
||||
Calendar::class,,,cal
|
||||
,CancelReason::class,cal.cancelReason,calcancel
|
||||
,Location::class,cal.location,calloc
|
||||
,User::class,cal.user,caluser
|
||||
VendeePerson::class,,,vp
|
||||
,SituationProfessionelle::class,vp.situationProfessionelle,vpprof
|
||||
,StatutLogement::class,vp.statutLogement,vplog
|
||||
,TempsDeTravail::class,vp.tempsDeTravail,vptt
|
|
74
exports_alias_conventions.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Export conventions
|
||||
|
||||
|
||||
Add condition with distinct alias on each export join clauses (Indicators + Filters + Aggregators)
|
||||
|
||||
These are alias conventions :
|
||||
|
||||
| Entity | Join | Attribute | Alias |
|
||||
|:----------------------------------------|:----------------------------------------|:-------------------------------------------|:---------------------------------------|
|
||||
| AccompanyingPeriod::class | | | acp |
|
||||
| | AccompanyingPeriodWork::class | acp.works | acpw |
|
||||
| | AccompanyingPeriodParticipation::class | acp.participations | acppart |
|
||||
| | Location::class | acp.administrativeLocation | acploc |
|
||||
| | ClosingMotive::class | acp.closingMotive | acpmotive |
|
||||
| | UserJob::class | acp.job | acpjob |
|
||||
| | Origin::class | acp.origin | acporigin |
|
||||
| | Scope::class | acp.scopes | acpscope |
|
||||
| | SocialIssue::class | acp.socialIssues | acpsocialissue |
|
||||
| | User::class | acp.user | acpuser |
|
||||
| | AccompanyingPeriopStepHistory::class | acp.stepHistories | acpstephistories |
|
||||
| AccompanyingPeriodWork::class | | | acpw |
|
||||
| | AccompanyingPeriodWorkEvaluation::class | acpw.accompanyingPeriodWorkEvaluations | workeval |
|
||||
| | User::class | acpw.referrers | acpwuser |
|
||||
| | SocialAction::class | acpw.socialAction | acpwsocialaction |
|
||||
| | Goal::class | acpw.goals | goal |
|
||||
| | Result::class | acpw.results | result |
|
||||
| AccompanyingPeriodParticipation::class | | | acppart |
|
||||
| | Person::class | acppart.person | partperson |
|
||||
| AccompanyingPeriodWorkEvaluation::class | | | workeval |
|
||||
| | Evaluation::class | workeval.evaluation | eval |
|
||||
| Goal::class | | | goal |
|
||||
| | Result::class | goal.results | goalresult |
|
||||
| Person::class | | | person |
|
||||
| | Center::class | person.center | center |
|
||||
| | HouseholdMember::class | partperson.householdParticipations | householdmember |
|
||||
| | MaritalStatus::class | person.maritalStatus | personmarital |
|
||||
| | VendeePerson::class | | vp |
|
||||
| | VendeePersonMineur::class | | vpm |
|
||||
| | CurrentPersonAddress::class | person.currentPersonAddress | currentPersonAddress (on a given date) |
|
||||
| ResidentialAddress::class | | | resaddr |
|
||||
| | ThirdParty::class | resaddr.hostThirdParty | tparty |
|
||||
| ThirdParty::class | | | tparty |
|
||||
| | ThirdPartyCategory::class | tparty.categories | tpartycat |
|
||||
| HouseholdMember::class | | | householdmember |
|
||||
| | Household::class | householdmember.household | household |
|
||||
| | Person::class | householdmember.person | memberperson |
|
||||
| | | memberperson.center | membercenter |
|
||||
| Household::class | | | household |
|
||||
| | HouseholdComposition::class | household.compositions | composition |
|
||||
| Activity::class | | | activity |
|
||||
| | Person::class | activity.person | actperson |
|
||||
| | AccompanyingPeriod::class | activity.accompanyingPeriod | acp |
|
||||
| | Person::class | activity\_person\_having\_activity.person | person\_person\_having\_activity |
|
||||
| | ActivityReason::class | activity\_person\_having\_activity.reasons | reasons\_person\_having\_activity |
|
||||
| | ActivityType::class | activity.activityType | acttype |
|
||||
| | Location::class | activity.location | actloc |
|
||||
| | SocialAction::class | activity.socialActions | actsocialaction |
|
||||
| | SocialIssue::class | activity.socialIssues | actsocialssue |
|
||||
| | ThirdParty::class | activity.thirdParties | acttparty |
|
||||
| | User::class | activity.user | actuser |
|
||||
| | User::class | activity.users | actusers |
|
||||
| | ActivityReason::class | activity.reasons | actreasons |
|
||||
| | Center::class | actperson.center | actcenter |
|
||||
| | Person::class | activity.createdBy | actcreator |
|
||||
| ActivityReason::class | | | actreasons |
|
||||
| | ActivityReasonCategory::class | actreason.category | actreasoncat |
|
||||
| Calendar::class | | | cal |
|
||||
| | CancelReason::class | cal.cancelReason | calcancel |
|
||||
| | Location::class | cal.location | calloc |
|
||||
| | User::class | cal.user | caluser |
|
||||
| VendeePerson::class | | | vp |
|
||||
| | SituationProfessionelle::class | vp.situationProfessionelle | vpprof |
|
||||
| | StatutLogement::class | vp.statutLogement | vplog |
|
||||
| | TempsDeTravail::class | vp.tempsDeTravail | vptt |
|
67
package.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "chill",
|
||||
"version": "2.0.0",
|
||||
"devDependencies": {
|
||||
"@alexlafroscia/yaml-merge": "^4.0.0",
|
||||
"@apidevtools/swagger-cli": "^4.0.4",
|
||||
"@babel/core": "^7.20.5",
|
||||
"@babel/preset-env": "^7.20.2",
|
||||
"@ckeditor/ckeditor5-build-classic": "^35.3.2",
|
||||
"@ckeditor/ckeditor5-dev-utils": "^31.1.13",
|
||||
"@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13",
|
||||
"@ckeditor/ckeditor5-markdown-gfm": "^35.3.2",
|
||||
"@ckeditor/ckeditor5-theme-lark": "^35.3.2",
|
||||
"@ckeditor/ckeditor5-vue": "^4.0.1",
|
||||
"@symfony/webpack-encore": "^4.1.0",
|
||||
"@tsconfig/node14": "^1.0.1",
|
||||
"bindings": "^1.5.0",
|
||||
"bootstrap": "^5.0.1",
|
||||
"chokidar": "^3.5.1",
|
||||
"fork-awesome": "^1.1.7",
|
||||
"jquery": "^3.6.0",
|
||||
"node-sass": "^8.0.0",
|
||||
"popper.js": "^1.16.1",
|
||||
"postcss-loader": "^7.0.2",
|
||||
"raw-loader": "^4.0.2",
|
||||
"sass-loader": "^13.0.0",
|
||||
"select2": "^4.0.13",
|
||||
"select2-bootstrap-theme": "0.1.0-beta.10",
|
||||
"style-loader": "^3.3.1",
|
||||
"ts-loader": "^9.3.1",
|
||||
"typescript": "^4.7.2",
|
||||
"vue-loader": "^17.0.0",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fullcalendar/core": "^5.11.0",
|
||||
"@fullcalendar/daygrid": "^5.11.0",
|
||||
"@fullcalendar/interaction": "^5.11.0",
|
||||
"@fullcalendar/list": "^5.11.0",
|
||||
"@fullcalendar/timegrid": "^5.11.0",
|
||||
"@fullcalendar/vue3": "^5.11.1",
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"dropzone": "^5.7.6",
|
||||
"es6-promise": "^4.2.8",
|
||||
"leaflet": "^1.7.1",
|
||||
"masonry-layout": "^4.2.2",
|
||||
"mime": "^3.0.0",
|
||||
"swagger-ui": "^4.15.5",
|
||||
"vis-network": "^9.1.0",
|
||||
"vue": "^3.2.37",
|
||||
"vue-i18n": "^9.1.6",
|
||||
"vue-multiselect": "3.0.0-alpha.2",
|
||||
"vue-toast-notification": "^2.0",
|
||||
"vuex": "^4.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"Firefox ESR"
|
||||
],
|
||||
"scripts": {
|
||||
"dev-server": "encore dev-server",
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production --progress"
|
||||
},
|
||||
"private": true
|
||||
}
|
@ -5,11 +5,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/AccompanyingPeriod.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\Household\\\\PersonHouseholdAddress\\:\\:\\$relation\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Entity/Household/PersonHouseholdAddress.php
|
||||
|
||||
-
|
||||
message: "#^Access to an undefined property Chill\\\\PersonBundle\\\\Entity\\\\AccompanyingPeriod\\:\\:\\$work\\.$#"
|
||||
count: 1
|
||||
@ -30,11 +25,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Serializer/Normalizer/MembersEditorNormalizer.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$choiceSlug$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: "#^Undefined variable\\: \\$choiceSlug$#"
|
||||
count: 1
|
||||
|
@ -23,150 +23,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityReasonAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityReasonAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityTypeAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityTypeAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Aggregator\\\\ActivityUserAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Aggregator/ActivityUserAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/CountActivity.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\CountActivity\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/CountActivity.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\ListActivity\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/ListActivity.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityDateFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityReasonFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityReasonFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\ActivityTypeFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/ActivityTypeFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ActivityBundle\\\\Export\\\\Filter\\\\PersonHavingActivityBetweenDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Filter/PersonHavingActivityBetweenDateFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Fetching class constant class of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
@ -359,31 +215,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/User.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\DirectExportInterface\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/DirectExportInterface.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\ExportInterface\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/ExportInterface.php
|
||||
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\MainBundle\\\\Export\\\\ModifierInterface\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/ModifierInterface.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Class Chill\\\\MainBundle\\\\Form\\\\Event\\\\CustomizeFormEvent extends deprecated class Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:
|
||||
@ -543,142 +374,6 @@ parameters:
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Entity/Person.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\AgeAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/AgeAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\CountryOfBirthAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\GenderAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/GenderAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Aggregator\\\\NationalityAggregator\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\CountPerson\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/CountPerson.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\ListPerson\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Call to deprecated method execute\\(\\) of class Doctrine\\\\DBAL\\\\Statement\\:
|
||||
Statement\\:\\:execute\\(\\) is deprecated, use Statement\\:\\:executeQuery\\(\\) or executeStatement\\(\\) instead$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Export\\\\ListPersonDuplicate\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPersonDuplicate.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodClosingFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodClosingFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\AccompanyingPeriodOpeningFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/AccompanyingPeriodOpeningFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\BirthdateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/BirthdateFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\GenderFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/GenderFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\PersonBundle\\\\Export\\\\Filter\\\\NationalityFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Filter/NationalityFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
@ -740,29 +435,6 @@ parameters:
|
||||
count: 3
|
||||
path: src/Bundle/ChillReportBundle/Controller/ReportController.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ReportBundle\\\\Export\\\\Export\\\\ReportList\\:\\:requiredRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Export/Export/ReportList.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Return type of method Chill\\\\ReportBundle\\\\Export\\\\Filter\\\\ReportDateFilter\\:\\:addRole\\(\\) has typehint with deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
since Symfony 4\\.3, to be removed in 5\\.0\\. Use strings as roles instead\\.$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillReportBundle/Export/Filter/ReportDateFilter.php
|
||||
|
||||
-
|
||||
message: """
|
||||
@ -845,14 +517,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Form/SingleTaskType.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Parameter \\$centerResolverDispatcher of method Chill\\\\TaskBundle\\\\Repository\\\\SingleTaskAclAwareRepository\\:\\:__construct\\(\\) has typehint with deprecated interface Chill\\\\MainBundle\\\\Security\\\\Resolver\\\\CenterResolverDispatcherInterface\\:
|
||||
Use CenterResolverManager and its interface CenterResolverManagerInterface$#
|
||||
"""
|
||||
count: 1
|
||||
path: src/Bundle/ChillTaskBundle/Repository/SingleTaskAclAwareRepository.php
|
||||
|
||||
-
|
||||
message: """
|
||||
#^Instantiation of deprecated class Symfony\\\\Component\\\\Security\\\\Core\\\\Role\\\\Role\\:
|
||||
|
@ -10,16 +10,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Entity/ActivityReasonCategory.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getDescription\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: "#^Method Chill\\\\ActivityBundle\\\\Export\\\\Export\\\\StatActivityDuration\\:\\:getTitle\\(\\) should return string but return statement is missing\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillActivityBundle/Export/Export/StatActivityDuration.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
@ -245,11 +235,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Entity/User.php
|
||||
|
||||
-
|
||||
message: "#^Only booleans are allowed in a ternary operator condition, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillMainBundle/Export/Formatter/SpreadsheetListFormatter.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
@ -335,21 +320,6 @@ parameters:
|
||||
count: 6
|
||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/CountryOfBirthAggregator.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
path: src/Bundle/ChillPersonBundle/Export/Aggregator/NationalityAggregator.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 2
|
||||
path: src/Bundle/ChillPersonBundle/Export/Export/ListPerson.php
|
||||
|
||||
-
|
||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||
count: 1
|
||||
|
@ -17,10 +17,11 @@ use Chill\ActivityBundle\Form\ActivityType;
|
||||
use Chill\ActivityBundle\Repository\ActivityACLAwareRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeCategoryRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Repository\LocationRepository;
|
||||
use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
@ -41,7 +42,6 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use function array_key_exists;
|
||||
|
||||
@ -55,7 +55,7 @@ final class ActivityController extends AbstractController
|
||||
|
||||
private ActivityTypeCategoryRepository $activityTypeCategoryRepository;
|
||||
|
||||
private ActivityTypeRepository $activityTypeRepository;
|
||||
private ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
private CenterResolverManagerInterface $centerResolver;
|
||||
|
||||
@ -73,9 +73,11 @@ final class ActivityController extends AbstractController
|
||||
|
||||
private ThirdPartyRepository $thirdPartyRepository;
|
||||
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(
|
||||
ActivityACLAwareRepositoryInterface $activityACLAwareRepository,
|
||||
ActivityTypeRepository $activityTypeRepository,
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
ActivityTypeCategoryRepository $activityTypeCategoryRepository,
|
||||
PersonRepository $personRepository,
|
||||
ThirdPartyRepository $thirdPartyRepository,
|
||||
@ -86,6 +88,7 @@ final class ActivityController extends AbstractController
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
LoggerInterface $logger,
|
||||
SerializerInterface $serializer,
|
||||
UserRepositoryInterface $userRepository,
|
||||
CenterResolverManagerInterface $centerResolver
|
||||
) {
|
||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||
@ -100,6 +103,7 @@ final class ActivityController extends AbstractController
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->logger = $logger;
|
||||
$this->serializer = $serializer;
|
||||
$this->userRepository = $userRepository;
|
||||
$this->centerResolver = $centerResolver;
|
||||
}
|
||||
|
||||
@ -372,7 +376,7 @@ final class ActivityController extends AbstractController
|
||||
if ($request->query->has('activityData')) {
|
||||
$activityData = $request->query->get('activityData');
|
||||
|
||||
if (array_key_exists('durationTime', $activityData)) {
|
||||
if (array_key_exists('durationTime', $activityData) && $activityType->getDurationTimeVisible() > 0) {
|
||||
$durationTimeInMinutes = $activityData['durationTime'];
|
||||
$hours = floor($durationTimeInMinutes / 60);
|
||||
$minutes = $durationTimeInMinutes % 60;
|
||||
@ -391,26 +395,36 @@ final class ActivityController extends AbstractController
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('personsId', $activityData)) {
|
||||
if (array_key_exists('personsId', $activityData) && $activityType->getPersonsVisible() > 0) {
|
||||
foreach ($activityData['personsId'] as $personId) {
|
||||
$concernedPerson = $this->personRepository->find($personId);
|
||||
$entity->addPerson($concernedPerson);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('professionalsId', $activityData)) {
|
||||
if (array_key_exists('professionalsId', $activityData) && $activityType->getThirdPartiesVisible() > 0) {
|
||||
foreach ($activityData['professionalsId'] as $professionalsId) {
|
||||
$professional = $this->thirdPartyRepository->find($professionalsId);
|
||||
$entity->addThirdParty($professional);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('location', $activityData)) {
|
||||
if (array_key_exists('usersId', $activityData) && $activityType->getUsersVisible() > 0) {
|
||||
foreach ($activityData['usersId'] as $userId) {
|
||||
$user = $this->userRepository->find($userId);
|
||||
|
||||
if (null !== $user) {
|
||||
$entity->addUser($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('location', $activityData) && $activityType->getLocationVisible() > 0) {
|
||||
$location = $this->locationRepository->find($activityData['location']);
|
||||
$entity->setLocation($location);
|
||||
}
|
||||
|
||||
if (array_key_exists('comment', $activityData)) {
|
||||
if (array_key_exists('comment', $activityData) && $activityType->getCommentVisible() > 0) {
|
||||
$comment = new CommentEmbeddable();
|
||||
$comment->setComment($activityData['comment']);
|
||||
$comment->setUserId($this->getUser()->getid());
|
||||
|
@ -13,6 +13,10 @@ namespace Chill\ActivityBundle\Entity;
|
||||
|
||||
use Chill\ActivityBundle\Validator\Constraints as ActivityValidator;
|
||||
use Chill\DocStoreBundle\Entity\StoredObject;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable;
|
||||
@ -55,8 +59,12 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
* getUserFunction="getUser",
|
||||
* path="scope")
|
||||
*/
|
||||
class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, HasCentersInterface, HasScopesInterface
|
||||
class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterface, HasCentersInterface, HasScopesInterface, TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
use TrackCreationTrait;
|
||||
|
||||
use TrackUpdateTrait;
|
||||
|
||||
public const SENTRECEIVED_RECEIVED = 'received';
|
||||
|
||||
public const SENTRECEIVED_SENT = 'sent';
|
||||
|
@ -516,6 +516,11 @@ class ActivityType
|
||||
return $this->userVisible;
|
||||
}
|
||||
|
||||
public function hasCategory(): bool
|
||||
{
|
||||
return null !== $this->getCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is active
|
||||
* return true if the type is active.
|
||||
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ByActivityNumberAggregator implements AggregatorInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb
|
||||
->addSelect('(SELECT COUNT(activity.id) FROM ' . Activity::class . ' activity WHERE activity.accompanyingPeriod = acp) AS activity_by_number_aggregator')
|
||||
->addGroupBy('activity_by_number_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return static function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $value;
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_by_number_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group acp by activity number';
|
||||
}
|
||||
}
|
@ -13,46 +13,34 @@ namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ByUserAggregator implements AggregatorInterface
|
||||
class ByCreatorAggregator implements AggregatorInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepository $userRepository;
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(
|
||||
UserRepository $userRepository,
|
||||
UserRepositoryInterface $userRepository,
|
||||
UserRender $userRender
|
||||
) {
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('user', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.users', 'user');
|
||||
}
|
||||
|
||||
$qb->addSelect('user.id AS users_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('users_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('users_aggregator');
|
||||
}
|
||||
$qb->addSelect('IDENTITY(activity.createdBy) AS creator_aggregator');
|
||||
$qb->addGroupBy('creator_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -69,7 +57,11 @@ class ByUserAggregator implements AggregatorInterface
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Accepted users';
|
||||
return 'Created by';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$u = $this->userRepository->find($value);
|
||||
@ -80,11 +72,11 @@ class ByUserAggregator implements AggregatorInterface
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['users_aggregator'];
|
||||
return ['creator_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group activity by linked users';
|
||||
return 'Group activity by creator';
|
||||
}
|
||||
}
|
@ -33,26 +33,19 @@ class BySocialActionAggregator implements AggregatorInterface
|
||||
$this->actionRepository = $actionRepository;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('socialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialActions', 'socialaction');
|
||||
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.socialActions', 'actsocialaction');
|
||||
}
|
||||
|
||||
$qb->addSelect('socialaction.id AS socialaction_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addSelect('actsocialaction.id AS socialaction_aggregator');
|
||||
$qb->addGroupBy('socialaction_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('socialaction_aggregator');
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -72,6 +65,10 @@ class BySocialActionAggregator implements AggregatorInterface
|
||||
return 'Social action';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$sa = $this->actionRepository->find($value);
|
||||
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
|
@ -33,26 +33,19 @@ class BySocialIssueAggregator implements AggregatorInterface
|
||||
$this->issueRender = $issueRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('socialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialIssues', 'socialissue');
|
||||
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.socialIssues', 'actsocialissue');
|
||||
}
|
||||
|
||||
$qb->addSelect('socialissue.id AS socialissue_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addSelect('actsocialissue.id AS socialissue_aggregator');
|
||||
$qb->addGroupBy('socialissue_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('socialissue_aggregator');
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -72,6 +65,10 @@ class BySocialIssueAggregator implements AggregatorInterface
|
||||
return 'Social issues';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$i = $this->issueRepository->find($value);
|
||||
|
||||
return $this->issueRender->renderString($i, []);
|
||||
|
@ -33,26 +33,19 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
||||
$this->thirdPartyRender = $thirdPartyRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('thirdparty', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.thirdParties', 'thirdparty');
|
||||
if (!in_array('acttparty', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.thirdParties', 'acttparty');
|
||||
}
|
||||
|
||||
$qb->addSelect('thirdparty.id AS thirdparty_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addSelect('acttparty.id AS thirdparty_aggregator');
|
||||
$qb->addGroupBy('thirdparty_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('thirdparty_aggregator');
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -72,6 +65,10 @@ class ByThirdpartyAggregator implements AggregatorInterface
|
||||
return 'Accepted thirdparty';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$tp = $this->thirdPartyRepository->find($value);
|
||||
|
||||
return $this->thirdPartyRender->renderString($tp, []);
|
||||
|
@ -19,7 +19,7 @@ use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class UserScopeAggregator implements AggregatorInterface
|
||||
class CreatorScopeAggregator implements AggregatorInterface
|
||||
{
|
||||
private ScopeRepository $scopeRepository;
|
||||
|
||||
@ -33,26 +33,19 @@ class UserScopeAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('user', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.user', 'user');
|
||||
if (!in_array('actcreator', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.createdBy', 'actcreator');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(user.mainScope) AS userscope_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('userscope_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('userscope_aggregator');
|
||||
}
|
||||
$qb->addSelect('IDENTITY(actcreator.mainScope) AS creatorscope_aggregator');
|
||||
$qb->addGroupBy('creatorscope_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -72,6 +65,10 @@ class UserScopeAggregator implements AggregatorInterface
|
||||
return 'Scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
@ -82,11 +79,11 @@ class UserScopeAggregator implements AggregatorInterface
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['userscope_aggregator'];
|
||||
return ['creatorscope_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Group activity by userscope';
|
||||
return 'Group activity by creator scope';
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ namespace Chill\ActivityBundle\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use DateTime;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
@ -38,7 +37,7 @@ class DateAggregator implements AggregatorInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -49,41 +48,27 @@ class DateAggregator implements AggregatorInterface
|
||||
|
||||
switch ($data['frequency']) {
|
||||
case 'month':
|
||||
$fmt = 'MM';
|
||||
$fmt = 'YYYY-MM';
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'week':
|
||||
$fmt = 'IW';
|
||||
$fmt = 'YYYY-IW';
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
$fmt = 'YYYY'; $order = 'DESC';
|
||||
|
||||
break;
|
||||
break; // order DESC does not works !
|
||||
|
||||
default:
|
||||
throw new RuntimeException(sprintf("The frequency data '%s' is invalid.", $data['frequency']));
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf("TO_CHAR(activity.date, '%s') AS date_aggregator", $fmt));
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy('date_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('date_aggregator');
|
||||
}
|
||||
|
||||
$orderBy = $qb->getDQLPart('orderBy');
|
||||
|
||||
if (!empty($orderBy)) {
|
||||
$qb->addOrderBy('date_aggregator', $order);
|
||||
} else {
|
||||
$qb->orderBy('date_aggregator', $order);
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -109,16 +94,12 @@ break;
|
||||
return 'by ' . $data['frequency'];
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch ($data['frequency']) {
|
||||
case 'month':
|
||||
$month = DateTime::createFromFormat('!m', $value);
|
||||
|
||||
return sprintf(
|
||||
'%02d (%s)',
|
||||
$value,
|
||||
$month->format('M')
|
||||
);
|
||||
|
||||
case 'week':
|
||||
//return $this->translator->trans('for week') .' '. $value ;
|
||||
|
||||
|
@ -33,26 +33,19 @@ class LocationTypeAggregator implements AggregatorInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('location', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.location', 'location');
|
||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.location', 'actloc');
|
||||
}
|
||||
|
||||
$qb->addSelect('IDENTITY(location.locationType) AS locationtype_aggregator');
|
||||
|
||||
$groupBy = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addSelect('IDENTITY(actloc.locationType) AS locationtype_aggregator');
|
||||
$qb->addGroupBy('locationtype_aggregator');
|
||||
} else {
|
||||
$qb->groupBy('locationtype_aggregator');
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -72,6 +65,10 @@ class LocationTypeAggregator implements AggregatorInterface
|
||||
return 'Accepted locationtype';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$lt = $this->locationTypeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
|
@ -12,53 +12,43 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Closure;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use function in_array;
|
||||
|
||||
class ActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
public const KEY = 'activity_type_aggregator';
|
||||
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ActivityTypeRepository $activityTypeRepository,
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('type', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.activityType', 'type');
|
||||
if (!in_array('acttype', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.activityType', 'acttype');
|
||||
}
|
||||
|
||||
$qb->addSelect(sprintf('IDENTITY(activity.activityType) AS %s', self::KEY));
|
||||
|
||||
$groupby = $qb->getDQLPart('groupBy');
|
||||
|
||||
if (!empty($groupBy)) {
|
||||
$qb->addGroupBy(self::KEY);
|
||||
} else {
|
||||
$qb->groupBy(self::KEY);
|
||||
}
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -81,6 +71,10 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
return 'Activity type';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$t = $this->activityTypeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize($t->getName());
|
||||
@ -96,23 +90,4 @@ class ActivityTypeAggregator implements AggregatorInterface
|
||||
{
|
||||
return 'Aggregate by activity type';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and another alias.
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @param string $alias the alias to search for
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias)
|
||||
{
|
||||
foreach ($joins as $join) {
|
||||
if ($join->getAlias() === $alias) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,12 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserRepository;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Closure;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class ActivityUserAggregator implements AggregatorInterface
|
||||
{
|
||||
@ -37,9 +35,9 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
@ -63,14 +61,15 @@ class ActivityUserAggregator implements AggregatorInterface
|
||||
|
||||
public function getLabels($key, $values, $data): Closure
|
||||
{
|
||||
// preload users at once
|
||||
$this->userRepository->findBy(['id' => $values]);
|
||||
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Activity user';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$u = $this->userRepository->find($value);
|
||||
|
||||
return $this->userRender->renderString($u, []);
|
||||
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersAggregator implements AggregatorInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(UserRepositoryInterface $userRepository, UserRender $userRender)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
|
||||
$qb
|
||||
->addSelect('actusers.id AS activity_users_aggregator')
|
||||
->addGroupBy('activity_users_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add on the form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Activity users';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$u = $this->userRepository->find($value);
|
||||
|
||||
return $this->userRender->renderString($u, []);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return ['activity_users_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Aggregate by activity users';
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorInterface
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
private UserJobRepositoryInterface $userJobRepository;
|
||||
|
||||
public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->userJobRepository = $userJobRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
|
||||
$qb
|
||||
->addSelect('IDENTITY(actusers.userJob) AS activity_users_job_aggregator')
|
||||
->addGroupBy('activity_users_job_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add in the form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Users \'s job';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$j = $this->userJobRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$j->getLabel()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_users_job_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Aggregate by users job';
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\AggregatorInterface
|
||||
{
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('actusers', $qb->getAllAliases(), true)) {
|
||||
$qb->leftJoin('activity.users', 'actusers');
|
||||
}
|
||||
|
||||
$qb
|
||||
->addSelect('IDENTITY(actusers.mainScope) AS activity_users_main_scope_aggregator')
|
||||
->addGroupBy('activity_users_main_scope_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// nothing to add in the form
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
return function ($value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'Users \'s scope';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$s = $this->scopeRepository->find($value);
|
||||
|
||||
return $this->translatableStringHelper->localize(
|
||||
$s->getName()
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_users_main_scope_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Aggregate by users scope';
|
||||
}
|
||||
}
|
@ -14,7 +14,6 @@ namespace Chill\ActivityBundle\Export\Aggregator\PersonAggregators;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
@ -24,11 +23,10 @@ use Doctrine\ORM\QueryBuilder;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
class ActivityReasonAggregator implements AggregatorInterface, ExportElementValidatedInterface
|
||||
{
|
||||
@ -48,19 +46,19 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// add select element
|
||||
if ('reasons' === $data['level']) {
|
||||
$elem = 'reasons.id';
|
||||
$elem = 'actreasons.id';
|
||||
$alias = 'activity_reasons_id';
|
||||
} elseif ('categories' === $data['level']) {
|
||||
$elem = 'category.id';
|
||||
$elem = 'actreasoncat.id';
|
||||
$alias = 'activity_categories_id';
|
||||
} else {
|
||||
throw new RuntimeException('The data provided are not recognized.');
|
||||
@ -69,29 +67,15 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
$qb->addSelect($elem . ' as ' . $alias);
|
||||
|
||||
// make a jointure only if needed
|
||||
$join = $qb->getDQLPart('join');
|
||||
|
||||
if (
|
||||
(
|
||||
array_key_exists('activity', $join)
|
||||
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
|
||||
)
|
||||
|| (!array_key_exists('activity', $join))
|
||||
) {
|
||||
$qb->add(
|
||||
'join',
|
||||
[
|
||||
'activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons'),
|
||||
],
|
||||
true
|
||||
);
|
||||
if (!in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
$qb->innerJoin('activity.reasons', 'actreasons');
|
||||
}
|
||||
|
||||
// join category if necessary
|
||||
if ('activity_categories_id' === $alias) {
|
||||
// add join only if needed
|
||||
if (!$this->checkJoinAlreadyDefined($qb->getDQLPart('join')['activity'], 'category')) {
|
||||
$qb->join('reasons.category', 'category');
|
||||
if (!in_array('actreasoncat', $qb->getAllAliases(), true)) {
|
||||
$qb->join('actreasons.category', 'actreasoncat');
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,23 +179,4 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and another alias.
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @param string $alias the alias to search for
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias)
|
||||
{
|
||||
foreach ($joins as $join) {
|
||||
if ($join->getAlias() === $alias) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\AggregatorInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class SentReceivedAggregator implements AggregatorInterface
|
||||
{
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data): void
|
||||
{
|
||||
$qb->addSelect('activity.sentReceived AS activity_sentreceived_aggregator')
|
||||
->addGroupBy('activity_sentreceived_aggregator');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder): void
|
||||
{
|
||||
// No form needed
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data): callable
|
||||
{
|
||||
return function (?string $value): string {
|
||||
if ('_header' === $value) {
|
||||
return 'export.aggregator.activity.by_sent_received.Sent or received';
|
||||
}
|
||||
|
||||
switch ($value) {
|
||||
case null:
|
||||
return '';
|
||||
|
||||
case 'sent':
|
||||
return $this->translator->trans('export.aggregator.activity.by_sent_received.is sent');
|
||||
|
||||
case 'received':
|
||||
return $this->translator->trans('export.aggregator.activity.by_sent_received.is received');
|
||||
|
||||
default:
|
||||
throw new LogicException(sprintf('The value %s is not valid', $value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function getQueryKeys($data): array
|
||||
{
|
||||
return ['activity_sentreceived_aggregator'];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'export.aggregator.activity.by_sent_received.Group activity by sentreceived';
|
||||
}
|
||||
}
|
@ -17,11 +17,14 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -35,7 +38,6 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
// TODO: Implement buildForm() method.
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes(): array
|
||||
@ -67,9 +69,9 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return ['export_avg_activity_duration'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@ -84,17 +86,34 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb->select('AVG(activity.durationTime) as export_avg_activity_duration');
|
||||
$qb = $this->repository->createQueryBuilder('activity');
|
||||
|
||||
$qb
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->select('AVG(activity.durationTime) as export_avg_activity_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
@ -102,7 +121,7 @@ class AvgActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_ACP,
|
||||
//PersonDeclarations::ACP_TYPE,
|
||||
PersonDeclarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,14 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -67,9 +70,9 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
return ['export_avg_activity_visit_duration'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@ -84,17 +87,34 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb->select('AVG(activity.travelTime) as export_avg_activity_visit_duration');
|
||||
$qb = $this->repository->createQueryBuilder('activity');
|
||||
|
||||
$qb
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->select('AVG(activity.travelTime) as export_avg_activity_visit_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.travelTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
@ -102,7 +122,7 @@ class AvgActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_ACP,
|
||||
//PersonDeclarations::ACP_TYPE,
|
||||
PersonDeclarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,14 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -68,9 +69,9 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
return ['export_count_activity'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@ -85,17 +86,33 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('activity')
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
|
||||
$qb->select('COUNT(activity.id) as export_count_activity');
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$qb->select('COUNT(DISTINCT activity.id) as export_count_activity');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
@ -103,7 +120,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_ACP,
|
||||
//PersonDeclarations::ACP_TYPE,
|
||||
PersonDeclarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export\LinkedToACP;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Export\ListActivityHelper;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
|
||||
use Chill\MainBundle\Export\ListInterface;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ListActivity implements ListInterface, GroupedExportInterface
|
||||
{
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private ListActivityHelper $helper;
|
||||
|
||||
private TranslatableStringExportLabelHelper $translatableStringExportLabelHelper;
|
||||
|
||||
public function __construct(
|
||||
ListActivityHelper $helper,
|
||||
EntityManagerInterface $entityManager,
|
||||
TranslatableStringExportLabelHelper $translatableStringExportLabelHelper
|
||||
) {
|
||||
$this->helper = $helper;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->translatableStringExportLabelHelper = $translatableStringExportLabelHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$this->helper->buildForm($builder);
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return $this->helper->getAllowedFormattersTypes();
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return ListActivityHelper::MSG_KEY . 'List activities linked to an accompanying course';
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
{
|
||||
return 'Exports of activities linked to an accompanying period';
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'acpId':
|
||||
return static function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return ListActivityHelper::MSG_KEY . 'accompanying course id';
|
||||
}
|
||||
|
||||
return $value ?? '';
|
||||
};
|
||||
|
||||
case 'scopesNames':
|
||||
return $this->translatableStringExportLabelHelper->getLabelMulti($key, $values, ListActivityHelper::MSG_KEY . 'course circles');
|
||||
|
||||
default:
|
||||
return $this->helper->getLabels($key, $values, $data);
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return
|
||||
array_merge(
|
||||
$this->helper->getQueryKeys($data),
|
||||
[
|
||||
'acpId',
|
||||
'scopesNames',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $this->helper->getResult($query, $data);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return ListActivityHelper::MSG_KEY . 'List activity linked to a course';
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->helper->getType();
|
||||
}
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->entityManager->createQueryBuilder();
|
||||
|
||||
$qb
|
||||
->distinct()
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->leftJoin('acp.participations', 'acppart')
|
||||
->leftJoin('acppart.person', 'person')
|
||||
->andWhere('acppart.startDate != acppart.endDate OR acppart.endDate IS NULL')
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1
|
||||
FROM ' . PersonCenterHistory::class . ' acl_count_person_history
|
||||
WHERE acl_count_person_history.person = person
|
||||
AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
// some grouping are necessary
|
||||
->addGroupBy('acp.id')
|
||||
->addOrderBy('activity.date')
|
||||
->addOrderBy('activity.id')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
$this->helper->addSelect($qb);
|
||||
|
||||
// add select for this step
|
||||
$qb
|
||||
->addSelect('acp.id AS acpId')
|
||||
->addSelect('(SELECT AGGREGATE(acpScope.name) FROM ' . Scope::class . ' acpScope WHERE acpScope MEMBER OF acp.scopes) AS scopesNames')
|
||||
->addGroupBy('scopesNames');
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return ActivityStatsVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return array_merge(
|
||||
$this->helper->supportsModifiers(),
|
||||
[
|
||||
\Chill\PersonBundle\Export\Declarations::ACP_TYPE,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@ -17,11 +17,14 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -67,9 +70,9 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return ['export_sum_activity_duration'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@ -84,17 +87,34 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('activity')
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
|
||||
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration');
|
||||
$qb->select('SUM(activity.durationTime) as export_sum_activity_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.durationTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
@ -102,7 +122,7 @@ class SumActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_ACP,
|
||||
//PersonDeclarations::ACP_TYPE,
|
||||
PersonDeclarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,14 @@ use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\GroupedExportInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
|
||||
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
|
||||
use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class SumActivityVisitDuration implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -67,9 +70,9 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
return ['export_sum_activity_visit_duration'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
@ -84,17 +87,34 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
|
||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('activity')
|
||||
$centers = array_map(static function ($el) {
|
||||
return $el['center'];
|
||||
}, $acl);
|
||||
|
||||
$qb = $this->repository
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.accompanyingPeriod', 'acp');
|
||||
|
||||
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration');
|
||||
$qb->select('SUM(activity.travelTime) as export_sum_activity_visit_duration')
|
||||
->andWhere($qb->expr()->isNotNull('activity.travelTime'));
|
||||
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . AccompanyingPeriodParticipation::class . ' acl_count_part
|
||||
JOIN ' . PersonCenterHistory::class . ' acl_count_person_history WITH IDENTITY(acl_count_person_history.person) = IDENTITY(acl_count_part.person)
|
||||
WHERE acl_count_part.accompanyingPeriod = acp.id AND acl_count_person_history.center IN (:authorized_centers)
|
||||
'
|
||||
)
|
||||
)
|
||||
->setParameter('authorized_centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole(): Role
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers(): array
|
||||
@ -102,7 +122,7 @@ class SumActivityVisitDuration implements ExportInterface, GroupedExportInterfac
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_ACP,
|
||||
//PersonDeclarations::ACP_TYPE,
|
||||
PersonDeclarations::ACP_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
@ -66,9 +65,9 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
return ['export_count_activity'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
@ -85,21 +84,32 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
{
|
||||
$centers = array_map(static fn ($el) => $el['center'], $acl);
|
||||
|
||||
$qb = $this->activityRepository->createQueryBuilder('activity')
|
||||
->join('activity.person', 'person');
|
||||
$qb = $this->activityRepository
|
||||
->createQueryBuilder('activity')
|
||||
->join('activity.person', 'person')
|
||||
->join('person.centerHistory', 'centerHistory');
|
||||
|
||||
$qb->select('COUNT(activity.id) as export_count_activity');
|
||||
|
||||
$qb
|
||||
->where($qb->expr()->in('person.center', ':centers'))
|
||||
->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('centerHistory.endDate'),
|
||||
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
@ -107,7 +117,7 @@ class CountActivity implements ExportInterface, GroupedExportInterface
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
Declarations::ACTIVITY_PERSON,
|
||||
//PersonDeclarations::PERSON_TYPE,
|
||||
PersonDeclarations::PERSON_TYPE,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\Query;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
@ -125,7 +124,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return 'attendee';
|
||||
}
|
||||
|
||||
return $value ? 1 : 0;
|
||||
return $value ? 'X' : '';
|
||||
};
|
||||
|
||||
case 'list_reasons':
|
||||
@ -211,10 +210,20 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
$qb
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->andWhere('center IN (:authorized_centers)')
|
||||
->setParameter('authorized_centers', $centers);
|
||||
->join('activity.person', 'actperson')
|
||||
->join('actperson.centerHistory', 'centerHistory');
|
||||
|
||||
$qb->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('centerHistory.endDate'),
|
||||
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
|
||||
foreach ($this->fields as $f) {
|
||||
if (in_array($f, $data['fields'], true)) {
|
||||
@ -225,23 +234,23 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
break;
|
||||
|
||||
case 'person_firstname':
|
||||
$qb->addSelect('person.firstName AS person_firstname');
|
||||
$qb->addSelect('actperson.firstName AS person_firstname');
|
||||
|
||||
break;
|
||||
|
||||
case 'person_lastname':
|
||||
$qb->addSelect('person.lastName AS person_lastname');
|
||||
$qb->addSelect('actperson.lastName AS person_lastname');
|
||||
|
||||
break;
|
||||
|
||||
case 'person_id':
|
||||
$qb->addSelect('person.id AS person_id');
|
||||
$qb->addSelect('actperson.id AS person_id');
|
||||
|
||||
break;
|
||||
|
||||
case 'user_username':
|
||||
$qb->join('activity.user', 'user');
|
||||
$qb->addSelect('user.username AS user_username');
|
||||
$qb->join('activity.user', 'actuser');
|
||||
$qb->addSelect('actuser.username AS user_username');
|
||||
|
||||
break;
|
||||
|
||||
@ -252,7 +261,7 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
break;
|
||||
|
||||
case 'type_name':
|
||||
$qb->join('activity.type', 'type');
|
||||
$qb->join('activity.activityType', 'type');
|
||||
$qb->addSelect('type.name AS type_name');
|
||||
|
||||
break;
|
||||
@ -264,6 +273,11 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
|
||||
break;
|
||||
|
||||
case 'attendee':
|
||||
$qb->addSelect('IDENTITY(activity.attendee) AS attendee');
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$qb->addSelect(sprintf('activity.%s as %s', $f, $f));
|
||||
|
||||
@ -275,9 +289,9 @@ class ListActivity implements ListInterface, GroupedExportInterface
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::LISTS);
|
||||
return ActivityStatsVoter::LISTS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
|
@ -22,7 +22,6 @@ use Chill\PersonBundle\Export\Declarations as PersonDeclarations;
|
||||
use Doctrine\ORM\Query;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
|
||||
/**
|
||||
* This export allow to compute stats on activity duration.
|
||||
@ -65,6 +64,8 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
if (self::SUM === $this->action) {
|
||||
return 'Sum activities linked to a person duration by various parameters.';
|
||||
}
|
||||
|
||||
throw new LogicException('this action is not supported: ' . $this->action);
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
@ -88,9 +89,9 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
return ['export_stat_activity'];
|
||||
}
|
||||
|
||||
public function getResult($qb, $data)
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $qb->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
@ -98,6 +99,8 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
if (self::SUM === $this->action) {
|
||||
return 'Sum activity linked to a person duration';
|
||||
}
|
||||
|
||||
throw new LogicException('This action is not supported: ' . $this->action);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
@ -120,16 +123,29 @@ class StatActivityDuration implements ExportInterface, GroupedExportInterface
|
||||
$select = 'SUM(activity.durationTime) AS export_stat_activity';
|
||||
}
|
||||
|
||||
return $qb->select($select)
|
||||
$qb->select($select)
|
||||
->join('activity.person', 'person')
|
||||
->join('person.center', 'center')
|
||||
->where($qb->expr()->in('center', ':centers'))
|
||||
->setParameter(':centers', $centers);
|
||||
->join('person.centerHistory', 'centerHistory');
|
||||
|
||||
$qb
|
||||
->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->lte('centerHistory.startDate', 'activity.date'),
|
||||
$qb->expr()->orX(
|
||||
$qb->expr()->isNull('centerHistory.endDate'),
|
||||
$qb->expr()->gt('centerHistory.endDate', 'activity.date')
|
||||
)
|
||||
)
|
||||
)
|
||||
->andWhere($qb->expr()->in('centerHistory.center', ':centers'))
|
||||
->setParameter('centers', $centers);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function requiredRole()
|
||||
public function requiredRole(): string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return ActivityStatsVoter::STATS;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
|
@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Export;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityPresenceRepositoryInterface;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\FormatterInterface;
|
||||
use Chill\MainBundle\Export\Helper\DateTimeHelper;
|
||||
use Chill\MainBundle\Export\Helper\TranslatableStringExportLabelHelper;
|
||||
use Chill\MainBundle\Export\Helper\UserHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Helper\LabelPersonHelper;
|
||||
use Chill\ThirdPartyBundle\Export\Helper\LabelThirdPartyHelper;
|
||||
use Doctrine\ORM\AbstractQuery;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use LogicException;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
class ListActivityHelper
|
||||
{
|
||||
public const MSG_KEY = 'export.list.activity.';
|
||||
|
||||
private ActivityPresenceRepositoryInterface $activityPresenceRepository;
|
||||
|
||||
private ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
private DateTimeHelper $dateTimeHelper;
|
||||
|
||||
private LabelPersonHelper $labelPersonHelper;
|
||||
|
||||
private LabelThirdPartyHelper $labelThirdPartyHelper;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
private TranslatableStringExportLabelHelper $translatableStringLabelHelper;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
private UserHelper $userHelper;
|
||||
|
||||
public function __construct(
|
||||
ActivityPresenceRepositoryInterface $activityPresenceRepository,
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
DateTimeHelper $dateTimeHelper,
|
||||
LabelPersonHelper $labelPersonHelper,
|
||||
LabelThirdPartyHelper $labelThirdPartyHelper,
|
||||
TranslatorInterface $translator,
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
TranslatableStringExportLabelHelper $translatableStringLabelHelper,
|
||||
UserHelper $userHelper
|
||||
) {
|
||||
$this->activityPresenceRepository = $activityPresenceRepository;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->dateTimeHelper = $dateTimeHelper;
|
||||
$this->labelPersonHelper = $labelPersonHelper;
|
||||
$this->labelThirdPartyHelper = $labelThirdPartyHelper;
|
||||
$this->translator = $translator;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->translatableStringLabelHelper = $translatableStringLabelHelper;
|
||||
$this->userHelper = $userHelper;
|
||||
}
|
||||
|
||||
public function addSelect(QueryBuilder $qb): void
|
||||
{
|
||||
$qb
|
||||
->addSelect('activity.id AS id')
|
||||
->addSelect('activity.date')
|
||||
->addSelect('IDENTITY(activity.activityType) AS typeName')
|
||||
->leftJoin('activity.reasons', 'reasons')
|
||||
->addSelect('AGGREGATE(reasons.name) AS listReasons')
|
||||
->leftJoin('activity.persons', 'actPerson')
|
||||
->addSelect('AGGREGATE(actPerson.id) AS personsIds')
|
||||
->addSelect('AGGREGATE(actPerson.id) AS personsNames')
|
||||
->leftJoin('activity.users', 'users_u')
|
||||
->addSelect('AGGREGATE(users_u.id) AS usersIds')
|
||||
->addSelect('AGGREGATE(users_u.id) AS usersNames')
|
||||
->leftJoin('activity.thirdParties', 'thirdparty')
|
||||
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesIds')
|
||||
->addSelect('AGGREGATE(thirdparty.id) AS thirdPartiesNames')
|
||||
->addSelect('IDENTITY(activity.attendee) AS attendeeName')
|
||||
->addSelect('activity.durationTime')
|
||||
->addSelect('activity.travelTime')
|
||||
->addSelect('activity.emergency')
|
||||
->leftJoin('activity.location', 'location')
|
||||
->addSelect('location.name AS locationName')
|
||||
->addSelect('activity.sentReceived')
|
||||
->addSelect('IDENTITY(activity.createdBy) AS createdBy')
|
||||
->addSelect('activity.createdAt')
|
||||
->addSelect('IDENTITY(activity.updatedBy) AS updatedBy')
|
||||
->addSelect('activity.updatedAt')
|
||||
->addGroupBy('activity.id')
|
||||
->addGroupBy('location.id');
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
}
|
||||
|
||||
public function getAllowedFormattersTypes()
|
||||
{
|
||||
return [FormatterInterface::TYPE_LIST];
|
||||
}
|
||||
|
||||
public function getLabels($key, array $values, $data)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'createdAt':
|
||||
case 'updatedAt':
|
||||
return $this->dateTimeHelper->getLabel($key);
|
||||
|
||||
case 'createdBy':
|
||||
case 'updatedBy':
|
||||
return $this->userHelper->getLabel($key, $values, $key);
|
||||
|
||||
case 'date':
|
||||
return $this->dateTimeHelper->getLabel(self::MSG_KEY . $key);
|
||||
|
||||
case 'attendeeName':
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Attendee';
|
||||
}
|
||||
|
||||
if (null === $value || null === $presence = $this->activityPresenceRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($presence->getName());
|
||||
};
|
||||
|
||||
case 'listReasons':
|
||||
return $this->translatableStringLabelHelper->getLabelMulti($key, $values, 'Activity Reasons');
|
||||
|
||||
case 'typeName':
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return 'Activity type';
|
||||
}
|
||||
|
||||
if (null === $value || null === $type = $this->activityTypeRepository->find($value)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($type->getName());
|
||||
};
|
||||
|
||||
case 'usersNames':
|
||||
return $this->userHelper->getLabelMulti($key, $values, self::MSG_KEY . 'users name');
|
||||
|
||||
case 'usersIds':
|
||||
case 'thirdPartiesIds':
|
||||
case 'personsIds':
|
||||
return static function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
switch ($key) {
|
||||
case 'usersIds':
|
||||
return self::MSG_KEY . 'users ids';
|
||||
|
||||
case 'thirdPartiesIds':
|
||||
return self::MSG_KEY . 'third parties ids';
|
||||
|
||||
case 'personsIds':
|
||||
return self::MSG_KEY . 'persons ids';
|
||||
|
||||
default:
|
||||
throw new LogicException('key not supported');
|
||||
}
|
||||
}
|
||||
|
||||
$decoded = json_decode($value);
|
||||
|
||||
return implode(
|
||||
'|',
|
||||
array_unique(
|
||||
array_filter($decoded, static fn (?int $id) => null !== $id),
|
||||
SORT_NUMERIC
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
case 'personsNames':
|
||||
return $this->labelPersonHelper->getLabelMulti($key, $values, self::MSG_KEY . 'persons name');
|
||||
|
||||
case 'thirdPartiesNames':
|
||||
return $this->labelThirdPartyHelper->getLabelMulti($key, $values, self::MSG_KEY . 'thirds parties');
|
||||
|
||||
case 'sentReceived':
|
||||
return function ($value) {
|
||||
if ('_header' === $value) {
|
||||
return self::MSG_KEY . 'sent received';
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translator->trans($value);
|
||||
};
|
||||
|
||||
default:
|
||||
return function ($value) use ($key) {
|
||||
if ('_header' === $value) {
|
||||
return self::MSG_KEY . $key;
|
||||
}
|
||||
|
||||
if (null === $value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->translator->trans($value);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryKeys($data)
|
||||
{
|
||||
return [
|
||||
'id',
|
||||
'date',
|
||||
'typeName',
|
||||
'listReasons',
|
||||
'attendeeName',
|
||||
'durationTime',
|
||||
'travelTime',
|
||||
'emergency',
|
||||
'locationName',
|
||||
'sentReceived',
|
||||
'personsIds',
|
||||
'personsNames',
|
||||
'usersIds',
|
||||
'usersNames',
|
||||
'thirdPartiesIds',
|
||||
'thirdPartiesNames',
|
||||
'createdBy',
|
||||
'createdAt',
|
||||
'updatedBy',
|
||||
'updatedAt',
|
||||
];
|
||||
}
|
||||
|
||||
public function getResult($query, $data)
|
||||
{
|
||||
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function supportsModifiers()
|
||||
{
|
||||
return [
|
||||
Declarations::ACTIVITY,
|
||||
];
|
||||
}
|
||||
}
|
@ -9,57 +9,49 @@ declare(strict_types=1);
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
|
||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* TODO merge with ActivityTypeFilter in ChillActivity (!?).
|
||||
*/
|
||||
class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelper $translatableStringHelper;
|
||||
private ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// One2many between activity and accompanyingperiod is not reversed !
|
||||
// we replace indicator 'from' clause by 'act', and put 'acp' in a join
|
||||
|
||||
$qb->resetDQLPart('from');
|
||||
$qb->from('ChillActivityBundle:Activity', 'act');
|
||||
|
||||
$qb
|
||||
->join('act.accompanyingPeriod', 'acp')
|
||||
->join('act.activityType', 'aty');
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('aty.id', ':activitytypes');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
if (!in_array('activity', $qb->getAllAliases(), true)) {
|
||||
$qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('activitytypes', $data['accepted_activitytypes']);
|
||||
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
||||
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('selected_activity_types', $data['types']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
@ -71,8 +63,12 @@ class ActivityTypeFilter implements FilterInterface
|
||||
{
|
||||
$builder->add('accepted_activitytypes', EntityType::class, [
|
||||
'class' => ActivityType::class,
|
||||
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||
'choice_label' => function (ActivityType $aty) {
|
||||
return $this->translatableStringHelper->localize($aty->getName());
|
||||
return
|
||||
($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||
.
|
||||
$this->translatableStringHelper->localize($aty->getName());
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
@ -88,7 +84,7 @@ class ActivityTypeFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered by activity types: only %activitytypes%', [
|
||||
'%activitytypes%' => implode(', ou ', $types),
|
||||
'%activitytypes%' => implode(', ', $types),
|
||||
]];
|
||||
}
|
||||
|
@ -12,16 +12,13 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
class ByUserFilter implements FilterInterface
|
||||
class ByCreatorFilter implements FilterInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
@ -30,29 +27,18 @@ class ByUserFilter implements FilterInterface
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
if (!in_array('user', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.users', 'user');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->in('user.id', ':users');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('users', $data['accepted_users']);
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->in('activity.createdBy', ':users')
|
||||
)
|
||||
->setParameter('users', $data['accepted_users']);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -62,13 +48,8 @@ class ByUserFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_users', EntityType::class, [
|
||||
'class' => User::class,
|
||||
'choice_label' => function (User $u) {
|
||||
return $this->userRender->renderString($u, []);
|
||||
},
|
||||
$builder->add('accepted_users', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -80,13 +61,13 @@ class ByUserFilter implements FilterInterface
|
||||
$users[] = $this->userRender->renderString($u, []);
|
||||
}
|
||||
|
||||
return ['Filtered activity by linked users: only %users%', [
|
||||
'%users%' => implode(', ou ', $users),
|
||||
return ['Filtered activity by creator: only %users%', [
|
||||
'%users%' => implode(', ', $users),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter activity by linked users';
|
||||
return 'Filter activity by creator';
|
||||
}
|
||||
}
|
@ -14,10 +14,9 @@ namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialAction;
|
||||
use Chill\PersonBundle\Form\Type\PickSocialActionType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
@ -30,29 +29,24 @@ class BySocialActionFilter implements FilterInterface
|
||||
$this->actionRender = $actionRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
if (!in_array('socialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialActions', 'socialaction');
|
||||
if (!in_array('actsocialaction', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialActions', 'actsocialaction');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->in('socialaction.id', ':socialactions');
|
||||
$clause = $qb->expr()->in('actsocialaction.id', ':socialactions');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('socialactions', $data['accepted_socialactions']);
|
||||
$qb->andWhere($clause)
|
||||
->setParameter(
|
||||
'socialactions',
|
||||
SocialAction::getDescendantsWithThisForActions($data['accepted_socialactions'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -62,13 +56,8 @@ class BySocialActionFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_socialactions', EntityType::class, [
|
||||
'class' => SocialAction::class,
|
||||
'choice_label' => function (SocialAction $sa) {
|
||||
return $this->actionRender->renderString($sa, []);
|
||||
},
|
||||
$builder->add('accepted_socialactions', PickSocialActionType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -76,12 +65,14 @@ class BySocialActionFilter implements FilterInterface
|
||||
{
|
||||
$actions = [];
|
||||
|
||||
foreach ($data['accepted_socialactions'] as $sa) {
|
||||
$actions[] = $this->actionRender->renderString($sa, []);
|
||||
foreach ($data['accepted_socialactions'] as $action) {
|
||||
$actions[] = $this->actionRender->renderString($action, [
|
||||
'show_and_children' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return ['Filtered activity by linked socialaction: only %actions%', [
|
||||
'%actions%' => implode(', ou ', $actions),
|
||||
'%actions%' => implode(', ', $actions),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,9 @@ namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
|
||||
use Chill\PersonBundle\Form\Type\PickSocialIssueType;
|
||||
use Chill\PersonBundle\Templating\Entity\SocialIssueRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
@ -30,29 +29,24 @@ class BySocialIssueFilter implements FilterInterface
|
||||
$this->issueRender = $issueRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
if (!in_array('socialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialIssues', 'socialissue');
|
||||
if (!in_array('actsocialissue', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.socialIssues', 'actsocialissue');
|
||||
}
|
||||
|
||||
$clause = $qb->expr()->in('socialissue.id', ':socialissues');
|
||||
$clause = $qb->expr()->in('actsocialissue.id', ':socialissues');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('socialissues', $data['accepted_socialissues']);
|
||||
$qb->andWhere($clause)
|
||||
->setParameter(
|
||||
'socialissues',
|
||||
SocialIssue::getDescendantsWithThisForIssues($data['accepted_socialissues'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -62,13 +56,8 @@ class BySocialIssueFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_socialissues', EntityType::class, [
|
||||
'class' => SocialIssue::class,
|
||||
'choice_label' => function (SocialIssue $si) {
|
||||
return $this->issueRender->renderString($si, []);
|
||||
},
|
||||
$builder->add('accepted_socialissues', PickSocialIssueType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -76,12 +65,14 @@ class BySocialIssueFilter implements FilterInterface
|
||||
{
|
||||
$issues = [];
|
||||
|
||||
foreach ($data['accepted_socialissues'] as $si) {
|
||||
$issues[] = $this->issueRender->renderString($si, []);
|
||||
foreach ($data['accepted_socialissues'] as $issue) {
|
||||
$issues[] = $this->issueRender->renderString($issue, [
|
||||
'show_and_children' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
return ['Filtered activity by linked socialissue: only %issues%', [
|
||||
'%issues%' => implode(', ou ', $issues),
|
||||
'%issues%' => implode(', ', $issues),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ class EmergencyFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -74,15 +74,13 @@ class EmergencyFilter implements FilterInterface
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
foreach (self::CHOICES as $k => $v) {
|
||||
if ($v === $data['accepted_emergency']) {
|
||||
$choice = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return ['Filtered activity by emergency: only %emergency%', [
|
||||
'%emergency%' => $this->translator->trans($choice),
|
||||
]];
|
||||
return [
|
||||
'Filtered by emergency: only %emergency%', [
|
||||
'%emergency%' => $this->translator->trans(
|
||||
$data['accepted_emergency'] ? 'is emergency' : 'is not emergency'
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\PersonBundle\Export\Declarations;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HasNoActivityFilter implements FilterInterface
|
||||
{
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->andWhere('
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM ' . Activity::class . ' activity
|
||||
WHERE activity.accompanyingPeriod = acp
|
||||
)
|
||||
');
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
{
|
||||
return Declarations::ACP_TYPE;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
//no form needed
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string'): array
|
||||
{
|
||||
return ['Filtered acp which has no activities', []];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter acp which has no activity';
|
||||
}
|
||||
}
|
@ -12,12 +12,11 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\LocationType;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickLocationTypeType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use function in_array;
|
||||
|
||||
@ -30,19 +29,19 @@ class LocationTypeFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('location', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.location', 'location');
|
||||
if (!in_array('actloc', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.location', 'actloc');
|
||||
}
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('location.locationType', ':locationtype');
|
||||
$clause = $qb->expr()->in('actloc.locationType', ':locationtype');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
@ -61,13 +60,9 @@ class LocationTypeFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_locationtype', EntityType::class, [
|
||||
'class' => LocationType::class,
|
||||
'choice_label' => function (LocationType $type) {
|
||||
return $this->translatableStringHelper->localize($type->getTitle());
|
||||
},
|
||||
$builder->add('accepted_locationtype', PickLocationTypeType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
//'label' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -82,7 +77,7 @@ class LocationTypeFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered activity by locationtype: only %types%', [
|
||||
'%types%' => implode(', ou ', $types),
|
||||
'%types%' => implode(', ', $types),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ class SentReceivedFilter implements FilterInterface
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -12,12 +12,11 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\Query\Expr\Andx;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UserFilter implements FilterInterface
|
||||
@ -29,7 +28,7 @@ class UserFilter implements FilterInterface
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -57,13 +56,8 @@ class UserFilter implements FilterInterface
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_users', EntityType::class, [
|
||||
'class' => User::class,
|
||||
'choice_label' => function (User $u) {
|
||||
return $this->userRender->renderString($u, []);
|
||||
},
|
||||
$builder->add('accepted_users', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'label' => 'Creators',
|
||||
]);
|
||||
}
|
||||
@ -77,7 +71,7 @@ class UserFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered activity by user: only %users%', [
|
||||
'%users%' => implode(', ou ', $users),
|
||||
'%users%' => implode(', ', $users),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -30,20 +30,20 @@ class UserScopeFilter implements FilterInterface
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
if (!in_array('user', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.user', 'user');
|
||||
if (!in_array('actuser', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.user', 'actuser');
|
||||
}
|
||||
|
||||
$where = $qb->getDQLPart('where');
|
||||
|
||||
$clause = $qb->expr()->in('user.mainScope', ':userscope');
|
||||
$clause = $qb->expr()->in('actuser.mainScope', ':userscope');
|
||||
|
||||
if ($where instanceof Andx) {
|
||||
$where->add($clause);
|
||||
@ -85,7 +85,7 @@ class UserScopeFilter implements FilterInterface
|
||||
}
|
||||
|
||||
return ['Filtered activity by userscope: only %scopes%', [
|
||||
'%scopes%' => implode(', ou ', $scopes),
|
||||
'%scopes%' => implode(', ', $scopes),
|
||||
]];
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,10 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\Export\FilterType;
|
||||
use DateTime;
|
||||
use Chill\MainBundle\Form\Type\PickRollingDateType;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDate;
|
||||
use Chill\MainBundle\Service\RollingDate\RollingDateConverterInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@ -28,12 +29,17 @@ class ActivityDateFilter implements FilterInterface
|
||||
{
|
||||
protected TranslatorInterface $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
private RollingDateConverterInterface $rollingDateConverter;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
RollingDateConverterInterface $rollingDateConverter
|
||||
) {
|
||||
$this->translator = $translator;
|
||||
$this->rollingDateConverter = $rollingDateConverter;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@ -54,8 +60,14 @@ class ActivityDateFilter implements FilterInterface
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->setParameter('date_from', $data['date_from']);
|
||||
$qb->setParameter('date_to', $data['date_to']);
|
||||
$qb->setParameter(
|
||||
'date_from',
|
||||
$this->rollingDateConverter->convert($data['date_from'])
|
||||
);
|
||||
$qb->setParameter(
|
||||
'date_to',
|
||||
$this->rollingDateConverter->convert($data['date_to'])
|
||||
);
|
||||
}
|
||||
|
||||
public function applyOn(): string
|
||||
@ -66,13 +78,13 @@ class ActivityDateFilter implements FilterInterface
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add('date_from', ChillDateType::class, [
|
||||
->add('date_from', PickRollingDateType::class, [
|
||||
'label' => 'Activities after this date',
|
||||
'data' => new DateTime(),
|
||||
'data' => new RollingDate(RollingDate::T_YEAR_PREVIOUS_START),
|
||||
])
|
||||
->add('date_to', ChillDateType::class, [
|
||||
->add('date_to', PickRollingDateType::class, [
|
||||
'label' => 'Activities before this date',
|
||||
'data' => new DateTime(),
|
||||
'data' => new RollingDate(RollingDate::T_TODAY),
|
||||
]);
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
|
||||
@ -121,8 +133,8 @@ class ActivityDateFilter implements FilterInterface
|
||||
return [
|
||||
'Filtered by date of activity: only between %date_from% and %date_to%',
|
||||
[
|
||||
'%date_from%' => $data['date_from']->format('d-m-Y'),
|
||||
'%date_to%' => $data['date_to']->format('d-m-Y'),
|
||||
'%date_from%' => $this->rollingDateConverter->convert($data['date_from'])->format('d-m-Y'),
|
||||
'%date_to%' => $this->rollingDateConverter->convert($data['date_to'])->format('d-m-Y'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
@ -13,52 +13,41 @@ namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function count;
|
||||
|
||||
class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelperInterface $translatableStringHelper,
|
||||
ActivityTypeRepository $activityTypeRepository
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$where = $qb->getDQLPart('where');
|
||||
$clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
$where->add($clause);
|
||||
} else {
|
||||
$where = $qb->expr()->andX($clause);
|
||||
}
|
||||
|
||||
$qb->add('where', $where);
|
||||
$qb->andWhere($clause);
|
||||
$qb->setParameter('selected_activity_types', $data['types']);
|
||||
}
|
||||
|
||||
@ -70,11 +59,26 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('types', EntityType::class, [
|
||||
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||
'class' => ActivityType::class,
|
||||
'choice_label' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getName()),
|
||||
'group_by' => fn (ActivityType $type) => $this->translatableStringHelper->localize($type->getCategory()->getName()),
|
||||
'choice_label' => function (ActivityType $aty) {
|
||||
return
|
||||
($aty->hasCategory() ? $this->translatableStringHelper->localize($aty->getCategory()->getName()) . ' > ' : '')
|
||||
.
|
||||
$this->translatableStringHelper->localize($aty->getName());
|
||||
},
|
||||
'group_by' => function (ActivityType $type) {
|
||||
if (!$type->hasCategory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->translatableStringHelper->localize($type->getCategory()->getName());
|
||||
},
|
||||
'multiple' => true,
|
||||
'expanded' => false,
|
||||
'attr' => [
|
||||
'class' => 'select2',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@ -87,7 +91,7 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
);
|
||||
|
||||
return ['Filtered by activity type: only %list%', [
|
||||
'%list%' => implode(', ou ', $reasonsNames),
|
||||
'%list%' => implode(', ', $reasonsNames),
|
||||
]];
|
||||
}
|
||||
|
||||
@ -104,23 +108,4 @@ class ActivityTypeFilter implements ExportElementValidatedInterface, FilterInter
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and Reason is already defined.
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @param mixed $alias
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias)
|
||||
{
|
||||
foreach ($joins as $join) {
|
||||
if ($join->getAlias() === $alias) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ActivityUsersFilter implements FilterInterface
|
||||
{
|
||||
private UserRender $userRender;
|
||||
|
||||
public function __construct(UserRender $userRender)
|
||||
{
|
||||
$this->userRender = $userRender;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$orX = $qb->expr()->orX();
|
||||
|
||||
foreach ($data['accepted_users'] as $key => $user) {
|
||||
$orX->add($qb->expr()->isMemberOf(':activity_users_filter_u' . $key, 'activity.users'));
|
||||
$qb->setParameter('activity_users_filter_u' . $key, $user);
|
||||
}
|
||||
|
||||
$qb->andWhere($orX);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('accepted_users', PickUserDynamicType::class, [
|
||||
'multiple' => true,
|
||||
'label' => 'Users',
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
$users = [];
|
||||
|
||||
foreach ($data['accepted_users'] as $u) {
|
||||
$users[] = $this->userRender->renderString($u, []);
|
||||
}
|
||||
|
||||
return ['Filtered activity by users: only %users%', [
|
||||
'%users%' => implode(', ', $users),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle(): string
|
||||
{
|
||||
return 'Filter activity by users';
|
||||
}
|
||||
}
|
@ -14,21 +14,18 @@ namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\Query\Expr;
|
||||
use Doctrine\ORM\Query\Expr\Join;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function in_array;
|
||||
|
||||
class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInterface
|
||||
{
|
||||
@ -44,9 +41,9 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
$this->activityReasonRepository = $activityReasonRepository;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return new Role(ActivityStatsVoter::STATS);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
@ -54,20 +51,9 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
$where = $qb->getDQLPart('where');
|
||||
$join = $qb->getDQLPart('join');
|
||||
$clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
|
||||
//dump($join);
|
||||
// add a join to reasons only if needed
|
||||
if (
|
||||
(
|
||||
array_key_exists('activity', $join)
|
||||
&& !$this->checkJoinAlreadyDefined($join['activity'], 'reasons')
|
||||
)
|
||||
|| (!array_key_exists('activity', $join))
|
||||
) {
|
||||
$qb->add(
|
||||
'join',
|
||||
['activity' => new Join(Join::INNER_JOIN, 'activity.reasons', 'reasons')],
|
||||
true
|
||||
);
|
||||
|
||||
if (!in_array('actreasons', $qb->getAllAliases(), true)) {
|
||||
$qb->join('activity.reasons', 'actreasons');
|
||||
}
|
||||
|
||||
if ($where instanceof Expr\Andx) {
|
||||
@ -125,21 +111,4 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a join between Activity and Reason is already defined.
|
||||
*
|
||||
* @param Join[] $joins
|
||||
* @param mixed $alias
|
||||
*/
|
||||
private function checkJoinAlreadyDefined(array $joins, $alias): bool
|
||||
{
|
||||
foreach ($joins as $join) {
|
||||
if ($join->getAlias() === $alias) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter\PersonFilters;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Entity\ActivityReason;
|
||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
|
||||
use Chill\MainBundle\Export\ExportElementValidatedInterface;
|
||||
@ -52,17 +53,17 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function addRole()
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
// create a query for activity
|
||||
// create a subquery for activity
|
||||
$sqb = $qb->getEntityManager()->createQueryBuilder();
|
||||
$sqb->select('person_person_having_activity.id')
|
||||
->from('ChillActivityBundle:Activity', 'activity_person_having_activity')
|
||||
->from(Activity::class, 'activity_person_having_activity')
|
||||
->join('activity_person_having_activity.person', 'person_person_having_activity');
|
||||
|
||||
// add clause between date
|
||||
@ -197,7 +198,7 @@ class PersonHavingActivityBetweenDateFilter implements ExportElementValidatedInt
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'Filtered by person having an activity in a period';
|
||||
return 'Filter by person having an activity in a period';
|
||||
}
|
||||
|
||||
public function validateForm($data, ExecutionContextInterface $context)
|
||||
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\UserJob;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UsersJobFilter implements FilterInterface
|
||||
{
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' activity_users_job_filter_act
|
||||
JOIN activity_users_job_filter_act.users users WHERE users.userJob IN (:activity_users_job_filter_jobs) AND activity_users_job_filter_act = activity '
|
||||
)
|
||||
)
|
||||
->setParameter('activity_users_job_filter_jobs', $data['jobs']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('jobs', EntityType::class, [
|
||||
'class' => UserJob::class,
|
||||
'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return ['export.filter.activity.by_usersjob.Filtered activity by users job: only %jobs%', [
|
||||
'%jobs%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
|
||||
$data['jobs']->toArray()
|
||||
)
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.filter.activity.by_usersjob.Filter by users job';
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Export\Filter;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Declarations;
|
||||
use Chill\MainBundle\Entity\Scope;
|
||||
use Chill\MainBundle\Export\FilterInterface;
|
||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class UsersScopeFilter implements FilterInterface
|
||||
{
|
||||
private ScopeRepositoryInterface $scopeRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
ScopeRepositoryInterface $scopeRepository,
|
||||
TranslatableStringHelperInterface $translatableStringHelper
|
||||
) {
|
||||
$this->scopeRepository = $scopeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function addRole(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function alterQuery(QueryBuilder $qb, $data)
|
||||
{
|
||||
$qb
|
||||
->andWhere(
|
||||
$qb->expr()->exists(
|
||||
'SELECT 1 FROM ' . Activity::class . ' activity_users_scope_filter_act
|
||||
JOIN activity_users_scope_filter_act.users users WHERE users.mainScope IN (:activity_users_scope_filter_scopes) AND activity_users_scope_filter_act = activity '
|
||||
)
|
||||
)
|
||||
->setParameter('activity_users_scope_filter_scopes', $data['scopes']);
|
||||
}
|
||||
|
||||
public function applyOn()
|
||||
{
|
||||
return Declarations::ACTIVITY;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder->add('scopes', EntityType::class, [
|
||||
'class' => Scope::class,
|
||||
'choices' => $this->scopeRepository->findAllActive(),
|
||||
'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function describeAction($data, $format = 'string')
|
||||
{
|
||||
return ['export.filter.activity.by_usersscope.Filtered activity by users scope: only %scopes%', [
|
||||
'%scopes%' => implode(
|
||||
', ',
|
||||
array_map(
|
||||
fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
|
||||
$data['scopes']->toArray()
|
||||
)
|
||||
),
|
||||
]];
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return 'export.filter.activity.by_usersscope.Filter by users scope';
|
||||
}
|
||||
}
|
@ -12,48 +12,33 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Form\Type;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepository;
|
||||
use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class TranslatableActivityType extends AbstractType
|
||||
{
|
||||
protected ActivityTypeRepository $activityTypeRepository;
|
||||
protected ActivityTypeRepositoryInterface $activityTypeRepository;
|
||||
|
||||
protected TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(
|
||||
TranslatableStringHelperInterface $helper,
|
||||
ActivityTypeRepository $activityTypeRepository
|
||||
ActivityTypeRepositoryInterface $activityTypeRepository
|
||||
) {
|
||||
$this->translatableStringHelper = $helper;
|
||||
$this->activityTypeRepository = $activityTypeRepository;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
/** @var QueryBuilder $qb */
|
||||
$qb = $options['query_builder'];
|
||||
|
||||
if (true === $options['active_only']) {
|
||||
$qb->where($qb->expr()->eq('at.active', ':active'));
|
||||
$qb->setParameter('active', true, Types::BOOLEAN);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'class' => ActivityType::class,
|
||||
'active_only' => true,
|
||||
'query_builder' => $this->activityTypeRepository
|
||||
->createQueryBuilder('at'),
|
||||
'choices' => $this->activityTypeRepository->findAllActive(),
|
||||
'choice_label' => function (ActivityType $type) {
|
||||
return $this->translatableStringHelper->localize($type->getName());
|
||||
},
|
||||
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityPresence;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class ActivityPresenceRepository implements ActivityPresenceRepositoryInterface
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository($this->getClassName());
|
||||
}
|
||||
|
||||
public function find($id): ?ActivityPresence
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||
{
|
||||
return $this->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?ActivityPresence
|
||||
{
|
||||
return $this->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return ActivityPresence::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityPresence;
|
||||
|
||||
interface ActivityPresenceRepositoryInterface
|
||||
{
|
||||
public function find($id): ?ActivityPresence;
|
||||
|
||||
/**
|
||||
* @return array|ActivityPresence[]
|
||||
*/
|
||||
public function findAll(): array;
|
||||
|
||||
/**
|
||||
* @return array|ActivityPresence[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
|
||||
|
||||
public function findOneBy(array $criteria): ?ActivityPresence;
|
||||
|
||||
public function getClassName(): string;
|
||||
}
|
@ -12,19 +12,54 @@ declare(strict_types=1);
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
/**
|
||||
* @method ActivityType|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method ActivityType|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method ActivityType[] findAll()
|
||||
* @method ActivityType[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ActivityTypeRepository extends ServiceEntityRepository
|
||||
final class ActivityTypeRepository implements ActivityTypeRepositoryInterface
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
{
|
||||
parent::__construct($registry, ActivityType::class);
|
||||
$this->repository = $em->getRepository(ActivityType::class);
|
||||
}
|
||||
|
||||
public function find($id): ?ActivityType
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|ActivityType[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|ActivityType[]
|
||||
*/
|
||||
public function findAllActive(): array
|
||||
{
|
||||
return $this->findBy(['active' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|ActivityType[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?ActivityType
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return ActivityType::class;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Repository;
|
||||
|
||||
use Chill\ActivityBundle\Entity\ActivityType;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
interface ActivityTypeRepositoryInterface extends ObjectRepository
|
||||
{
|
||||
/**
|
||||
* @return array|ActivityType[]
|
||||
*/
|
||||
public function findAllActive(): array;
|
||||
}
|
@ -35,6 +35,13 @@ const getLocationTypeByDefaultFor = (entity) => {
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Post a location
|
||||
*
|
||||
* **NOTE**: also in use for Calendar
|
||||
* @param body
|
||||
* @returns {Promise<T>}
|
||||
*/
|
||||
const postLocation = (body) => {
|
||||
const url = `/api/1.0/main/location.json`;
|
||||
return fetch(url, {
|
||||
|
@ -58,7 +58,7 @@ const makeAccompanyingPeriodLocation = (locationType, store) => {
|
||||
|
||||
export default function prepareLocations(store) {
|
||||
|
||||
// find the locations
|
||||
// find the locations
|
||||
let allLocations = getLocations().then(
|
||||
(results) => {
|
||||
store.commit('addAvailableLocationGroup', {
|
||||
@ -114,7 +114,7 @@ export default function prepareLocations(store) {
|
||||
if (window.default_location_id) {
|
||||
for (let group of store.state.availableLocations) {
|
||||
let location = group.locations.find((l) => l.id === window.default_location_id);
|
||||
if (location !== undefined & store.state.activity.location === null) {
|
||||
if (location !== undefined && store.state.activity.location === null) {
|
||||
store.dispatch('updateLocation', location);
|
||||
break;
|
||||
}
|
||||
|
@ -1,3 +1,14 @@
|
||||
{#
|
||||
WARNING: this file is in use in both ActivityBundle and CalendarBundle.
|
||||
|
||||
Take care when editing this file.
|
||||
|
||||
Maybe should we think about abstracting this file a bit more ? Moving it to PersonBundle ?
|
||||
#}
|
||||
{% if context == 'calendar_accompanyingCourse' %}
|
||||
{% import "@ChillCalendar/_invite.html.twig" as invite %}
|
||||
{% endif %}
|
||||
|
||||
{% macro href(pathname, key, value) %}
|
||||
{% set parms = { (key): value } %}
|
||||
{{ path(pathname, parms) }}
|
||||
@ -18,7 +29,7 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% set blocks = [] %}
|
||||
{% if entity.activityType.personsVisible %}
|
||||
{% if context == 'calendar_accompanyingCourse' or context == 'calendar_person' or entity.activityType.personsVisible %}
|
||||
{% if context == 'person' %}
|
||||
{% set blocks = blocks|merge([{
|
||||
'title': 'Others persons'|trans,
|
||||
@ -43,7 +54,7 @@
|
||||
}]) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if entity.activityType.thirdPartiesVisible %}
|
||||
{% if context == 'calendar_accompanyingCourse' or context == 'calendar_person' or entity.activityType.thirdPartiesVisible %}
|
||||
{% set blocks = blocks|merge([{
|
||||
'title': 'Third parties'|trans,
|
||||
'items': entity.thirdParties,
|
||||
@ -52,7 +63,7 @@
|
||||
'key' : 'id',
|
||||
}]) %}
|
||||
{% endif %}
|
||||
{% if entity.activityType.usersVisible %}
|
||||
{% if context == 'calendar_accompanyingCourse' or context == 'calendar_person' or entity.activityType.usersVisible %}
|
||||
{% set blocks = blocks|merge([{
|
||||
'title': 'Users concerned'|trans,
|
||||
'items': entity.users,
|
||||
@ -132,6 +143,12 @@
|
||||
{% if bloc.type == 'user' %}
|
||||
<span class="badge-user">
|
||||
{{ item|chill_entity_render_box({'render': 'raw', 'addAltNames': false }) }}
|
||||
{%- if context == 'calendar_accompanyingCourse' or context == 'calendar_person' %}
|
||||
{% set invite = entity.inviteForUser(item) %}
|
||||
{% if invite is not null %}
|
||||
{{ invite.invite_span(invite) }}
|
||||
{% endif %}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{% else %}
|
||||
{{ _self.insert_onthefly(bloc.type, item) }}
|
||||
|
@ -13,10 +13,10 @@ namespace Chill\ActivityBundle\Security\Authorization;
|
||||
|
||||
use Chill\MainBundle\Entity\Center;
|
||||
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
|
||||
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperFactoryInterface;
|
||||
use Chill\MainBundle\Security\Authorization\VoterHelperInterface;
|
||||
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
|
||||
|
||||
use function in_array;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
|
||||
class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||
{
|
||||
@ -24,14 +24,14 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
|
||||
|
||||
public const STATS = 'CHILL_ACTIVITY_STATS';
|
||||
|
||||
/**
|
||||
* @var AuthorizationHelper
|
||||
*/
|
||||
protected $helper;
|
||||
protected VoterHelperInterface $helper;
|
||||
|
||||
public function __construct(AuthorizationHelper $helper)
|
||||
public function __construct(VoterHelperFactoryInterface $voterHelperFactory)
|
||||
{
|
||||
$this->helper = $helper;
|
||||
$this->helper = $voterHelperFactory
|
||||
->generate(self::class)
|
||||
->addCheckFor(Center::class, [self::STATS, self::LISTS])
|
||||
->build();
|
||||
}
|
||||
|
||||
public function getRoles(): array
|
||||
@ -49,30 +49,14 @@ class ActivityStatsVoter extends AbstractChillVoter implements ProvideRoleHierar
|
||||
return $this->getAttributes();
|
||||
}
|
||||
|
||||
protected function getSupportedClasses()
|
||||
{
|
||||
return [Center::class];
|
||||
}
|
||||
|
||||
protected function isGranted($attribute, $object, $user = null)
|
||||
{
|
||||
if (!$user instanceof \Symfony\Component\Security\Core\User\UserInterface) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->helper->userHasAccess($user, $object, $attribute);
|
||||
}
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
if (
|
||||
$subject instanceof Center
|
||||
&& in_array($attribute, $this->getAttributes(), true)
|
||||
) {
|
||||
return true;
|
||||
return $this->helper->supports($attribute, $subject);
|
||||
}
|
||||
|
||||
return false;
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||
{
|
||||
return $this->helper->voteOnAttribute($attribute, $subject, $token);
|
||||
}
|
||||
|
||||
private function getAttributes()
|
||||
|
@ -369,8 +369,12 @@ final class ActivityControllerTest extends WebTestCase
|
||||
$center
|
||||
);
|
||||
$reachableScopesId = array_intersect(
|
||||
array_map(static function ($s) { return $s->getId(); }, $reachableScopesDelete),
|
||||
array_map(static function ($s) { return $s->getId(); }, $reachableScopesUpdate)
|
||||
array_map(static function ($s) {
|
||||
return $s->getId();
|
||||
}, $reachableScopesDelete),
|
||||
array_map(static function ($s) {
|
||||
return $s->getId();
|
||||
}, $reachableScopesUpdate)
|
||||
);
|
||||
|
||||
if (count($reachableScopesId) === 0) {
|
||||
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialActionAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class BySocialActionAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private BySocialActionAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.bysocialaction_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.socialActions', 'actsocialaction'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\BySocialIssueAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class BySocialIssueAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private BySocialIssueAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.bysocialissue_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.socialIssues', 'actsocialissue'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByThirdpartyAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class ByThirdpartyAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private ByThirdpartyAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.bythirdparty_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.thirdParties', 'acttparty'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\ByCreatorAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class ByUserAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private ByCreatorAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.byuser_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.users', 'actusers'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\DateAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class DateAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private DateAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.date_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'frequency' => 'month',
|
||||
],
|
||||
[
|
||||
'frequency' => 'week',
|
||||
],
|
||||
[
|
||||
'frequency' => 'year',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\LocationTypeAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class LocationTypeAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private LocationTypeAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.locationtype_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.location', 'actloc'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator\ACPAggregators;
|
||||
|
||||
use Chill\ActivityBundle\Entity\Activity;
|
||||
use Chill\ActivityBundle\Export\Aggregator\ACPAggregators\CreatorScopeAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class UserScopeAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
private CreatorScopeAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->aggregator = self::$container->get('chill.activity.export.userscope_aggregator');
|
||||
}
|
||||
|
||||
public function getAggregator()
|
||||
{
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from(Activity::class, 'activity')
|
||||
->join('activity.accompanyingPeriod', 'acp')
|
||||
->join('activity.user', 'actuser'),
|
||||
];
|
||||
}
|
||||
}
|
@ -11,7 +11,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Aggregator\ActivityTypeAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* Add tests for ActivityTypeAggregator.
|
||||
@ -21,26 +24,22 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
*/
|
||||
final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
/**
|
||||
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityReasonAggregator
|
||||
*/
|
||||
private $aggregator;
|
||||
use ProphecyTrait;
|
||||
|
||||
private ActivityTypeAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
$this->aggregator = self::$container->get('chill.activity.export.type_aggregator');
|
||||
|
||||
$this->aggregator = $container->get('chill.activity.export.type_aggregator');
|
||||
$request = $this->prophesize()
|
||||
->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
|
||||
// add a fake request with a default locale (used in translatable string)
|
||||
$prophet = new \Prophecy\Prophet();
|
||||
$request = $prophet->prophesize();
|
||||
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
$request->getLocale()->willReturn('fr');
|
||||
|
||||
$container->get('request_stack')
|
||||
self::$container->get('request_stack')
|
||||
->push($request->reveal());
|
||||
}
|
||||
|
||||
@ -62,8 +61,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$kernel->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
@ -72,12 +70,7 @@ final class ActivityTypeAggregatorTest extends AbstractAggregatorTest
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.reasons', 'reasons'),
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.reasons', 'reasons')
|
||||
->join('reasons.category', 'category'),
|
||||
->join('activity.activityType', 'acttype'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\ActivityBundle\Tests\Export\Aggregator;
|
||||
|
||||
use Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator;
|
||||
use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Prophecy\PhpUnit\ProphecyTrait;
|
||||
|
||||
/**
|
||||
* Add tests for ActivityUsernAggregator.
|
||||
@ -21,26 +24,22 @@ use Chill\MainBundle\Test\Export\AbstractAggregatorTest;
|
||||
*/
|
||||
final class ActivityUserAggregatorTest extends AbstractAggregatorTest
|
||||
{
|
||||
/**
|
||||
* @var \Chill\ActivityBundle\Export\Aggregator\ActivityUserAggregator
|
||||
*/
|
||||
private $aggregator;
|
||||
use ProphecyTrait;
|
||||
|
||||
private ActivityUserAggregator $aggregator;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
$this->aggregator = self::$container->get('chill.activity.export.user_aggregator');
|
||||
|
||||
$this->aggregator = $container->get('chill.activity.export.user_aggregator');
|
||||
$request = $this->prophesize()
|
||||
->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
|
||||
// add a fake request with a default locale (used in translatable string)
|
||||
$prophet = new \Prophecy\Prophet();
|
||||
$request = $prophet->prophesize();
|
||||
$request->willExtend(\Symfony\Component\HttpFoundation\Request::class);
|
||||
$request->getLocale()->willReturn('fr');
|
||||
|
||||
$container->get('request_stack')
|
||||
self::$container->get('request_stack')
|
||||
->push($request->reveal());
|
||||
}
|
||||
|
||||
@ -49,35 +48,25 @@ final class ActivityUserAggregatorTest extends AbstractAggregatorTest
|
||||
return $this->aggregator;
|
||||
}
|
||||
|
||||
public function getFormData()
|
||||
public function getFormData(): array
|
||||
{
|
||||
return [
|
||||
[],
|
||||
];
|
||||
}
|
||||
|
||||
public function getQueryBuilders()
|
||||
public function getQueryBuilders(): array
|
||||
{
|
||||
if (null === self::$kernel) {
|
||||
self::bootKernel();
|
||||
}
|
||||
|
||||
$em = self::$kernel->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
$em = self::$container->get(EntityManagerInterface::class);
|
||||
|
||||
return [
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from('ChillActivityBundle:Activity', 'activity'),
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.reasons', 'reasons'),
|
||||
$em->createQueryBuilder()
|
||||
->select('count(activity.id)')
|
||||
->from('ChillActivityBundle:Activity', 'activity')
|
||||
->join('activity.reasons', 'reasons')
|
||||
->join('reasons.category', 'category'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|