Ver Fonte

avances doctrine action event subscriber

Guillermo Espinoza há 8 anos atrás
pai
commit
3d6c4b0da6

+ 61 - 0
Command/WorkflowRunActionCommand.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace WorkflowBundle\Command;
+
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use WorkflowBundle\Utils\WorkFlowEntityClasses;
+
+class WorkflowRunActionCommand extends ContainerAwareCommand
+{
+
+    protected function configure()
+    {
+        $this
+            ->setName('workflow:run:action')
+            ->setDescription('Ejecuta un Action de workflow para una Entidad')
+            ->setHelp('Ejecuta un Action (WorflowBundle\Entity\Action) de workflow para una Entidad (WorkflowBundle\Utils\WorkFlowEntityClasses)')
+            ->addOption(
+                'action',
+                null,
+                InputOption::VALUE_REQUIRED,
+                'Action name'
+            )
+            ->addOption(
+                'entity',
+                null,
+                InputOption::VALUE_REQUIRED,
+                'Entity Class. Possible values: ' . implode(', ', WorkFlowEntityClasses::getConstants()) 
+            )
+            ->addOption(
+                'id',
+                null,
+                InputOption::VALUE_REQUIRED,
+                'Entity id'
+            )
+        ;
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        /* @var $producerService \WorkflowBundle\Services\ProducerService */
+        $producerService = $this->getContainer()->get("workflow.producer_service");
+        $actionName = $input->getOption('action');
+        $entityClass = $input->getOption('entity');
+        $entityId = $input->getOption('id');
+        
+        if ($actionName && $entityClass && $entityId) {
+            $producerService->executeAction($actionName, $entityClass, $entityId);
+            $output->writeln("<info>Action '{$actionName}' para la entidad '{$entityClass}' ejecutada</info>");
+        } else {
+            $output->writeln('<error>Ingrese todas las opciones</error>');
+        }
+    }
+
+}

+ 46 - 3
Entity/Action.php

@@ -83,6 +83,18 @@ class Action
      */
     protected $tenancyId = 1;
 
+    /**
+     * Array con variables de contexto a utilizar en el render del template
+     *
+     * @var array
+     */
+    protected $twigParams;
+    
+    
+    public function __construct()
+    {
+        $this->twigParams = array();
+    }
     
     /**
      * @return string
@@ -311,15 +323,46 @@ class Action
     {
         return $this->tenancyId;
     }
-    
+
+    /**
+     * @return array
+     */
+    public function getTwigParams()
+    {
+        return $this->twigParams;
+    }
+
+    /**
+     * @param array $twigParams
+     * 
+     * @return $this
+     */
+    public function setTwigParams($twigParams)
+    {
+        $this->twigParams = $twigParams;
+        
+        return $this;
+    }
+        
     /**
      * @param Entity $entity
      * 
      * @return string
      */
-    public function getCmd($entity)
+    public function render($entity)
     {
-        return '';
+        $template = $this->template;
+        $loader = new \Twig_Loader_Array(array(
+            $this->name => $template
+        ));
+        $twig = new \Twig_Environment($loader, array(
+            'cache' => false,
+        ));
+        
+        return $twig->render($this->name, array(
+            'entity' => $entity,
+            'params' => $this->twigParams,
+        ));
     }
 
 }

