rewrite task list action

This commit is contained in:
Julien Fastré 2021-10-30 00:41:28 +02:00
parent c63b1015e1
commit e0cb5a88bd
4 changed files with 123 additions and 203 deletions

View File

@ -126,6 +126,7 @@ final class SingleTaskController extends AbstractController
} }
$task->setPerson($person); $task->setPerson($person);
$role = TaskVoter::CREATE_PERSON;
break; break;
case 'course': case 'course':
$course = $this->getDoctrine()->getManager() $course = $this->getDoctrine()->getManager()
@ -137,15 +138,16 @@ final class SingleTaskController extends AbstractController
} }
$task->setCourse($course); $task->setCourse($course);
$role = TaskVoter::CREATE_COURSE;
break; break;
default: default:
return new BadRequestHttpException("context with {$entityType} is not supported"); return new BadRequestHttpException("context with {$entityType} is not supported");
} }
$this->denyAccessUnlessGranted(TaskVoter::CREATE, $task, 'You are not ' $this->denyAccessUnlessGranted($role, $task, 'You are not '
. 'allowed to create this task'); . 'allowed to create this task');
$form = $this->setCreateForm($task, new Role(TaskVoter::CREATE)); $form = $this->setCreateForm($task, new Role($role));
$form->handleRequest($request); $form->handleRequest($request);
@ -266,8 +268,8 @@ final class SingleTaskController extends AbstractController
$this->addFlash('success', $this->translator $this->addFlash('success', $this->translator
->trans("The task has been updated")); ->trans("The task has been updated"));
if ($person = $task->getContext() instanceof Person) { if ($task->getContext() instanceof Person) {
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($task->getPerson(), array(
'element_class' => SingleTask::class, 'element_class' => SingleTask::class,
'element_id' => $task->getId(), 'element_id' => $task->getId(),
'action' => 'update' 'action' => 'update'
@ -301,8 +303,8 @@ final class SingleTaskController extends AbstractController
return $event->getResponse(); return $event->getResponse();
} }
if ($person = $task->getContext() instanceof Person) { if ($task->getContext() instanceof Person) {
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($task->getPerson(), array(
'element_class' => SingleTask::class, 'element_class' => SingleTask::class,
'element_id' => $task->getId(), 'element_id' => $task->getId(),
'action' => 'edit' 'action' => 'edit'
@ -511,7 +513,7 @@ final class SingleTaskController extends AbstractController
* Arguments: * Arguments:
* - user_id * - user_id
* - scope_id * - scope_id
* - course_id * - s
* - person_id * - person_id
* - hide_form (hide the form to filter the tasks) * - hide_form (hide the form to filter the tasks)
* - status: date state, amongst SingleTaskRepository::DATE_STATUSES, or 'closed' * - status: date state, amongst SingleTaskRepository::DATE_STATUSES, or 'closed'
@ -522,212 +524,44 @@ final class SingleTaskController extends AbstractController
* ) * )
*/ */
public function listAction( public function listAction(
PaginatorFactory $paginatorFactory,
SingleTaskRepository $taskRepository,
PersonRepository $personRepository,
AccompanyingPeriodRepository $courseRepository,
CenterRepository $centerRepository,
FormFactoryInterface $formFactory,
Request $request Request $request
) { ) {
/* @var $viewParams array The parameters for the view */ $this->denyAccessUnlessGranted(TaskVoter::SHOW, null);
/* @var $params array The parameters for the query */
$viewParams['person'] = null; $filterOrder = $this->buildFilterOrder();
$params['person'] = null; $flags = \array_merge(
$viewParams['user'] = null; $filterOrder->getCheckboxData('status'),
$params['user'] = null; \array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states'))
$viewParams['center'] = null; );
$params['types'] = null; $nb = $this->singleTaskAclAwareRepository->countByAllViewable(
$viewParams['accompanyingCourse'] = null; $filterOrder->getQueryString(),
$params['accompanyingCourse'] = null; $flags
);
$paginator = $this->paginatorFactory->create($nb);
if (!empty($request->query->get('person_id', NULL))) { if (0 < $nb) {
$tasks = $this->singleTaskAclAwareRepository->findByAllViewable(
$personId = $request->query->getInt('person_id', 0); $filterOrder->getQueryString(),
$person = $personRepository->find($personId); $flags,
$paginator->getCurrentPageFirstItemNumber(),
if ($person === null) { $paginator->getItemsPerPage(),
throw $this->createNotFoundException("This person ' $personId ' does not exist."); [
} 'startDate' => 'DESC',
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person); 'endDate' => 'DESC',
]
$viewParams['person'] = $person; );
$params['person'] = $person;
}
if (!empty($request->query->get('course_id', NULL))) {
$courseId = $request->query->getInt('course_id', 0);
$course = $courseRepository->find($courseId);
if ($course === null) {
throw $this->createNotFoundException("This accompanying course ' $courseId ' does not exist.");
}
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $course);
$viewParams['accompanyingCourse'] = $course;
$params['accompanyingCourse'] = $course;
}
if (!empty($request->query->get('center_id', NULL))) {
$center = $centerRepository->find($request->query->getInt('center_id'));
if ($center === null) {
throw $this->createNotFoundException('center not found');
}
$params['center'] = $center;
}
if(!empty($request->query->get('types', []))) {
$types = $request->query->get('types', []);
if (count($types) > 0) {
$params['types'] = $types;
}
}
if (!empty($request->query->get('user_id', null))) {
if ($request->query->get('user_id') === '_unassigned') {
$params['unassigned'] = true;
} else {
$userId = $request->query->getInt('user_id', 0);
$user = $this->getDoctrine()->getManager()
->getRepository(User::class)
->find($userId);
if ($user === null) {
throw $this->createNotFoundException("This user ' $userId ' does not exist.");
}
$viewParams['user'] = $user;
$params['user'] = $user;
}
}
if (!empty($request->query->get('scope_id'))) {
$scopeId = $request->query->getInt('scope_id', 0);
$scope = $this->getDoctrine()->getManager()
->getRepository(Scope::class)
->find($scopeId);
if ($scope === null) {
throw $this->createNotFoundException("This scope' $scopeId 'does not exist.");
}
$viewParams['scope'] = $scope;
$params['scope'] = $scope;
}
$possibleStatuses = \array_merge(SingleTaskRepository::DATE_STATUSES, [ 'closed' ]);
$statuses = $request->query->get('status', $possibleStatuses);
$diff = \array_diff($statuses, $possibleStatuses);
if (count($diff) > 0) {
return new Response(
'date_status not allowed: '. \implode(', ', $diff),
Response::HTTP_BAD_REQUEST
);
}
$viewParams['isSingleStatus'] = $singleStatus = count($statuses) === 1;
$tasks_count = 0;
foreach($statuses as $status) {
if($request->query->has('status')
&& FALSE === \in_array($status, $statuses)) {
continue;
}
if (in_array($status, SingleTaskRepository::DATE_STATUSES)) {
$params['date_status'] = $status;
$params['is_closed'] = false;
} else {
$params['date_status'] = null;
$params['is_closed'] = true;
}
$count = $taskRepository
->countByParameters($params, $this->getUser())
;
$paginator = $paginatorFactory->create($count);
$viewParams['single_task_'.$status.'_count'] = $count;
$viewParams['single_task_'.$status.'_paginator'] = $paginator;
$viewParams['single_task_'.$status.'_tasks'] = $taskRepository
->findByParameters($params, $this->getUser(),
$singleStatus ? $paginator->getCurrentPage()->getFirstItemNumber() : 0,
$singleStatus ? $paginator->getItemsPerPage() : 10)
;
$tasks_count = $tasks_count + $count;
}
$viewParams['tasks_count'] = $tasks_count;
if ($viewParams['person'] !== null){
$viewParams['layout'] = '@ChillPerson/Person/layout.html.twig';
} else if ($viewParams['accompanyingCourse'] !== null){
$viewParams['layout'] = '@ChillPerson/AccompanyingCourse/layout.html.twig';
} else { } else {
$viewParams['layout'] = '@ChillMain/layout.html.twig'; $tasks = [];
} }
$form = $formFactory->createNamed(null, SingleTaskListType::class, null, [ return $this->render('@ChillTask/SingleTask/List/index.html.twig', [
'person' => $viewParams['person'], 'tasks' => $tasks,
'method' => Request::METHOD_GET, 'paginator' => $paginator,
'csrf_protection' => false, 'filter_order' => $filterOrder
'add_type' => true ]);
]);
$form->handleRequest($request);
if (isset($person)) {
$event = new PrivacyEvent($person, array(
'element_class' => SingleTask::class,
'action' => 'list'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
}
return $this->render('@ChillTask/SingleTask/index.html.twig',
array_merge($viewParams, [ 'form' => $form->createView() ]));
} }
/*
protected function getPersonParam(EntityManagerInterface $em)
{
$person = $em->getRepository(Person::class)
->find($request->query->getInt('person_id'))
;
if (NULL === $person) {
throw $this->createNotFoundException('person not found');
}
$this->denyAccessUnlessGranted(PersonVoter::SEE, $person, "You are "
. "not allowed to see this person");
return $person;
}
protected function getUserParam(EntityManagerInterface $em)
{
$user = $em->getRepository(User::class)
->find($request->query->getInt('user_id'))
;
if (NULL === $user) {
throw $this->createNotFoundException('user not found');
}
return $user;
}
*/
/** /**
* Creates a form to delete a Task entity by id. * Creates a form to delete a Task entity by id.
* *

View File

@ -19,6 +19,10 @@ use Doctrine\Common\Collections\Collection;
* @ORM\Index( * @ORM\Index(
* name="by_current_state", * name="by_current_state",
* columns={ "current_states" } * columns={ "current_states" }
* ),
* @ORM\Index(
* name="by_end_date",
* columns={ "end_date" }
* ) * )
* } * }
* ) * )

View File

@ -106,6 +106,31 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
->getQuery()->getSingleScalarResult(); ->getQuery()->getSingleScalarResult();
} }
public function countByAllViewable(
?string $pattern = null,
?array $flags = []
): int {
$qb = $this->buildBaseQuery($pattern, $flags);
return $this
->addACLGlobal($qb)
->select('COUNT(t)')
->getQuery()->getSingleScalarResult();
}
public function findByAllViewable(
?string $pattern = null,
?array $flags = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []
): array {
$qb = $this->buildBaseQuery($pattern, $flags);
$qb = $this->addACLGlobal($qb);
return $this->getResult($qb, $start, $limit, $orderBy);
}
public function buildQueryByCourse( public function buildQueryByCourse(
AccompanyingPeriod $course, AccompanyingPeriod $course,
?string $pattern = null, ?string $pattern = null,
@ -175,6 +200,50 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
->setParameter('scopes', $scopes); ->setParameter('scopes', $scopes);
} }
private function addACLGlobal(
QueryBuilder $qb
): QueryBuilder {
$allowedCenters = $this->authorizationHelper
->getReachableCenters($this->security->getUser(), TaskVoter::SHOW);
if ([] === $allowedCenters) {
$qb
->andWhere($qb->expr()->lt('t.id', ':falseid'))
->setParameter('falseid', -1);
}
$qb->leftJoin('t.person', 'person')
->leftJoin('t.course', 'course')
->leftJoin('course.participations', 'participation')
->leftJoin('participation.person', 'person_p')
;
$qb->distinct(true);
$k = 0;
$orX = $qb->expr()->orX();
foreach ($allowedCenters as $center) {
$allowedScopes = $this->authorizationHelper->getReachableScopes($this->security->getUser(),
TaskVoter::SHOW, $center);
$and = $qb->expr()->andX(
$qb->expr()->orX(
$qb->expr()->eq('person.center', ':center_'.$k),
$qb->expr()->eq('person_p.center', ':center_'.$k)
),
$qb->expr()->in('t.circle', ':scopes_'.$k)
);
$qb
->setParameter('center_'.$k, $center)
->setParameter('scopes_'.$k, $allowedScopes);
$orX->add($and);
$k++;
}
$qb->andWhere($orX);
return $qb;
}
public function buildBaseQuery ( public function buildBaseQuery (
?string $pattern = null, ?string $pattern = null,
?array $flags = [] ?array $flags = []

View File

@ -40,4 +40,17 @@ interface SingleTaskAclAwareRepositoryInterface
?string $pattern = null, ?string $pattern = null,
?array $flags = [] ?array $flags = []
): int; ): int;
public function countByAllViewable(
?string $pattern = null,
?array $flags = []
): int;
public function findByAllViewable(
?string $pattern = null,
?array $flags = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []
): array;
} }