diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentWorkflowHandlerTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentWorkflowHandlerTest.php new file mode 100644 index 000000000..cf8bc9c7c --- /dev/null +++ b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentWorkflowHandlerTest.php @@ -0,0 +1,94 @@ +setCourse($accompanyingPeriod)->setUser($user1 = new User()); + $accompanyingPeriod->setUser($user = new User()); + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setRelatedEntityId(1); + + $handler = new AccompanyingCourseDocumentWorkflowHandler( + $this->prophesize(TranslatorInterface::class)->reveal(), + $this->prophesize(EntityWorkflowRepository::class)->reveal(), + $this->buildRepository($document, 1), + new WorkflowWithPublicViewDocumentHelper($this->prophesize(Environment::class)->reveal()), + $this->prophesize(ProvideThirdPartiesAssociated::class)->reveal(), + $this->prophesize(ProvidePersonsAssociated::class)->reveal(), + ); + + $users = $handler->getSuggestedUsers($entityWorkflow); + + self::assertCount(2, $users); + self::assertContains($user, $users); + self::assertContains($user1, $users); + } + + public function testGetSuggestedUsersWithDuplicates() + { + $accompanyingPeriod = new AccompanyingPeriod(); + $document = new AccompanyingCourseDocument(); + $document->setCourse($accompanyingPeriod)->setUser($user1 = new User()); + $accompanyingPeriod->setUser($user1); + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setRelatedEntityId(1); + + $handler = new AccompanyingCourseDocumentWorkflowHandler( + $this->prophesize(TranslatorInterface::class)->reveal(), + $this->prophesize(EntityWorkflowRepository::class)->reveal(), + $this->buildRepository($document, 1), + new WorkflowWithPublicViewDocumentHelper($this->prophesize(Environment::class)->reveal()), + $this->prophesize(ProvideThirdPartiesAssociated::class)->reveal(), + $this->prophesize(ProvidePersonsAssociated::class)->reveal(), + ); + + $users = $handler->getSuggestedUsers($entityWorkflow); + + self::assertCount(1, $users); + self::assertContains($user1, $users); + } + + private function buildRepository(AccompanyingCourseDocument $document, int $id): AccompanyingCourseDocumentRepository + { + $repository = $this->prophesize(AccompanyingCourseDocumentRepository::class); + $repository->find($id)->willReturn($document); + + return $repository->reveal(); + } +} diff --git a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php index 4f4655b94..193568286 100644 --- a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php +++ b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php @@ -22,6 +22,8 @@ use Chill\MainBundle\Workflow\EntityWorkflowWithPublicViewInterface; use Chill\MainBundle\Workflow\EntityWorkflowWithStoredObjectHandlerInterface; use Chill\MainBundle\Workflow\Templating\EntityWorkflowViewMetadataDTO; use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; +use Chill\PersonBundle\Service\AccompanyingPeriod\ProvideThirdPartiesAssociated; +use Chill\PersonBundle\Service\AccompanyingPeriod\ProvidePersonsAssociated; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -34,6 +36,8 @@ final readonly class AccompanyingCourseDocumentWorkflowHandler implements Entity private EntityWorkflowRepository $workflowRepository, private AccompanyingCourseDocumentRepository $repository, private WorkflowWithPublicViewDocumentHelper $publicViewDocumentHelper, + private ProvideThirdPartiesAssociated $thirdPartiesAssociated, + private ProvidePersonsAssociated $providePersonsAssociated, ) {} public function getDeletionRoles(): array @@ -91,12 +95,28 @@ final readonly class AccompanyingCourseDocumentWorkflowHandler implements Entity public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array { - $suggestedUsers = $entityWorkflow->getUsersInvolved(); + $related = $this->getRelatedEntity($entityWorkflow); - $referrer = $this->getRelatedEntity($entityWorkflow)->getCourse()->getUser(); - $suggestedUsers[spl_object_hash($referrer)] = $referrer; + if (null === $related) { + return []; + } - return $suggestedUsers; + $users = []; + if (null !== $user = $related->getUser()) { + $users[] = $user; + } + if (null !== $user = $related->getCourse()->getUser()) { + $users[] = $user; + } + + return array_values( + // filter objects to remove duplicates + array_filter( + $users, + fn ($o, $k) => array_search($o, $users, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); } public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string @@ -145,4 +165,26 @@ final readonly class AccompanyingCourseDocumentWorkflowHandler implements Entity { return $this->publicViewDocumentHelper->render($entityWorkflowSend, $metadata, $this); } + + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->providePersonsAssociated->getPersonsAssociated($related->getCourse()); + } + + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->thirdPartiesAssociated->getThirdPartiesAssociated($related->getCourse()); + } } diff --git a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php index e10cac6a4..1f1372cd2 100644 --- a/src/Bundle/ChillMainBundle/Controller/WorkflowController.php +++ b/src/Bundle/ChillMainBundle/Controller/WorkflowController.php @@ -300,19 +300,12 @@ class WorkflowController extends AbstractController 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, ] ); diff --git a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php index e5769a28e..222927b42 100644 --- a/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php +++ b/src/Bundle/ChillMainBundle/Form/WorkflowStepType.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Form\Type\ChillTextareaType; use Chill\MainBundle\Form\Type\PickUserDynamicType; use Chill\MainBundle\Form\Type\PickUserGroupOrUserDynamicType; use Chill\MainBundle\Templating\TranslatableStringHelperInterface; +use Chill\MainBundle\Workflow\EntityWorkflowManager; use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO; use Chill\PersonBundle\Form\Type\PickPersonDynamicType; use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType; @@ -34,6 +35,7 @@ class WorkflowStepType extends AbstractType public function __construct( private readonly Registry $registry, private readonly TranslatableStringHelperInterface $translatableStringHelper, + private readonly EntityWorkflowManager $entityWorkflowManager, ) {} public function buildForm(FormBuilderInterface $builder, array $options) @@ -43,6 +45,9 @@ class WorkflowStepType extends AbstractType $workflow = $this->registry->get($entityWorkflow, $entityWorkflow->getWorkflowName()); $place = $workflow->getMarking($entityWorkflow); $placeMetadata = $workflow->getMetadataStore()->getPlaceMetadata(array_keys($place->getPlaces())[0]); + $suggestedUsers = $this->entityWorkflowManager->getSuggestedUsers($entityWorkflow); + $suggestedThirdParties = $this->entityWorkflowManager->getSuggestedThirdParties($entityWorkflow); + $suggestedPersons = $this->entityWorkflowManager->getSuggestedPersons($entityWorkflow); if (null === $options['entity_workflow']) { throw new \LogicException('if transition is true, entity_workflow should be defined'); @@ -152,24 +157,26 @@ class WorkflowStepType extends AbstractType 'label' => 'workflow.signature_zone.person signatures', 'multiple' => true, 'empty_data' => '[]', + 'suggested' => $suggestedPersons, ]) ->add('futureUserSignature', PickUserDynamicType::class, [ 'label' => 'workflow.signature_zone.user signature', 'multiple' => false, 'suggest_myself' => true, + 'suggested' => $suggestedUsers, ]) ->add('futureDestUsers', PickUserGroupOrUserDynamicType::class, [ 'label' => 'workflow.dest for next steps', 'multiple' => true, 'empty_data' => '[]', - 'suggested' => $options['suggested_users'], + 'suggested' => $suggestedUsers, 'suggest_myself' => true, ]) ->add('futureCcUsers', PickUserDynamicType::class, [ 'label' => 'workflow.cc for next steps', 'multiple' => true, 'required' => false, - 'suggested' => $options['suggested_users'], + 'suggested' => $suggestedUsers, 'empty_data' => '[]', 'attr' => ['class' => 'future-cc-users'], 'suggest_myself' => true, @@ -192,6 +199,7 @@ class WorkflowStepType extends AbstractType 'help' => 'workflow.transition_destinee_third_party_help', 'multiple' => true, 'empty_data' => [], + 'suggested' => $suggestedThirdParties, ]); $builder @@ -207,7 +215,6 @@ class WorkflowStepType extends AbstractType $resolver ->setDefault('data_class', WorkflowTransitionContextDTO::class) ->setRequired('entity_workflow') - ->setAllowedTypes('entity_workflow', EntityWorkflow::class) - ->setDefault('suggested_users', []); + ->setAllowedTypes('entity_workflow', EntityWorkflow::class); } } diff --git a/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowViewSendPublicControllerTest.php b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowViewSendPublicControllerTest.php index 02bee8f4f..d5a4d6561 100644 --- a/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowViewSendPublicControllerTest.php +++ b/src/Bundle/ChillMainBundle/Tests/Controller/WorkflowViewSendPublicControllerTest.php @@ -238,6 +238,16 @@ class WorkflowViewSendPublicControllerTest extends TestCase { return 'content'; } + + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + return []; + } + + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + return []; + } }; } diff --git a/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowManagerTest.php b/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowManagerTest.php new file mode 100644 index 000000000..4570d86b8 --- /dev/null +++ b/src/Bundle/ChillMainBundle/Tests/Workflow/EntityWorkflowManagerTest.php @@ -0,0 +1,49 @@ +createMock(EntityWorkflow::class); + $entityWorkflow->method('getUsersInvolved')->willReturn([$user1, $user2]); + + $user3 = new User(); + $handler = $this->createMock(EntityWorkflowHandlerInterface::class); + $handler->method('getSuggestedUsers')->willReturn([$user1, $user3]); + $handler->method('supports')->willReturn(true); + + $manager = new EntityWorkflowManager([$handler], new Registry()); + + $users = $manager->getSuggestedUsers($entityWorkflow); + + self::assertcount(3, $users); + self::assertContains($user1, $users); + self::assertContains($user2, $users); + self::assertContains($user3, $users); + } +} diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php index c0d6469f6..0cc03084e 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowHandlerInterface.php @@ -13,6 +13,8 @@ namespace Chill\MainBundle\Workflow; use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; +use Chill\PersonBundle\Entity\Person; +use Chill\ThirdPartyBundle\Entity\ThirdParty; /** * @template T of object @@ -48,6 +50,16 @@ interface EntityWorkflowHandlerInterface */ public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array; + /** + * @return list + */ + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array; + + /** + * @return list + */ + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array; + public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string; public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array; diff --git a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php index f1c87fd4e..474370127 100644 --- a/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php +++ b/src/Bundle/ChillMainBundle/Workflow/EntityWorkflowManager.php @@ -12,11 +12,14 @@ declare(strict_types=1); namespace Chill\MainBundle\Workflow; use Chill\DocStoreBundle\Entity\StoredObject; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Entity\Workflow\EntityWorkflowSend; use Chill\MainBundle\Workflow\Exception\HandlerNotFoundException; use Chill\MainBundle\Workflow\Exception\HandlerWithPublicViewNotFoundException; use Chill\MainBundle\Workflow\Templating\EntityWorkflowViewMetadataDTO; +use Chill\PersonBundle\Entity\Person; +use Chill\ThirdPartyBundle\Entity\ThirdParty; use Symfony\Component\Workflow\Registry; /** @@ -93,4 +96,46 @@ class EntityWorkflowManager throw new HandlerWithPublicViewNotFoundException(); } + + /** + * @return list + */ + public function getSuggestedUsers(EntityWorkflow $entityWorkflow, bool $addUsersInvolved = true): array + { + $users = []; + if ($addUsersInvolved) { + foreach ($entityWorkflow->getUsersInvolved() as $user) { + $users[] = $user; + } + } + + foreach ($this->getHandler($entityWorkflow)->getSuggestedUsers($entityWorkflow) as $user) { + $users[] = $user; + } + + return array_values( + // filter objects to remove duplicates + array_filter( + $users, + fn ($o, $k) => array_search($o, $users, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); + } + + /** + * @return list + */ + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + return $this->getHandler($entityWorkflow)->getSuggestedPersons($entityWorkflow); + } + + /** + * @return list + */ + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + return $this->getHandler($entityWorkflow)->getSuggestedThirdParties($entityWorkflow); + } } diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php index e3a484f0b..6baa0d069 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkEvaluationDocumentRepository.php @@ -19,9 +19,9 @@ use Doctrine\ORM\EntityRepository; use Doctrine\ORM\NonUniqueResultException; use Doctrine\Persistence\ObjectRepository; -readonly class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository, AssociatedEntityToStoredObjectInterface +class AccompanyingPeriodWorkEvaluationDocumentRepository implements ObjectRepository, AssociatedEntityToStoredObjectInterface { - private EntityRepository $repository; + private readonly EntityRepository $repository; public function __construct(EntityManagerInterface $em) { diff --git a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php index 95b995e74..0d5bf5eee 100644 --- a/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php +++ b/src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriod/AccompanyingPeriodWorkRepository.php @@ -22,11 +22,11 @@ use Doctrine\ORM\Query\ResultSetMappingBuilder; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; -final readonly class AccompanyingPeriodWorkRepository implements ObjectRepository +class AccompanyingPeriodWorkRepository implements ObjectRepository { - private EntityRepository $repository; + private readonly EntityRepository $repository; - public function __construct(private EntityManagerInterface $em) + public function __construct(private readonly EntityManagerInterface $em) { $this->repository = $em->getRepository(AccompanyingPeriodWork::class); } diff --git a/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvidePersonsAssociated.php b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvidePersonsAssociated.php new file mode 100644 index 000000000..af1ae6e0f --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvidePersonsAssociated.php @@ -0,0 +1,34 @@ + + */ + public function getPersonsAssociated(AccompanyingPeriod $period): array + { + return array_values( + $period->getCurrentParticipations() + ->map(fn (AccompanyingPeriodParticipation $participation) => $participation->getPerson()) + ->toArray() + ); + } +} diff --git a/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvideThirdPartiesAssociated.php b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvideThirdPartiesAssociated.php new file mode 100644 index 000000000..5aa24bcda --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriod/ProvideThirdPartiesAssociated.php @@ -0,0 +1,50 @@ + + */ + public function getThirdPartiesAssociated(AccompanyingPeriod $period): array + { + $thirdParties = []; + + foreach ( + $period + ->getResources()->filter(fn (Resource $resource) => null !== $resource->getThirdParty()) + ->map(fn (Resource $resource) => $resource->getThirdParty()) as $thirdParty) { + $thirdParties[] = $thirdParty; + } + + if (null !== $requestor = $period->getRequestorThirdParty()) { + $thirdParties[] = $requestor; + } + + return array_values( + // filter objects to remove duplicates + array_filter( + $thirdParties, + fn ($o, $k) => array_search($o, $thirdParties, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); + } +} diff --git a/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvidePersonsAssociated.php b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvidePersonsAssociated.php new file mode 100644 index 000000000..5fd885948 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvidePersonsAssociated.php @@ -0,0 +1,32 @@ + + */ + public function getPersonsAssociated(AccompanyingPeriod\AccompanyingPeriodWork $work): array + { + return $this->providePersonsAssociated->getPersonsAssociated($work->getAccompanyingPeriod()); + } +} diff --git a/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociated.php b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociated.php new file mode 100644 index 000000000..2aa73935d --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociated.php @@ -0,0 +1,49 @@ + + */ + public function getThirdPartiesAssociated(AccompanyingPeriodWork $accompanyingPeriodWork): array + { + $thirdParties = $this->thirdPartiesAssociated->getThirdPartiesAssociated($accompanyingPeriodWork->getAccompanyingPeriod()); + + if (null !== $tp = $accompanyingPeriodWork->getHandlingThierParty()) { + $thirdParties[] = $tp; + } + + foreach ($accompanyingPeriodWork->getThirdParties() as $thirdParty) { + $thirdParties[] = $thirdParty; + } + + return array_values( + // filter objects to remove duplicates + array_filter( + $thirdParties, + fn ($o, $k) => array_search($o, $thirdParties, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriod/ProvideThirdPartiesAssociatedTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriod/ProvideThirdPartiesAssociatedTest.php new file mode 100644 index 000000000..ccc2a902e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriod/ProvideThirdPartiesAssociatedTest.php @@ -0,0 +1,45 @@ +setRequestor($tp1 = new ThirdParty()); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($tp1)); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($tp2 = new ThirdParty())); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($p1 = new Person())); + + $provider = new ProvideThirdPartiesAssociated(); + + $thirdParties = $provider->getThirdPartiesAssociated($period); + + self::assertCount(2, $thirdParties); + self::assertContains($tp1, $thirdParties); + self::assertContains($tp2, $thirdParties); + self::assertNotContains($p1, $thirdParties); + self::assertNotContains(null, $thirdParties); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociatedTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociatedTest.php new file mode 100644 index 000000000..5ce7b953e --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWork/ProvideThirdPartiesAssociatedTest.php @@ -0,0 +1,52 @@ +setRequestor($tp1 = new ThirdParty()); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($tp1)); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($tp2 = new ThirdParty())); + $period->addResource((new AccompanyingPeriod\Resource())->setResource($p1 = new Person())); + $period->addWork($work = new AccompanyingPeriod\AccompanyingPeriodWork()); + $work->addThirdParty($tp3 = new ThirdParty()); + $work->addThirdParty($tp1); + $work->setHandlingThierParty($tp4 = new ThirdParty()); + + $providerAccPeriod = new \Chill\PersonBundle\Service\AccompanyingPeriod\ProvideThirdPartiesAssociated(); + $provider = new ProvideThirdPartiesAssociated($providerAccPeriod); + + + $thirdParties = $provider->getThirdPartiesAssociated($work); + + self::assertContains($tp1, $thirdParties); + self::assertContains($tp2, $thirdParties); + self::assertContains($tp3, $thirdParties); + self::assertContains($tp4, $thirdParties); + self::assertNotContains($p1, $thirdParties); + self::assertCount(4, $thirdParties); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandlerTest.php b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandlerTest.php new file mode 100644 index 000000000..df701d906 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandlerTest.php @@ -0,0 +1,86 @@ +setUser($referrer = new User()); + $accompanyingCourse->addWork($work = new AccompanyingPeriod\AccompanyingPeriodWork()); + $work->addReferrer($workReferrer1 = new User()); + $work->addReferrer($workReferrer2 = new User()); + $work->addReferrer($referrer); + $work->addAccompanyingPeriodWorkEvaluation($eval = new AccompanyingPeriod\AccompanyingPeriodWorkEvaluation()); + $eval->addDocument($doc = new AccompanyingPeriodWorkEvaluationDocument()); + $entityWorkflow = new EntityWorkflow(); + + // Prophesize each dependency + $workflowRepositoryProphecy = $this->prophesize(EntityWorkflowRepository::class); + $translatableStringHelperProphecy = $this->prophesize(TranslatableStringHelperInterface::class); + $translatorProphecy = $this->prophesize(TranslatorInterface::class); + $twig = $this->prophesize(Environment::class); + + // Create an instance of the class under test using revealed prophecies directly + $handler = new AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler( + $this->buildRepository($doc, 1), + $workflowRepositoryProphecy->reveal(), + $translatableStringHelperProphecy->reveal(), + $translatorProphecy->reveal(), + new WorkflowWithPublicViewDocumentHelper($twig->reveal()), + $this->prophesize(ProvideThirdPartiesAssociated::class)->reveal(), + $this->prophesize(ProvidePersonsAssociated::class)->reveal(), + ); + + $entityWorkflow->setRelatedEntityId(1); + $entityWorkflow->setRelatedEntityClass(AccompanyingPeriodWorkEvaluationDocument::class); + + $users = $handler->getSuggestedUsers($entityWorkflow); + + self::assertContains($referrer, $users); + self::assertContains($workReferrer1, $users); + self::assertContains($workReferrer2, $users); + } + + private function buildRepository(AccompanyingPeriodWorkEvaluationDocument $document, int $id): AccompanyingPeriodWorkEvaluationDocumentRepository + { + $repository = $this->prophesize(AccompanyingPeriodWorkEvaluationDocumentRepository::class); + + $repository->find($id)->willReturn($document); + + return $repository->reveal(); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandlerTest.php b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandlerTest.php new file mode 100644 index 000000000..bcd1e8c8a --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandlerTest.php @@ -0,0 +1,77 @@ +setUser($referrer = new User()); + $accompanyingCourse->addWork($work = new AccompanyingPeriod\AccompanyingPeriodWork()); + $work->addReferrer($workReferrer1 = new User()); + $work->addReferrer($workReferrer2 = new User()); + $work->addReferrer($referrer); + $work->addAccompanyingPeriodWorkEvaluation($eval = new AccompanyingPeriod\AccompanyingPeriodWorkEvaluation()); + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setRelatedEntityId(1); + + // Prophesize each dependency + $workflowRepositoryProphecy = $this->prophesize(EntityWorkflowRepository::class); + $translatableStringHelperProphecy = $this->prophesize(TranslatableStringHelperInterface::class); + $translatorProphecy = $this->prophesize(TranslatorInterface::class); + + // Create an instance of the class under test using revealed prophecies directly + $handler = new AccompanyingPeriodWorkEvaluationWorkflowHandler( + $this->buildRepository($eval, 1), + $workflowRepositoryProphecy->reveal(), + $translatableStringHelperProphecy->reveal(), + $translatorProphecy->reveal(), + $this->prophesize(ProvideThirdPartiesAssociated::class)->reveal(), + $this->prophesize(ProvidePersonsAssociated::class)->reveal(), + ); + + $users = $handler->getSuggestedUsers($entityWorkflow); + + self::assertContains($referrer, $users); + self::assertContains($workReferrer1, $users); + self::assertContains($workReferrer2, $users); + } + + private function buildRepository(AccompanyingPeriod\AccompanyingPeriodWorkEvaluation $evaluation, int $id): AccompanyingPeriodWorkEvaluationRepository + { + $evaluationRepositoryProphecy = $this->prophesize(AccompanyingPeriodWorkEvaluationRepository::class); + $evaluationRepositoryProphecy->find($id)->willReturn($evaluation); + + return $evaluationRepositoryProphecy->reveal(); + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkWorkflowHandlerTest.php b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkWorkflowHandlerTest.php new file mode 100644 index 000000000..5fcaf8eb4 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Workflow/AccompanyingPeriodWorkWorkflowHandlerTest.php @@ -0,0 +1,78 @@ +setUser($referrer = new User()); + $accompanyingCourse->addWork($work = new AccompanyingPeriod\AccompanyingPeriodWork()); + $work->addReferrer($workReferrer1 = new User()); + $work->addReferrer($workReferrer2 = new User()); + $work->addReferrer($referrer); + $entityWorkflow = new EntityWorkflow(); + $entityWorkflow->setRelatedEntityId(1); + + // Prophesize each dependency + $workflowRepositoryProphecy = $this->prophesize(EntityWorkflowRepository::class); + $translatableStringHelperProphecy = $this->prophesize(TranslatableStringHelperInterface::class); + $translatorProphecy = $this->prophesize(TranslatorInterface::class); + + // Create an instance of the class under test using revealed prophecies directly + $handler = new AccompanyingPeriodWorkWorkflowHandler( + $this->buildRepository($work, 1), + $workflowRepositoryProphecy->reveal(), + $translatableStringHelperProphecy->reveal(), + $translatorProphecy->reveal(), + $this->prophesize(ProvideThirdPartiesAssociated::class)->reveal(), + $this->prophesize(ProvidePersonsAssociated::class)->reveal(), + ); + + $users = $handler->getSuggestedUsers($entityWorkflow); + + self::assertContains($referrer, $users); + self::assertContains($workReferrer1, $users); + self::assertContains($workReferrer2, $users); + } + + private function buildRepository(AccompanyingPeriod\AccompanyingPeriodWork $work, int $int): AccompanyingPeriodWorkRepository + { + $accompanyingPeriodWorkRepositoryProphecy = $this->prophesize(AccompanyingPeriodWorkRepository::class); + $accompanyingPeriodWorkRepositoryProphecy + ->find($int) + ->willReturn($work); + + return $accompanyingPeriodWorkRepositoryProphecy->reveal(); + } +} diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php index e2f8e7666..780b81c1d 100644 --- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php +++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler.php @@ -23,6 +23,8 @@ use Chill\MainBundle\Workflow\Templating\EntityWorkflowViewMetadataDTO; use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationDocumentVoter; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvidePersonsAssociated; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvideThirdPartiesAssociated; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -36,6 +38,8 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW private readonly TranslatableStringHelperInterface $translatableStringHelper, private readonly TranslatorInterface $translator, private readonly WorkflowWithPublicViewDocumentHelper $publicViewDocumentHelper, + private readonly ProvideThirdPartiesAssociated $provideThirdPartiesAssociated, + private readonly ProvidePersonsAssociated $providePersonsAssociated, ) {} public function getDeletionRoles(): array @@ -98,17 +102,36 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array { - $suggestedUsers = $entityWorkflow->getUsersInvolved(); + $related = $this->getRelatedEntity($entityWorkflow); - $referrer = $this->getRelatedEntity($entityWorkflow) - ->getAccompanyingPeriodWorkEvaluation() + if (null === $related) { + return []; + } + + $users = []; + if (null !== $referrer = $related->getAccompanyingPeriodWorkEvaluation() ->getAccompanyingPeriodWork() ->getAccompanyingPeriod() - ->getUser(); + ->getUser() + ) { + $users[] = $referrer; + } - $suggestedUsers[spl_object_hash($referrer)] = $referrer; + foreach ($related->getAccompanyingPeriodWorkEvaluation() + ->getAccompanyingPeriodWork() + ->getReferrersHistoryCurrent() as $referrerHistory + ) { + $users[] = $referrerHistory->getUser(); + } - return $suggestedUsers; + return array_values( + // filter objects to remove duplicates + array_filter( + $users, + fn ($o, $k) => array_search($o, $users, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); } public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string @@ -160,4 +183,26 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW { return $this->publicViewDocumentHelper->render($entityWorkflowSend, $metadata, $this); } + + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->providePersonsAssociated->getPersonsAssociated($related->getAccompanyingPeriodWorkEvaluation()->getAccompanyingPeriodWork()); + } + + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->provideThirdPartiesAssociated->getThirdPartiesAssociated($related->getAccompanyingPeriodWorkEvaluation()->getAccompanyingPeriodWork()); + } } diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php index e619532ff..3e72e65bd 100644 --- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php +++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkEvaluationWorkflowHandler.php @@ -19,6 +19,8 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluatio use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationRepository; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvidePersonsAssociated; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvideThirdPartiesAssociated; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -31,6 +33,8 @@ readonly class AccompanyingPeriodWorkEvaluationWorkflowHandler implements Entity private EntityWorkflowRepository $workflowRepository, private TranslatableStringHelperInterface $translatableStringHelper, private TranslatorInterface $translator, + private ProvideThirdPartiesAssociated $provideThirdPartiesAssociated, + private ProvidePersonsAssociated $providePersonsAssociated, ) {} public function getDeletionRoles(): array @@ -81,16 +85,34 @@ readonly class AccompanyingPeriodWorkEvaluationWorkflowHandler implements Entity public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array { - $suggestedUsers = $entityWorkflow->getUsersInvolved(); + $related = $this->getRelatedEntity($entityWorkflow); - $referrer = $this->getRelatedEntity($entityWorkflow) - ->getAccompanyingPeriodWork() + if (null === $related) { + return []; + } + + $users = []; + if (null !== $referrer = $related->getAccompanyingPeriodWork() ->getAccompanyingPeriod() - ->getUser(); + ->getUser() + ) { + $users[] = $referrer; + } - $suggestedUsers[spl_object_hash($referrer)] = $referrer; + foreach ($related->getAccompanyingPeriodWork() + ->getReferrersHistoryCurrent() as $referrerHistory + ) { + $users[] = $referrerHistory->getUser(); + } - return $suggestedUsers; + return array_values( + // filter objects to remove duplicates + array_filter( + $users, + fn ($o, $k) => array_search($o, $users, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); } public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string @@ -129,4 +151,26 @@ readonly class AccompanyingPeriodWorkEvaluationWorkflowHandler implements Entity return $this->workflowRepository->findByRelatedEntity(AccompanyingPeriodWorkEvaluation::class, $object->getId()); } + + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->providePersonsAssociated->getPersonsAssociated($related->getAccompanyingPeriodWork()); + } + + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->provideThirdPartiesAssociated->getThirdPartiesAssociated($related->getAccompanyingPeriodWork()); + } } diff --git a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php index 772523ad5..58d3c9875 100644 --- a/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php +++ b/src/Bundle/ChillPersonBundle/Workflow/AccompanyingPeriodWorkWorkflowHandler.php @@ -20,6 +20,8 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluatio use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument; use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository; use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvidePersonsAssociated; +use Chill\PersonBundle\Service\AccompanyingPeriodWork\ProvideThirdPartiesAssociated; use Symfony\Contracts\Translation\TranslatorInterface; /** @@ -32,6 +34,8 @@ readonly class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHa private EntityWorkflowRepository $workflowRepository, private TranslatableStringHelperInterface $translatableStringHelper, private TranslatorInterface $translator, + private ProvideThirdPartiesAssociated $thirdPartiesAssociated, + private ProvidePersonsAssociated $providePersonsAssociated, ) {} public function getDeletionRoles(): array @@ -87,17 +91,32 @@ readonly class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHa public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array { - $suggestedUsers = $entityWorkflow->getUsersInvolved(); + $related = $this->getRelatedEntity($entityWorkflow); - $referrer = $this->getRelatedEntity($entityWorkflow) - ->getAccompanyingPeriod() - ->getUser(); - - if (null !== $referrer) { - $suggestedUsers[spl_object_hash($referrer)] = $referrer; + if (null === $related) { + return []; } - return $suggestedUsers; + $users = []; + if (null !== $referrer = $related->getAccompanyingPeriod() + ->getUser() + ) { + $users[] = $referrer; + } + + foreach ($related->getReferrersHistoryCurrent() as $referrerHistory + ) { + $users[] = $referrerHistory->getUser(); + } + + return array_values( + // filter objects to remove duplicates + array_filter( + $users, + fn ($o, $k) => array_search($o, $users, true) === $k, + ARRAY_FILTER_USE_BOTH + ) + ); } public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string @@ -136,4 +155,26 @@ readonly class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHa return $this->workflowRepository->findByRelatedEntity(AccompanyingPeriodWork::class, $object->getId()); } + + public function getSuggestedPersons(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->providePersonsAssociated->getPersonsAssociated($related); + } + + public function getSuggestedThirdParties(EntityWorkflow $entityWorkflow): array + { + $related = $this->getRelatedEntity($entityWorkflow); + + if (null === $related) { + return []; + } + + return $this->thirdPartiesAssociated->getThirdPartiesAssociated($related); + } }