[wip] CRUD

This commit is contained in:
Julien Fastré 2019-12-03 15:04:39 +01:00
parent 1860a6bae4
commit 257d101fbe
5 changed files with 136 additions and 31 deletions

View File

@ -28,6 +28,9 @@ use Chill\MainBundle\Pagination\PaginatorFactory;
use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormInterface;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/** /**
* *
@ -129,9 +132,42 @@ class CRUDController extends AbstractController
return $this->formEditAction('edit', $request, $id); return $this->formEditAction('edit', $request, $id);
} }
protected function formEditAction($action, Request $request, $id, $formClass = null): Response public function view(Request $request, $id): Response
{ {
$entity = $this->getEntity($id, $request); return $this->viewAction('view', $request, $id);
}
protected function viewAction($action, Request $request, $id)
{
$entity = $this->getEntity($action, $id, $request);
$postFetch = $this->onPostFetchEntity($action, $request, $entity);
if ($postFetch instanceof Response) {
return $postFetch;
}
$this->checkACL($action, $entity);
$postCheckACL = $this->onPostCheckACL($action, $request, $entity);
if ($postCheckACL instanceof Response) {
return $postCheckACL;
}
$defaultTemplateParameters = [
'entity' => $entity
];
return $this->render(
$this->getTemplateFor($action, $entity, $request),
$this->generateTemplateParameter($action, $entity, $request, $defaultTemplateParameters)
);
}
protected function formEditAction($action, Request $request, $id, $formClass = null, $formOptions = []): Response
{
$entity = $this->getEntity($action, $id, $request);
if (NULL === $entity) { if (NULL === $entity) {
throw $this->createNotFoundException(sprintf("The %s with id %s " throw $this->createNotFoundException(sprintf("The %s with id %s "
@ -140,7 +176,7 @@ class CRUDController extends AbstractController
$this->checkACL($action, $entity); $this->checkACL($action, $entity);
$form = $this->createFormFor($action, $entity, $formClass); $form = $this->createFormFor($action, $entity, $formClass, $formOptions);
$form->handleRequest($request); $form->handleRequest($request);
@ -165,7 +201,7 @@ class CRUDController extends AbstractController
]); ]);
} elseif ($form->isSubmitted()) { } elseif ($form->isSubmitted()) {
$this->addFlash('error', $this->generateFormErrorMessage($form)); $this->addFlash('error', $this->generateFormErrorMessage($action, $form));
} }
$defaultTemplateParameters = [ $defaultTemplateParameters = [
@ -213,7 +249,7 @@ class CRUDController extends AbstractController
return $this->redirectToRoute('chill_crud_'.$this->get, ['id' => $entity->getId()]); return $this->redirectToRoute('chill_crud_'.$this->get, ['id' => $entity->getId()]);
} elseif ($form->isSubmitted()) { } elseif ($form->isSubmitted()) {
$this->addFlash('error', $this->generateFormErrorMessage($form)); $this->addFlash('error', $this->generateFormErrorMessage($action, $form));
} }
$defaultTemplateParameters = [ $defaultTemplateParameters = [
@ -233,11 +269,14 @@ class CRUDController extends AbstractController
* @param string $id * @param string $id
* @return object * @return object
*/ */
protected function getEntity($id, Request $request): ?object protected function getEntity($action, $id, Request $request): ?object
{ {
return $this->getDoctrine() return $this->getDoctrine()
->getRepository($this->getEntityClass()) ->getRepository($this->getEntityClass())
->find($id); ->find($id);
} }
protected function getEntityClass(): string protected function getEntityClass(): string
@ -279,18 +318,29 @@ class CRUDController extends AbstractController
?? $this->crudConfig['form_class']; ?? $this->crudConfig['form_class'];
} }
protected function createFormFor($action, $entity, $formClass = null) protected function createFormFor($action, $entity, $formClass = null, $formOptions = [])
{ {
$formClass = $formClass ?? $this->getFormClassFor($action); $formClass = $formClass ?? $this->getFormClassFor($action);
$form = $this->createForm($formClass, $entity); $form = $this->createForm($formClass, $entity, $formOptions);
$form->add('submit', SubmitType::class, [
'label' => $action $this->addDefaultButtons($action, $form);
]);
return $form; return $form;
} }
protected function addDefaultButtons($action, FormInterface $form)
{
$form->add('submit', SubmitType::class, [
'label' => $this->generateLabelForButton($action, 'submit', $form)
]);
}
protected function generateLabelForButton($action, $formName, $form)
{
return $action;
}
protected function generateFormErrorMessage($action, FormInterface $form): string protected function generateFormErrorMessage($action, FormInterface $form): string
{ {
$msg = 'This form contains errors'; $msg = 'This form contains errors';
@ -365,6 +415,16 @@ class CRUDController extends AbstractController
{ {
} }
protected function onPostFetchEntity($action, Request $request, $entity): ?Response
{
return null;
}
protected function onPostCheckACL($action, Request $request, $entity): ?Response
{
return null;
}
protected function onFormValid(object $entity, FormInterface $form, Request $request) protected function onFormValid(object $entity, FormInterface $form, Request $request)
{ {
} }
@ -383,6 +443,23 @@ class CRUDController extends AbstractController
return $this->container->get('translator'); return $this->container->get('translator');
} }
protected function getAuthorizationHelper(): AuthorizationHelper
{
return $this->container->get(AuthorizationHelper::class);
}
protected function getReachableCenters(Role $role, Scope $scope = null)
{
return $this->getAuthorizationHelper()
->getReachableCenters($this->getUser(), $role, $scope)
;
}
protected function getEventDispatcher(): EventDispatcherInterface
{
return $this->get(EventDispatcherInterface::class);
}
public static function getSubscribedServices() public static function getSubscribedServices()
{ {
return \array_merge( return \array_merge(
@ -390,7 +467,9 @@ class CRUDController extends AbstractController
[ [
PaginatorFactory::class => PaginatorFactory::class, PaginatorFactory::class => PaginatorFactory::class,
'translator' => TranslatorInterface::class, 'translator' => TranslatorInterface::class,
AuthorizationHelper::class => AuthorizationHelper::class,
EventDispatcherInterface::class => EventDispatcherInterface::class,
] ]
); );
} }
} }

