Controller/CRUDController.php
<?php
/*
* Copyright 2016-2018 Arnaud Bienvenu
*
* This file is part of Kyela.
* Kyela is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Kyela is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with Kyela. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace Abienvenu\KyelaBundle\Controller;
use Abienvenu\KyelaBundle\Entity\Entity;
use Abienvenu\KyelaBundle\Entity\Poll;
use Abienvenu\KyelaBundle\Form\Type\FormActionsType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormTypeInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
abstract class CRUDController extends PollSetterController
{
// Member variables that must be defined in the custom controller
protected $entityName;
protected $cancelRoute;
protected $successRoute;
protected $deleteRoute;
protected $deleteSuccessRoute;
// Methods to be implemented in the custom controller
abstract public function newAction(Request $request);
abstract public function editAction(Request $request, $id);
abstract public function deleteAction(Request $request, $id);
/**
* Adds pollUrl into the parameters if not explicitly set
*
* @param string $route
* @param mixed $parameters
* @param Boolean $absolute
*/
protected function generateUrlWithPoll($route, $parameters = [], $absolute = UrlGeneratorInterface::ABSOLUTE_PATH)
{
if (!isset($parameters['pollUrl']) && $this->poll)
{
$parameters['pollUrl'] = $this->poll->getUrl();
}
return parent::generateUrl($route, $parameters, $absolute);
}
/**
* Create a form to create a new entity, and create it when the form is submited
*/
protected function doNewAction($formType, Entity $entity, Request $request, $successMessage = null, $extra = [])
{
$form = $this->doCreateCreateForm($formType, $entity, $request->get('_route'), $extra);
if ($request->isMethod('POST'))
{
$form->handleRequest($request);
if ($entity instanceof Poll)
{
$this->poll = $entity;
}
else
{
$entity->setPoll($this->poll);
}
if ($form->get('actions')->has('cancel') && $form->get('actions')->get('cancel')->isClicked()) {
return $this->redirect($this->generateUrlWithPoll($this->cancelRoute));
}
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
if ($successMessage) {
$request->getSession()->getFlashBag()->add('success', $successMessage);
}
return $this->redirect($this->generateUrlWithPoll($this->successRoute));
}
}
return [
'poll' => $this->poll,
'entity' => $entity,
'form' => $form->createView(),
];
}
/**
* Create a form to edit an entity, and update it when the form is submited
*
* @param string $formType
* @param int $id The entity id
* @param Request $request
*/
protected function doEditAction($formType, $id, Request $request, $extra = [])
{
$em = $this->getDoctrine()->getManager();
/** @var Entity $entity */
$entity = $em->getRepository($this->entityName)->find($id);
if (!$entity) {
throw $this->createNotFoundException("Unable to find entity.");
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->doCreateEditForm($formType, $entity, $request->get('_route'), $extra);
if ($request->isMethod('PUT'))
{
$editForm->handleRequest($request);
if ($editForm->get('actions')->get('cancel')->isClicked()) {
$em->refresh($entity);
return $this->redirect($this->generateUrlWithPoll($this->cancelRoute));
}
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrlWithPoll($this->successRoute));
}
else {
$em->refresh($entity);
}
}
return [
'poll' => $this->poll,
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
];
}
/**
* Deletes an entity
*
* @param Request $request
* @param mixed $id The entity id
*
*/
public function doDeleteAction(Request $request, $id)
{
$form = $this->createDeleteForm($id);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository($this->entityName)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find entity.');
}
$em->remove($entity);
$em->flush();
if ($entity instanceof Poll) {
$this->unsetPoll($request);
}
$flashMessage = $this->get('translator')->trans('deleted');
$request->getSession()->getFlashBag()->add('success', $flashMessage);
}
return $this->redirect($this->generateUrlWithPoll($this->deleteSuccessRoute));
}
/**
* Creates a form to create an entity
*
* @param FormTypeInterface $formType The form builder
* @param Entity $entity The new entity
* @param string $action The name of the route to the action
*
* @return \Symfony\Component\Form\Form The form
*/
protected function doCreateCreateForm($formType, Entity $entity, $action, $extra)
{
$options = $extra + [
'action' => $this->generateUrlWithPoll($action),
'method' => 'POST',
];
$form = $this->createForm($formType, $entity, $options);
$options = [
'buttons' => [
'save' => ['type' => SubmitType::class, 'options' => ['label' => 'create']],
]
];
if (!($entity instanceof Poll))
{
$options['buttons']['cancel'] = ['type' => SubmitType::class, 'options' => ['label' => 'cancel', 'attr' => ['type' => 'default', 'novalidate' => true]]];
}
$form->add('actions', FormActionsType::class, $options);
return $form;
}
/**
* Creates a form to edit an entity
*
* @param string $formType The form builder
* @param Entity $entity The entity to edit
* @param string $action The name of the route to the action
*
* @return \Symfony\Component\Form\Form The form
*/
protected function doCreateEditForm($formType, Entity $entity, $action, $extra = [])
{
$options = $extra + [
'action' => $this->generateUrlWithPoll($action, ['id' => $entity->getId()]),
'method' => 'PUT',
];
$form = $this->createForm($formType, $entity, $options);
$form->add('actions', FormActionsType::class, [
'buttons' => [
'save' => ['type' => SubmitType::class, 'options' => ['label' => 'save']],
'cancel' => ['type' => SubmitType::class, 'options' => ['label' => 'cancel', 'attr' => ['type' => 'default', 'novalidate' => true]]],
]
]);
return $form;
}
/**
* Creates a form to delete an entity by id.
*
* @param int $id The entity id
*
* @return \Symfony\Component\Form\Form The form
*/
protected function createDeleteForm($id)
{
$t = $this->get('translator');
return $this->createFormBuilder()
->setAction($this->generateUrlWithPoll($this->deleteRoute, ['id' => $id]))
->setMethod('DELETE')
->add('submit', SubmitType::class, ['label' => 'delete', 'attr' => ['type' => 'danger', 'onclick' => "return confirm('{$t->trans("are.you.sure.to.delete")}');"]])
->getForm();
}
}