Pierstoval
4/24/2017 - 8:05 PM

A subscriber that allow you to check what entities have been updated/inserted/unchanged based on a "batch action" from a controller

A subscriber that allow you to check what entities have been updated/inserted/unchanged based on a "batch action" from a controller

<?php

namespace AppBundle\Controller;

use AppBundle\Entity\Post;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class ApiController extends Controller
{
    /**
     * @Route("/api/update", name="api_update")
     */
    public function indexAction()
    {
        /**
         * A bunch of actions that reproduce:
         * - One insert
         * - One update
         * - One "unchanged"
         */
        $em = $this->getDoctrine()->getManager();

        $post = new Post();
        $post->setAuthor($this->getUser());
        $post->setTitle('New title');
        $post->setSlug('new-title');
        $post->setSummary('new summary');
        $post->setContent('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod.');

        $em->persist($post);

        $lastPost = $em->getRepository('AppBundle:Post')->findOneBy([]);

        $anotherPost = $em->getRepository('AppBundle:Post')->find(2);

        $em->persist($anotherPost);

        $lastPost->setSummary('Lorem ipsum dolor sit amet, consectetur adipisicing');

        $em->flush();

        dump('ok');exit;
    }

}
<?php

/**
 * This file is part of the symfony_demo package.
 *
 * (c) Alexandre Rock Ancelet <alex@orbitale.io>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace AppBundle\Doctrine;

use AppBundle\Entity\Post;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;

class EntitySuscriber implements EventSubscriber
{
    const SUPPORTED_CLASSES = [
        Post::class,
    ];

    /**
     * @var array[]
     */
    private $eventSuscriberParamsExtractor;

    /**
     * @var array
     */
    private $extractor;

    public function __construct()
    {
        $this->eventSuscriberParamsExtractor = [];

        $this->extractor = [
            'inserted' => [],
            'noaction' => [],
            'updated'  => [],
        ];
    }

    /**
     * @param OnFlushEventArgs $onFlushEventArgs
     */
    public function onFlush(OnFlushEventArgs $onFlushEventArgs)
    {
        $em = $onFlushEventArgs->getEntityManager();
        $uow = $em->getUnitOfWork();

        //Insertions
        foreach ($uow->getScheduledEntityInsertions() as $entity) {
            $class = get_class($entity);
            if (!in_array($class, static::SUPPORTED_CLASSES, true)) {
                continue;
            }
            $this->extractor['inserted'][$class][] = $entity;
        }

        //Updates
        foreach ($uow->getScheduledEntityUpdates() as $entity) {
            $class = get_class($entity);
            if (!in_array($class, static::SUPPORTED_CLASSES, true)) {
                continue;
            }
            $this->extractor['updated'][$class][] = $entity;
        }

        foreach ($uow->getIdentityMap() as $class => $entities) {
            if (!count($entities) || !in_array($class, static::SUPPORTED_CLASSES, true)) {
                continue;
            }
            foreach ($entities as $entity) {
                if (!count($uow->getEntityChangeSet($entity))) {
                    $this->extractor['noaction'][$class][] = $entity;
                }
            }
        }

        dump($this->extractor);
        exit;
    }

    /**
     * Gets all succesfully entities flushed
     *
     * @param PostFlushEventArgs $postFlushEventArgs Event args
     */
    public function postFlush(PostFlushEventArgs $postFlushEventArgs)
    {
        $this->eventSuscriberParamsExtractor->setExtractor($this->extractor);
    }

    /**
     * Returns an array of events this subscriber wants to listen to.
     *
     * @return array
     */
    public function getSubscribedEvents(): array
    {
        return [
            'onFlush',
            'preUpdate',
            'postFlush',
        ];
    }
}