diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarDocController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarDocController.php index 1f6b42dea..d25998e1e 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarDocController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarDocController.php @@ -12,12 +12,20 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Controller; use Chill\CalendarBundle\Entity\Calendar; +use Chill\CalendarBundle\Entity\CalendarDoc; +use Chill\CalendarBundle\Form\CalendarDocCreateType; +use Chill\CalendarBundle\Form\CalendarDocEditType; +use Chill\CalendarBundle\Security\Voter\CalendarDocVoter; use Chill\CalendarBundle\Security\Voter\CalendarVoter; use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository; +use Doctrine\ORM\EntityManagerInterface; use RuntimeException; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -32,18 +40,202 @@ class CalendarDocController private EngineInterface $engine; + private EntityManagerInterface $entityManager; + + private FormFactoryInterface $formFactory; + private Security $security; private SerializerInterface $serializer; private UrlGeneratorInterface $urlGenerator; - public function __construct(Security $security, DocGeneratorTemplateRepository $docGeneratorTemplateRepository, UrlGeneratorInterface $urlGenerator, EngineInterface $engine) - { - $this->security = $security; + public function __construct( + DocGeneratorTemplateRepository $docGeneratorTemplateRepository, + EngineInterface $engine, + EntityManagerInterface $entityManager, + FormFactoryInterface $formFactory, + Security $security, + UrlGeneratorInterface $urlGenerator + ) { $this->docGeneratorTemplateRepository = $docGeneratorTemplateRepository; - $this->urlGenerator = $urlGenerator; $this->engine = $engine; + $this->entityManager = $entityManager; + $this->formFactory = $formFactory; + $this->security = $security; + $this->urlGenerator = $urlGenerator; + } + + /** + * @Route("/{_locale}/calendar/calendar-doc/{id}/new", name="chill_calendar_calendardoc_new") + */ + public function create(Calendar $calendar, Request $request): Response + { + $calendarDoc = (new CalendarDoc($calendar, null))->setCalendar($calendar); + + if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) { + throw new AccessDeniedHttpException(); + } + + // set variables + switch ($calendarDoc->getCalendar()->getContext()) { + case 'accompanying_period': + $view = '@ChillCalendar/CalendarDoc/new_accompanying_period.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_period'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()]; + + break; + + case 'person': + $view = '@ChillCalendar/CalendarDoc/new_person.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_person'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()]; + + break; + + default: + throw new UnexpectedValueException('Unsupported context'); + } + + $calendarDocDTO = new CalendarDoc\CalendarDocCreateDTO(); + $form = $this->formFactory->create(CalendarDocCreateType::class, $calendarDocDTO); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $calendarDoc->createFromDTO($calendarDocDTO); + + $this->entityManager->persist($calendarDoc); + $this->entityManager->flush(); + + if ($request->query->has('returnPath')) { + return new RedirectResponse($request->query->get('returnPath')); + } + + return new RedirectResponse( + $this->urlGenerator->generate($returnRoute, $returnParams) + ); + } + + return new Response( + $this->engine->render( + $view, + ['calendar_doc' => $calendarDoc, 'form' => $form->createView()] + ) + ); + } + + /** + * @Route("/{_locale}/calendar/calendar-doc/{id}/delete", name="chill_calendar_calendardoc_delete") + */ + public function delete(CalendarDoc $calendarDoc, Request $request): Response + { + if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) { + throw new AccessDeniedHttpException('Not authorized to delete document'); + } + + switch ($calendarDoc->getCalendar()->getContext()) { + case 'accompanying_period': + $view = '@ChillCalendar/CalendarDoc/delete_accompanying_period.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_period'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()]; + + break; + + case 'person': + $view = '@ChillCalendar/CalendarDoc/delete_person.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_person'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()]; + + break; + } + + $form = $this->formFactory->createBuilder() + ->add('submit', SubmitType::class, [ + 'label' => 'Delete', + ]) + ->getForm(); + + $form->handleRequest($request); + + if ($form->isSubmitted()) { + $this->entityManager->remove($calendarDoc); + $this->entityManager->flush(); + + if ($request->query->has('returnPath')) { + return new RedirectResponse($request->query->get('returnPath')); + } + + return new RedirectResponse( + $this->urlGenerator->generate($returnRoute, $returnParams) + ); + } + + return new Response( + $this->engine->render( + $view, + [ + 'calendar_doc' => $calendarDoc, + 'form' => $form->createView(), + ] + ) + ); + } + + /** + * @Route("/{_locale}/calendar/calendar-doc/{id}/edit", name="chill_calendar_calendardoc_edit") + */ + public function edit(CalendarDoc $calendarDoc, Request $request): Response + { + if (!$this->security->isGranted(CalendarDocVoter::EDIT, $calendarDoc)) { + throw new AccessDeniedHttpException(); + } + + // set variables + switch ($calendarDoc->getCalendar()->getContext()) { + case 'accompanying_period': + $view = '@ChillCalendar/CalendarDoc/edit_accompanying_period.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_period'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getAccompanyingPeriod()->getId()]; + + break; + + case 'person': + $view = '@ChillCalendar/CalendarDoc/edit_person.html.twig'; + $returnRoute = 'chill_calendar_calendar_list_by_person'; + $returnParams = ['id' => $calendarDoc->getCalendar()->getPerson()->getId()]; + + break; + + default: + throw new UnexpectedValueException('Unsupported context'); + } + + $calendarDocEditDTO = new CalendarDoc\CalendarDocEditDTO($calendarDoc); + $form = $this->formFactory->create(CalendarDocEditType::class, $calendarDocEditDTO); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $calendarDoc->editFromDTO($calendarDocEditDTO); + + $this->entityManager->flush(); + + if ($request->query->has('returnPath')) { + return new RedirectResponse($request->query->get('returnPath')); + } + + return new RedirectResponse( + $this->urlGenerator->generate($returnRoute, $returnParams) + ); + } + + return new Response( + $this->engine->render( + $view, + ['calendar_doc' => $calendarDoc, 'form' => $form->createView()] + ) + ); } /** diff --git a/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc.php b/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc.php index 458f38654..7012b64e0 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc.php +++ b/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc.php @@ -11,6 +11,8 @@ declare(strict_types=1); namespace Chill\CalendarBundle\Entity; +use Chill\CalendarBundle\Entity\CalendarDoc\CalendarDocCreateDTO; +use Chill\CalendarBundle\Entity\CalendarDoc\CalendarDocEditDTO; use Chill\DocStoreBundle\Entity\StoredObject; use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; use Chill\MainBundle\Doctrine\Model\TrackCreationTrait; @@ -52,14 +54,14 @@ class CalendarDoc implements TrackCreationInterface, TrackUpdateInterface * @ORM\ManyToOne(targetEntity=StoredObject::class, cascade={"persist"}) * @ORM\JoinColumn(nullable=false) */ - private StoredObject $storedObject; + private ?StoredObject $storedObject; /** * @ORM\Column(type="boolean", nullable=false, options={"default": false}) */ private bool $trackDateTimeVersion = false; - public function __construct(Calendar $calendar, StoredObject $storedObject) + public function __construct(Calendar $calendar, ?StoredObject $storedObject) { $this->setCalendar($calendar); @@ -67,6 +69,22 @@ class CalendarDoc implements TrackCreationInterface, TrackUpdateInterface $this->datetimeVersion = $calendar->getDateTimeVersion(); } + public function createFromDTO(CalendarDocCreateDTO $calendarDocCreateDTO): void + { + $this->storedObject = $calendarDocCreateDTO->doc; + $this->storedObject->setTitle($calendarDocCreateDTO->title); + } + + public function editFromDTO(CalendarDocEditDTO $calendarDocEditDTO): void + { + if (null !== $calendarDocEditDTO->doc) { + $calendarDocEditDTO->doc->setTitle($this->getStoredObject()->getTitle()); + $this->setStoredObject($calendarDocEditDTO->doc); + } + + $this->getStoredObject()->setTitle($calendarDocEditDTO->title); + } + public function getCalendar(): Calendar { return $this->calendar; diff --git a/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc/CalendarDocCreateDTO.php b/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc/CalendarDocCreateDTO.php new file mode 100644 index 000000000..b7209e46f --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Entity/CalendarDoc/CalendarDocCreateDTO.php @@ -0,0 +1,30 @@ +title = $calendarDoc->getStoredObject()->getTitle(); + } +} diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarDocCreateType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarDocCreateType.php new file mode 100644 index 000000000..b77886097 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarDocCreateType.php @@ -0,0 +1,42 @@ +add('title', TextType::class, [ + 'label' => 'chill_calendar.Document title', + 'required' => true, + ]) + ->add('doc', StoredObjectType::class, [ + 'label' => 'chill_calendar.Document object', + 'required' => true, + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => CalendarDocCreateDTO::class, + ]); + } +} diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarDocEditType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarDocEditType.php new file mode 100644 index 000000000..26a9d59e2 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarDocEditType.php @@ -0,0 +1,41 @@ +add('title', TextType::class, [ + 'label' => 'chill_calendar.Document title', + 'required' => true, + ]) + ->add('doc', StoredObjectType::class, [ + 'label' => 'chill_calendar.Document object', + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => CalendarDocEditDTO::class, + ]); + } +} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/_documents.twig.html b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/_documents.twig.html index 187f36dd7..e05711422 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/_documents.twig.html +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/_documents.twig.html @@ -17,27 +17,37 @@ {% for d in calendar.documents %} - - -