Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the best way to override object deletion in Sonata Admin?

I already have a custom CRUD controller. So do I just need to override Controller::deleteAction() and Controller::batchDeleteAction() from Sonata\AdminBundle\Controller ?

Or is it preferable / better practice to override the Admin class's delete methods?

My desired behaviour is that I want to update a record with an archived flag rather than delete the entity.

The docs are incomplete on this subject

Update

The following code in my Entity's Repository class iterates over a query object as per the batchDelete method in the ModelManager

public function batchArchive($class, ProxyQuery $queryProxy)
    {

        $queryProxy->select('DISTINCT '.$queryProxy->getRootAlias());

        try {
            $entityManager = $this->getEntityManager();

            $batchSize = 20;
            $i = 0;

            foreach ($queryProxy->getQuery()->iterate() as $pos => $object) {

                $this->archiveMyEntity($object); //???
                if (($i % $batchSize)  == 0) {
                    $entityManager->flush();
                    $entityManager->clear();
                }
                ++$i;
            }

        } catch (\PDOException $e) {
            throw new ModelManagerException('', 0, $e);
        } catch (DBALException $e) {
            throw new ModelManagerException('', 0, $e);
        }
    }

The problem I have is that the object my archiveMyEntity() method expects is an Entity object not a query object.

like image 446
codecowboy Avatar asked May 21 '14 13:05

codecowboy


2 Answers

I overwrote the delete logic in the admin class than in my custom CRUD controller I overwrote the batchActionDelete logic with the following:

public function batchActionDelete(\Sonata\AdminBundle\Datagrid\ProxyQueryInterface $query)
    {
        if (false === $this->admin->isGranted('DELETE')) {
            throw new AccessDeniedException();
        }

        $res = $query->execute();

        if (count($res)) {
            foreach ($res as $sqTeamEntity) {
                $this->admin->delete($sqTeamEntity, false);
            }

            $this->admin->flushDoctrine(); //custom method in the admin class
            $this->addFlash('sonata_flash_success', 'flash_batch_delete_success');
        }

        return new RedirectResponse(
            $this->admin->generateUrl('list',
                $this->admin->getFilterParameters())
        );
    }

So I fetch all the entities and just call the delete method from the admin class.

Hope this helps.

like image 87
AntonioCS Avatar answered Nov 15 '22 04:11

AntonioCS


If you wish to override the controller logic or view, overriding the methods you indicated is the way to go.

However, if your objective is to perform custom logic before or after the deletion, you may override the Admin::preRemove($object) or Admin::postRemove($object) methods.

You may as well override the whole logic by overriding the Admin::delete($object) method.

Feel free to submit a PR - or comment in the related Github issue - to improve the docs as well.

like image 43
Hugo Briand Avatar answered Nov 15 '22 05:11

Hugo Briand