src_legacy/Tionvel/WorkflowBundle/Entity/WorkflowProcess.php line 22

Open in your IDE?
  1. <?php
  2. namespace Tionvel\WorkflowBundle\Entity;
  3. use App\Entity\User;
  4. use DateTime;
  5. use Doctrine\Common\Collections\ArrayCollection;
  6. use Doctrine\Common\Collections\Collection;
  7. use Doctrine\Common\Collections\Criteria;
  8. use Doctrine\ORM\Mapping as ORM;
  9. use Exception;
  10. use Symfony\Component\Security\Core\User\UserInterface;
  11. use Tionvel\WorkflowBundle\Utils\AttributeResolver;
  12. use Tionvel\WorkflowBundle\Utils\Dot;
  13. /**
  14.  * Class WorkflowProcess
  15.  * @package Tionvel\WorkflowBundle\Entity
  16.  * @ORM\Entity(repositoryClass="Tionvel\WorkflowBundle\Repository\WorkflowProcessRepository")
  17.  * @ORM\Table(name="workflow_processes")
  18.  */
  19. class WorkflowProcess
  20. {
  21.     /**
  22.      * @var int
  23.      * @ORM\Id @ORM\Column(type="integer")
  24.      * @ORM\GeneratedValue(strategy="AUTO")
  25.      */
  26.     private $id;
  27.     /**
  28.      * @ORM\Column(type="string", nullable=true)
  29.      */
  30.     private $uuid;
  31.     /**
  32.      * @var string
  33.      * @ORM\Column(type="string")
  34.      */
  35.     private $workflow;
  36.     /**
  37.      * @var string
  38.      * @ORM\Column(type="string", nullable=true)
  39.      */
  40.     private $subWorkflow;
  41.     /**
  42.      * @var User
  43.      * @ORM\ManyToOne(targetEntity="App\Entity\User")
  44.      * @ORM\JoinColumn(onDelete="CASCADE")
  45.      */
  46.     private $owner;
  47.     /**
  48.      * @var ArrayCollection
  49.      * @ORM\OneToMany(
  50.      *     targetEntity="Tionvel\WorkflowBundle\Entity\WorkflowState",
  51.      *     mappedBy="process",
  52.      *     fetch="LAZY",
  53.      *     cascade={"persist"},
  54.      *     orphanRemoval=false
  55.      * )
  56.      */
  57.     private $states;
  58.     /**
  59.      * @var ArrayCollection
  60.      * @ORM\OneToMany(
  61.      *     targetEntity="Tionvel\WorkflowBundle\Entity\WorkflowAttribute",
  62.      *     mappedBy="process",
  63.      *     fetch="LAZY",
  64.      *     cascade={"persist"},
  65.      *     orphanRemoval=false
  66.      * )
  67.      */
  68.     private $attributes;
  69.     /**
  70.      * @var Dot
  71.      */
  72.     private $resolvedAttrs;
  73.     /**
  74.      * WorkflowProcess constructor.
  75.      * @throws Exception
  76.      */
  77.     public function __construct()
  78.     {
  79.         $this->attributes = new ArrayCollection;
  80.         $this->states = new ArrayCollection;
  81.         $this->resolvedAttrs = new Dot;
  82.     }
  83.     /**
  84.      * @param $workflowId
  85.      * @param User $user
  86.      * @return WorkflowProcess
  87.      * @throws Exception
  88.      */
  89.     public static function init($workflowIdUser $user)
  90.     {
  91.         list (
  92.             $workflowId,
  93.             $subWorkflowId
  94.             ) = explode('/'$workflowId);
  95.         $self = new self;
  96.         $self->setOwner($user);
  97.         $self->setWorkflow($workflowId);
  98.         $self->setSubWorkflow($subWorkflowId);
  99.         $self->addState(WorkflowState::start($self$user));
  100.         $self->addAssignee('owner'$user);
  101.         return $self;
  102.     }
  103.     /**
  104.      * @param $state
  105.      * @param User $user
  106.      * @param string $transition
  107.      * @throws Exception
  108.      */
  109.     public function transition($state$user$transition)
  110.     {
  111.         $newState WorkflowState::start($this$user$state$transition);
  112.         $currentState $this->getCurrentState();
  113.         $currentState->finish($newState$user$transition);
  114.         $newState->setPrev($currentState);
  115.         $this->addState($newState);
  116.     }
  117.     /**
  118.      * @return string
  119.      */
  120.     public function getId()
  121.     {
  122.         return $this->id;
  123.     }
  124.     public function getUuid()
  125.     {
  126.         return $this->uuid;
  127.     }
  128.     public function setUuid($uuid)
  129.     {
  130.         $this->uuid $uuid;
  131.     }
  132.     /**
  133.      * @return string
  134.      */
  135.     public function getWorkflow()
  136.     {
  137.         return $this->workflow;
  138.     }
  139.     /**
  140.      * @param string $workflow
  141.      */
  142.     public function setWorkflow(string $workflow)
  143.     {
  144.         $this->workflow $workflow;
  145.     }
  146.     /**
  147.      * @return User
  148.      */
  149.     public function getOwner()
  150.     {
  151.         return $this->owner;
  152.     }
  153.     /**
  154.      * @param User $owner
  155.      */
  156.     public function setOwner(User $owner)
  157.     {
  158.         $this->owner $owner;
  159.     }
  160.     /**
  161.      * @return ArrayCollection
  162.      */
  163.     public function getStates()
  164.     {
  165.         return $this->states;
  166.     }
  167.     /**
  168.      * @param ArrayCollection $states
  169.      */
  170.     public function setStates($states)
  171.     {
  172.         $this->states $states;
  173.     }
  174.     /**
  175.      * @param WorkflowState $state
  176.      */
  177.     public function addState(WorkflowState $state)
  178.     {
  179.         if (!$this->states->contains($state)) {
  180.             $this->states[] = $state;
  181.             $state->setProcess($this);
  182.         }
  183.     }
  184.     /**
  185.      * @param string $key
  186.      * @return bool
  187.      */
  188.     public function hasStateByKey(string $key)
  189.     {
  190.         return (bool) !$this->states->filter(function (WorkflowState $state) use ($key) {
  191.             return $state->isState($key);
  192.         })->isEmpty();
  193.     }
  194.     /**
  195.      * @param string $key
  196.      * @return ArrayCollection|Collection
  197.      */
  198.     public function getStateByKey(string $key)
  199.     {
  200.         return $this->states->filter(function (WorkflowState $state) use ($key) {
  201.             return $state->isState($key);
  202.         })->last();
  203.     }
  204.     /**
  205.      * @return WorkflowState
  206.      * @throws Exception
  207.      */
  208.     public function getCurrentState()
  209.     {
  210.         if ($state $this->states->last()) {
  211.             return $state;
  212.         }
  213.         return WorkflowState::start($this$this->owner);
  214.     }
  215.     /**
  216.      * @return string
  217.      * @throws Exception
  218.      */
  219.     public function getState()
  220.     {
  221.         return $this->getCurrentState()->getState();
  222.     }
  223.     /**
  224.      * @param $state
  225.      * @return bool
  226.      */
  227.     public function inState($state)
  228.     {
  229.         /** @var WorkflowState $current */
  230.         if (!$current $this->states->last()) {
  231.             return false;
  232.         }
  233.         return $current->isState($state);
  234.     }
  235.     /**
  236.      * @return bool
  237.      */
  238.     public function isStarted()
  239.     {
  240.         return !$this->inState(WorkflowState::START_STATE);
  241.     }
  242.     /**
  243.      * @return DateTime
  244.      * @throws Exception
  245.      */
  246.     public function getStartedAt()
  247.     {
  248.         if ($state $this->getStates()->first()) {
  249.             return $state->getStartedAt();
  250.         }
  251.         return WorkflowState::start($this$this->owner)->getStartedAt();
  252.     }
  253.     /**
  254.      * @return DateTime
  255.      * @throws Exception
  256.      */
  257.     public function getStartCompletedAt(): ?DateTime
  258.     {
  259.         if ($state $this->getStates()->first()) {
  260.             return $state->getCompletedAt();
  261.         }
  262.         return null;
  263.     }
  264.     /**
  265.      * @return ArrayCollection
  266.      */
  267.     public function getAttributes()
  268.     {
  269.         return $this->attributes;
  270.     }
  271.     /**
  272.      * @param ArrayCollection $attributes
  273.      */
  274.     public function setAttributes(ArrayCollection $attributes)
  275.     {
  276.         $this->attributes $attributes;
  277.     }
  278.     /**
  279.      * @return array
  280.      */
  281.     public function getArrayAttributes()
  282.     {
  283.         $attributes = [];
  284.         /** @var WorkflowAttribute $attribute */
  285.         foreach ($this->attributes as $attribute) {
  286.             $attributes[$attribute->getPath()] = $attribute->toArray();
  287.         }
  288.         return $attributes;
  289.     }
  290.     /**
  291.      * @param array $attributes
  292.      */
  293.     public function setResolvedAttributes(array $attributes = [])
  294.     {
  295.         $this->resolvedAttrs Dot::create($attributes);
  296.     }
  297.     /**
  298.      * @return Dot
  299.      */
  300.     public function getResolvedAttributes()
  301.     {
  302.         return $this->resolvedAttrs;
  303.     }
  304.     /**
  305.      * @return array
  306.      */
  307.     public function attrs()
  308.     {
  309.         return $this->resolvedAttrs->all();
  310.     }
  311.     /**
  312.      * @param $path
  313.      * @param $default
  314.      * @return mixed
  315.      */
  316.     public function attr($path$default null)
  317.     {
  318.         return $this->resolvedAttrs->get($path$default);
  319.     }
  320.     /**
  321.      * @param $path
  322.      * @return array
  323.      */
  324.     public function arrayAttr($path)
  325.     {
  326.         $attr $this->attr($path, []);
  327.         if ((is_array($attr) && isset($attr['created_at']) || !is_array($attr))) {
  328.             return [$attr];
  329.         }
  330.         return $attr;
  331.     }
  332.     /**
  333.      * @param $path
  334.      * @return array
  335.      */
  336.     public function arrayAttrList($path)
  337.     {
  338.         $attr $this->attr($path, []);
  339.         if (count($attr) > ) {
  340.             return $attr;
  341.         }
  342.         return [$attr];
  343.     }
  344.     /**
  345.      * @param $path
  346.      * @return bool
  347.      */
  348.     public function has($path)
  349.     {
  350.         return $this->resolvedAttrs->has($path);
  351.     }
  352.     /**
  353.      * @param $path
  354.      * @param null $default
  355.      * @return mixed
  356.      */
  357.     public function first($path$default null)
  358.     {
  359.         $attr $this->attr($path$default);
  360.         return is_array($attr) ? reset($attr) : $attr;
  361.     }
  362.     /**
  363.      * @param $path
  364.      * @param null $default
  365.      * @return mixed
  366.      */
  367.     public function last($path$default null)
  368.     {
  369.         $attr $this->attr($path$default);
  370.         return is_array($attr) ? end($attr) : $attr;
  371.     }
  372.     /**
  373.      * @param WorkflowAttribute $attribute
  374.      */
  375.     public function addAttribute(WorkflowAttribute $attribute)
  376.     {
  377.         if (!$this->attributes->contains($attribute)) {
  378.             $this->attributes->add($attribute);
  379.             $attribute->setProcess($this);
  380.         }
  381.     }
  382.     public function removeAttr($key)
  383.     {
  384.         $this->attributes->matching(
  385.             Criteria::create()->where(Criteria::expr()->eq('key0'$key))
  386.         )->map(function (WorkflowAttribute $attribute) {
  387.             $this->attributes->removeElement($attribute);
  388.             $attribute->setProcess(null);
  389.         });
  390.     }
  391.     public function removeAttrByPath($path)
  392.     {
  393.         $keys explode('.',$path);
  394.         $criteria Criteria::create();
  395.         foreach ($keys as $i => $key) {
  396.             $expr Criteria::expr()->eq('key'.$i$key);
  397.             $i == $criteria->where($expr) : $criteria->andWhere($expr);
  398.         }
  399.         $this->attributes->matching($criteria)->map(function (WorkflowAttribute $attribute) {
  400.             $this->attributes->removeElement($attribute);
  401.             $attribute->setProcess(null);
  402.         });
  403.     }
  404.     /**
  405.      * @param User $user
  406.      * @return bool
  407.      * @throws Exception
  408.      */
  409.     public function userIsAssignee(User $user)
  410.     {
  411.         return $user === $this->owner || $this->hasAssignee($user);
  412.     }
  413.     /**
  414.      * @param User $user
  415.      * @param $key
  416.      * @return bool
  417.      * @throws Exception
  418.      */
  419.     public function userIs(UserInterface $user$key)
  420.     {
  421.         return !$this->getCurrentState()
  422.             ->getAssignees()
  423.             ->filter(function (WorkflowAssignee $assignee) use ($user$key) {
  424.                 return $assignee->isUser($user) && $assignee->isType($key);
  425.             })
  426.             ->isEmpty()
  427.             ;
  428.     }
  429.     /**
  430.      *
  431.      * @param User $user
  432.      * @return array
  433.      * @throws Exception
  434.      */
  435.     public function getUserRole(UserInterface $user)
  436.     {
  437.         $roles $this->getCurrentState()
  438.             ->getAssignees()
  439.             ->filter(function (WorkflowAssignee $assignee) use ($user) {
  440.                 return $assignee->isUser($user);
  441.             })
  442.             ->map(function (WorkflowAssignee $assignee) {
  443.                 return $assignee->getName();
  444.             })
  445.             ->toArray()
  446.         ;
  447.         return array_unique($roles);
  448.     }
  449.     /**
  450.      * @param User $user
  451.      * @return bool
  452.      * @throws Exception
  453.      */
  454.     public function hasAssignee(User $user)
  455.     {
  456.         return !$this->getCurrentState()
  457.             ->getAssignees()
  458.             ->filter(function (WorkflowAssignee $assignee) use ($user) {
  459.                 return $assignee->isUser($user);
  460.             })
  461.             ->isEmpty()
  462.             ;
  463.     }
  464.     /**
  465.      * @param $key
  466.      * @param User $user
  467.      * @throws Exception
  468.      */
  469.     public function addAssignee($keyUser $user)
  470.     {
  471.         $this->getCurrentState()->addAssignee(WorkflowAssignee::create($user$key));
  472.     }
  473.     public function removeAssigneeAsRole(User $user$role)
  474.     {
  475.         foreach ($this->getAssignees() as $assignee) {
  476.             if ($assignee->isType($role) && $assignee->isUser($user)) {
  477.                 $this->getAssignees()->removeElement($assignee);
  478.             }
  479.         }
  480.     }
  481.     /**
  482.      * @param $key
  483.      * @throws Exception
  484.      */
  485.     public function removeAssigneeByKey($key)
  486.     {
  487.         $this->getCurrentState()->removeAssigneeByKey($key);
  488.     }
  489.     /**
  490.      * @return ArrayCollection|WorkflowAssignee[]
  491.      * @throws Exception
  492.      */
  493.     public function getAssignees()
  494.     {
  495.         return $this->getCurrentState()->getAssignees();
  496.     }
  497.     public function getOldAssigneesArray() {
  498.         $assignees = [];
  499.         $states $this->getStates()->filter(function(WorkflowState $state) {
  500.             return !$state->isCurrent();
  501.         });
  502.         /** @var WorkflowState $state */
  503.         foreach ($states as $state) {
  504.             foreach ($state->getAssignees() as $assignee) {
  505.                 $assignees[] = [
  506.                     'username' => $assignee->getUser()->getUserIdentifier(),
  507.                     'user' => $assignee->getUser()->getId(),
  508.                     'role' => $assignee->getName()
  509.                 ];
  510.             }
  511.         }
  512.         return array_unique($assigneesSORT_REGULAR);
  513.     }
  514.     public function getCurrentAssigneesArray() {
  515.         $assignees = [];
  516.         $currentAssignees $this->getCurrentState()->getAssignees();
  517.         foreach($currentAssignees as $assignee) {
  518.             $assignees[] = [
  519.                 'username' => $assignee->getUser()->getUserIdentifier(),
  520.                 'user' => $assignee->getUser()->getId(),
  521.                 'role' => $assignee->getName()
  522.             ];
  523.         }
  524.         return $assignees;
  525.     }
  526.     public function getDiffCurrentAssignees() {
  527.         $currentAssignees $this->getCurrentAssigneesArray();
  528.         $oldAssignees $this->getOldAssigneesArray();
  529.         foreach ($currentAssignees as $key => $a) {
  530.             foreach($oldAssignees as $b) {
  531.                 if($a['role'] == $b['role'] && $a['user'] == $b['user']) {
  532.                     unset($currentAssignees[$key]);
  533.                 }
  534.             }
  535.         }
  536.         return $currentAssignees;
  537.     }
  538.     /**
  539.      * @return array
  540.      * @throws Exception
  541.      */
  542.     public function getRolesMap()
  543.     {
  544.         $rolesMap = [];
  545.         /** @var WorkflowAssignee $assignee */
  546.         foreach ($this->getAssignees() as $assignee) {
  547.             $role $assignee->getName();
  548.             $user $assignee->getUser();
  549.             if (!isset($rolesMap[$role])) {
  550.                 $rolesMap[$role] = [];
  551.             }
  552.             $rolesMap[$role][] = $user;
  553.         }
  554.         return array_map(function ($i) {
  555.             return count($i) === $i[0] : $i;
  556.         }, $rolesMap);
  557.     }
  558.     /**
  559.      * @param DateTime $timeout
  560.      * @throws Exception
  561.      */
  562.     public function setTimeout(DateTime $timeout)
  563.     {
  564.         $this->getCurrentState()->setDeadline($timeout);
  565.     }
  566.     /**
  567.      * @return string
  568.      */
  569.     public function getSubWorkflow()
  570.     {
  571.         return $this->subWorkflow;
  572.     }
  573.     /**
  574.      * @param string $subWorkflow
  575.      */
  576.     public function setSubWorkflow($subWorkflow)
  577.     {
  578.         $this->subWorkflow $subWorkflow;
  579.     }
  580. }