Browse Source

Se adapta useOneDefaultInterface a workflow

Espinoza Guillermo 7 năm trước cách đây
mục cha
commit
fcac5fb310

+ 34 - 21
Admin/WorkflowAdmin.php

@@ -7,6 +7,7 @@ use Sonata\AdminBundle\Datagrid\DatagridMapper;
 use Sonata\AdminBundle\Datagrid\ListMapper;
 use Sonata\AdminBundle\Form\FormMapper;
 use Sonata\AdminBundle\Show\ShowMapper;
+use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
 use Symfony\Component\Yaml\Yaml;
 use WorkflowBundle\Utils\WorkFlowEntityClasses;
 
@@ -48,14 +49,14 @@ class WorkflowAdmin extends BaseAdmin
             ->add('name')
             ->add('description')
             ->add('enable')
+            ->add('usedByDefault')
             ->add('_action', null, array(
                 'actions' => array(
                     'show' => array(),
                     'edit' => array(),
                     'delete' => array()
                 )
-            ))
-        ;
+            ));
     }
 
     /**
@@ -85,24 +86,42 @@ transitions:
     to: state_one
 ";        
         // Create => template_example
-        $tempate_options = array("attr" => array('style' => 'height:500px;'));
-        if(is_null($this->getSubject()->getId())) {
+        $tempate_options = array(
+            "attr" => array(
+                'style' => 'height:500px;',
+            ),
+        );
+        if (is_null($this->getSubject()->getId())) {
             $tempate_options['data'] = $template_example;
         } else {
-            $this->parameters = array('workflow_name' => $this->getSubject()->getName(), 'workflow_subject' => $this->getSubject()->getSubject());
+            $this->parameters = array(
+                'workflow_name' => $this->getSubject()->getName(),
+                'workflow_subject' => $this->getSubject()->getSubject());
         }
                 
         $formMapper
             ->add('name')
             ->add('description')
             ->add('enable')
-            ->add('type', 'choice', array('choices' => array('state_machine' => 'state_machine', 'workflow' => 'workflow')))
-            ->add('markingType', 'choice', array('choices' => array('single_state' => 'single_state', 'multiple_state' => 'multiple_state')))
-            ->add('markingName', 'choice', array('choices' => array('currentState' => 'currentState')))
-            ->add('support', 'choice', array(
+            ->add('usedByDefault')
+            ->add('type', ChoiceType::class, array(
+                'choices' => array(
+                    'state_machine' => 'state_machine', 
+                    'workflow' => 'workflow',
+                )))
+            ->add('markingType', ChoiceType::class, array(
+                'choices' => array(
+                    'single_state' => 'single_state', 
+                    'multiple_state' => 'multiple_state',
+                )))
+            ->add('markingName', ChoiceType::class, array(
+                'choices' => array(
+                    'currentState' => 'currentState',
+                )))
+            ->add('support', ChoiceType::class, array(
                 'choices' => array_filter(WorkFlowEntityClasses::getChoices(), 'class_exists'),
                 'multiple'   => true, 
-                'required' => true
+                'required' => true,
                 ))
             ->add('template', null, $tempate_options)
 
@@ -112,15 +131,7 @@ transitions:
                'markingType' => $this->trans("helps.workflow_label_marking_type"),
                'markingName' => $this->trans("helps.workflow_label_marking_name"),
                'template' => $this->trans("helps.workflow_label_template"),
-            ))
-            ;
-            
-            /*
-            if(is_null($this->getSubject()->getId())) {
-                $formMapper
-                    ->add('subject', null, array('template' => 'WorkflowBundle:Workflow:'));
-            }
-            */
+            ));
     }
 
     /**
@@ -133,14 +144,16 @@ transitions:
             ->add('name')
             ->add('description')
             ->add('enable')
+            ->add('usedByDefault')
             ->add('created')
             ->add('updated')
             ->add('type')
             ->add('markingType')
             ->add('markingName')
             ->add('support')
-            ->add('template','string', array('template' => 'WorkflowBundle:Workflow:show_template.html.twig'))
-        ;
+            ->add('template','string', array(
+                'template' => 'WorkflowBundle:Workflow:show_template.html.twig'
+            ));
     }
 
 }

+ 15 - 7
Entity/Workflow.php

@@ -2,32 +2,37 @@
 
 namespace WorkflowBundle\Entity;
 
+use Base\AdminBundle\Traits\UseOneDefaultTrait;
 use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
 use Gedmo\Mapping\Annotation as Gedmo;
+use OwnerVoterBundle\Entity\Traits\OwnerTraitInterface;
+use OwnerVoterBundle\Entity\Traits\OwnerTrait;
 use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 use Symfony\Component\Validator\Constraints as Assert;
-use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
 use Symfony\Component\Yaml\Yaml;
 use Symfony\Bundle\FrameworkBundle\Console\Application;
 use Symfony\Component\Console\Input\ArrayInput;
 use Symfony\Component\Console\Output\BufferedOutput;
-use WorkflowBundle\Validator\Constraints as WorkflowAssert;
 use Symfony\Component\Workflow\Registry;
-
-use OwnerVoterBundle\Entity\Traits\OwnerTraitInterface;
-use OwnerVoterBundle\Entity\Traits\OwnerTrait;
+use WorkflowBundle\Validator\Constraints as WorkflowAssert;
+use WorkflowBundle\Interfaces\UseOneDefaultFilterInterface;
 
 /**
  * Workflow
  *
  * @ORM\Entity(repositoryClass="WorkflowBundle\Repository\WorkflowRepository")
  * @ORM\HasLifecycleCallbacks
- * @UniqueEntity(fields={"name", "tenancyId"}, message="errors.duplicate_key")
  * @ORM\Table(uniqueConstraints={@ORM\UniqueConstraint(name="unique_idx", columns={"name", "tenancy_id"})})
+ *
+ * @UniqueEntity(fields={"name", "tenancyId"}, message="errors.duplicate_key")
  */