+ 46 - 0
EventListener/ActionEventSubscriber.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace WorkflowBundle\EventListener;
+
+use Doctrine\Common\EventSubscriber;
+use Doctrine\ORM\Event\LifecycleEventArgs;
+use WorkflowBundle\Entity\Action;
+use WorkflowBundle\Utils\DoctrineEvents;
+
+class ActionEventSubscriber implements EventSubscriber
+{
+    
+    /**
+     * @var array
+     */
+    protected $twigParams;
+
+    
+    public function __construct()
+    {
+        $this->twigParams = func_get_args();
+    }
+
+    /**
+     * @return array
+     */
+    public function getSubscribedEvents()
+    {
+        return array(
+            DoctrineEvents::POST_LOAD,
+        );
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     */
+    public function postLoad(LifecycleEventArgs $args)
+    {
+        $entity = $args->getEntity();
+        if ($entity instanceof Action) {
+            $twigParams = $this->twigParams;
+            $entity->setTwigParams($twigParams);
+        }
+    }
+
+}

+ 17 - 27
EventListener/DoctrineEventSubscriber.php

@@ -5,24 +5,25 @@ namespace WorkflowBundle\EventListener;
 use Doctrine\Common\EventSubscriber;
 use Doctrine\ORM\Event\LifecycleEventArgs;
 use WorkflowBundle\Utils\DoctrineEvents;
-use WorkflowBundle\Utils\WorkFlowEntityClasses;
-use OldSound\RabbitMqBundle\RabbitMq\Producer;
+use WorkflowBundle\Services\ProducerService;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 class DoctrineEventSubscriber implements EventSubscriber
 {
     
     /**
-     * @var Producer
+     * @var ProducerService
      */
-    private $producer;
+    private $producerService;
     
     
     /**
-     * @param Producer $producer
+     * @param ContainerInterface $serviceContainer
      */    
-    public function __construct(Producer $producer)
+    public function __construct(ContainerInterface $serviceContainer)
     {
-        $this->producer = $producer;
+        /* @var $this->producerService ProducerService */
+        $this->producerService = $serviceContainer->get('workflow.producer_service');
     }
 
     /**
@@ -30,7 +31,14 @@ class DoctrineEventSubscriber implements EventSubscriber
      */
     public function getSubscribedEvents()
     {
-        return DoctrineEvents::getConstants();
+        return array(
+            DoctrineEvents::PRE_PERSIST,
+            DoctrineEvents::POST_PERSIST,
+            DoctrineEvents::PRE_UPDATE,
+            DoctrineEvents::POST_UPDATE,
+            DoctrineEvents::PRE_REMOVE,
+            DoctrineEvents::POST_REMOVE,
+        );
     }
 
     /**
@@ -87,25 +95,7 @@ class DoctrineEventSubscriber implements EventSubscriber
      */
     public function execute(LifecycleEventArgs $args, $eventName = DoctrineEvents::PRE_PERSIST)
     {
-        $entity = $args->getEntity();
-        $entityManager = $args->getEntityManager();
-        $entityClass = get_class($entity);
-        
-        // la $entity esta dentro de las entidades con workflow
-        if (in_array($entityClass, WorkFlowEntityClasses::getConstants())) {
-            $doctrine2WorkFlowActionRepository = $entityManager->getRepository('WorkflowBundle:Doctrine2WorkFlowAction');
-            $doctrine2WorkFlowActions = $doctrine2WorkFlowActionRepository->findAllByEventAndEntityClass($eventName, $entityClass);
-            foreach ($doctrine2WorkFlowActions as $doctrine2WorkFlowAction) {
-                $actions = $doctrine2WorkFlowAction->getActions();
-                foreach ($actions as $action) {
-                    $msg = array(
-                        'id' => uniqid(),
-                        'cmd' => $action->getCmd($entity),
-                    );
-                    $this->producer->publish(serialize($msg));
-                }
-            }
-        }
+        $this->producerService->execute($args->getEntity(), $eventName);
     }
 
 }

+ 4 - 0
Resources/config/rabbit_mq/services.yml

@@ -1,6 +1,10 @@
 parameters:
     tasklogger_service.class: WorkflowBundle\Services\TaskLoggerService
+    workflow.producer_service.class: WorkflowBundle\Services\ProducerService
 
 services:
     flowdat_tasklogger_service:
         class: '%tasklogger_service.class%'
+    workflow.producer_service:
+        class: '%workflow.producer_service.class%'
+        arguments: ['@service_container']

+ 7 - 1
Resources/config/services.yml

@@ -26,7 +26,7 @@ services:
             - [setTranslationDomain, [WorkflowBundle]]
     workflow.doctrine_event.subscriber:
         class: WorkflowBundle\EventListener\DoctrineEventSubscriber
-        arguments: ['@old_sound_rabbit_mq.flowdat_tasklogger_producer']
+        arguments: ['@service_container']
         tags:
             - { name: doctrine.event_subscriber, connection: default }
     workflow.event.subscriber:
@@ -39,3 +39,9 @@ services:
         tags:
             - { name: twig.extension }
         arguments: ["@workflow.registry"]
+    workflow.action_event.subscriber:
+        class: WorkflowBundle\EventListener\ActionEventSubscriber
+        tags:
+            - { name: doctrine.event_subscriber, connection: default }       
+    # Lo que se pase en arguments se setea en el campo twigParams de la entity Action
+#        arguments: ['@service_container']

+ 97 - 0
Services/ProducerService.php

@@ -0,0 +1,97 @@
+<?php
+
+namespace WorkflowBundle\Services;
+
+use OldSound\RabbitMqBundle\RabbitMq\Producer;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use WorkflowBundle\Entity\Action;
+use WorkflowBundle\Utils\DoctrineEvents;
+use WorkflowBundle\Utils\WorkFlowEntityClasses;
+
+class ProducerService
+{
+
+    /**
+     * @var Producer
+     */
+    private $producer;
+
+    /**
+     * @var ContainerInterface
+     */
+    private $serviceContainer;
+
+
+    /**
+     * @param ContainerInterface $serviceContainer
+     */
+    public function __construct(ContainerInterface $serviceContainer)
+    {
+        $this->serviceContainer = $serviceContainer;
+        /* @var $this->producer Producer */
+        $this->producer = $serviceContainer->get('old_sound_rabbit_mq.flowdat_tasklogger_producer');
+    }
+    
+    /**
+     * @return EntityManagerInterface
+     */
+    public function getEntityManager()
+    {
+        return $this->serviceContainer->get('doctrine.orm.entity_manager');
+    }
+
+    /**
+     * @param Entity $entity
+     * @param string $eventName
+     */
+    public function execute($entity, $eventName = DoctrineEvents::PRE_PERSIST)
+    {
+        $entityClass = get_class($entity);
+
+        // la $entity esta dentro de las entidades con workflow
+        if (in_array($entityClass, WorkFlowEntityClasses::getConstants())) {
+            $doctrine2WorkFlowActionRepository = $this->getEntityManager()->getRepository('WorkflowBundle:Doctrine2WorkFlowAction');
+            $doctrine2WorkFlowActions = $doctrine2WorkFlowActionRepository->findAllByEventAndEntityClass($eventName, $entityClass);
+            foreach ($doctrine2WorkFlowActions as $doctrine2WorkFlowAction) {
+                $actions = $doctrine2WorkFlowAction->getActions();
+                foreach ($actions as $action) {
+                    $this->publishMessage($action, $entity);
+                }
+            }
+        }
+    }
+    
+    /**
+     * @param array $actionName
+     * @param array $entityClass
+     * @param array $entityId
+     */
+    public function executeAction($actionName, $entityClass, $entityId)
+    {
+        $entityManager = $this->getEntityManager();
+        $actionRepository = $entityManager->getRepository('WorkflowBundle:Action');
+        $action = $actionRepository->findOneBy(array(
+            'name' => $actionName,
+            'objectClass' => $entityClass,
+        ));
+        $entityRepository = $entityManager->getRepository($entityClass);
+        $entity = $entityRepository->find($entityId);
+        if (in_array($entityClass, WorkFlowEntityClasses::getConstants())) {
+            $this->publishMessage($action, $entity);
+        }
+    }
+
+    /**
+     * @param Action $action
+     * @param Entity $entity
+     */
+    public function publishMessage(Action $action, $entity)
+    {
+        $msg = array(
+            'id' => uniqid(),
+            'content' => $action->render($entity),
+        );
+        $this->producer->publish(serialize($msg));
+    }
+
+}

+ 15 - 15
Services/TaskLoggerService.php

@@ -12,7 +12,7 @@ class TaskLoggerService implements ConsumerInterface
     /**
      * Directorio donde se guardan los script
      */
-    const TASKLOGGER_DIR = '/tmp/tasklogger';
+    const TASKLOGGER_PATH = '/tmp/tasklogger';
 
     
     /**
@@ -23,13 +23,13 @@ class TaskLoggerService implements ConsumerInterface
      */
     public function execute(AMQPMessage $msg)
     {
-        $data = unserialize($msg->getBody());
-        if (isset($data['id']) && isset($data['cmd'])) {
-            $taskloggerId = $data['id'];
-            $cmd = $data['cmd'];
+        $msgBody = unserialize($msg->getBody());
+        if (isset($msgBody['id']) && isset($msgBody['content'])) {
+            $taskloggerId = $msgBody['id'];
+            $content = $msgBody['content'];
                         
-            $file_name = $this->createTaskLoggerCmdFile($taskloggerId, $cmd);
-            $output = $this->runFileProcess($file_name);
+            $filename = $this->createTaskLoggerCmdFile($taskloggerId, $content);
+            $output = $this->runProcess($filename);
 
             return true;
         }
@@ -39,23 +39,23 @@ class TaskLoggerService implements ConsumerInterface
     
     /**
      * @param string $taskloggerId
-     * @param string $cmd
+     * @param string $data
      * 
      * @return string
      */
-    public function createTaskLoggerCmdFile($taskloggerId, $cmd)
+    public function createTaskLoggerCmdFile($taskloggerId, $data)
     {
         $mode = 0777;
-        $tasklogger_dir = self::TASKLOGGER_DIR . DIRECTORY_SEPARATOR . $taskloggerId;
+        $tasklogger_dir = self::TASKLOGGER_PATH . DIRECTORY_SEPARATOR . $taskloggerId;
         if (!file_exists($tasklogger_dir)) {
             mkdir($tasklogger_dir, $mode, true);
         }
         
-        $file_name = $tasklogger_dir . DIRECTORY_SEPARATOR .'cmd.sh';
-        file_put_contents($file_name, $cmd);
-        chmod($file_name, $mode);
+        $filename = $tasklogger_dir . DIRECTORY_SEPARATOR . 'cmd.sh';
+        file_put_contents($filename, $data);
+        chmod($filename, $mode);
         
-        return $file_name;
+        return $filename;
     }
     
     /**
@@ -63,7 +63,7 @@ class TaskLoggerService implements ConsumerInterface
      * 
      * @return string
      */
-    public function runFileProcess($filename)
+    public function runProcess($filename)
     {
         $process = new Process($filename);
         $process->run();

+ 3 - 1
Utils/DoctrineEvents.php

@@ -18,5 +18,7 @@ class DoctrineEvents
     const PRE_REMOVE = 'preRemove';
 
     const POST_REMOVE = 'postRemove';
-
+    
+    const POST_LOAD = 'postLoad';
+    
 }