Search code examples
phpsymfonysonata-admin

Symfony2: Overriding createAction() in SonataAdmin


I've been googling as crazy the last days trying to figure out (with no success) how override a SonataAdmin action to capture the session username and save it in the foreign key field.

AttachmentAdminController class:

<?php

namespace Application\Sonata\UserBundle\Controller;

use Sonata\AdminBundle\Controller\CRUDController as Controller;
#use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\UserBundle\Entity\User;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Symfony\Bridge\Monolog\Logger;
use Mercury\CargoRecognitionBundle\Entity\Attachment;

class AttachmentAdminController extends Controller
{
    /**
     * (non-PHPdoc)
     * @see Sonata\AdminBundle\Controller.CRUDController::createAction()
     */
    public function createAction()
    {
        $result = parent::createAction();

        if ($this->get('request')->getMethod() == 'POST')
        {
            $flash = $this->get('session')->getFlash('sonata_flash_success');

            if (!empty($flash) && $flash == 'flash_create_success')
            {
                #$userManager = $this->container->get('fos_user.user_manager');
                #$user = $this->container->get('context.user');
                #$userManager = $session->get('username');
                $user = $this->container->get('security.context')->getToken()->getUser()->getUsername();

                $attachment = new Attachment();
                $attachment->setPath('/tmp/image.jpg');
                $attachment->setNotes('nothing interesting to say');
                $attachment->getSystemUser($user);

                $em = $this->getDoctrine()->getEntityManager();
                $em->persist($product);
                $em->flush();
            }
        }

        return $result;
    }
}

service attachment:

mercury.cargo_recognition.admin.attachment:
    class: Mercury\CargoRecognitionBundle\Admin\AttachmentAdmin
    tags:
        - { name: sonata.admin, manager_type: orm, group: General, label: Attachments }
    arguments: [ null, Mercury\CargoRecognitionBundle\Entity\Attachment, "SonataAdminBundle:CRUD" ]

Seems to me as the actionController() is been ignored by SonataAdminBundle (and maybe the whole class file), because there's not error messages at all, but I don't know why. Actually, I'm not sure if I'm fetching the username from the session.

I really need a good tutorial about this, but seems like any information I get about this is obsolete in some aspect. By the way, I'm using Symfony 2.0.16


Solution

  • Finally I got to the solution. I'm sure there are some others (like using event listeners, for example, that seems to be simpler), but right now it's the best I could find (it works, and that's what matters).

    I was trying to override the createAction() based on examples that I found in another forum thread, but I was getting two records in the table instead of one only. The most important thing was overriding the WHOLE action method and put the custom code in it.

    Controller:

    <?php
    
    namespace Mercury\CargoRecognitionBundle\Controller;
    
    use Symfony\Component\Security\Core\SecurityContextInterface;
    use Symfony\Bridge\Monolog\Logger;
    use Sonata\AdminBundle\Controller\CRUDController as Controller;
    use Application\Sonata\UserBundle\Entity\User;
    use Mercury\CargoRecognitionBundle\Entity\Attachment;
    use Mercury\CargoRecognitionBundle\Entity\SystemUser;
    use Mercury\CargoRecognitionBundle\Repository\SystemUserRepository;
    
    class AttachmentAdminController extends Controller
    {
        /**
         * Set the system user ID
         */
        private function updateFields($object)
        {
            $userName = $this->container->get('security.context')
                            ->getToken()
                            ->getUser()
                            ->getUsername();
    
            $user = $this->getDoctrine()
                        ->getRepository('ApplicationSonataUserBundle:User')
                        ->findOneByUsername($userName);
    
            $object->setSystemUser($user);
    
            return $object;
        }
    
        /**
         * (non-PHPdoc)
         * @see Sonata\AdminBundle\Controller.CRUDController::createAction()
         */
        public function createAction()
        {
            // the key used to lookup the template
            $templateKey = 'edit';
    
            if (false === $this->admin->isGranted('CREATE')) {
                throw new AccessDeniedException();
            }
    
            $object = $this->admin->getNewInstance();
    
            $object = $this->updateFields($object);
    
            // custom method
            $this->admin->setSubject($object);
    
            $form = $this->admin->getForm();
            $form->setData($object);
    
            if ($this->get('request')->getMethod() == 'POST') {
                $form->bindRequest($this->get('request'));
    
                $isFormValid = $form->isValid();
    
                // persist if the form was valid and if in preview mode the preview was approved
                if ($isFormValid && (!$this->isInPreviewMode() || $this->isPreviewApproved())) {
                    $this->admin->create($object);
    
                    if ($this->isXmlHttpRequest()) {
                        return $this->renderJson(array(
                            'result' => 'ok',
                            'objectId' => $this->admin->getNormalizedIdentifier($object)
                        ));
                    }
    
                    $this->get('session')->setFlash('sonata_flash_success','flash_create_success');
                    // redirect to edit mode
                    return $this->redirectTo($object);
                }
    
                // show an error message if the form failed validation
                if (!$isFormValid) {
                    $this->get('session')->setFlash('sonata_flash_error', 'flash_create_error');
                } elseif ($this->isPreviewRequested()) {
                    // pick the preview template if the form was valid and preview was requested
                    $templateKey = 'preview';
                }
            }
    
            $view = $form->createView();
    
            // set the theme for the current Admin Form
            $this->get('twig')->getExtension('form')->setTheme($view, $this->admin->getFormTheme());
    
            return $this->render($this->admin->getTemplate($templateKey), array(
                'action' => 'create',
                'form'   => $view,
                'object' => $object,
            ));
        }
    }
    

    Service for the controller:

    mercury.cargo_recognition.admin.attachment:
        class: Mercury\CargoRecognitionBundle\Admin\AttachmentAdmin
        tags:
            - { name: sonata.admin, manager_type: orm, group: General, label: Attachments }
        arguments: [ null, Mercury\CargoRecognitionBundle\Entity\Attachment, "MercuryCargoRecognitionBundle:AttachmentAdmin" ]
    

    I took the solution from the following sites:

    (And the Sonata Project documentation)