<commit_before><?php
/**
 * Created by PhpStorm.
 * User: AlexanderC <<EMAIL>>
 * Date: 7/22/14
 * Time: 11:10
 */

namespace AlexanderC\Api\MasheryBundle\EventListener;


use AlexanderC\Api\Mashery\InternalObjectInterface;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmRemoveException;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmSyncException;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmValidationException;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use AlexanderC\Api\Mashery\Mashery;

class OrmSyncSubscriber implements EventSubscriber
{
    use ContainerAwareTrait;

    const CREATE = 0x001;
    const UPDATE = 0x002;
    const REMOVE = 0x003;

    const MASHERY_TRAIT = 'AlexanderC\Api\MasheryBundle\Orm\MasheryObjectTrait';

    /**
     * @var array
     */
    protected $usesCache = [];

    /**
     * {@inheritdoc}
     */
    public function getSubscribedEvents()
    {
        return [
            'prePersist',
            'preUpdate',
            'postPersist',
            'postUpdate',
            'postRemove'
        ];
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        $this->managePreEvent($args, self::UPDATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function prePersist(LifecycleEventArgs $args)
    {
        $this->managePreEvent($args, self::CREATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postUpdate(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::UPDATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postPersist(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::CREATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postRemove(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::REMOVE);
    }

    /**
     * @param LifecycleEventArgs $args
     * @param int $eventType
     * @throws Exception\OrmValidationException
     */
    protected function managePreEvent(LifecycleEventArgs $args, $eventType)
    {
        $entity = $args->getEntity();

        switch($eventType) {
            case self::CREATE:
            case self::UPDATE:
                if($this->isMasheryObject($entity) && false === $entity->getSkipValidation()) {
                    $response = $this->getMashery()->validate($entity);

                    // verify for entity validity
                    if($response->isError()) {
                        throw new OrmValidationException($entity, $response->getError());
                    }
                }
                break;
        }
    }

    /**
     * @param LifecycleEventArgs $args
     * @param int $eventType
     * @throws Exception\OrmRemoveException
     * @throws Exception\OrmSyncException
     */
    protected function managePostEvent(LifecycleEventArgs $args, $eventType)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        switch($eventType) {
            case self::CREATE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->create($entity);

                    if($response->isError()) {
                        throw new OrmSyncException($entity, $response->getError());
                    }

                    $entity->setMasherySyncState(false);
                    $entityManager->persist($entity);
                    $entityManager->flush();
                    $entity->setMasherySyncState(true);
                }
                break;
            case self::UPDATE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->update($entity);

                    if($response->isError()) {
                        throw new OrmSyncException($entity, $response->getError());
                    }

                    $entity->setMasherySyncState(false);
                    $entityManager->persist($entity);
                    $entityManager->flush();
                    $entity->setMasherySyncState(true);
                }
                break;
            case self::REMOVE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->delete($entity);

                    if($response->isError()) {
                        throw new OrmRemoveException($entity, $response->getError());
                    }
                }
                break;
        }
    }

    /**
     * @param object $entity
     * @return bool
     */
    protected function isMasheryObject($entity)
    {
        $entityClass = get_class($entity);

        if(!isset($this->usesCache[$entityClass])) {
            $this->usesCache[$entityClass] = self::classUsesDeep($entityClass);
        }

        return $entity instanceof InternalObjectInterface
                && in_array(self::MASHERY_TRAIT, $this->usesCache[$entityClass])
                // disable classes that does not need to be synced
                && true === $entity->getMasherySyncState();
    }

    /**
     * @param string $class
     * @return array
     */
    protected static function classUsesDeep($class)
    {
        $traits = [];

        // Get traits of all parent classes
        do {
            $traits = array_merge(class_uses($class, true), $traits);
        } while ($class = get_parent_class($class));

        // Get traits of all parent traits
        $traitsToSearch = $traits;

        while (!empty($traitsToSearch)) {
            $newTraits = class_uses(array_pop($traitsToSearch), true);
            $traits = array_merge($newTraits, $traits);
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
        }

        foreach ($traits as $trait => $same) {
            $traits = array_merge(class_uses($trait, true), $traits);
        }

        return array_unique($traits);
    }

    /**
     * @return Mashery
     */
    protected function getMashery()
    {
        return $this->container->get('mashery.api');
    }
} <commit_msg>fix pre update validation mashery issue<commit_after><?php
/**
 * Created by PhpStorm.
 * User: AlexanderC <<EMAIL>>
 * Date: 7/22/14
 * Time: 11:10
 */

namespace AlexanderC\Api\MasheryBundle\EventListener;


use AlexanderC\Api\Mashery\InternalObjectInterface;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmRemoveException;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmSyncException;
use AlexanderC\Api\MasheryBundle\EventListener\Exception\OrmValidationException;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use AlexanderC\Api\Mashery\Mashery;

class OrmSyncSubscriber implements EventSubscriber
{
    use ContainerAwareTrait;

