I'm using Symfony workflow on my project. I can pass the first transition and see that the next transitions are enabled with $workflow->getEnabledTransitions($entity);
. When passing to another route which introduce the next transition (part of the enabled transitions) it seems that the workflow has initialized back itself when checking the enabled transitions.
Here is my workflow.yaml configuration file :
framework:
workflows:
produit_selection:
type: 'workflow' # or 'state_machine'
audit_trail:
enabled: true
marking_store:
type: 'single_state'
arguments:
- 'currentPlace'
supports:
- App\Entity\Produit
initial_place: initiale
places:
- initiale
- commande
- selectionne
- invalide_selection
transitions:
commander:
from: initiale
to: commande
selectionner:
from: commande
to: selectionne
invalider_selection:
from: commande
to: invalide_selection
Here is my commandeProduit
controller action :
/**
* @Route("/produit/commande/{id<\d+>}", name="produit_commande")
* @param Request $request
* @param $id
* @param ProduitRequestCommandeUpdateHandler $updateHandler
* @return \Symfony\Component\HttpFoundation\Response
* @Security("has_role('ROLE_MARKETING')")
*/
public function commandeProduit(
Request $request,
$id,
ProduitRequestCommandeUpdateHandler $updateHandler,
Registry $workflows
) {
$repository = $this->getDoctrine()->getRepository(Produit::class);
/** @var Produit $produit */
$produit = $repository->find($id);
$produitRequest = ProduitRequest::createFromProduit($produit);
$form = $this->createForm(ProduitCommandeType::class, $produitRequest)->handleRequest($request);
$box = $produit->getBox();
if ($form->isSubmitted() AND $form->isValid()) {
$produit = $updateHandler->handle($produitRequest, $produit, $box);
if (null === $produit) {
$this->addFlash(
'error',
"La commande a été annulée car elle dépasse le budget."
);
} elseif ($produit->getCommande()) {
$workflow = $workflows->get($produit, 'produit_selection');
//$workflow->getMarking($produit);
if ($workflow->can($produit, 'commander')) {
try {
$workflow->apply($produit, 'commander');
} catch (TransitionException $exception) {
// ... if the transition is not allowed
}
}
$transitions = $workflow->getEnabledTransitions($produit);
/** @var Transition $transition */
foreach($transitions as $transition) {
$this->addFlash(
'error',
$transition->getName()
);
}
$this->addFlash(
'notice',
"La commande du produit a bien été prise en compte avec la quantité " . $produit->getQuantite() . "."
);
} else {
$this->addFlash(
'warning',
"Le produit n'est pas disponible."
);
}
return $this->redirectToRoute("produits_commande");
}
$fournisseur = $produit->getFournisseur();
return $this->render('produits/commande_produit.html.twig', [
'box' => $box,
'fournisseur' => $fournisseur,
'form' => $form->createView()
]);
}
And here is my selectionProduit
controller action :
/**
* @Route("/produit/selection/{id<\d+>}", name="produit_selection")
* @param Request $request
* @param $id
* @param ProduitRequestUpdateHandler $updateHandler
* @param Registry $workflows
* @return \Symfony\Component\HttpFoundation\Response
* @Security("has_role('ROLE_MARKETING')")
*/
public function selectionProduit(
Request $request,
$id,
ProduitRequestUpdateHandler $updateHandler,
Registry $workflows
) {
$repository = $this->getDoctrine()->getRepository(Produit::class);
/** @var Produit $produit */
$produit = $repository->find($id);
$produitRequest = ProduitRequest::createFromProduit($produit);
$form = $this->createForm(ProduitSelectionType::class, $produitRequest)->handleRequest($request);
if($form->isSubmitted() AND $form->isValid()) {
$produit = $updateHandler->handle($produitRequest, $produit);
if ($produit->getSelectionne()) {
$workflow = $workflows->get($produit, 'produit_selection');
//$workflow->getMarking($produit);
$workflow->can($produit, 'selectionner');
try {
$workflow->apply($produit, 'selectionner');
} catch (TransitionException $exception) {
// ... if the transition is not allowed
}
$transitions = $workflow->getEnabledTransitions($produit);
/** @var Transition $transition */
foreach($transitions as $transition) {
$this->addFlash(
'error',
$transition->getName()
);
}
$this->addFlash(
'notice',
"Le produit a bien été sélectionné avec la quantité " . $produit->getQuantite() . ".");
} else {
$workflow = $workflows->get($produit, 'produit_selection');
//$workflow->getMarking($produit);
if ($workflow->can($produit, 'invalider_selection')) {
try {
$workflow->apply($produit, 'invalider_selection');
} catch (TransitionException $exception) {
// ... if the transition is not allowed
}
}
$transitions = $workflow->getEnabledTransitions($produit);
$this->addFlash(
'warning',
"Le produit n'a pas été sélectionné.");
}
return $this->redirectToRoute("produits_selection");
}
$box = $produit->getBox();
$fournisseur = $produit->getFournisseur();
return $this->render('produits/selection_produit.html.twig', [
'box' => $box,
'fournisseur' => $fournisseur,
'form' => $form->createView()
]);
}
Why the workflow doesn't transit to the next place after changing route ? How to fix that ? Thanks for help.
I found it. We have to flush the entity to store the current place :
$workflow->apply($produit, 'selectionner');
$this->getDoctrine()->getManager()->flush();
And in the entity we have a field defined like this :
/**
* @ORM\Column(type="string", length=100)
*/
public $currentPlace;