Use [#MapEntity()] attribute to inject entity into method + for now set controller_resolver.auto_mapping to true

This commit is contained in:
Julie Lenaerts 2025-05-28 14:58:59 +02:00
parent 793dcbfa9a
commit 3fdf494f1c
24 changed files with 120 additions and 117 deletions

View File

@ -7,9 +7,12 @@ doctrine:
#server_version: '16'
use_savepoints: true
orm:
enable_lazy_ghost_objects: true
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.default
auto_mapping: true
controller_resolver:
auto_mapping: true
when@test:
doctrine:

View File

@ -15,15 +15,14 @@ use Chill\BudgetBundle\Entity\Charge;
use Chill\BudgetBundle\Form\ChargeType;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class ChargeController extends AbstractElementController
{
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/charge/{id}/delete', name: 'chill_budget_charge_delete')]
public function deleteAction(Request $request, Charge $charge): \Symfony\Component\HttpFoundation\Response
#[Route(path: '{_locale}/budget/charge/{id}/delete', name: 'chill_budget_charge_delete')]
public function deleteAction(Request $request, #[MapEntity(id: 'id')] Charge $charge): \Symfony\Component\HttpFoundation\Response
{
return $this->_delete(
$charge,
@ -33,11 +32,8 @@ class ChargeController extends AbstractElementController
);
}
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/charge/{id}/edit', name: 'chill_budget_charge_edit')]
public function editAction(Request $request, Charge $charge): \Symfony\Component\HttpFoundation\Response
#[Route(path: '{_locale}/budget/charge/{id}/edit', name: 'chill_budget_charge_edit')]
public function editAction(Request $request, #[MapEntity(id: 'id')] Charge $charge): \Symfony\Component\HttpFoundation\Response
{
return $this->_edit(
$charge,
@ -50,8 +46,8 @@ class ChargeController extends AbstractElementController
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/charge/by-person/{id}/new', name: 'chill_budget_charge_new')]
public function newAction(Request $request, Person $person)
#[Route(path: '{_locale}/budget/charge/by-person/{id}/new', name: 'chill_budget_charge_new')]
public function newAction(Request $request, #[MapEntity(id: 'id')] Person $person)
{
return $this->_new(
$person,
@ -64,8 +60,8 @@ class ChargeController extends AbstractElementController
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/charge/by-household/{id}/new', name: 'chill_budget_charge_household_new')]
public function newHouseholdAction(Request $request, Household $household)
#[Route(path: '{_locale}/budget/charge/by-household/{id}/new', name: 'chill_budget_charge_household_new')]
public function newHouseholdAction(Request $request, #[MapEntity(id: 'id')] Household $household)
{
return $this->_new(
$household,
@ -78,13 +74,13 @@ class ChargeController extends AbstractElementController
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/charge/{id}/view', name: 'chill_budget_charge_view')]
public function viewAction(Charge $charge)
#[Route(path: '{_locale}/budget/charge/{id}/view', name: 'chill_budget_charge_view')]
public function viewAction(#[MapEntity(id: 'id')] Charge $charge)
{
return $this->_view($charge, '@ChillBudget/Charge/view.html.twig');
}
protected function createNewElement(): \Chill\BudgetBundle\Entity\Charge
protected function createNewElement(): Charge
{
return new Charge();
}

View File

@ -17,14 +17,16 @@ use Chill\BudgetBundle\Repository\ResourceRepository;
use Chill\BudgetBundle\Security\Authorization\BudgetElementVoter;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class ElementController extends AbstractController
{
public function __construct(private readonly CalculatorManager $calculator, private readonly ResourceRepository $resourceRepository, private readonly ChargeRepository $chargeRepository) {}
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/elements/by-person/{id}', name: 'chill_budget_elements_index')]
public function indexAction(Person $person): \Symfony\Component\HttpFoundation\Response
#[Route(path: '{_locale}/budget/elements/by-person/{id}', name: 'chill_budget_elements_index')]
public function indexAction(#[MapEntity(id: 'id')] Person $person): \Symfony\Component\HttpFoundation\Response
{
$this->denyAccessUnlessGranted(BudgetElementVoter::SEE, $person);
@ -45,8 +47,8 @@ class ElementController extends AbstractController
]);
}
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/elements/by-household/{id}', name: 'chill_budget_elements_household_index')]
public function indexHouseholdAction(Household $household): \Symfony\Component\HttpFoundation\Response
#[Route(path: '{_locale}/budget/elements/by-household/{id}', name: 'chill_budget_elements_household_index')]
public function indexHouseholdAction(#[MapEntity(id: 'id')] Household $household): \Symfony\Component\HttpFoundation\Response
{
$this->denyAccessUnlessGranted(BudgetElementVoter::SEE, $household);

View File

@ -15,13 +15,15 @@ use Chill\BudgetBundle\Entity\Resource;
use Chill\BudgetBundle\Form\ResourceType;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Person;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class ResourceController extends AbstractElementController
{
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/resource/{id}/delete', name: 'chill_budget_resource_delete')]
public function deleteAction(Request $request, Resource $resource): \Symfony\Component\HttpFoundation\Response
#[Route(path: '{_locale}/budget/resource/{id}/delete', name: 'chill_budget_resource_delete')]
public function deleteAction(Request $request, #[MapEntity(id: 'id')] Resource $resource): Response
{
return $this->_delete(
$resource,
@ -31,8 +33,8 @@ class ResourceController extends AbstractElementController
);
}
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/resource/{id}/edit', name: 'chill_budget_resource_edit')]
public function editAction(Request $request, Resource $resource): Response
#[Route(path: '{_locale}/budget/resource/{id}/edit', name: 'chill_budget_resource_edit')]
public function editAction(Request $request, #[MapEntity(id: 'id')] Resource $resource): Response
{
return $this->_edit(
$resource,
@ -45,8 +47,8 @@ class ResourceController extends AbstractElementController
/**
* Create a new budget element for a person.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/resource/by-person/{id}/new', name: 'chill_budget_resource_new')]
public function newAction(Request $request, Person $person): Response
#[Route(path: '{_locale}/budget/resource/by-person/{id}/new', name: 'chill_budget_resource_new')]
public function newAction(Request $request, #[MapEntity(id: 'id')] Person $person): Response
{
return $this->_new(
$person,
@ -59,8 +61,8 @@ class ResourceController extends AbstractElementController
/**
* Create new budget element for a household.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/resource/by-household/{id}/new', name: 'chill_budget_resource_household_new')]
public function newHouseholdAction(Request $request, Household $household): Response
#[Route(path: '{_locale}/budget/resource/by-household/{id}/new', name: 'chill_budget_resource_household_new')]
public function newHouseholdAction(Request $request, #[MapEntity(id: 'id')] Household $household): Response
{
return $this->_new(
$household,
@ -70,8 +72,8 @@ class ResourceController extends AbstractElementController
);
}
#[\Symfony\Component\Routing\Annotation\Route(path: '{_locale}/budget/resource/{id}/view', name: 'chill_budget_resource_view')]
public function viewAction(Resource $resource): Response
#[Route(path: '{_locale}/budget/resource/{id}/view', name: 'chill_budget_resource_view')]
public function viewAction(#[MapEntity(id: 'id')] Resource $resource): Response
{
return $this->_view($resource, '@ChillBudget/Resource/view.html.twig');
}

View File

@ -16,6 +16,7 @@ use Chill\EventBundle\Form\EventTypeType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class EventTypeController.
@ -51,7 +52,7 @@ class EventTypeController extends AbstractController
/**
* Deletes a EventType entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/{id}/delete', name: 'chill_eventtype_admin_delete', methods: ['POST', 'DELETE'])]
#[Route(path: '/{_locale}/admin/event/event_type/{id}/delete', name: 'chill_eventtype_admin_delete', methods: ['POST', 'DELETE'])]
public function deleteAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse
{
$form = $this->createDeleteForm($id);
@ -75,7 +76,7 @@ class EventTypeController extends AbstractController
/**
* Displays a form to edit an existing EventType entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/{id}/edit', name: 'chill_eventtype_admin_edit')]
#[Route(path: '/{_locale}/admin/event/event_type/{id}/edit', name: 'chill_eventtype_admin_edit')]
public function editAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -99,7 +100,7 @@ class EventTypeController extends AbstractController
/**
* Lists all EventType entities.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/', name: 'chill_eventtype_admin', options: [null])]
#[Route(path: '/{_locale}/admin/event/event_type/', name: 'chill_eventtype_admin', options: [null])]
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -114,7 +115,7 @@ class EventTypeController extends AbstractController
/**
* Displays a form to create a new EventType entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/new', name: 'chill_eventtype_admin_new')]
#[Route(path: '/{_locale}/admin/event/event_type/new', name: 'chill_eventtype_admin_new')]
public function newAction(): \Symfony\Component\HttpFoundation\Response
{
$entity = new EventType();
@ -129,7 +130,7 @@ class EventTypeController extends AbstractController
/**
* Finds and displays a EventType entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/{id}/show', name: 'chill_eventtype_admin_show')]
#[Route(path: '/{_locale}/admin/event/event_type/{id}/show', name: 'chill_eventtype_admin_show')]
public function showAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -151,7 +152,7 @@ class EventTypeController extends AbstractController
/**
* Edits an existing EventType entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/event_type/{id}/update', name: 'chill_eventtype_admin_update', methods: ['POST', 'PUT'])]
#[Route(path: '/{_locale}/admin/event/event_type/{id}/update', name: 'chill_eventtype_admin_update', methods: ['POST', 'PUT'])]
public function updateAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();

View File

@ -16,6 +16,7 @@ use Chill\EventBundle\Form\RoleType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class RoleController.
@ -51,7 +52,7 @@ class RoleController extends AbstractController
/**
* Deletes a Role entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/{id}/delete', name: 'chill_event_admin_role_delete', methods: ['POST', 'DELETE'])]
#[Route(path: '/{_locale}/admin/event/role/{id}/delete', name: 'chill_event_admin_role_delete', methods: ['POST', 'DELETE'])]
public function deleteAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse
{
$form = $this->createDeleteForm($id);
@ -75,7 +76,7 @@ class RoleController extends AbstractController
/**
* Displays a form to edit an existing Role entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/{id}/edit', name: 'chill_event_admin_role_edit')]
#[Route(path: '/{_locale}/admin/event/role/{id}/edit', name: 'chill_event_admin_role_edit')]
public function editAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -99,7 +100,7 @@ class RoleController extends AbstractController
/**
* Lists all Role entities.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/', name: 'chill_event_admin_role', options: [null])]
#[Route(path: '/{_locale}/admin/event/role/', name: 'chill_event_admin_role', options: [null])]
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -114,7 +115,7 @@ class RoleController extends AbstractController
/**
* Displays a form to create a new Role entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/new', name: 'chill_event_admin_role_new')]
#[Route(path: '/{_locale}/admin/event/role/new', name: 'chill_event_admin_role_new')]
public function newAction(): \Symfony\Component\HttpFoundation\Response
{
$entity = new Role();
@ -129,7 +130,7 @@ class RoleController extends AbstractController
/**
* Finds and displays a Role entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/{id}/show', name: 'chill_event_admin_role_show')]
#[Route(path: '/{_locale}/admin/event/role/{id}/show', name: 'chill_event_admin_role_show')]
public function showAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -151,7 +152,7 @@ class RoleController extends AbstractController
/**
* Edits an existing Role entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/role/{id}/update', name: 'chill_event_admin_role_update', methods: ['POST', 'PUT'])]
#[Route(path: '/{_locale}/admin/event/role/{id}/update', name: 'chill_event_admin_role_update', methods: ['POST', 'PUT'])]
public function updateAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();

View File

@ -16,6 +16,7 @@ use Chill\EventBundle\Form\StatusType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class StatusController.
@ -51,7 +52,7 @@ class StatusController extends AbstractController
/**
* Deletes a Status entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/{id}/delete', name: 'chill_event_admin_status_delete', methods: ['POST', 'DELETE'])]
#[Route(path: '/{_locale}/admin/event/status/{id}/delete', name: 'chill_event_admin_status_delete', methods: ['POST', 'DELETE'])]
public function deleteAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse
{
$form = $this->createDeleteForm($id);
@ -75,7 +76,7 @@ class StatusController extends AbstractController
/**
* Displays a form to edit an existing Status entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/{id}/edit', name: 'chill_event_admin_status_edit')]
#[Route(path: '/{_locale}/admin/event/status/{id}/edit', name: 'chill_event_admin_status_edit')]
public function editAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -99,7 +100,7 @@ class StatusController extends AbstractController
/**
* Lists all Status entities.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/', name: 'chill_event_admin_status', options: [null])]
#[Route(path: '/{_locale}/admin/event/status/', name: 'chill_event_admin_status', options: [null])]
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -114,7 +115,7 @@ class StatusController extends AbstractController
/**
* Displays a form to create a new Status entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/new', name: 'chill_event_admin_status_new')]
#[Route(path: '/{_locale}/admin/event/status/new', name: 'chill_event_admin_status_new')]
public function newAction(): \Symfony\Component\HttpFoundation\Response
{
$entity = new Status();
@ -129,7 +130,7 @@ class StatusController extends AbstractController
/**
* Finds and displays a Status entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/{id}/show', name: 'chill_event_admin_status_show')]
#[Route(path: '/{_locale}/admin/event/status/{id}/show', name: 'chill_event_admin_status_show')]
public function showAction(mixed $id): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -151,7 +152,7 @@ class StatusController extends AbstractController
/**
* Edits an existing Status entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/event/status/{id}/update', name: 'chill_event_admin_status_update', methods: ['POST', 'PUT'])]
#[Route(path: '/{_locale}/admin/event/status/{id}/update', name: 'chill_event_admin_status_update', methods: ['POST', 'PUT'])]
public function updateAction(Request $request, mixed $id): \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();

View File

@ -14,6 +14,7 @@ namespace Chill\MainBundle\Controller;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Chill\MainBundle\Entity\Address;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -33,7 +34,7 @@ class AddressApiController extends ApiController
* Duplicate an existing address.
*/
#[Route(path: '/api/1.0/main/address/{id}/duplicate.json', name: 'chill_api_main_address_duplicate', methods: ['POST'])]
public function duplicate(Address $address): JsonResponse
public function duplicate(#[MapEntity(id: 'id')] Address $address): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_USER');
$new = Address::createFromAddress($address);

View File

@ -17,6 +17,7 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Chill\MainBundle\Repository\AddressReferenceRepository;
use Chill\MainBundle\Serializer\Model\Collection;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -29,7 +30,7 @@ final class AddressReferenceAPIController extends ApiController
public function __construct(private readonly AddressReferenceRepository $addressReferenceRepository, private readonly PaginatorFactory $paginatorFactory) {}
#[Route(path: '/api/1.0/main/address-reference/by-postal-code/{id}/search.json')]
public function search(PostalCode $postalCode, Request $request): JsonResponse
public function search(#[MapEntity(id: 'id')] PostalCode $postalCode, Request $request): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_USER');

View File

@ -13,6 +13,7 @@ namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Address;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
@ -26,7 +27,7 @@ class AddressToReferenceMatcherController
public function __construct(private readonly Security $security, private readonly EntityManagerInterface $entityManager, private readonly SerializerInterface $serializer) {}
#[Route(path: '/api/1.0/main/address/reference-match/{id}/set/reviewed', methods: ['POST'])]
public function markAddressAsReviewed(Address $address): JsonResponse
public function markAddressAsReviewed(#[MapEntity(id: 'id')] Address $address): JsonResponse
{
if (!$this->security->isGranted('ROLE_USER')) {
throw new AccessDeniedHttpException();
@ -48,7 +49,7 @@ class AddressToReferenceMatcherController
* Set an address back to "to review". Only if the address is in "reviewed" state.
*/
#[Route(path: '/api/1.0/main/address/reference-match/{id}/set/to_review', methods: ['POST'])]
public function markAddressAsToReview(Address $address): JsonResponse
public function markAddressAsToReview(#[MapEntity(id: 'id')] Address $address): JsonResponse
{
if (!$this->security->isGranted('ROLE_USER')) {
throw new AccessDeniedHttpException();
@ -71,7 +72,7 @@ class AddressToReferenceMatcherController
}
#[Route(path: '/api/1.0/main/address/reference-match/{id}/sync-with-reference', methods: ['POST'])]
public function syncAddressWithReference(Address $address): JsonResponse
public function syncAddressWithReference(#[MapEntity(id: 'id')] Address $address): JsonResponse
{
if (null === $address->getAddressReference()) {
throw new BadRequestHttpException('this address does not have any address reference');

View File

@ -26,6 +26,7 @@ use Chill\MainBundle\Repository\SavedExportRepositoryInterface;
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\Extension\Core\Type\FormType;
@ -128,7 +129,7 @@ class ExportController extends AbstractController
* @throws \RedisException
*/
#[Route(path: '/{_locale}/exports/generate-from-saved/{id}', name: 'chill_main_export_generate_from_saved')]
public function generateFromSavedExport(SavedExport $savedExport): RedirectResponse
public function generateFromSavedExport(#[MapEntity(id: 'id')] SavedExport $savedExport): RedirectResponse
{
$this->denyAccessUnlessGranted(SavedExportVoter::GENERATE, $savedExport);
@ -198,7 +199,7 @@ class ExportController extends AbstractController
}
#[Route(path: '/{_locale}/export/saved/update-from-key/{id}/{key}', name: 'chill_main_export_saved_edit_options_from_key')]
public function editSavedExportOptionsFromKey(SavedExport $savedExport, string $key): Response
public function editSavedExportOptionsFromKey(#[MapEntity(id: 'id')] SavedExport $savedExport, string $key): Response
{
$this->denyAccessUnlessGranted('ROLE_USER');
$user = $this->getUser();

View File

@ -15,6 +15,7 @@ use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
use Chill\MainBundle\Serializer\Model\Collection;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Routing\Annotation\Route;
@ -27,7 +28,7 @@ class GeographicalUnitByAddressApiController
public function __construct(private readonly PaginatorFactory $paginatorFactory, private readonly GeographicalUnitRepositoryInterface $geographicalUnitRepository, private readonly Security $security, private readonly SerializerInterface $serializer) {}
#[Route(path: '/api/1.0/main/geographical-unit/by-address/{id}.{_format}', requirements: ['_format' => 'json'])]
public function getGeographicalUnitCoveringAddress(Address $address): JsonResponse
public function getGeographicalUnitCoveringAddress(#[MapEntity(id: 'id')] Address $address): JsonResponse
{
if (!$this->security->isGranted('ROLE_USER')) {
throw new AccessDeniedHttpException();

View File

@ -16,10 +16,14 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Repository\NewsItemRepository;
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
use Chill\MainBundle\Templating\Listing\FilterOrderHelperFactoryInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
final readonly class NewsItemHistoryController
{
@ -46,8 +50,13 @@ final readonly class NewsItemHistoryController
]));
}
/**
* @throws SyntaxError
* @throws RuntimeError
* @throws LoaderError
*/
#[Route(path: '/{_locale}/news-items/{id}', name: 'chill_main_single_news_item')]
public function showSingleItem(NewsItem $newsItem, Request $request): Response
public function showSingleItem(#[MapEntity(id: 'id')] NewsItem $newsItem, Request $request): Response
{
return new Response($this->environment->render(
'@ChillMain/NewsItem/show.html.twig',

View File

@ -19,6 +19,7 @@ use Chill\MainBundle\Security\Authorization\NotificationVoter;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\MainBundle\Serializer\Model\Counter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
@ -32,13 +33,13 @@ class NotificationApiController
public function __construct(private readonly EntityManagerInterface $entityManager, private readonly NotificationRepository $notificationRepository, private readonly PaginatorFactory $paginatorFactory, private readonly Security $security, private readonly SerializerInterface $serializer) {}
#[Route(path: '/{id}/mark/read', name: 'chill_api_main_notification_mark_read', methods: ['POST'])]
public function markAsRead(Notification $notification): JsonResponse
public function markAsRead(#[MapEntity(id: 'id')] Notification $notification): JsonResponse
{
return $this->markAs('read', $notification);
}
#[Route(path: '/{id}/mark/unread', name: 'chill_api_main_notification_mark_unread', methods: ['POST'])]
public function markAsUnread(Notification $notification): JsonResponse
public function markAsUnread(#[MapEntity(id: 'id')] Notification $notification): JsonResponse
{
return $this->markAs('unread', $notification);
}

View File

@ -24,6 +24,7 @@ use Chill\MainBundle\Security\Authorization\NotificationVoter;
use Chill\MainBundle\Security\ChillSecurity;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
@ -99,7 +100,7 @@ class NotificationController extends AbstractController
}
#[Route(path: '/{id}/edit', name: 'chill_main_notification_edit')]
public function editAction(Notification $notification, Request $request): Response
public function editAction(#[MapEntity(id: 'id')] Notification $notification, Request $request): Response
{
$this->denyAccessUnlessGranted(NotificationVoter::NOTIFICATION_UPDATE, $notification);
@ -127,7 +128,7 @@ class NotificationController extends AbstractController
}
#[Route(path: '/{id}/access_key', name: 'chill_main_notification_grant_access_by_access_key')]
public function getAccessByAccessKey(Notification $notification, Request $request): Response
public function getAccessByAccessKey(#[MapEntity(id: 'id')] Notification $notification, Request $request): Response
{
$this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');
@ -215,7 +216,7 @@ class NotificationController extends AbstractController
}
#[Route(path: '/{id}/show', name: 'chill_main_notification_show')]
public function showAction(Notification $notification, Request $request): Response
public function showAction(#[MapEntity(id: 'id')] Notification $notification, Request $request): Response
{
$this->denyAccessUnlessGranted(NotificationVoter::NOTIFICATION_SEE, $notification);

View File

@ -26,6 +26,7 @@ use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
@ -208,7 +209,7 @@ final class PermissionsGroupController extends AbstractController
/**
* Displays a form to edit an existing PermissionsGroup entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/edit', name: 'admin_permissionsgroup_edit')]
#[Route(path: '/{_locale}/admin/permissionsgroup/{id}/edit', name: 'admin_permissionsgroup_edit')]
public function editAction(int $id): Response
{
$permissionsGroup = $this->permissionsGroupRepository->find($id);
@ -255,7 +256,7 @@ final class PermissionsGroupController extends AbstractController
/**
* Lists all PermissionsGroup entities.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/', name: 'admin_permissionsgroup')]
#[Route(path: '/{_locale}/admin/permissionsgroup/', name: 'admin_permissionsgroup')]
public function indexAction(): Response
{
$entities = $this->permissionsGroupRepository->findAllOrderedAlphabetically();
@ -268,7 +269,7 @@ final class PermissionsGroupController extends AbstractController
/**
* Displays a form to create a new PermissionsGroup entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/new', name: 'admin_permissionsgroup_new')]
#[Route(path: '/{_locale}/admin/permissionsgroup/new', name: 'admin_permissionsgroup_new')]
public function newAction(): Response
{
$permissionsGroup = new PermissionsGroup();
@ -283,7 +284,7 @@ final class PermissionsGroupController extends AbstractController
/**
* Finds and displays a PermissionsGroup entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/show', name: 'admin_permissionsgroup_show')]
#[Route(path: '/{_locale}/admin/permissionsgroup/{id}/show', name: 'admin_permissionsgroup_show')]
public function showAction(int $id): Response
{
$permissionsGroup = $this->permissionsGroupRepository->find($id);
@ -335,7 +336,7 @@ final class PermissionsGroupController extends AbstractController
/**
* Edits an existing PermissionsGroup entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/permissionsgroup/{id}/update', name: 'admin_permissionsgroup_update', methods: ['POST', 'PUT'])]
#[Route(path: '/{_locale}/admin/permissionsgroup/{id}/update', name: 'admin_permissionsgroup_update', methods: ['POST', 'PUT'])]
public function updateAction(Request $request, int $id): Response
{
$permissionsGroup = $this->permissionsGroupRepository

View File

@ -20,6 +20,7 @@ use Chill\MainBundle\Form\SavedExportType;
use Chill\MainBundle\Repository\SavedExportRepositoryInterface;
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -37,7 +38,7 @@ class SavedExportController
public function __construct(private readonly \Twig\Environment $templating, private readonly EntityManagerInterface $entityManager, private readonly ExportManager $exportManager, private readonly FormFactoryInterface $formFactory, private readonly SavedExportRepositoryInterface $savedExportRepository, private readonly Security $security, private readonly RequestStack $requestStack, private readonly TranslatorInterface $translator, private readonly UrlGeneratorInterface $urlGenerator) {}
#[Route(path: '/{_locale}/exports/saved/{id}/delete', name: 'chill_main_export_saved_delete')]
public function delete(SavedExport $savedExport, Request $request): Response
public function delete(#[MapEntity(id: 'id')] SavedExport $savedExport, Request $request): Response
{
if (!$this->security->isGranted(SavedExportVoter::DELETE, $savedExport)) {
throw new AccessDeniedHttpException();
@ -70,7 +71,7 @@ class SavedExportController
}
#[Route(path: '/{_locale}/exports/saved/{id}/edit', name: 'chill_main_export_saved_edit')]
public function edit(SavedExport $savedExport, Request $request): Response
public function edit(#[MapEntity(id: 'id')] SavedExport $savedExport, Request $request): Response
{
if (!$this->security->isGranted(SavedExportVoter::EDIT, $savedExport)) {
throw new AccessDeniedHttpException();

View File

@ -14,11 +14,13 @@ namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Form\ScopeType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* Class ScopeController.
@ -57,8 +59,8 @@ class ScopeController extends AbstractController
/**
* Displays a form to edit an existing Scope entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/{id}/edit', name: 'admin_scope_edit')]
public function editAction(Scope $scope, Request $request): Response
#[Route(path: '/{_locale}/admin/scope/{id}/edit', name: 'admin_scope_edit')]
public function editAction(#[MapEntity(id: 'id')] Scope $scope, Request $request): Response
{
$editForm = $this->createEditForm($scope);
$editForm->handleRequest($request);
@ -78,7 +80,7 @@ class ScopeController extends AbstractController
/**
* Lists all Scope entities.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/', name: 'admin_scope')]
#[Route(path: '/{_locale}/admin/scope/', name: 'admin_scope')]
public function indexAction(): \Symfony\Component\HttpFoundation\Response
{
$em = $this->managerRegistry->getManager();
@ -93,7 +95,7 @@ class ScopeController extends AbstractController
/**
* Displays a form to create a new Scope entity.
*/
#[\Symfony\Component\Routing\Annotation\Route(path: '/{_locale}/admin/scope/new', name: 'admin_scope_new')]
#[Route(path: '/{_locale}/admin/scope/new', name: 'admin_scope_new')]
public function newAction(): \Symfony\Component\HttpFoundation\Response
{
$scope = new Scope();

View File

@ -26,6 +26,7 @@ use Chill\MainBundle\Security\ChillSecurity;
use Chill\MainBundle\Templating\Listing\FilterOrderHelper;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Form;
@ -235,7 +236,7 @@ class UserController extends CRUDController
* Displays a form to edit the user password.
*/
#[Route(path: '/{_locale}/admin/user/{id}/edit_password', name: 'admin_user_edit_password')]
public function editPasswordAction(User $user, Request $request): RedirectResponse|Response
public function editPasswordAction(#[MapEntity(id: 'id')] User $user, Request $request): RedirectResponse|Response
{
$editForm = $this->createEditPasswordForm($user);
$editForm->handleRequest($request);

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Controller;
use Chill\MainBundle\Entity\User;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -24,7 +25,7 @@ class UserJobScopeHistoriesController extends AbstractController
) {}
#[Route(path: '/{_locale}/admin/main/user/{id}/job-scope-history', name: 'admin_user_job_scope_history')]
public function indexAction(User $user): Response
public function indexAction(#[MapEntity(id: 'id')] User $user): Response
{
$jobHistories = $user->getUserJobHistoriesOrdered();
$scopeHistories = $user->getMainScopeHistoriesOrdered();

View File

@ -18,6 +18,7 @@ use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Serializer\Model\Collection;
use Chill\MainBundle\Serializer\Model\Counter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@ -108,13 +109,13 @@ class WorkflowApiController
}
#[Route(path: '/api/1.0/main/workflow/{id}/subscribe', methods: ['POST'])]
public function subscribe(EntityWorkflow $entityWorkflow, Request $request): Response
public function subscribe(#[MapEntity(id: 'id')] EntityWorkflow $entityWorkflow, Request $request): Response
{
return $this->handleSubscription($entityWorkflow, $request, 'subscribe');
}
#[Route(path: '/api/1.0/main/workflow/{id}/unsubscribe', methods: ['POST'])]
public function unsubscribe(EntityWorkflow $entityWorkflow, Request $request): Response
public function unsubscribe(#[MapEntity(id: 'id')] EntityWorkflow $entityWorkflow, Request $request): Response
{
return $this->handleSubscription($entityWorkflow, $request, 'unsubscribe');
}

View File

@ -25,6 +25,7 @@ use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\Form\Extension\Core\Type\FormType;
@ -101,7 +102,7 @@ class WorkflowController extends AbstractController
}
#[Route(path: '/{_locale}/main/workflow/{id}/delete', name: 'chill_main_workflow_delete')]
public function delete(EntityWorkflow $entityWorkflow, Request $request): Response
public function delete(#[MapEntity(id: 'id')] EntityWorkflow $entityWorkflow, Request $request): Response
{
$this->denyAccessUnlessGranted(EntityWorkflowVoter::DELETE, $entityWorkflow);
@ -126,7 +127,7 @@ class WorkflowController extends AbstractController
}
#[Route(path: '/{_locale}/main/workflow-step/{id}/access_key', name: 'chill_main_workflow_grant_access_by_key')]
public function getAccessByAccessKey(EntityWorkflowStep $entityWorkflowStep, Request $request): Response
public function getAccessByAccessKey(#[MapEntity(id: 'id')] EntityWorkflowStep $entityWorkflowStep, Request $request): Response
{
if (null === $accessKey = $request->query->get('accessKey', null)) {
throw new BadRequestHttpException('accessKey is missing');
@ -288,7 +289,7 @@ class WorkflowController extends AbstractController
* @throws NonUniqueResultException
*/
#[Route(path: '/{_locale}/main/workflow/{id}/show', name: 'chill_main_workflow_show')]
public function show(EntityWorkflow $entityWorkflow, Request $request): Response
public function show(#[MapEntity(id: 'id')] EntityWorkflow $entityWorkflow, Request $request): Response
{
$this->denyAccessUnlessGranted(EntityWorkflowVoter::SEE, $entityWorkflow);

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Entity;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
@ -24,6 +25,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Index(name: 'chill_main_notification_related_entity_idx', columns: ['relatedentityclass', 'relatedentityid'])]
class Notification implements TrackUpdateInterface
{
use TrackUpdateTrait;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false)]
private string $accessKey;
@ -94,12 +96,6 @@ class Notification implements TrackUpdateInterface
#[ORM\JoinTable(name: 'chill_main_notification_addresses_unread')]
private Collection $unreadBy;
#[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_IMMUTABLE)]
private ?\DateTimeImmutable $updatedAt = null;
#[ORM\ManyToOne(targetEntity: User::class)]
private ?User $updatedBy = null;
public function __construct()
{
$this->addressees = new ArrayCollection();
@ -243,16 +239,6 @@ class Notification implements TrackUpdateInterface
return $this->unreadBy;
}
public function getUpdatedAt(): ?\DateTimeImmutable
{
return $this->updatedAt;
}
public function getUpdatedBy(): ?User
{
return $this->updatedBy;
}
public function isReadBy(User $user): bool
{
return !$this->unreadBy->contains($user);
@ -375,18 +361,4 @@ class Notification implements TrackUpdateInterface
return $this;
}
public function setUpdatedAt(\DateTimeInterface $datetime): self
{
$this->updatedAt = $datetime;
return $this;
}
public function setUpdatedBy(User $user): self
{
$this->updatedBy = $user;
return $this;
}
}

View File

@ -31,6 +31,7 @@ use Chill\TaskBundle\Repository\SingleTaskRepository;
use Chill\TaskBundle\Repository\SingleTaskStateRepository;
use Chill\TaskBundle\Security\Authorization\TaskVoter;
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
@ -159,9 +160,9 @@ final class SingleTaskController extends AbstractController
#[Route(path: '/{_locale}/task/single-task/{id}/edit', name: 'chill_task_single_task_edit')]
public function editAction(
SingleTask $task,
#[MapEntity(id: 'id')] SingleTask $task,
Request $request,
) {
): Response {
$this->denyAccessUnlessGranted(TaskVoter::UPDATE, $task, 'You are not '
.'allowed to edit this task');
@ -251,7 +252,7 @@ final class SingleTaskController extends AbstractController
#[Route(path: '/{_locale}/task/single-task/list', name: 'chill_task_singletask_list')]
public function listAction(
Request $request,
): \Symfony\Component\HttpFoundation\Response {
): Response {
$this->denyAccessUnlessGranted(TaskVoter::SHOW, null);
$showMissionTypeFilter = $this->singleTaskRepository->countByDistinctTypes() > 1;
@ -350,7 +351,7 @@ final class SingleTaskController extends AbstractController
#[Route(path: '/{_locale}/task/single-task/by-person/{id}', name: 'chill_task_singletask_by-person_list')]
public function listPersonTasks(
Person $person,
#[MapEntity(id: 'id')] Person $person,
): Response {
$this->denyAccessUnlessGranted(TaskVoter::SHOW, $person);
@ -398,7 +399,7 @@ final class SingleTaskController extends AbstractController
*/
#[Route(path: '/{_locale}/task/single-task/list/my', name: 'chill_task_singletask_my_tasks', defaults: ['_format' => 'html'])]
#[Route(path: '/api/1.0/task/single-task/list/my', defaults: ['_format' => 'json'])]
public function myTasksAction(string $_format, Request $request): \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
public function myTasksAction(string $_format, Request $request): JsonResponse|Response
{
$this->denyAccessUnlessGranted('ROLE_USER');
@ -565,7 +566,7 @@ final class SingleTaskController extends AbstractController
}
#[Route(path: '/{_locale}/task/single-task/{id}/show', name: 'chill_task_single_task_show')]
public function showAction(SingleTask $task, Request $request): \Symfony\Component\HttpFoundation\Response
public function showAction(#[MapEntity(id: 'id')] SingleTask $task, Request $request): Response
{
$this->denyAccessUnlessGranted(TaskVoter::SHOW, $task);