    const CREATE = 0x001;
    const UPDATE = 0x002;
    const REMOVE = 0x003;

    const MASHERY_TRAIT = 'AlexanderC\Api\MasheryBundle\Orm\MasheryObjectTrait';

    /**
     * @var array
     */
    protected $usesCache = [];

    /**
     * {@inheritdoc}
     */
    public function getSubscribedEvents()
    {
        return [
            'prePersist',
            'preUpdate',
            'postPersist',
            'postUpdate',
            'postRemove'
        ];
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function preUpdate(LifecycleEventArgs $args)
    {
        $this->managePreEvent($args, self::UPDATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function prePersist(LifecycleEventArgs $args)
    {
        $this->managePreEvent($args, self::CREATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postUpdate(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::UPDATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postPersist(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::CREATE);
    }

    /**
     * @param LifecycleEventArgs $args
     */
    public function postRemove(LifecycleEventArgs $args)
    {
        $this->managePostEvent($args, self::REMOVE);
    }

    /**
     * @param LifecycleEventArgs $args
     * @param int $eventType
     * @throws Exception\OrmValidationException
     */
    protected function managePreEvent(LifecycleEventArgs $args, $eventType)
    {
        $entity = $args->getEntity();

        $skipUpdateFields = false;

        switch($eventType) {
            case self::UPDATE:
                $skipUpdateFields = true;
            case self::CREATE:
                if($this->isMasheryObject($entity) && false === $entity->getSkipValidation()) {
                    $response = $this->getMashery()->validate($entity, $skipUpdateFields);

                    // verify for entity validity
                    if($response->isError()) {
                        throw new OrmValidationException($entity, $response->getError());
                    }
                }
                break;
        }
    }

    /**
     * @param LifecycleEventArgs $args
     * @param int $eventType
     * @throws Exception\OrmRemoveException
     * @throws Exception\OrmSyncException
     */
    protected function managePostEvent(LifecycleEventArgs $args, $eventType)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        switch($eventType) {
            case self::CREATE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->create($entity);

                    if($response->isError()) {
                        throw new OrmSyncException($entity, $response->getError());
                    }

                    $entity->setMasherySyncState(false);
                    $entityManager->persist($entity);
                    $entityManager->flush();
                    $entity->setMasherySyncState(true);
                }
                break;
            case self::UPDATE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->update($entity);

                    if($response->isError()) {
                        throw new OrmSyncException($entity, $response->getError());
                    }

                    $entity->setMasherySyncState(false);
                    $entityManager->persist($entity);
                    $entityManager->flush();
                    $entity->setMasherySyncState(true);
                }
                break;
            case self::REMOVE:
                if($this->isMasheryObject($entity)) {
                    $response = $this->getMashery()->delete($entity);

                    if($response->isError()) {
                        throw new OrmRemoveException($entity, $response->getError());
                    }
                }
                break;
        }
    }

    /**
     * @param object $entity
     * @return bool
     */
    protected function isMasheryObject($entity)
    {
        $entityClass = get_class($entity);

        if(!isset($this->usesCache[$entityClass])) {
            $this->usesCache[$entityClass] = self::classUsesDeep($entityClass);
        }

        return $entity instanceof InternalObjectInterface
                && in_array(self::MASHERY_TRAIT, $this->usesCache[$entityClass])
                // disable classes that does not need to be synced
                && true === $entity->getMasherySyncState();
    }

    /**
     * @param string $class
     * @return array
     */
    protected static function classUsesDeep($class)
    {
        $traits = [];

        // Get traits of all parent classes
        do {
            $traits = array_merge(class_uses($class, true), $traits);
        } while ($class = get_parent_class($class));

        // Get traits of all parent traits
        $traitsToSearch = $traits;

        while (!empty($traitsToSearch)) {
            $newTraits = class_uses(array_pop($traitsToSearch), true);
            $traits = array_merge($newTraits, $traits);
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
        }

        foreach ($traits as $trait => $same) {
            $traits = array_merge(class_uses($trait, true), $traits);
        }

        return array_unique($traits);
    }

    /**
     * @return Mashery
     */
    protected function getMashery()
    {
        return $this->container->get('mashery.api');
    }
} 
{'fraction_non_alphanumeric': 0.12172682236376504, 'fraction_numerical': 0.0033026657230478887, 'mean_word_length': 1.9521819870009285, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5267650', 'n_tokens_mistral': 3634, 'n_tokens_neox': 3353, 'n_words': 596}