Merge remote-tracking branch 'origin/master' into rector/rules-up-to-php80

Conflicts:
	src/Bundle/ChillActivityBundle/Controller/ActivityController.php
	src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php
	src/Bundle/ChillActivityBundle/Menu/PersonMenuBuilder.php
	src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
	src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php
	src/Bundle/ChillCalendarBundle/Command/MapAndSubscribeUserCalendarCommand.php
	src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSGraphUserRepository.php
	src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
	src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
	src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
	src/Bundle/ChillEventBundle/Search/EventSearch.php
	src/Bundle/ChillMainBundle/Controller/ExportController.php
	src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php
	src/Bundle/ChillMainBundle/Cron/CronManager.php
	src/Bundle/ChillMainBundle/Entity/CronJobExecution.php
	src/Bundle/ChillMainBundle/Export/ExportManager.php
	src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
	src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php
	src/Bundle/ChillMainBundle/Repository/NotificationRepository.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php
	src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php
	src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php
	src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php
	src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php
	src/Bundle/ChillPersonBundle/Export/Export/ListHouseholdInPeriod.php
	src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
	src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php
	src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
	src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php
This commit is contained in:
2023-07-17 12:49:13 +02:00
544 changed files with 18622 additions and 2105 deletions

View File

@@ -26,6 +26,7 @@ use Chill\TaskBundle\Event\TaskEvent;
use Chill\TaskBundle\Event\UI\UIEvent;
use Chill\TaskBundle\Form\SingleTaskType;
use Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface;
use Chill\TaskBundle\Repository\SingleTaskStateRepository;
use Chill\TaskBundle\Security\Authorization\TaskVoter;
use LogicException;
use Psr\Log\LoggerInterface;
@@ -47,8 +48,41 @@ use function array_merge;
final class SingleTaskController extends AbstractController
{
public function __construct(private CenterResolverDispatcherInterface $centerResolverDispatcher, private PaginatorFactory $paginatorFactory, private SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository, private TranslatorInterface $translator, private EventDispatcherInterface $eventDispatcher, private TimelineBuilder $timelineBuilder, private LoggerInterface $logger, private FilterOrderHelperFactoryInterface $filterOrderHelperFactory)
{
private CenterResolverDispatcherInterface $centerResolverDispatcher;
private EventDispatcherInterface $eventDispatcher;
private FilterOrderHelperFactoryInterface $filterOrderHelperFactory;
private LoggerInterface $logger;
private PaginatorFactory $paginatorFactory;
private SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository;
private TimelineBuilder $timelineBuilder;
private TranslatorInterface $translator;
public function __construct(
CenterResolverDispatcherInterface $centerResolverDispatcher,
PaginatorFactory $paginatorFactory,
SingleTaskAclAwareRepositoryInterface $singleTaskAclAwareRepository,
TranslatorInterface $translator,
EventDispatcherInterface $eventDispatcher,
TimelineBuilder $timelineBuilder,
LoggerInterface $logger,
FilterOrderHelperFactoryInterface $filterOrderHelperFactory,
private SingleTaskStateRepository $singleTaskStateRepository
) {
$this->eventDispatcher = $eventDispatcher;
$this->timelineBuilder = $timelineBuilder;
$this->logger = $logger;
$this->translator = $translator;
$this->centerResolverDispatcher = $centerResolverDispatcher;
$this->paginatorFactory = $paginatorFactory;
$this->singleTaskAclAwareRepository = $singleTaskAclAwareRepository;
$this->filterOrderHelperFactory = $filterOrderHelperFactory;
}
/**
@@ -56,8 +90,10 @@ final class SingleTaskController extends AbstractController
* "/{_locale}/task/single-task/{id}/delete",
* name="chill_task_single_task_delete"
* )
*
* @param mixed $id
*/
public function deleteAction(Request $request, mixed $id)
public function deleteAction(Request $request, $id)
{
$course = null;
$em = $this->getDoctrine()->getManager();
@@ -265,13 +301,17 @@ final class SingleTaskController extends AbstractController
$this->denyAccessUnlessGranted(TaskVoter::SHOW, null);
$filterOrder = $this->buildFilterOrder();
$filteredUsers = $filterOrder->getUserPickerData('userPicker');
$flags = array_merge(
$filterOrder->getCheckboxData('status'),
array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
array_map(static fn ($i) => 'state_' . $i, $filterOrder->hasCheckboxData('states') ? $filterOrder->getCheckboxData('states') : [])
);
$nb = $this->singleTaskAclAwareRepository->countByAllViewable(
$filterOrder->getQueryString(),
$flags
$flags,
$filteredUsers
);
$paginator = $this->paginatorFactory->create($nb);
@@ -279,6 +319,7 @@ final class SingleTaskController extends AbstractController
$tasks = $this->singleTaskAclAwareRepository->findByAllViewable(
$filterOrder->getQueryString(),
$flags,
$filteredUsers,
$paginator->getCurrentPageFirstItemNumber(),
$paginator->getItemsPerPage(),
[
@@ -312,7 +353,7 @@ final class SingleTaskController extends AbstractController
$filterOrder = $this->buildFilterOrder();
$flags = array_merge(
$filterOrder->getCheckboxData('status'),
array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
array_map(static fn ($i) => 'state_' . $i, $filterOrder->hasCheckboxData('states') ? $filterOrder->getCheckboxData('states') : [])
);
$nb = $this->singleTaskAclAwareRepository->countByCourse(
$course,
@@ -361,7 +402,7 @@ final class SingleTaskController extends AbstractController
$filterOrder = $this->buildFilterOrder();
$flags = array_merge(
$filterOrder->getCheckboxData('status'),
array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
array_map(static fn ($i) => 'state_' . $i, $filterOrder->hasCheckboxData('states') ? $filterOrder->getCheckboxData('states') : [])
);
$nb = $this->singleTaskAclAwareRepository->countByPerson(
$person,
@@ -413,10 +454,10 @@ final class SingleTaskController extends AbstractController
{
$this->denyAccessUnlessGranted('ROLE_USER');
$filterOrder = $this->buildFilterOrder();
$filterOrder = $this->buildFilterOrder(false);
$flags = array_merge(
$filterOrder->getCheckboxData('status'),
array_map(static fn ($i) => 'state_' . $i, $filterOrder->getCheckboxData('states'))
array_map(static fn ($i) => 'state_' . $i, $filterOrder->hasCheckboxData('states') ? $filterOrder->getCheckboxData('states') : [])
);
$nb = $this->singleTaskAclAwareRepository->countByCurrentUsersTasks(
$filterOrder->getQueryString(),
@@ -559,19 +600,24 @@ final class SingleTaskController extends AbstractController
}
}
return match ($entityType) {
'person' => $this->render('@ChillTask/SingleTask/Person/new.html.twig', [
'form' => $form->createView(),
'task' => $task,
'person' => $task->getPerson(),
]),
'course' => $this->render('@ChillTask/SingleTask/AccompanyingCourse/new.html.twig', [
'form' => $form->createView(),
'task' => $task,
'accompanyingCourse' => $task->getCourse(),
]),
default => throw new LogicException('entity context not supported'),
};
switch ($entityType) {
case 'person':
return $this->render('@ChillTask/SingleTask/Person/new.html.twig', [
'form' => $form->createView(),
'task' => $task,
'person' => $task->getPerson(),
]);
case 'course':
return $this->render('@ChillTask/SingleTask/AccompanyingCourse/new.html.twig', [
'form' => $form->createView(),
'task' => $task,
'accompanyingCourse' => $task->getCourse(),
]);
default:
throw new LogicException('entity context not supported');
}
}
/**
@@ -623,7 +669,7 @@ final class SingleTaskController extends AbstractController
return $form;
}
private function buildFilterOrder(): FilterOrderHelper
private function buildFilterOrder($includeFilterByUser = true): FilterOrderHelper
{
$statuses = ['no-alert', 'warning', 'alert'];
$statusTrans = [
@@ -631,23 +677,33 @@ final class SingleTaskController extends AbstractController
'Tasks near deadline',
'Tasks over deadline',
];
$states = [
// todo: get a list of possible states dynamically
'new', 'in_progress', 'closed', 'canceled',
];
return $this->filterOrderHelperFactory
$filterBuilder = $this->filterOrderHelperFactory
->create(self::class)
->addSearchBox()
->addCheckbox('status', $statuses, $statuses, $statusTrans)
->addCheckbox('states', $states, ['new', 'in_progress'])
->build();
->addCheckbox('status', $statuses, $statuses, $statusTrans);
$states = $this->singleTaskStateRepository->findAllExistingStates();
$checked = array_values(array_filter($states, fn (string $state) => !in_array($state, ['closed', 'canceled', 'validated'], true)));
if ([] !== $states) {
$filterBuilder
->addCheckbox('states', $states, $checked);
}
if ($includeFilterByUser) {
$filterBuilder
->addUserPicker('userPicker', 'Filter by user', ['multiple' => true, 'required' => false]);
}
return $filterBuilder->build();
}
/**
* Creates a form to delete a Task entity by id.
* @param mixed $id
*/
private function createDeleteForm(mixed $id): FormInterface
private function createDeleteForm($id): FormInterface
{
return $this->createFormBuilder()
->setAction($this->generateUrl(

View File

@@ -35,18 +35,37 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
public function buildBaseQuery(
?string $pattern = null,
?array $flags = []
?array $flags = [],
?array $users = []
): QueryBuilder {
$qb = $this->em->createQueryBuilder();
$qb
->from(SingleTask::class, 't');
if (!empty($pattern)) {
if (null !== $pattern && '' !== $pattern) {
$qb->andWhere($qb->expr()->like('LOWER(UNACCENT(t.title))', 'LOWER(UNACCENT(:pattern))'))
->setParameter('pattern', '%' . $pattern . '%');
}
if (count($flags) > 0) {
if (null !== $users && count($users) > 0) {
$orXUser = $qb->expr()->orX();
foreach ($users as $key => $user) {
$orXUser->add(
$qb->expr()->eq('t.assignee', ':user_' . $key)
);
$qb->setParameter('user_' . $key, $user);
}
if ($orXUser->count() > 0) {
$qb->andWhere($orXUser);
}
return $qb;
}
if (null !== $flags && count($flags) > 0) {
$orXDate = $qb->expr()->orX();
$orXState = $qb->expr()->orX();
$now = new DateTime();
@@ -167,9 +186,10 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
public function countByAllViewable(
?string $pattern = null,
?array $flags = []
?array $flags = [],
?array $users = []
): int {
$qb = $this->buildBaseQuery($pattern, $flags);
$qb = $this->buildBaseQuery($pattern, $flags, $users);
return $this
->addACLGlobal($qb)
@@ -215,11 +235,12 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
public function findByAllViewable(
?string $pattern = null,
?array $flags = [],
?array $users = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []
): array {
$qb = $this->buildBaseQuery($pattern, $flags);
$qb = $this->buildBaseQuery($pattern, $flags, $users);
$qb = $this->addACLGlobal($qb);
return $this->getResult($qb, $start, $limit, $orderBy);

View File

@@ -18,7 +18,8 @@ interface SingleTaskAclAwareRepositoryInterface
{
public function countByAllViewable(
?string $pattern = null,
?array $flags = []
?array $flags = [],
?array $users = []
): int;
public function countByCourse(
@@ -38,6 +39,7 @@ interface SingleTaskAclAwareRepositoryInterface
public function findByAllViewable(
?string $pattern = null,
?array $flags = [],
?array $users = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []

View File

@@ -0,0 +1,47 @@
<?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\TaskBundle\Repository;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
class SingleTaskStateRepository
{
private const FIND_ALL_STATES = <<<'SQL'
SELECT DISTINCT jsonb_array_elements_text(current_states) FROM chill_task.single_task
SQL;
public function __construct(
private Connection $connection
) {
}
/**
* Return a list of all states associated to at least one single task in the database
*
* @return list<string>
* @throws Exception
*/
public function findAllExistingStates(): array
{
$states = [];
foreach ($this->connection->fetchAllNumeric(self::FIND_ALL_STATES) as $row) {
if ('' !== $row[0] && null !== $row[0]) {
$states[] = $row[0];
}
}
return $states;
}
}

View File

@@ -27,8 +27,10 @@
{% block css %}
{{ parent() }}
{{ encore_entry_link_tags('page_task_list') }}
{{ encore_entry_link_tags('mod_pickentity_type') }}
{% endblock %}
{% block js %}
{{ parent() }}
{{ encore_entry_script_tags('page_task_list') }}
{{ encore_entry_script_tags('mod_pickentity_type') }}
{% endblock %}

View File

@@ -1,4 +1,8 @@
services:
_defaults:
autowire: true
autoconfigure: true
chill_task.single_task_repository:
class: Chill\TaskBundle\Repository\SingleTaskRepository
factory: ['@doctrine.orm.entity_manager', getRepository]
@@ -10,8 +14,8 @@ services:
- "@chill.main.security.authorization.helper"
Chill\TaskBundle\Repository\SingleTaskRepository: '@chill_task.single_task_repository'
Chill\TaskBundle\Repository\SingleTaskAclAwareRepository:
autowire: true
autoconfigure: true
Chill\TaskBundle\Repository\SingleTaskAclAwareRepository: ~
Chill\TaskBundle\Repository\SingleTaskAclAwareRepositoryInterface: '@Chill\TaskBundle\Repository\SingleTaskAclAwareRepository'
Chill\TaskBundle\Repository\SingleTaskStateRepository: ~

View File

@@ -65,6 +65,7 @@ Not assigned: Aucun utilisateur assigné
For person: Pour
By: Par
Any tasks: Aucune tâche
Filter by user: Filtrer par utilisateur(s)
# transitions - default task definition
"new": "nouvelle"