-class Workflow implements OwnerTraitInterface
+class Workflow implements OwnerTraitInterface, UseOneDefaultFilterInterface
 {
+    
     use OwnerTrait;
+    use UseOneDefaultTrait;
+    
     /**
      * @var int
      *
@@ -110,10 +115,12 @@ class Workflow implements OwnerTraitInterface
      *
      */
     protected $support = array();
+    
     /**
      * var mixed Contiene el contenedor.
      */
     private $container;
+    
 
     /**
      * Workflow constructor.
@@ -523,4 +530,5 @@ class Workflow implements OwnerTraitInterface
     {
         $this->container = $container;
     }
+        
 }

+ 84 - 0
EventListener/UseOneDefaultFilterSubscriber.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace WorkflowBundle\EventListener;
+
+use Doctrine\Common\EventSubscriber;
+use Doctrine\ORM\Event\LifecycleEventArgs;
+use WorkflowBundle\Entity\Workflow;
+use WorkflowBundle\Interfaces\UseOneDefaultFilterInterface;
+
+class UseOneDefaultFilterSubscriber implements EventSubscriber
+{
+
+    /**
+     * @return array
+     */
+    public function getSubscribedEvents()
+    {
+        return array(
+            'prePersist',
+            'preUpdate',
+        );
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     */
+    public function prePersist(LifecycleEventArgs $args)
+    {
+        $this->execute($args);
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     */
+    public function preUpdate(LifecycleEventArgs $args)
+    {
+        $this->execute($args, 'preUpdate');
+    }
+
+    /**
+     * @param LifecycleEventArgs $args
+     * @param string $eventName
+     */
+    public function execute(LifecycleEventArgs $args, $eventName = 'prePersist')
+    {
+        $em = $args->getEntityManager();
+        $entity = $args->getEntity();
+        $class = get_class($entity);
+        if ($entity instanceof UseOneDefaultFilterInterface) {
+            // busco los workflow segun las clases que soporta
+            $support = $entity->getSupport();
+            $workflowRepository = $em->getRepository(Workflow::class);
+            $workflows = [];
+            foreach ($support as $s) {
+                $workflows = array_merge($workflows, $workflowRepository->findAllSupportedBy($s, $entity->getId()));
+            }
+            $workflows = implode(',', array_unique($workflows));
+            
+            if ($entity->getUsedByDefault() && $workflows != '') {
+                // actualizo los workflow que soportan la misma class
+                $dql = "UPDATE {$class} u SET u.usedByDefault = 0 WHERE u.id IN ({$workflows})";
+                $em->createQuery($dql)->execute();
+            } elseif ($workflows != '') {
+                // verifico que haya workflow que soporten y en default 
+                // sino pongo en default el que se esta guardando
+                $dql = "SELECT count(u) as c FROM {$class} u WHERE u.usedByDefault = 1 AND u.id IN ({$workflows})";
+                $rtr = $em->createQuery($dql)->getSingleScalarResult();
+                if ($rtr == 0) {
+                    $entity->setUsedByDefault(true);
+                }
+            } else {
+                // seteo en default=true porque no hay workflow que soporten la misma class
+                $entity->setUsedByDefault(true);
+            }
+                        
+            if ($eventName == 'preUpdate') {
+                $uow = $em->getUnitOfWork();
+                $meta = $em->getClassMetadata($class);
+                $uow->recomputeSingleEntityChangeSet($meta, $entity);
+            }
+        }
+    }
+
+}

+ 20 - 0
Interfaces/UseOneDefaultFilterInterface.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace WorkflowBundle\Interfaces;
+
+interface UseOneDefaultFilterInterface
+{
+    
+    /**
+     * @param boolean $usedByDefaul
+     *
+     * @return UseOneDefaultFilterInterface
+     */
+    public function setUsedByDefault($usedByDefault);
+
+    /**
+     * @return boolean
+     */
+    public function getUsedByDefault();
+    
+}

+ 41 - 2
Repository/WorkflowRepository.php

@@ -8,15 +8,28 @@ class WorkflowRepository extends EntityRepository
 {
 
     /**
+     * Retorna los workflow habilitados (enable=true) y 
+     * que estén por defecto (usedByDefault=true) según la clase
+     * si no encuentra, retorna los habilitados
+     *
      * @param string $class
      * 
      * @return array
      */
     public function findAllByClass($class)
     {
-        $results = $this->createQueryBuilder('Workflow')
-                ->where('Workflow.enable = :enable')->setParameter('enable', true)
+        $qb = $this->createQueryBuilder('Workflow')
+                ->where('Workflow.enable = :enable')->setParameter('enable', true);
+                
+        $results = $qb->andWhere('Workflow.usedByDefault = :usedByDefault')
+                ->setParameter('usedByDefault', true)
                 ->getQuery()->getResult();
+        
+        // No hay workflow enable y usedByDefault, busco los enable
+        if (count($results) == 0) {
+            $results = $qb->getQuery()->getResult();
+        }
+        
         foreach ($results as $key => &$result) {
             if (!in_array($class, $result->getSupport())) {
                 unset($results[$key]);
@@ -26,4 +39,30 @@ class WorkflowRepository extends EntityRepository
         return $results;
     }
 
+    /**
+     * Retorna los workflow soportados por $class
+     *
+     * @param string $class
+     * 
+     * @return array
+     */
+    public function findAllSupportedBy($class, $id = null)
+    {
+        $qb = $this->createQueryBuilder('Workflow')
+                ->select('Workflow.id, Workflow.support');
+        if ($id) {
+            $qb->andWhere('Workflow.id <> :id')->setParameter('id', $id);
+        }
+        $results = $qb->getQuery()->getResult();
+        foreach ($results as $key => &$result) {
+            if (!in_array($class, $result['support'])) {
+                unset($results[$key]);
+            }
+        }
+        
+        return array_map(function($result) {
+            return $result['id'];
+        }, $results);
+    }
+
 }

+ 5 - 0
Resources/config/services.yml

@@ -55,3 +55,8 @@ services:
         tags:
             - { name: doctrine.event_subscriber }
         arguments: ['@service_container']
+        
+    workflow.use_one_default.subscriber:
+        class: WorkflowBundle\EventListener\UseOneDefaultFilterSubscriber
+        tags:
+            - { name: doctrine.event_subscriber, connection: default }

+ 9 - 0
Resources/translations/WorkflowBundle.es.yml

@@ -16,6 +16,8 @@ filter:
     label_entity_class: Entidad
     label_support: Supports
     label_event_name: Evento
+    label_used_by_default: Default
+    
 breadcrumb:
     link_workflow_list: Listado Workflows
     link_workflow_create: Crear Workflow
@@ -23,6 +25,7 @@ breadcrumb:
     link_action_list: Listado Acciones
     link_action_create: Crear Acción
     link_action_delete: Eliminar Acción
+    
 form:
     label_id: Id
     label_name: Nombre
@@ -44,6 +47,8 @@ form:
     label_entity_class: Entidad
     label_support: Supports
     label_event_name: Evento
+    label_used_by_default: Default
+    
 list:
     label_id: Id
     label_name: Nombre
@@ -65,6 +70,8 @@ list:
     label_entity_class: Entidad
     label_support: Supports
     label_event_name: Evento
+    label_used_by_default: Default
+    
 show:
     label_id: Id
     label_name: Nombre
@@ -86,6 +93,8 @@ show:
     label_entity_class: Entidad
     label_support: Supports
     label_event_name: Evento
+    label_used_by_default: Default
+    
 helps:
     workflow_label_name: Nombre con el que se identificará el workflow. Se convertirá a minúscula y los espacios se reemplazarán por "_"
     workflow_label_type: "Tipo de Workflow: state_machine o workflow"