Browse Source

Merge branch 'master' of ssh://200.50.168.30:222/VendorSoftwareFlowdat3/WorkflowBundle

Luciano Andrade 8 years ago
parent
commit
0156a8a4d4

+ 128 - 0
Controller/WorkflowController.php

@@ -0,0 +1,128 @@
+<?php
+
+namespace WorkflowBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\Workflow\Exception\ExceptionInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Sonata\AdminBundle\Admin\Pool;
+
+class WorkflowController extends Controller
+{
+    var $class;
+    var $object;
+    var $admin;
+
+    public function applyTransitionAction($id, $transition, $workflow = null, Request $request)
+    {
+        $class = $request->get('class');
+        $em = $this->get('doctrine')->getManager();
+
+        if(!$this->validate($class,$id)) {
+            return $this->redirect($this->generateUrl("sonata_admin_dashboard"));
+        }
+
+        $object = $this->object;
+        $admin = $this->admin;
+        $back_route = $admin->getBaseRouteName()."_list";
+
+        if(is_null($workflow)) {$workflow = "{$object->getWorkflowType()}.{$object->getWorkflow()}";}
+
+        try {
+            $this->get("{$workflow}")->apply($object, $transition);
+            $em->persist($object);
+            $em->flush();
+        } catch (ExceptionInterface $e) {
+            $this->get('session')->getFlashBag()->add('danger', $e->getMessage());
+        }
+
+        return $this->redirect($this->generateUrl($back_route));
+    }
+
+    public function showWorkflowAction($id, Request $request)
+    {
+        $class = $request->get('class');
+
+        if(!$this->validate($class,$id)) {
+            return $this->redirect($this->generateUrl("sonata_admin_dashboard"));
+        }
+
+        $object = $this->object;
+        $admin = $this->admin;
+        $back_route = $admin->getBaseRouteName()."_list";
+
+        return $this->render('WorkflowBundle:Workflow:show_workflow.html.twig', ['object' => $object,'back_route' => $back_route]);
+    }
+
+    public function resetStateAction($id, Request $request)
+    {
+        $class = $request->get('class');
+        $em = $this->get('doctrine')->getManager();
+
+        if(!$this->validate($class,$id)) {
+            return $this->redirect($this->generateUrl("sonata_admin_dashboard"));
+        }
+
+        $object = $this->object;
+        $admin = $this->admin;
+        $back_route = $admin->getBaseRouteName()."_list";
+
+        if(is_null($object->getWorkflow())) {
+            $object->setCurrentState(null);
+            $em->persist($object);
+            $em->flush();
+
+            return $this->redirect($this->generateUrl($back_route));
+        }
+
+        $workflow = $object->getServiceWorkflow();
+
+        if($workflow) {
+            $definition = $workflow->getDefinition();
+            if($definition) {
+                $object->setCurrentState($definition->getInitialPlace($object));
+            } else {
+                $object->setCurrentState(null);
+            }
+        } else {
+            $object->setCurrentState(null);
+        }
+
+        $em->persist($object);
+        $em->flush();
+
+        return $this->redirect($this->generateUrl($back_route));
+    }
+
+    public function validate($class, $id) {
+        
+        if(!class_exists($class)) {
+            $this->get('session')->getFlashBag()->add('danger', $this->get('translator')->trans('Class not found',array(),'WorkflowBundle'));
+            return false;
+        }
+
+        /* @var $adminPool \Sonata\AdminBundle\Admin\Pool */
+        $adminPool = $this->get('sonata.admin.pool');
+
+        $em = $this->get('doctrine')->getManager();
+        try {
+            $object = $em->getRepository($class)->findOneById($id);
+            $admin = $adminPool->getAdminByClass($class);
+        } catch (ExceptionInterface $e) {
+            $this->get('session')->getFlashBag()->add('danger', $e->getMessage());
+            return false;
+        }
+        
+        if(is_null($object) || is_null($admin)) {
+            $this->get('session')->getFlashBag()->add('danger', $this->get('translator')->trans('Object not found',array(),'WorkflowBundle'));
+            return false;
+        }
+
+        $this->object = $object;
+        $this->class = $class;
+        $this->admin = $admin;
+
+        return true;
+    }
+}

