query->has('entityClass')) { throw new BadRequestHttpException('Missing entityClass parameter'); } if (!$request->query->has('entityId')) { throw new BadRequestHttpException('missing entityId parameter'); } if (!$request->query->has('workflow')) { throw new BadRequestHttpException('missing workflow parameter'); } $entityWorkflow = new EntityWorkflow(); $entityWorkflow ->setRelatedEntityClass($request->query->get('entityClass')) ->setRelatedEntityId($request->query->getInt('entityId')) ->setWorkflowName($request->query->get('workflow')) ->addSubscriberToFinal($this->security->getUser()); $errors = $this->validator->validate($entityWorkflow, null, ['creation']); if (\count($errors) > 0) { $msg = []; foreach ($errors as $error) { /* @var \Symfony\Component\Validator\ConstraintViolationInterface $error */ $msg[] = $error->getMessage(); } return new Response(implode("\n", $msg), Response::HTTP_UNPROCESSABLE_ENTITY); } $this->denyAccessUnlessGranted(EntityWorkflowVoter::CREATE, $entityWorkflow); $em = $this->managerRegistry->getManager(); $em->persist($entityWorkflow); $em->flush(); return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]); } #[Route(path: '/{_locale}/main/workflow/{id}/delete', name: 'chill_main_workflow_delete')] public function delete(EntityWorkflow $entityWorkflow, Request $request): Response { $this->denyAccessUnlessGranted(EntityWorkflowVoter::DELETE, $entityWorkflow); $form = $this->createForm(FormType::class); $form->add('submit', SubmitType::class, ['label' => 'workflow.Delete workflow']); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $this->entityManager->remove($entityWorkflow); $this->entityManager->flush(); $this->addFlash('success', $this->translator->trans('workflow.Workflow deleted with success')); return $this->redirectToRoute('chill_main_homepage'); } return $this->render('@ChillMain/Workflow/delete.html.twig', [ 'entityWorkflow' => $entityWorkflow, 'delete_form' => $form->createView(), 'handler' => $this->entityWorkflowManager->getHandler($entityWorkflow), ]); } #[Route(path: '/{_locale}/main/workflow-step/{id}/access_key', name: 'chill_main_workflow_grant_access_by_key')] public function getAccessByAccessKey(EntityWorkflowStep $entityWorkflowStep, Request $request): Response { if (null === $accessKey = $request->query->get('accessKey', null)) { throw new BadRequestHttpException('accessKey is missing'); } if (!$this->getUser() instanceof User) { throw new AccessDeniedHttpException('Not a valid user'); } if ($entityWorkflowStep->getAccessKey() !== $accessKey) { throw new AccessDeniedHttpException('Access key is invalid'); } if (!$entityWorkflowStep->isWaitingForTransition()) { $this->addFlash('error', $this->translator->trans('workflow.Steps is not waiting for transition. Maybe someone apply the transition before you ?')); } else { $entityWorkflowStep->addDestUserByAccessKey($this->security->getUser()); $this->entityManager->flush(); $this->addFlash('success', $this->translator->trans('workflow.You get access to this step')); } return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflowStep->getEntityWorkflow()->getId()]); } /** * Previous workflows where the user has applyed a transition. */ #[Route(path: '/{_locale}/main/workflow/list/previous_transitionned', name: 'chill_main_workflow_list_previous_transitionned')] public function myPreviousWorkflowsTransitionned(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); $total = $this->entityWorkflowRepository->countByPreviousTransitionned($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByPreviousTransitionned( $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return $this->render( '@ChillMain/Workflow/list.html.twig', [ 'help' => 'workflow.Previous workflow transitionned help', 'workflows' => $this->buildHandler($workflows), 'paginator' => $paginator, 'step' => 'previous_transitionned', ] ); } /** * Previous workflows where the user was mentioned, but did not give any reaction. */ #[Route(path: '/{_locale}/main/workflow/list/previous_without_reaction', name: 'chill_main_workflow_list_previous_without_reaction')] public function myPreviousWorkflowsWithoutReaction(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); $total = $this->entityWorkflowRepository->countByPreviousDestWithoutReaction($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByPreviousDestWithoutReaction( $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return $this->render( '@ChillMain/Workflow/list.html.twig', [ 'help' => 'workflow.Previous workflow without reaction help', 'workflows' => $this->buildHandler($workflows), 'paginator' => $paginator, 'step' => 'previous_without_reaction', ] ); } #[Route(path: '/{_locale}/main/workflow/list/cc', name: 'chill_main_workflow_list_cc')] public function myWorkflowsCc(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); $total = $this->entityWorkflowRepository->countByDest($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByCc( $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return $this->render( '@ChillMain/Workflow/list.html.twig', [ 'workflows' => $this->buildHandler($workflows), 'paginator' => $paginator, 'step' => 'cc', ] ); } #[Route(path: '/{_locale}/main/workflow/list/dest', name: 'chill_main_workflow_list_dest')] public function myWorkflowsDest(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); $total = $this->entityWorkflowRepository->countByDest($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findByDest( $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return $this->render( '@ChillMain/Workflow/list.html.twig', [ 'workflows' => $this->buildHandler($workflows), 'paginator' => $paginator, 'step' => 'dest', ] ); } #[Route(path: '/{_locale}/main/workflow/list/subscribed', name: 'chill_main_workflow_list_subscribed')] public function myWorkflowsSubscribed(Request $request): Response { $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED'); $total = $this->entityWorkflowRepository->countBySubscriber($this->security->getUser()); $paginator = $this->paginatorFactory->create($total); $workflows = $this->entityWorkflowRepository->findBySubscriber( $this->security->getUser(), ['createdAt' => 'DESC'], $paginator->getItemsPerPage(), $paginator->getCurrentPageFirstItemNumber() ); return $this->render( '@ChillMain/Workflow/list.html.twig', [ 'workflows' => $this->buildHandler($workflows), 'paginator' => $paginator, 'step' => 'subscribed', ] ); } #[Route(path: '/{_locale}/main/workflow/{id}/show', name: 'chill_main_workflow_show')] public function show(EntityWorkflow $entityWorkflow, Request $request): Response { $this->denyAccessUnlessGranted(EntityWorkflowVoter::SEE, $entityWorkflow); $handler = $this->entityWorkflowManager->getHandler($entityWorkflow); $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); $errors = []; $signatures = $entityWorkflow->getCurrentStep()->getSignatures(); if (\count($workflow->getEnabledTransitions($entityWorkflow)) > 0) { // possible transition $stepDTO = new WorkflowTransitionContextDTO($entityWorkflow); $usersInvolved = $entityWorkflow->getUsersInvolved(); $currentUserFound = array_search($this->security->getUser(), $usersInvolved, true); if (false !== $currentUserFound) { unset($usersInvolved[$currentUserFound]); } $transitionForm = $this->createForm( WorkflowStepType::class, $stepDTO, [ 'entity_workflow' => $entityWorkflow, 'suggested_users' => $usersInvolved, ] ); $transitionForm->handleRequest($request); if ($transitionForm->isSubmitted() && $transitionForm->isValid()) { if (!$workflow->can($entityWorkflow, $transition = $transitionForm['transition']->getData()->getName())) { $blockers = $workflow->buildTransitionBlockerList($entityWorkflow, $transition); $msgs = array_map(fn (TransitionBlocker $tb) => $this->translator->trans( $tb->getMessage(), $tb->getParameters() ), iterator_to_array($blockers)); throw $this->createAccessDeniedException(sprintf("not allowed to apply transition {$transition}: %s", implode(', ', $msgs))); } $byUser = $this->security->getUser(); $workflow->apply($entityWorkflow, $transition, [ 'context' => $stepDTO, 'byUser' => $byUser, 'transition' => $transition, 'transitionAt' => $this->clock->now(), ]); $this->entityManager->flush(); return $this->redirectToRoute('chill_main_workflow_show', ['id' => $entityWorkflow->getId()]); } if ($transitionForm->isSubmitted() && !$transitionForm->isValid()) { $this->addFlash('error', $this->translator->trans('This form contains errors')); } } return $this->render( '@ChillMain/Workflow/index.html.twig', [ 'handler' => $handler, 'handler_template' => $handler->getTemplate($entityWorkflow), 'handler_template_data' => $handler->getTemplateData($entityWorkflow), 'transition_form' => isset($transitionForm) ? $transitionForm->createView() : null, 'entity_workflow' => $entityWorkflow, 'transition_form_errors' => $errors, 'signatures' => $signatures, ] ); } private function buildHandler(array $workflows): array { $lines = []; foreach ($workflows as $workflow) { $handler = $this->entityWorkflowManager->getHandler($workflow); $lines[] = [ 'handler' => $handler, 'entity_workflow' => $workflow, ]; } return $lines; } #[Route(path: '/{_locale}/main/workflow/signature/{signature_id}/metadata', name: 'chill_main_workflow_signature_metadata')] public function addSignatureMetadata(int $signature_id, Request $request): Response { $signature = $this->entityManager->getRepository(EntityWorkflowStepSignature::class)->find($signature_id); if ($signature->getSigner() instanceof User) { return $this->redirectToRoute('chill_main_workflow_signature_add', ['id' => $signature_id]); } $metadataForm = $this->createForm(WorkflowSignatureMetadataType::class); $metadataForm->add('submit', SubmitType::class, ['label' => $this->translator->trans('Save')]); $metadataForm->handleRequest($request); if ($metadataForm->isSubmitted() && $metadataForm->isValid()) { $data = $metadataForm->getData(); $signature->setSignatureMetadata( [ 'base_signer' => [ 'document_type' => $data['documentType'], 'document_number' => $data['documentNumber'], 'expiration_date' => $data['expirationDate'], ], ] ); $this->entityManager->persist($signature); $this->entityManager->flush(); return $this->redirectToRoute('chill_main_workflow_signature_add', ['id' => $signature_id]); } return $this->render( '@ChillMain/Workflow/_signature_metadata.html.twig', [ 'metadata_form' => $metadataForm->createView(), 'person' => $signature->getSigner(), ] ); } }