adapta list of tasks for a person

This commit is contained in:
Julien Fastré 2021-10-29 16:26:19 +02:00
parent 4017f8db48
commit db15a3d53c
10 changed files with 224 additions and 344 deletions

View File

@ -17,6 +17,7 @@
*/ */
namespace Chill\CalendarBundle\Menu; namespace Chill\CalendarBundle\Menu;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Routing\LocalMenuBuilderInterface; use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
use Knp\Menu\MenuItem; use Knp\Menu\MenuItem;
use Chill\TaskBundle\Templating\UI\CountNotificationTask; use Chill\TaskBundle\Templating\UI\CountNotificationTask;
@ -72,17 +73,19 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
{ {
$user = $this->tokenStorage->getToken()->getUser(); $user = $this->tokenStorage->getToken()->getUser();
if ($this->authorizationChecker->isGranted('ROLE_USER')){ if ($this->authorizationChecker->isGranted('ROLE_USER')
$menu->addChild("My calendar list", [ && $user instanceof User
'route' => 'chill_calendar_calendar_list', ) {
'routeParameters' => [ $menu->addChild("My calendar list", [
'user_id' => $user->getId(), 'route' => 'chill_calendar_calendar_list',
] 'routeParameters' => [
]) 'user_id' => $user->getId(),
->setExtras([ ]
'order' => 9, ])
'icon' => 'tasks' ->setExtras([
]); 'order' => 9,
'icon' => 'tasks'
]);
} }
} }
@ -90,5 +93,5 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
{ {
return [ 'user' ]; return [ 'user' ];
} }
} }

View File

@ -165,8 +165,8 @@ final class SingleTaskController extends AbstractController
} }
if ($entityType === 'person') { if ($entityType === 'person') {
return $this->redirectToRoute('chill_task_singletask_list', [ return $this->redirectToRoute('chill_task_singletask_by-person_list', [
'person_id' => $task->getPerson()->getId() 'id' => $task->getPerson()->getId()
]); ]);
} elseif ($entityType === 'course') { } elseif ($entityType === 'course') {
return $this->redirectToRoute('chill_task_singletask_by-course_list', [ return $this->redirectToRoute('chill_task_singletask_by-course_list', [
@ -399,17 +399,16 @@ final class SingleTaskController extends AbstractController
$this->addFlash('success', $this->translator $this->addFlash('success', $this->translator
->trans("The task has been successfully removed.")); ->trans("The task has been successfully removed."));
if($task->getContext() instanceof Person){ if ($task->getContext() instanceof Person) {
return $this->redirect($this->generateUrl( return $this->redirect($this->generateUrl(
'chill_task_singletask_list', 'chill_task_singletask_by-person_list',
$request->query->get('list_params', [ [ 'id' => $task->getPerson()->getId() ]
'person_id' => $person->getId() ));
])));
} else { } else {
return $this->redirect($this->generateUrl( return $this->redirect($this->generateUrl(
'chill_task_singletask_by-course_list', 'chill_task_singletask_by-course_list',
['id' => $course->getId()] ['id' => $task->getCourse()->getId()]
)); ));
} }
} }
} }
@ -753,13 +752,14 @@ final class SingleTaskController extends AbstractController
* "/{_locale}/task/single-task/by-course/{id}", * "/{_locale}/task/single-task/by-course/{id}",
* name="chill_task_singletask_by-course_list") * name="chill_task_singletask_by-course_list")
*/ */
public function listCourseTasks( public function listCourseTasks(
AccompanyingPeriod $course, AccompanyingPeriod $course,
FormFactoryInterface $formFactory, FormFactoryInterface $formFactory,
Request $request Request $request
): Response ): Response
{ {
$this->denyAccessUnlessGranted(TaskVoter::SHOW, $course);
$filterOrder = $this->buildFilterOrder(); $filterOrder = $this->buildFilterOrder();
$flags = \array_merge( $flags = \array_merge(
$filterOrder->getCheckboxData('status'), $filterOrder->getCheckboxData('status'),
@ -771,17 +771,22 @@ final class SingleTaskController extends AbstractController
$flags $flags
); );
$paginator = $this->paginatorFactory->create($nb); $paginator = $this->paginatorFactory->create($nb);
$tasks = $this->singleTaskAclAwareRepository->findByCourse(
$course, if (0 < $nb) {
$filterOrder->getQueryString(), $tasks = $this->singleTaskAclAwareRepository->findByCourse(
$flags, $course,
$paginator->getCurrentPageFirstItemNumber(), $filterOrder->getQueryString(),
$paginator->getItemsPerPage(), $flags,
[ $paginator->getCurrentPageFirstItemNumber(),
'startDate' => 'DESC', $paginator->getItemsPerPage(),
'endDate' => 'DESC', [
] 'startDate' => 'DESC',
); 'endDate' => 'DESC',
]
);
} else {
$tasks = [];
}
return $this->render( return $this->render(
'@ChillTask/SingleTask/AccompanyingCourse/list.html.twig', '@ChillTask/SingleTask/AccompanyingCourse/list.html.twig',
@ -793,4 +798,52 @@ final class SingleTaskController extends AbstractController
]); ]);
} }
/**
* @Route(
* "/{_locale}/task/single-task/by-person/{id}",
* name="chill_task_singletask_by-person_list")
*/
public function listPersonTasks(
Person $person
): Response {
$this->denyAccessUnlessGranted(TaskVoter::SHOW, $person);
$filterOrder = $this->buildFilterOrder();
$flags = \array_merge(
$filterOrder->getCheckboxData('status'),
\array_map(fn ($i) => 'state_'.$i, $filterOrder->getCheckboxData('states'))
);
$nb = $this->singleTaskAclAwareRepository->countByPerson(
$person,
$filterOrder->getQueryString(),
$flags
);
$paginator = $this->paginatorFactory->create($nb);
if (0 < $nb) {
$tasks = $this->singleTaskAclAwareRepository->findByPerson(
$person,
$filterOrder->getQueryString(),
$flags,
$paginator->getCurrentPageFirstItemNumber(),
$paginator->getItemsPerPage(),
[
'startDate' => 'DESC',
'endDate' => 'DESC',
]
);
} else {
$tasks = [];
}
return $this->render(
'@ChillTask/SingleTask/Person/list.html.twig',
[
'tasks' => $tasks,
'person' => $person,
'paginator' => $paginator,
'filter_order' => $filterOrder
]);
}
} }

