Sonata Admin:如何验证删除操作?

Sonata Admin: how validate remove action?

如何在 sonata-admin 中删除操作和设置 flash 消息之前检查条件?

我不想删除超级用户。我当前的代码:

public function preRemove($object)
    {
        parent::preRemove($object);
        if ($object->getId() === User::SUPER_USER_ID) {
            throw new AccessDeniedException();
        }
    }

它抛出异常。我需要在管理面板中发送 flash 消息。

这是覆盖功能。如果你想停止删除或删除,如果一切正常,你只需将 parent::preRemove($object);parent::remove($object); 放在函数的末尾。

public function preRemove($object)
{
    if ($object->getId() === User::SUPER_USER_ID) {
        $this->getRequest()->getSession()->getFlashBag()->add(
            'error',
            'Title, Abstract and Small tile Media are required'
        );
        return;
    }
    //other code to check here

    parent::preRemove($object); 
}

public function remove($object)
{
    if ($object->getId() === User::SUPER_USER_ID) {
        $this->getRequest()->getSession()->getFlashBag()->add(
            'error',
            'Title, Abstract and Small tile Media are required'
        );
        return;
    }
    //other code to check here

    parent::remove($object); 
}

谢谢 Ryuk Lee,他让我研究了代码 :)

解决方案:

public function preRemove($object)
    {
        parent::preRemove($object);
        if ($object->getId() === User::SUPER_USER_ID) {
            $this->getRequest()->getSession()->getFlashBag()->add('sonata_flash_error','Not delete super user');
            throw new ModelManagerException();
        }
    }

ModelManagerException - 这是使奏鸣曲正常工作的异常。不要删除对象并在管理面板中写错误消息,没有 "success" 消息。只工作 debug = false.

$kernel = new AppKernel('dev', false);

但是我遇到了一个问题,toogle 错误消息("more"):

2个解决方案:

1) 覆盖模板

config.xml

sonata_admin:
    templates:
        layout: 'admin/layout.html.twig'

layout.html.twig

{% extends '@SonataAdmin/standard_layout.html.twig' %}

{% block notice %}
    {% include 'admin/flash_messages.html.twig' %}
{% endblock notice %}

flash_messages.html.twig

{% for type in sonata_flashmessages_types() %}
    {% set domain = domain is defined ? domain : null %}
    {% set messages = sonata_flashmessages_get(type, domain) %}
    {% if messages|length > 0 %}
        {% for message in messages %}
            <div class="alert alert-{{ type|sonata_status_class }} alert-dismissable">
                <button
                        type="button"
                        class="close"
                        data-dismiss="alert"
                        aria-hidden="true"
                        aria-label="{{ 'message_close'|trans({}, 'SonataCoreBundle') }}">
                    &times;
                </button>
                {{ message | raw }}
            </div>
        {% endfor %}
    {% endif %}
{% endfor %}

结果:

2) 覆盖管理控制器。

serivices.yml

admin.user.admin:
    class: AppBundle\Admin\AdminUserAdmin
    arguments: [~, AppBundle\Entity\User, AppBundle\Controller\Admin\AdminUserCRUDController]
    tags:
      - { name: sonata.admin, manager_type: orm, label: 'Admins' }

AdminUserCRUDController

class AdminUserCRUDController extends CRUDController
{
   public function deleteAction($id)
   {
       $redirectResponse = parent::deleteAction($id);
       /** @var FlashBagInterface $flashBag */
       $flashBag = $this->container->get('session')->getFlashBag();
       if($errors = $flashBag->get('sonata_flash_error')){
           $flashBag->set(
               'sonata_flash_error',
               implode('. ',array_unique($errors))
           );
       }
       return $redirectResponse;
   }

结果:

我为此使用了 CRUD 控制器 preDelete() 钩子。

class MyCrudController extends CRUDController
{
    protected function preDelete(Request $request, $object): ?RedirectResponse
    {
        if (/* some blocking condition */) {
            $this->addFlash(
                'sonata_flash_error',
                $this->trans(
                    'flash_not_allowed_because_of_reasons',
                    ['%name%' => $this->escapeHtml($object)],
                    'SonataAdminBundle'
                )
            );
            return $this->redirectTo($object);
        }

        return null;
    }
}

在 Sonata Admin CRUD Controller 中它将运行这个检查:

    $preResponse = $this->preDelete($request, $object);
    if (null !== $preResponse) {
        return $preResponse;
    }

因此,如果您 return 来自 preDelete() 方法的响应,则 Sonata Admin 将不会继续删除。使用这种方法,您将只有一条闪现消息。