+ 14 - 0
Entity/Workflow.php

@@ -434,6 +434,20 @@ class Workflow
         }
     }
 
+    public function getDefinition($subject) {
+        global $kernel;
+
+        try {
+            $registry = $kernel->getContainer()->get("workflow.registry");
+            $definition = $registry->get($subject, $this->name)->getDefinition();
+        } catch (\Exception $e) {
+            return null;
+        }
+
+        return $definition;
+
+    }
+
     public function getInitialPlace($subject) {
 
         global $kernel;

+ 16 - 0
Resources/config/routing/admin.xml

@@ -3,5 +3,21 @@
 <routes xmlns="http://symfony.com/schema/routing"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
+
+    <route id="admin_workflow_workflow_apply_transition" path="/workflow/workflow/apply_transition/{id}/{transition}">
+        <default key="_controller">WorkflowBundle:Workflow:applyTransition</default>
+        <default key="id"></default>
+        <default key="transition"></default>
+    </route>
+    
+    <route id="admin_workflow_workflow_show_workflow" path="/workflow/workflow/{id}/show_workflow">
+        <default key="_controller">WorkflowBundle:Workflow:showWorkflow</default>
+        <default key="id"></default>
+    </route>
+    
+    <route id="admin_workflow_workflow_reset_state" path="/workflow/workflow/{id}/reset_state">
+        <default key="_controller">WorkflowBundle:Workflow:resetState</default>
+        <default key="id"></default>
+    </route>
     
 </routes>

+ 6 - 1
Resources/translations/WorkflowBundle.es.yml

@@ -95,4 +95,9 @@ helps:
     action_label_template: Template en twig con las acciones a realizar en dicha Acción
 Workflow: Workflow
 Action: Action
-Doctrine2WorkFlowAction: Doctrine2WorkFlowAction
+Doctrine2WorkFlowAction: Doctrine2WorkFlowAction
+Class not found: Clase no encontrada
+Object not found: Objecto no encontrado
+Undefined State: Sin estado
+Incorrect State: Estado erróneo
+Undefined Workflow: Sin workflow

+ 7 - 0
Resources/views/Workflow/base_list_field_current_state.html.twig

@@ -0,0 +1,7 @@
+{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
+
+{% block field %}
+    <div>
+        <a href="{{path('admin_workflow_workflow_show_workflow',{class: get_class(object), id:object.getId()})}}">{{object.getCurrentState()}}</a>
+    </div>
+{% endblock %}

+ 33 - 0
Resources/views/Workflow/layout.html.twig

@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <title>Workflow demo application</title>
+        {% block stylesheets %}
+            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
+            <style>
+                svg text {
+                    font-size: 0.75em;
+                    font-weight: bold;
+                }
+            </style>
+        {% endblock %}
+    </head>
+    <body>
+        <div class="container">
+
+            {% block content %}
+
+                {% block main '' %}
+            
+                <hr />
+            {% endblock %}
+        </div>
+        {% block javascripts %}
+            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
+            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
+        {% endblock %}
+    </body>
+</html>

+ 19 - 0
Resources/views/Workflow/show_transitions.html.twig

@@ -0,0 +1,19 @@
+{% if object.getWorkflowObject() is null %}
+    <a  href="#" name="transition" value="" class="btn btn-sm view_link btn-danger" disabled="disabled">{{ "Undefined Workflow"|trans({},'WorkflowBundle') }}</a>
+{% else %}
+    {% if workflow_correct_state(object, object.getWorkflow()) %}
+        {% for transition in workflow_transitions(object, object.getWorkflow()) %}
+            <a  href="{{path('admin_workflow_workflow_apply_transition',{class: get_class(object), id:object.getId(), transition:transition.name})}}" name="transition" value="{{ transition.name }}"
+            {% if workflow_can(object, transition.name, object.getWorkflow()) -%}
+                class="btn btn-sm btn-default view_link"
+            {% else %}
+                class="btn btn-sm btn-default view_link btn-danger" disabled="disabled"
+            {% endif %}
+        > {{ transition.name }}</a>
+        {% endfor %}
+    {% elseif object.getCurrentState() is null %}
+        <a  href="{{ path('admin_workflow_workflow_reset_state', {class: get_class(object), id: object.getId()}) }}" name="transition" value="" class="btn btn-sm view_link btn-danger">{{ "Undefined State"|trans({},'WorkflowBundle') }}</a>
+    {% else %}
+        <a  href="{{ path('admin_workflow_workflow_reset_state', {class: get_class(object), id: object.getId()}) }}" name="transition" value="" class="btn btn-sm view_link btn-danger">{{ "Incorrect State"|trans({},'WorkflowBundle') }}</a>
+    {% endif %}
+{% endif %}

+ 53 - 0
Resources/views/Workflow/show_workflow.html.twig

@@ -0,0 +1,53 @@
+{% extends 'WorkflowBundle:Workflow:layout.html.twig' %}
+
+{% block main %}
+    <h1>Object "{{ object}}"</h1>
+    <div class="row">
+        <div class="col-md-5">
+            <h2>Workflow: {{object.getWorkflow()}}</h2>
+            <p>
+                <code>
+                    {{get_class(object)}}::current_state = {{ object.getCurrentState() }}
+                </code>
+            </p>
+            <p>
+                <form action="{{ path('admin_workflow_workflow_reset_state', {class: get_class(object),id: object.getId()}) }}" method="post" class="form-inline">
+                    <button type="submit" class="btn btn-danger btn-xs">Reset State</button>
+                </form>
+            </p>
+        </div>
+        <div class="col-md-6">
+            <h2>What can you do?</h2>
+                <div class="btn-group-vertical" role="group">
+                    <code style="color:black;text-align:center">current_state</code> 
+                    {% if workflow_transitions(object, object.getWorkflow())|length > 0 %}
+                        {% for transition in workflow_transitions(object, object.getWorkflow()) %}
+                            <a  href="{{path('admin_workflow_workflow_apply_transition',{class: get_class(object),id:object.getId(),transition:transition.name})}}" name="transition" value="{{ transition.name }}"
+                                {% if workflow_can(object, transition.name, object.getWorkflow()) -%}
+                                    class="btn btn-primary"
+                                {%- else -%}
+                                    class="btn btn-danger" disabled="disabled"
+                                {%- endif -%}
+                            >
+                                {{ transition.name }}
+                            </a>
+                        {% endfor %}
+                    {% else %}
+                        <a  href="" name="transition" class="btn btn-danger" disabled="disabled">Sin opciones</a>
+                    {% endif %}
+                </div>
+            <br />
+        </div>
+    </div>
+    <div>
+        <br />
+        <img src="{{ app.request.schemeAndHttpHost ~ app.request.baseUrl }}/../workflows_png/{{object.getWorkflow()}}.png?nocache={{ date().timestamp }}" />
+    </div>
+    <br />
+    <div>
+        <a  href="{{path(back_route)}}" class="btn btn-primary">
+            Volver al dashboard
+        </a>
+    </div>
+    
+{% endblock %}

+ 7 - 1
Twig/WorkflowExtension.php

@@ -18,7 +18,8 @@ class WorkflowExtension extends \Twig_Extension
         return array(
             new \Twig_SimpleFunction('workflow_can', array($this, 'canTransition')),
             new \Twig_SimpleFunction('workflow_transitions', array($this, 'getEnabledTransitions')),
-            new \Twig_SimpleFunction('workflow_correct_state', array($this, 'isCorrectState'))
+            new \Twig_SimpleFunction('workflow_correct_state', array($this, 'isCorrectState')),
+            new \Twig_SimpleFunction('get_class', array($this, 'getClass'))
         );
     }
 
@@ -59,4 +60,9 @@ class WorkflowExtension extends \Twig_Extension
     {
         return 'workflow';
     }
+
+    public function getClass($object)
+    {
+        return get_class($object);
+    }
 }