View File

@ -40,7 +40,7 @@ class LoadTaskACL extends AbstractFixture implements OrderedFixtureInterface
return 16000; return 16000;
} }
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) { foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
@ -58,33 +58,38 @@ class LoadTaskACL extends AbstractFixture implements OrderedFixtureInterface
case 'direction': case 'direction':
if (in_array($scope->getName()['en'], array('administrative', 'social'))) { if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
break 2; // we do not want any power on social or administrative break 2; // we do not want any power on social or administrative
} }
break; break;
} }
printf("Adding CHILL_TASK_TASK_UPDATE & CHILL_TASK_TASK_CREATE & Chill_TASK_TASK_DELETE permissions to %s " printf("Adding CHILL_TASK_TASK_UPDATE & CHILL_TASK_TASK_CREATE & Chill_TASK_TASK_DELETE permissions to %s "
. "permission group, scope '%s' \n", . "permission group, scope '%s' \n",
$permissionsGroup->getName(), $scope->getName()['en']); $permissionsGroup->getName(), $scope->getName()['en']);
$roleScopeUpdate = (new RoleScope()) $roleScopeUpdate = (new RoleScope())
->setRole(TaskVoter::UPDATE) ->setRole(TaskVoter::UPDATE)
->setScope($scope); ->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeUpdate); $permissionsGroup->addRoleScope($roleScopeUpdate);
$roleScopeCreate = (new RoleScope()) $roleScopeCreateP = (new RoleScope())
->setRole(TaskVoter::CREATE) ->setRole(TaskVoter::CREATE_PERSON)
->setScope($scope); ->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeCreate); $permissionsGroup->addRoleScope($roleScopeCreateP);
$roleScopeCreateC = (new RoleScope())
->setRole(TaskVoter::CREATE_COURSE)
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeCreateC);
$roleScopeDelete = (new RoleScope()) $roleScopeDelete = (new RoleScope())
->setRole(TaskVoter::DELETE) ->setRole(TaskVoter::DELETE)
->setScope($scope); ->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeDelete); $permissionsGroup->addRoleScope($roleScopeDelete);
$manager->persist($roleScopeUpdate); $manager->persist($roleScopeUpdate);
$manager->persist($roleScopeCreate); $manager->persist($roleScopeCreateP);
$manager->persist($roleScopeCreateC);
$manager->persist($roleScopeDelete); $manager->persist($roleScopeDelete);
} }
} }
$manager->flush(); $manager->flush();
} }

