mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-10-02 03:19:43 +00:00
Compare commits
7 Commits
285-cancel
...
385-invita
Author | SHA1 | Date | |
---|---|---|---|
74c9eb5585 | |||
f93c7e014f | |||
e6a799abc4 | |||
68a0ef7115 | |||
1675c56f3d | |||
675e8450fc | |||
4ffd7034d0 |
6
.changes/unreleased/Feature-20250808-120802.yaml
Normal file
6
.changes/unreleased/Feature-20250808-120802.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
kind: Feature
|
||||||
|
body: Create invitation list in user menu
|
||||||
|
time: 2025-08-08T12:08:02.446361367+02:00
|
||||||
|
custom:
|
||||||
|
Issue: "385"
|
||||||
|
SchemaChange: No schema change
|
@@ -266,7 +266,7 @@ class CalendarController extends AbstractController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->getUser() instanceof User) {
|
if (!$this->getUser() instanceof User) {
|
||||||
throw new UnauthorizedHttpException('you are not an user');
|
throw new UnauthorizedHttpException('you are not a user');
|
||||||
}
|
}
|
||||||
|
|
||||||
$view = '@ChillCalendar/Calendar/listByUser.html.twig';
|
$view = '@ChillCalendar/Calendar/listByUser.html.twig';
|
||||||
|
@@ -0,0 +1,58 @@
|
|||||||
|
<?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\CalendarBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\CalendarBundle\Entity\Calendar;
|
||||||
|
use Chill\CalendarBundle\Repository\InviteRepository;
|
||||||
|
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
|
class MyInvitationsController extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(private readonly InviteRepository $inviteRepository, private readonly PaginatorFactory $paginator, private readonly DocGeneratorTemplateRepositoryInterface $docGeneratorTemplateRepository) {}
|
||||||
|
|
||||||
|
#[Route(path: '/{_locale}/calendar/invitations/my', name: 'chill_calendar_invitations_list_my')]
|
||||||
|
public function myInvitations(Request $request): Response
|
||||||
|
{
|
||||||
|
$this->denyAccessUnlessGranted('ROLE_USER');
|
||||||
|
|
||||||
|
$user = $this->getUser();
|
||||||
|
|
||||||
|
if (!$user instanceof User) {
|
||||||
|
throw new UnauthorizedHttpException('you are not a user');
|
||||||
|
}
|
||||||
|
|
||||||
|
$total = count($this->inviteRepository->findBy(['user' => $user]));
|
||||||
|
$paginator = $this->paginator->create($total);
|
||||||
|
|
||||||
|
$invitations = $this->inviteRepository->findBy(
|
||||||
|
['user' => $user],
|
||||||
|
['createdAt' => 'DESC'],
|
||||||
|
$paginator->getItemsPerPage(),
|
||||||
|
$paginator->getCurrentPageFirstItemNumber()
|
||||||
|
);
|
||||||
|
|
||||||
|
$view = '@ChillCalendar/Invitations/listByUser.html.twig';
|
||||||
|
|
||||||
|
return $this->render($view, [
|
||||||
|
'invitations' => $invitations,
|
||||||
|
'paginator' => $paginator,
|
||||||
|
'templates' => $this->docGeneratorTemplateRepository->findByEntity(Calendar::class),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -30,6 +30,13 @@ class UserMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
'order' => 9,
|
'order' => 9,
|
||||||
'icon' => 'tasks',
|
'icon' => 'tasks',
|
||||||
]);
|
]);
|
||||||
|
$menu->addChild('My invitations list', [
|
||||||
|
'route' => 'chill_calendar_invitations_list_my',
|
||||||
|
])
|
||||||
|
->setExtras([
|
||||||
|
'order' => 9,
|
||||||
|
'icon' => 'tasks',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ class InviteRepository implements ObjectRepository
|
|||||||
/**
|
/**
|
||||||
* @return array|Invite[]
|
* @return array|Invite[]
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null)
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||||
{
|
{
|
||||||
return $this->entityRepository->findBy($criteria, $orderBy, $limit, $offset);
|
return $this->entityRepository->findBy($criteria, $orderBy, $limit, $offset);
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,6 @@
|
|||||||
{# list used in context of person or accompanyingPeriod #}
|
{# list used in context of person, accompanyingPeriod or user #}
|
||||||
|
|
||||||
{% if calendarItems|length > 0 %}
|
<div class="item-bloc">
|
||||||
<div class="flex-table list-records context-accompanyingCourse">
|
|
||||||
|
|
||||||
{% for calendar in calendarItems %}
|
|
||||||
|
|
||||||
<div class="item-bloc">
|
|
||||||
<div class="item-row main">
|
<div class="item-row main">
|
||||||
<div class="item-col">
|
<div class="item-col">
|
||||||
<div class="wrap-header">
|
<div class="wrap-header">
|
||||||
@@ -229,12 +224,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if calendarItems|length < paginator.getTotalItems %}
|
|
||||||
{{ chill_pagination(paginator) }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
@@ -34,7 +34,18 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% if calendarItems|length > 0 %}
|
||||||
|
<div class="flex-table list-records context-accompanyingCourse">
|
||||||
|
{% for calendar in calendarItems %}
|
||||||
{{ include('@ChillCalendar/Calendar/_list.html.twig', {context: 'accompanying_course'}) }}
|
{{ include('@ChillCalendar/Calendar/_list.html.twig', {context: 'accompanying_course'}) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if calendarItems|length < paginator.getTotalItems %}
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
|
@@ -33,7 +33,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% if calendarItems|length > 0 %}
|
||||||
|
<div class="flex-table list-records context-person">
|
||||||
|
{% for calendar in calendarItems %}
|
||||||
{{ include ('@ChillCalendar/Calendar/_list.html.twig', {context: 'person'}) }}
|
{{ include ('@ChillCalendar/Calendar/_list.html.twig', {context: 'person'}) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if calendarItems|length < paginator.getTotalItems %}
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
|
@@ -0,0 +1,40 @@
|
|||||||
|
{% extends "@ChillMain/layout.html.twig" %}
|
||||||
|
|
||||||
|
{% set activeRouteKey = 'chill_calendar_invitations_list' %}
|
||||||
|
|
||||||
|
{% block title %}{{ 'My invitations list' |trans }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>{{ 'invite.list.title'|trans }}</h1>
|
||||||
|
|
||||||
|
{% if invitations|length == 0 %}
|
||||||
|
<p class="chill-no-data-statement">
|
||||||
|
{{ "invite.list.none"|trans }}
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<div class="flex-table list-records">
|
||||||
|
{% for invitation in invitations %}
|
||||||
|
{% set calendar = invitation.getCalendar %}
|
||||||
|
{{ include('@ChillCalendar/Calendar/_list.html.twig', {context: 'user'}) }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if invitations|length < paginator.getTotalItems %}
|
||||||
|
{{ chill_pagination(paginator) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{{ parent() }}
|
||||||
|
{{ encore_entry_script_tags('mod_answer') }}
|
||||||
|
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{{ parent() }}
|
||||||
|
{{ encore_entry_link_tags('mod_answer') }}
|
||||||
|
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
|
||||||
|
{% endblock %}
|
@@ -0,0 +1,292 @@
|
|||||||
|
<?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\CalendarBundle\Tests\Controller;
|
||||||
|
|
||||||
|
use Chill\CalendarBundle\Controller\MyInvitationsController;
|
||||||
|
use Chill\CalendarBundle\Entity\Calendar;
|
||||||
|
use Chill\CalendarBundle\Entity\Invite;
|
||||||
|
use Chill\CalendarBundle\Repository\InviteRepository;
|
||||||
|
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||||
|
use Twig\Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
final class MyInvitationsControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
private MyInvitationsController $controller;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
// Create prophecies for dependencies
|
||||||
|
$inviteRepository = $this->prophesize(InviteRepository::class);
|
||||||
|
$paginatorFactory = $this->prophesize(PaginatorFactory::class);
|
||||||
|
$docGeneratorTemplateRepository = $this->prophesize(DocGeneratorTemplateRepositoryInterface::class);
|
||||||
|
|
||||||
|
// Create controller instance
|
||||||
|
$this->controller = new MyInvitationsController(
|
||||||
|
$inviteRepository->reveal(),
|
||||||
|
$paginatorFactory->reveal(),
|
||||||
|
$docGeneratorTemplateRepository->reveal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up necessary services for AbstractController
|
||||||
|
$authorizationChecker = $this->prophesize(AuthorizationCheckerInterface::class);
|
||||||
|
$tokenStorage = $this->prophesize(TokenStorageInterface::class);
|
||||||
|
$twig = $this->prophesize(Environment::class);
|
||||||
|
|
||||||
|
// Use reflection to set the container
|
||||||
|
$reflection = new \ReflectionClass($this->controller);
|
||||||
|
$containerProperty = $reflection->getParentClass()->getProperty('container');
|
||||||
|
$containerProperty->setAccessible(true);
|
||||||
|
|
||||||
|
// Create a mock container
|
||||||
|
$container = $this->prophesize(\Psr\Container\ContainerInterface::class);
|
||||||
|
$container->has('security.authorization_checker')->willReturn(true);
|
||||||
|
$container->get('security.authorization_checker')->willReturn($authorizationChecker->reveal());
|
||||||
|
$container->has('security.token_storage')->willReturn(true);
|
||||||
|
$container->get('security.token_storage')->willReturn($tokenStorage->reveal());
|
||||||
|
$container->has('twig')->willReturn(true);
|
||||||
|
$container->get('twig')->willReturn($twig->reveal());
|
||||||
|
|
||||||
|
$containerProperty->setValue($this->controller, $container->reveal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMyInvitationsReturnsCorrectAmountOfInvitations(): void
|
||||||
|
{
|
||||||
|
// Create test user
|
||||||
|
$user = new User();
|
||||||
|
$user->setUsername('testuser');
|
||||||
|
|
||||||
|
// Create test invitations
|
||||||
|
$invite1 = new Invite();
|
||||||
|
$invite1->setUser($user);
|
||||||
|
$invite1->setStatus(Invite::PENDING);
|
||||||
|
|
||||||
|
$invite2 = new Invite();
|
||||||
|
$invite2->setUser($user);
|
||||||
|
$invite2->setStatus(Invite::ACCEPTED);
|
||||||
|
|
||||||
|
$invite3 = new Invite();
|
||||||
|
$invite3->setUser($user);
|
||||||
|
$invite3->setStatus(Invite::DECLINED);
|
||||||
|
|
||||||
|
$allInvitations = [$invite1, $invite2, $invite3];
|
||||||
|
$paginatedInvitations = [$invite1, $invite2]; // First page with 2 items per page
|
||||||
|
|
||||||
|
// Set up repository prophecies
|
||||||
|
$inviteRepository = $this->prophesize(InviteRepository::class);
|
||||||
|
$inviteRepository->findBy(['user' => $user])->willReturn($allInvitations);
|
||||||
|
$inviteRepository->findBy(
|
||||||
|
['user' => $user],
|
||||||
|
['createdAt' => 'DESC'],
|
||||||
|
2, // items per page
|
||||||
|
0 // offset
|
||||||
|
)->willReturn($paginatedInvitations);
|
||||||
|
|
||||||
|
// Set up paginator prophecies
|
||||||
|
$paginator = $this->prophesize(PaginatorInterface::class);
|
||||||
|
$paginator->getItemsPerPage()->willReturn(2);
|
||||||
|
$paginator->getCurrentPageFirstItemNumber()->willReturn(0);
|
||||||
|
|
||||||
|
$paginatorFactory = $this->prophesize(PaginatorFactory::class);
|
||||||
|
$paginatorFactory->create(3)->willReturn($paginator->reveal());
|
||||||
|
|
||||||
|
// Set up doc generator repository
|
||||||
|
$docGeneratorTemplateRepository = $this->prophesize(DocGeneratorTemplateRepositoryInterface::class);
|
||||||
|
$docGeneratorTemplateRepository->findByEntity(Calendar::class)->willReturn([]);
|
||||||
|
|
||||||
|
// Create controller with mocked dependencies
|
||||||
|
$controller = new MyInvitationsController(
|
||||||
|
$inviteRepository->reveal(),
|
||||||
|
$paginatorFactory->reveal(),
|
||||||
|
$docGeneratorTemplateRepository->reveal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up authorization checker to return true for ROLE_USER
|
||||||
|
$authorizationChecker = $this->prophesize(AuthorizationCheckerInterface::class);
|
||||||
|
$authorizationChecker->isGranted('ROLE_USER', null)->willReturn(true);
|
||||||
|
|
||||||
|
// Set up token storage to return user
|
||||||
|
$token = $this->prophesize(TokenInterface::class);
|
||||||
|
$token->getUser()->willReturn($user);
|
||||||
|
$tokenStorage = $this->prophesize(TokenStorageInterface::class);
|
||||||
|
$tokenStorage->getToken()->willReturn($token->reveal());
|
||||||
|
|
||||||
|
// Set up twig to return a response
|
||||||
|
$twig = $this->prophesize(Environment::class);
|
||||||
|
$twig->render('@ChillCalendar/Invitations/listByUser.html.twig', [
|
||||||
|
'invitations' => $paginatedInvitations,
|
||||||
|
'paginator' => $paginator->reveal(),
|
||||||
|
'templates' => [],
|
||||||
|
])->willReturn('rendered content');
|
||||||
|
|
||||||
|
// Set up container
|
||||||
|
$container = $this->prophesize(\Psr\Container\ContainerInterface::class);
|
||||||
|
$container->has('security.authorization_checker')->willReturn(true);
|
||||||
|
$container->get('security.authorization_checker')->willReturn($authorizationChecker->reveal());
|
||||||
|
$container->has('security.token_storage')->willReturn(true);
|
||||||
|
$container->get('security.token_storage')->willReturn($tokenStorage->reveal());
|
||||||
|
$container->has('twig')->willReturn(true);
|
||||||
|
$container->get('twig')->willReturn($twig->reveal());
|
||||||
|
|
||||||
|
// Use reflection to set the container
|
||||||
|
$reflection = new \ReflectionClass($controller);
|
||||||
|
$containerProperty = $reflection->getParentClass()->getProperty('container');
|
||||||
|
$containerProperty->setAccessible(true);
|
||||||
|
$containerProperty->setValue($controller, $container->reveal());
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
$request = new Request();
|
||||||
|
|
||||||
|
// Execute the action
|
||||||
|
$response = $controller->myInvitations($request);
|
||||||
|
|
||||||
|
// Assert that response is successful
|
||||||
|
self::assertInstanceOf(Response::class, $response);
|
||||||
|
self::assertSame(200, $response->getStatusCode());
|
||||||
|
self::assertSame('rendered content', $response->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMyInvitationsPageLoads(): void
|
||||||
|
{
|
||||||
|
// Create test user
|
||||||
|
$user = new User();
|
||||||
|
$user->setUsername('testuser');
|
||||||
|
|
||||||
|
// Set up repository prophecies - no invitations
|
||||||
|
$inviteRepository = $this->prophesize(InviteRepository::class);
|
||||||
|
$inviteRepository->findBy(['user' => $user])->willReturn([]);
|
||||||
|
$inviteRepository->findBy(
|
||||||
|
['user' => $user],
|
||||||
|
['createdAt' => 'DESC'],
|
||||||
|
20, // default items per page
|
||||||
|
0 // offset
|
||||||
|
)->willReturn([]);
|
||||||
|
|
||||||
|
// Set up paginator prophecies
|
||||||
|
$paginator = $this->prophesize(PaginatorInterface::class);
|
||||||
|
$paginator->getItemsPerPage()->willReturn(20);
|
||||||
|
$paginator->getCurrentPageFirstItemNumber()->willReturn(0);
|
||||||
|
|
||||||
|
$paginatorFactory = $this->prophesize(PaginatorFactory::class);
|
||||||
|
$paginatorFactory->create(0)->willReturn($paginator->reveal());
|
||||||
|
|
||||||
|
// Set up doc generator repository
|
||||||
|
$docGeneratorTemplateRepository = $this->prophesize(DocGeneratorTemplateRepositoryInterface::class);
|
||||||
|
$docGeneratorTemplateRepository->findByEntity(Calendar::class)->willReturn([]);
|
||||||
|
|
||||||
|
// Create controller with mocked dependencies
|
||||||
|
$controller = new MyInvitationsController(
|
||||||
|
$inviteRepository->reveal(),
|
||||||
|
$paginatorFactory->reveal(),
|
||||||
|
$docGeneratorTemplateRepository->reveal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up authorization checker to return true for ROLE_USER
|
||||||
|
$authorizationChecker = $this->prophesize(AuthorizationCheckerInterface::class);
|
||||||
|
$authorizationChecker->isGranted('ROLE_USER', null)->willReturn(true);
|
||||||
|
|
||||||
|
// Set up token storage to return user
|
||||||
|
$token = $this->prophesize(TokenInterface::class);
|
||||||
|
$token->getUser()->willReturn($user);
|
||||||
|
$tokenStorage = $this->prophesize(TokenStorageInterface::class);
|
||||||
|
$tokenStorage->getToken()->willReturn($token->reveal());
|
||||||
|
|
||||||
|
// Set up twig to return a response
|
||||||
|
$twig = $this->prophesize(Environment::class);
|
||||||
|
$twig->render('@ChillCalendar/Invitations/listByUser.html.twig', [
|
||||||
|
'invitations' => [],
|
||||||
|
'paginator' => $paginator->reveal(),
|
||||||
|
'templates' => [],
|
||||||
|
])->willReturn('empty page content');
|
||||||
|
|
||||||
|
// Set up container
|
||||||
|
$container = $this->prophesize(\Psr\Container\ContainerInterface::class);
|
||||||
|
$container->has('security.authorization_checker')->willReturn(true);
|
||||||
|
$container->get('security.authorization_checker')->willReturn($authorizationChecker->reveal());
|
||||||
|
$container->has('security.token_storage')->willReturn(true);
|
||||||
|
$container->get('security.token_storage')->willReturn($tokenStorage->reveal());
|
||||||
|
$container->has('twig')->willReturn(true);
|
||||||
|
$container->get('twig')->willReturn($twig->reveal());
|
||||||
|
|
||||||
|
// Use reflection to set the container
|
||||||
|
$reflection = new \ReflectionClass($controller);
|
||||||
|
$containerProperty = $reflection->getParentClass()->getProperty('container');
|
||||||
|
$containerProperty->setAccessible(true);
|
||||||
|
$containerProperty->setValue($controller, $container->reveal());
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
$request = new Request();
|
||||||
|
|
||||||
|
// Execute the action
|
||||||
|
$response = $controller->myInvitations($request);
|
||||||
|
|
||||||
|
// Assert that page loads successfully
|
||||||
|
self::assertInstanceOf(Response::class, $response);
|
||||||
|
self::assertSame(200, $response->getStatusCode());
|
||||||
|
self::assertSame('empty page content', $response->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMyInvitationsRequiresAuthentication(): void
|
||||||
|
{
|
||||||
|
// Create controller with minimal dependencies
|
||||||
|
$inviteRepository = $this->prophesize(InviteRepository::class);
|
||||||
|
$paginatorFactory = $this->prophesize(PaginatorFactory::class);
|
||||||
|
$docGeneratorTemplateRepository = $this->prophesize(DocGeneratorTemplateRepositoryInterface::class);
|
||||||
|
|
||||||
|
$controller = new MyInvitationsController(
|
||||||
|
$inviteRepository->reveal(),
|
||||||
|
$paginatorFactory->reveal(),
|
||||||
|
$docGeneratorTemplateRepository->reveal()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set up authorization checker to return false for ROLE_USER
|
||||||
|
$authorizationChecker = $this->prophesize(AuthorizationCheckerInterface::class);
|
||||||
|
$authorizationChecker->isGranted('ROLE_USER')->willReturn(false);
|
||||||
|
$authorizationChecker->isGranted('ROLE_USER', null)->willReturn(false);
|
||||||
|
|
||||||
|
// Set up container
|
||||||
|
$container = $this->prophesize(\Psr\Container\ContainerInterface::class);
|
||||||
|
$container->has('security.authorization_checker')->willReturn(true);
|
||||||
|
$container->get('security.authorization_checker')->willReturn($authorizationChecker->reveal());
|
||||||
|
|
||||||
|
// Use reflection to set the container
|
||||||
|
$reflection = new \ReflectionClass($controller);
|
||||||
|
$containerProperty = $reflection->getParentClass()->getProperty('container');
|
||||||
|
$containerProperty->setAccessible(true);
|
||||||
|
$containerProperty->setValue($controller, $container->reveal());
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
$request = new Request();
|
||||||
|
|
||||||
|
// Expect AccessDeniedException
|
||||||
|
$this->expectException(\Symfony\Component\Security\Core\Exception\AccessDeniedException::class);
|
||||||
|
|
||||||
|
// Execute the action
|
||||||
|
$controller->myInvitations($request);
|
||||||
|
}
|
||||||
|
}
|
@@ -86,6 +86,9 @@ invite:
|
|||||||
declined: Refusé
|
declined: Refusé
|
||||||
pending: En attente
|
pending: En attente
|
||||||
tentative: Accepté provisoirement
|
tentative: Accepté provisoirement
|
||||||
|
list:
|
||||||
|
none: Il n'y aucun invitation
|
||||||
|
title: Mes invitations
|
||||||
|
|
||||||
# exports
|
# exports
|
||||||
Exports of calendar: Exports des rendez-vous
|
Exports of calendar: Exports des rendez-vous
|
||||||
|
@@ -20,4 +20,9 @@ use Doctrine\Persistence\ObjectRepository;
|
|||||||
interface DocGeneratorTemplateRepositoryInterface extends ObjectRepository
|
interface DocGeneratorTemplateRepositoryInterface extends ObjectRepository
|
||||||
{
|
{
|
||||||
public function countByEntity(string $entity): int;
|
public function countByEntity(string $entity): int;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|DocGeneratorTemplate[]
|
||||||
|
*/
|
||||||
|
public function findByEntity(string $entity, ?int $start = 0, ?int $limit = 50): array;
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ use Symfony\Component\Routing\RouterInterface;
|
|||||||
/**
|
/**
|
||||||
* Create paginator instances.
|
* Create paginator instances.
|
||||||
*/
|
*/
|
||||||
final readonly class PaginatorFactory implements PaginatorFactoryInterface
|
class PaginatorFactory implements PaginatorFactoryInterface
|
||||||
{
|
{
|
||||||
final public const DEFAULT_CURRENT_PAGE_KEY = 'page';
|
final public const DEFAULT_CURRENT_PAGE_KEY = 'page';
|
||||||
|
|
||||||
@@ -29,16 +29,16 @@ final readonly class PaginatorFactory implements PaginatorFactoryInterface
|
|||||||
/**
|
/**
|
||||||
* the request stack.
|
* the request stack.
|
||||||
*/
|
*/
|
||||||
private RequestStack $requestStack,
|
private readonly RequestStack $requestStack,
|
||||||
/**
|
/**
|
||||||
* the router and generator for url.
|
* the router and generator for url.
|
||||||
*/
|
*/
|
||||||
private RouterInterface $router,
|
private readonly RouterInterface $router,
|
||||||
/**
|
/**
|
||||||
* the default item per page. This may be overriden by
|
* the default item per page. This may be overriden by
|
||||||
* the request or inside the paginator.
|
* the request or inside the paginator.
|
||||||
*/
|
*/
|
||||||
private int $itemPerPage = 20,
|
private readonly int $itemPerPage = 20,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user