View File

@ -63,23 +63,23 @@ class CRUDRoutesLoader
{ {
$collection = new RouteCollection(); $collection = new RouteCollection();
foreach ($config['actions'] as $action) { foreach ($config['actions'] as $name => $action) {
$defaults = [ $defaults = [
'_controller' => $config['controller'].'::'.$action '_controller' => $action['controller'] ?? $config['controller'].'::'.$name
]; ];
if ($action === 'index') { if ($action === 'index') {
$path = "{_locale}".$config['base_path']; $path = "{_locale}".$config['base_path'];
$route = new Route($path, $defaults); $route = new Route($path, $defaults);
} else { } else {
$path = "{_locale}".$config['base_path'].'/{id}/'.$action; $path = "{_locale}".$config['base_path'].($action['path'] ?? '/{id}/'.$name);
$requirements = [ $requirements = $action['requirements'] ?? [
'{id}' => '\d+' '{id}' => '\d+'
]; ];
$route = new Route($path, $defaults, $requirements); $route = new Route($path, $defaults, $requirements);
} }
$collection->add('chill_crud_'.$config['name'].'_'.$action, $route); $collection->add('chill_crud_'.$config['name'].'_'.$name, $route);
} }
return $collection; return $collection;

View File

@ -127,9 +127,32 @@ class Configuration implements ConfigurationInterface
->scalarNode('base_role')->defaultNull()->end() ->scalarNode('base_role')->defaultNull()->end()
->scalarNode('form_class')->defaultNull()->end() ->scalarNode('form_class')->defaultNull()->end()
->arrayNode('actions') ->arrayNode('actions')
->scalarPrototype()->end() ->defaultValue([
->defaultValue(['index', 'new', 'edit', 'show', 'delete']) 'edit' => [],
'new' => []
])
->useAttributeAsKey('name')
->arrayPrototype()
->children()
->scalarNode('controller')
->defaultValue('')
->info('the method name to call in the route. Will be set to the action name if left empty.')
->example("'MyBundle\Controller\MyCrudController::action'")
->end()
->scalarNode('path')
->defaultValue('')
->info('the path that will be **appended** after the base path. Do not forget to add '
. 'arguments for the method. Will be set to the action name, including an `{id}` '
. 'parameter if left empty.')
->example('/{id}/my-action')
->end()
->arrayNode('requirements')
->ignoreExtraKeys(false)
->info('the requirements for the route. Will be set to `[ \'id\' => \'\d+\' ]` if left empty.')
->end()
->end()
->end() ->end()
->end()
->end() ->end()
->end() ->end()

View File

@ -34,6 +34,7 @@ Save: Enregistrer
This form contains errors: Ce formulaire contient des erreurs This form contains errors: Ce formulaire contient des erreurs
Choose an user: Choisir un utilisateur Choose an user: Choisir un utilisateur
'You are going to leave a page with unsubmitted data. Are you sure you want to leave ?': "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?" 'You are going to leave a page with unsubmitted data. Are you sure you want to leave ?': "Vous allez quitter la page alors que des données n'ont pas été enregistrées. Êtes vous sûr de vouloir partir ?"
No value: Aucune information
Edit: Modifier Edit: Modifier
Update: Mettre à jour Update: Mettre à jour

View File

@ -5,22 +5,24 @@
{% block crud_content_form %} {% block crud_content_form %}
{{ form_start(form) }} {{ form_start(form) }}
{% block crud_content_form_rows %}
{% for f in form if f.vars.name != 'submit' %} {% for f in form if f.vars.name != 'submit' %}
{{ form_row(f) }} {{ form_row(f) }}
{% endfor %} {% endfor %}
{% endblock crud_content_form_rows %}
{% block crud_content_form_actions %} {% block crud_content_form_actions %}
<div class="{% block crud_content_form_actions_class %}grid-12 centered sticky-form-buttons{% endblock %}"> <ul class="record_actions sticky-form-buttons">
<ul class="record_actions"> {% block content_form_actions_back %}
{% block content_form_actions_back %} <li class="cancel">
<li class="cancel"> <a class="sc-button bt-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}">
<a class="sc-button bt-cancel" href="{{ chill_return_path_or('chill_crud_'~crud_name~'_index') }}"> {{ 'Cancel'|trans }}
{{ 'Cancel'|trans }} </a>
</a> </li>
{% endblock %} {% endblock %}
<li>{{ form_widget(form.submit, { 'attr': { 'class': 'sc-button bt-edit'} } ) }}</li> <li>{{ form_widget(form.submit, { 'attr': { 'class': 'sc-button bt-edit'} } ) }}</li>
</ul> </ul>
</div>
{% endblock %} {% endblock %}
{{ form_end(form) }} {{ form_end(form) }}