View File

@ -44,7 +44,7 @@ class ChillTaskExtension extends Extension implements PrependExtensionInterface
$this->prependRoute($container); $this->prependRoute($container);
$this->prependWorkflows($container); $this->prependWorkflows($container);
} }
protected function prependRoute(ContainerBuilder $container) protected function prependRoute(ContainerBuilder $container)
{ {
//declare routes for task bundle //declare routes for task bundle
@ -56,17 +56,18 @@ class ChillTaskExtension extends Extension implements PrependExtensionInterface
) )
)); ));
} }
protected function prependAuthorization(ContainerBuilder $container) protected function prependAuthorization(ContainerBuilder $container)
{ {
$container->prependExtensionConfig('security', array( $container->prependExtensionConfig('security', array(
'role_hierarchy' => array( 'role_hierarchy' => array(
TaskVoter::UPDATE => [TaskVoter::SHOW], TaskVoter::UPDATE => [TaskVoter::SHOW],
TaskVoter::CREATE => [TaskVoter::SHOW] TaskVoter::CREATE_COURSE => [TaskVoter::SHOW],
TaskVoter::CREATE_PERSON => [TaskVoter::SHOW],
) )
)); ));
} }
protected function prependWorkflows(ContainerBuilder $container) protected function prependWorkflows(ContainerBuilder $container)
{ {
$container->prependExtensionConfig('framework', [ $container->prependExtensionConfig('framework', [

View File

@ -76,9 +76,9 @@ class MenuBuilder implements LocalMenuBuilderInterface
if ($this->authorizationChecker->isGranted(TaskVoter::SHOW, $person)) { if ($this->authorizationChecker->isGranted(TaskVoter::SHOW, $person)) {
$menu->addChild( $menu->addChild(
$this->translator->trans('Tasks'), [ $this->translator->trans('Tasks'), [
'route' => 'chill_task_singletask_list', 'route' => 'chill_task_singletask_by-person_list',
'routeParameters' => 'routeParameters' =>
[ 'person_id' => $person->getId() ] [ 'id' => $person->getId() ]
]) ])
->setExtra('order', 400); ->setExtra('order', 400);
} }

View File

@ -5,6 +5,7 @@ namespace Chill\TaskBundle\Repository;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface; use Chill\MainBundle\Security\Authorization\AuthorizationHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher; use Chill\MainBundle\Security\Resolver\CenterResolverDispatcher;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Chill\TaskBundle\Entity\SingleTask; use Chill\TaskBundle\Entity\SingleTask;
use Chill\TaskBundle\Security\Authorization\TaskVoter; use Chill\TaskBundle\Security\Authorization\TaskVoter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
@ -78,6 +79,33 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
->getQuery()->getSingleScalarResult(); ->getQuery()->getSingleScalarResult();
} }
public function findByPerson(
Person $person,
?string $pattern = null,
?array $flags = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []
): array {
$qb = $this->buildQueryByPerson($person, $pattern, $flags);
$qb = $this->addACL($qb, $person);
return $this->getResult($qb, $start, $limit, $orderBy);
}
public function countByPerson(
Person $person,
?string $pattern = null,
?array $flags = []
): int {
$qb = $this->buildQueryByPerson($person, $pattern, $flags);
return $this
->addACL($qb, $person)
->select('COUNT(t)')
->getQuery()->getSingleScalarResult();
}
public function buildQueryByCourse( public function buildQueryByCourse(
AccompanyingPeriod $course, AccompanyingPeriod $course,
?string $pattern = null, ?string $pattern = null,
@ -91,6 +119,19 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
; ;
} }
public function buildQueryByPerson(
Person $person,
?string $pattern = null,
?array $flags = []
): QueryBuilder
{
$qb = $this->buildBaseQuery($pattern, $flags);
return $qb
->andWhere($qb->expr()->eq('t.person', ':person'))
->setParameter('person', $person);
}
public function buildQueryMyTasks( public function buildQueryMyTasks(
?string $pattern = null, ?string $pattern = null,
?array $flags = [] ?array $flags = []
@ -123,7 +164,7 @@ final class SingleTaskAclAwareRepository implements SingleTaskAclAwareRepository
return $qb->getQuery()->getResult(); return $qb->getQuery()->getResult();
} }
public function addACL( private function addACL(
QueryBuilder $qb, QueryBuilder $qb,
$entity $entity
): QueryBuilder { ): QueryBuilder {

View File

@ -3,6 +3,7 @@
namespace Chill\TaskBundle\Repository; namespace Chill\TaskBundle\Repository;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
interface SingleTaskAclAwareRepositoryInterface interface SingleTaskAclAwareRepositoryInterface
{ {
@ -25,4 +26,18 @@ interface SingleTaskAclAwareRepositoryInterface
?array $flags = [] ?array $flags = []
): int; ): int;
public function findByPerson(
Person $person,
?string $pattern = null,
?array $flags = [],
?int $start = 0,
?int $limit = 50,
?array $orderBy = []
): array;
public function countByPerson(
Person $person,
?string $pattern = null,
?array $flags = []
): int;
} }

View File

@ -21,15 +21,17 @@
{{ chill_pagination(paginator) }} {{ chill_pagination(paginator) }}
<ul class="record_actions sticky-form-buttons"> {% if is_granted('CHILL_TASK_TASK_CREATE_FOR_COURSE', person) %}
<li> <ul class="record_actions sticky-form-buttons">
{% if accompanyingCourse is not null %} <li>
<a href="{{ path('chill_task_single_task_new', {'course_id': accompanyingCourse.id}) }}" class="btn btn-create"> {% if accompanyingCourse is not null %}
{{ 'Create' | trans }} <a href="{{ path('chill_task_single_task_new', {'course_id': accompanyingCourse.id}) }}" class="btn btn-create">
</a> {{ 'Create' | trans }}
{% endif %} </a>
</li> {% endif %}
</ul> </li>
</ul>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,251 +1,44 @@
{% macro date_status(title, tasks, count, paginator, status, isSingleStatus, person, user) %} {% extends '@ChillPerson/Person/layout.html.twig' %}
{% if tasks|length > 0 %}
<h3>{{ title|trans }}</h3>
<table class="table table-bordered border-dark chill-task-list"> {% set activeRouteKey = '' %}
<tbody>
{% for task in tasks %}
<tr>
<td>
<div>
<span class="chill-task-list__row__title">{{ task.title }}</span>
</div>
{% if person is null %} {% block title 'Tasks for {{ name }}'|trans({ '{{ name }}' : person|chill_entity_render_string }) %}
<div>
<span class="chill-task-list__row__person-for">{{ 'For person'|trans }}&nbsp;:</span>
<span class="chill-task-list__row__person">
<a href="{{ path('chill_person_view', {person_id : task.person.Id}) }}">{{ task.person}}</a>
</span>
</div>
{% endif %}
<div> {% block personcontent %}
<span class="chill-task-list__row__type">{{ task_workflow_metadata(task, 'definition.name')|trans }}</span> <div class="col-md-10 col-xxl">
</div>
<div> <h1>{{ block('title') }}</h1>
{% for place in workflow_marked_places(task) %}
<span class="task-status box type-{{ task.type }} place-{{ place }}">{{ place|trans }}</span>
{% endfor %}
{% if task.assignee is not null %}
<div class="chill-task-list__row__assignee">
<span class="chill_task-list__row__assignee_by">{{ 'By'|trans }}&nbsp;:</span>
{{ task.assignee.username }}</div>
{% endif %}
</div>
{% if task.startDate is not null or task.warningDate is not null or task.endDate is not null %} {{ filter_order|chill_render_filter_order_helper }}
<div class="chill-task-list__row__dates">
<ul class="record_actions column">
{% if task.startDate is not null %}
<li title="{{ 'Start'|trans|escape('html_attr') }}">
<i class="fa fa-play"></i>
{{ task.startDate|format_date('medium') }}
</li>
{% endif %}
{% if task.warningDate is not null %}
<li title="{{ 'Warning'|trans|escape('html_attr') }}">
<i class="fa fa-exclamation-triangle"></i>
{{ task.warningDate|format_date('medium') }}
</li>
{% endif %}
{% if task.endDate is not null %}
<li title="{{ 'End'|trans|escape('html_attr') }}">
<i class="fa fa-hourglass-end"></i>
{{ task.endDate|format_date('medium') }}
</li>
{% endif %}
</ul>
</div>
{% endif %}
</td> {% if tasks|length == 0 %}
<td> <p class="chill-no-data-statement">{{ 'Any tasks'|trans }}</p>
<ul class="record_actions"> {% else %}
{% if workflow_transitions(task)|length > 0 %} <div class="flex-table chill-task-list">
<li> {% for task in tasks %}
<div class="btn-group"> {% include 'ChillTaskBundle:SingleTask/List:index_item.html.twig' with { 'showContext' : false } %}
<a class="btn btn-task-exchange dropdown-toggle" href="#" role="button" id="taskExchange" data-bs-toggle="dropdown" aria-expanded="false"> {% endfor %}
{{'Change task status'|trans}} </div>
</a> {% endif %}
<ul class="dropdown-menu" aria-labelledby="taskExchange">
{% for transition in workflow_transitions(task) %}
<li>
<a class="dropdown-item" href="{{ path('chill_task_task_transition', { 'taskId': task.id, 'transition': transition.name, 'kind': 'single-task', 'list_params': app.request.query.all }) }}" class="{{ task_workflow_metadata(task, 'transition.class', transition)|e('html_attr') }}">
{{ task_workflow_metadata(task, 'transition.verb', transition)|trans }}
</a>
</li>
{% endfor %}
</ul>
</div>
</li>
{% endif %}
<li> {{ chill_pagination(paginator) }}
<a href="{{ path('chill_task_single_task_show', { 'id': task.id, 'list_params': app.request.query.all }) }}" class="btn btn-show "></a>
</li>
{% if is_granted('CHILL_TASK_TASK_UPDATE', task) %} {% if is_granted('CHILL_TASK_TASK_CREATE_FOR_PERSON', person) %}
<li> <ul class="record_actions sticky-form-buttons">
<a href="{{ path('chill_task_single_task_edit', { 'id': task.id, 'list_params': app.request.query.all }) }}" class="btn btn-update "></a> <li>
</li> <a href="{{ path('chill_task_single_task_new', {'person_id': person.id}) }}" class="btn btn-create">
{% endif %} {{ 'Create' | trans }}
</a>
</li>
</ul>
{% endif %}
{% if is_granted('CHILL_TASK_TASK_DELETE', task) %} </div>
<li> {% endblock %}
<a href="{{ path('chill_task_single_task_delete', { 'id': task.id, 'list_params': app.request.query.all } ) }}" class="btn btn-delete "></a>
</li>
{% endif %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if isSingleStatus %} {% block css %}
{% if tasks|length < paginator.getTotalItems %} {{ encore_entry_link_tags('page_task_list') }}
{{ chill_pagination(paginator) }} {% endblock %}
{% endif %} {% block js %}
{{ encore_entry_script_tags('page_task_list') }}
<!-- lien retour --> {% endblock %}
<ul class="record_actions">
<li>
{% if person is not null %}
<a href="{{ path('chill_task_singletask_list', {'person_id': person.id}) }}" class="btn btn-cancel">
{{ 'Back to the list' | trans }}
</a>
{% endif %}
{% if user is not null %}
<a href="{{ path('chill_task_singletask_list') }}" class="btn btn-cancel">
{{ 'Back to the list' | trans }}
</a>
{% endif %}
</li>
<li>
{% if person is not null %}
<a href="{{ path('chill_task_single_task_new', {'person_id': person.id}) }}" class="btn btn-create">
{{ 'Add a new task' | trans }}
</a>
{% endif %}
{% if user is not null %}
<a href="{{ path('chill_task_single_task_new') }}" class="btn btn-create">
{{ 'Add a new task' | trans }}
</a>
{% endif %}
</li>
</ul>
{% else %}
<ul class="record_actions">
<li>
<a href="{{ path('chill_task_singletask_list', app.request.query.all|merge({ 'status': [ status ] })) }}" class="btn btn-misc">
{{ 'See more' | trans }}
</a>
</li>
</ul>
{% endif %}
{% endif %}
{% endmacro %}
{% import _self as helper %}
<h1>{{ app.request.query.get('title', null)|escape('html')|default('Task list'|trans) }}</h1>
{% if false == app.request.query.boolean('hide_form', false) %}
<h2>{{ 'Filter the tasks'|trans }}</h2>
{{ form_start(form) }}
{{ form_row(form.user_id) }}
{% if form.status is defined %}
{{ form_row(form.status) }}
{% endif %}
{% if form.types is defined %}
{{ form_row(form.types) }}
{% endif %}
{% if form.person_id is defined %}
{{ form_row(form.person_id) }}
{% endif %}
{% if form.center_id is defined %}
{{ form_row(form.center_id) }}
{% endif %}
<ul class="record_actions">
<li>
<button type="submit" class="btn btn-submit">{{ 'Filter'|trans }}</button>
</li>
</ul>
{{ form_end(form)}}
{% endif %}
{% if tasks_count == 0 %}
<p class="chill-no-data-statement">{{ "There is no tasks."|trans }}</p>
{% if person is not null and is_granted('CHILL_TASK_TASK_CREATE', person) %}
<ul class="record_actions">
<li>
{% if person is not null %}
<a href="{{ path('chill_task_single_task_new', {'person_id': person.id}) }}" class="btn btn-create">
{{ 'Add a new task' | trans }}
</a>
{% endif %}
</li>
</ul>
{% endif %}
{% else %}
{% if false == app.request.query.boolean('hide_form', false) %}
<h2>{{ 'Tasks'|trans }}</h2>
{% endif %}
{# TODO reimplement right to create task. #}
{# {% if person is not null and is_granted('CHILL_TASK_TASK_CREATE', person) %} #}
<ul class="record_actions">
<li>
{% if person is not null %}
<a href="{{ path('chill_task_single_task_new', {'person_id': person.id}) }}" class="btn btn-create">
{{ 'Add a new task' | trans }}
</a>
{% endif %}
</li>
</ul>
{# {% endif %} #}
{% if single_task_ended_tasks is defined %}
{{ helper.date_status('Tasks with expired deadline', single_task_ended_tasks, single_task_ended_count, single_task_ended_paginator, 'ended', isSingleStatus, person) }}
{% endif %}
{% if single_task_warning_tasks is defined %}
{{ helper.date_status('Tasks with warning deadline reached', single_task_warning_tasks, single_task_warning_count, single_task_warning_paginator, 'warning', isSingleStatus, person) }}
{% endif %}
{% if single_task_current_tasks is defined %}
{{ helper.date_status('Current tasks', single_task_current_tasks, single_task_current_count, single_task_current_paginator, 'current', isSingleStatus, person) }}
{% endif %}
{% if single_task_not_started_tasks is defined %}
{{ helper.date_status('Tasks not started', single_task_not_started_tasks, single_task_not_started_count, single_task_not_started_paginator, 'not_started', isSingleStatus, person) }}
{% endif %}
{% if single_task_closed_tasks is defined %}
{{ helper.date_status('Closed tasks', single_task_closed_tasks, single_task_closed_count, single_task_closed_paginator, 'closed', isSingleStatus, person) }}
{% endif %}
{% if isSingleStatus == false %}
<ul class="record_actions sticky-form-buttons">
<li>
{% if person is not null and is_granted('CHILL_TASK_TASK_CREATE', person) %}
<a href="{{ path('chill_task_single_task_new', {'person_id': person.id}) }}" class="btn btn-create">
{{ 'Create' | trans }}
</a>
{% endif %}
</li>
</ul>
{% endif %}
{% endif %}

View File

@ -41,16 +41,18 @@ use Chill\TaskBundle\Security\Authorization\AuthorizationEvent;
final class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface final class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{ {
const CREATE = 'CHILL_TASK_TASK_CREATE'; const CREATE_COURSE = 'CHILL_TASK_TASK_CREATE_FOR_COURSE';
const UPDATE = 'CHILL_TASK_TASK_UPDATE'; const CREATE_PERSON = 'CHILL_TASK_TASK_CREATE_FOR_PERSON';
const SHOW = 'CHILL_TASK_TASK_SHOW';
const DELETE = 'CHILL_TASK_TASK_DELETE'; const DELETE = 'CHILL_TASK_TASK_DELETE';
const SHOW = 'CHILL_TASK_TASK_SHOW';
const UPDATE = 'CHILL_TASK_TASK_UPDATE';
const ROLES = [ const ROLES = [
self::CREATE, self::CREATE_COURSE,
self::UPDATE, self::CREATE_PERSON,
self::DELETE,
self::SHOW, self::SHOW,
self::DELETE self::UPDATE,
]; ];
protected AuthorizationHelper $authorizationHelper; protected AuthorizationHelper $authorizationHelper;
@ -84,8 +86,8 @@ final class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchy
$this->voter = $voterFactory $this->voter = $voterFactory
->generate(AbstractTask::class) ->generate(AbstractTask::class)
->addCheckFor(AbstractTask::class, self::ROLES) ->addCheckFor(AbstractTask::class, self::ROLES)
->addCheckFor(Person::class, [self::SHOW, self::CREATE]) ->addCheckFor(Person::class, [self::SHOW, self::CREATE_PERSON])
->addCheckFor(AccompanyingPeriod::class, [self::SHOW, self::CREATE]) ->addCheckFor(AccompanyingPeriod::class, [self::SHOW, self::CREATE_COURSE])
->addCheckFor(null, [self::SHOW]) ->addCheckFor(null, [self::SHOW])
->build() ->build()
; ;
@ -147,41 +149,6 @@ final class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchy
// do regular check. // do regular check.
return $this->voter->voteOnAttribute($attribute, $subject, $token); return $this->voter->voteOnAttribute($attribute, $subject, $token);
if ($subject instanceof AbstractTask) {
$associated = $subject->getPerson() ?? $subject->getCourse();
if ($associated === null) {
throw new \LogicException("You should associate a person with task "
. "in order to check autorizations");
}
$person = $subject->getPerson();
} elseif ($subject instanceof Person) {
// subject is null. We check that at least one center is reachable
$centers = $this->authorizationHelper->getReachableCenters($token->getUser(), new Role($attribute));
return count($centers) > 0;
}
if (!$this->accessDecisionManager->decide($token, [PersonVoter::SEE], $person)) {
return false;
}
$center = $this->centerResolverDispatcher->resolveCenter($subject);
if (NULL === $center) {
return false;
} elseif ($associated instanceof AccompanyingPeriod && !$this->accessDecisionManager->decide($token, [AccompanyingPeriodVoter::SEE], $associated)) {
return false;
} elseif ($associated instanceof AccompanyingPeriod && !$this->accessDecisionManager->decide($token, [AccompanyingPeriodVoter::SEE], $associated)) {
return false;
}
return $this->authorizationHelper->userHasAccess(
$token->getUser(),
$subject,
$attribute
);
} }
public function getRoles() public function getRoles()