Merge remote-tracking branch 'origin/signature-app-master' into 286-storedobject-voter

This commit is contained in:
Julien Fastré 2024-07-16 13:34:36 +02:00
commit 8aec69f0f9
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
17 changed files with 326 additions and 41 deletions

View File

@ -11,6 +11,9 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureRepository;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
@ -23,10 +26,27 @@ final readonly class PdfSignedMessageHandler implements MessageHandlerInterface
public function __construct(
private LoggerInterface $logger,
private EntityWorkflowManager $entityWorkflowManager,
private StoredObjectManagerInterface $storedObjectManager,
private EntityWorkflowStepSignatureRepository $entityWorkflowStepSignatureRepository,
) {}
public function __invoke(PdfSignedMessage $message): void
{
$this->logger->info(self::P.'a message is received', ['signaturedId' => $message->signatureId]);
$signature = $this->entityWorkflowStepSignatureRepository->find($message->signatureId);
if (null === $signature) {
throw new \RuntimeException('no signature found');
}
$storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($signature->getStep()->getEntityWorkflow());
if (null === $storedObject) {
throw new \RuntimeException('no stored object found');
}
$this->storedObjectManager->write($storedObject, $message->content);
}
}

View File

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\DocStoreBundle\Tests\Service\Signature\Driver\BaseSigner;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessage;
use Chill\DocStoreBundle\Service\Signature\Driver\BaseSigner\PdfSignedMessageHandler;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowStepSignatureRepository;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Chill\PersonBundle\Entity\Person;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
/**
* @internal
*
* @coversNothing
*/
class PdfSignedMessageHandlerTest extends TestCase
{
public function testThatObjectIsWrittenInStoredObjectManagerHappyScenario(): void
{
// a dummy stored object
$storedObject = new StoredObject();
// build the associated EntityWorkflow, with one step with a person signature
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = new Person();
$entityWorkflow->setStep('new_step', $dto, 'new_transition', new \DateTimeImmutable(), new User());
$step = $entityWorkflow->getCurrentStep();
$signature = $step->getSignatures()->first();
$handler = new PdfSignedMessageHandler(
new NullLogger(),
$this->buildEntityWorkflowManager($storedObject),
$this->buildStoredObjectManager($storedObject, $expectedContent = '1234'),
$this->buildSignatureRepository($signature)
);
// we simply call the handler. The mocked StoredObjectManager will check that the "write" method is invoked once
// with the content "1234"
$handler(new PdfSignedMessage(10, $expectedContent));
}
private function buildSignatureRepository(EntityWorkflowStepSignature $signature): EntityWorkflowStepSignatureRepository
{
$entityWorkflowStepSignatureRepository = $this->createMock(EntityWorkflowStepSignatureRepository::class);
$entityWorkflowStepSignatureRepository->method('find')->with($this->isType('int'))->willReturn($signature);
return $entityWorkflowStepSignatureRepository;
}
private function buildEntityWorkflowManager(?StoredObject $associatedStoredObject): EntityWorkflowManager
{
$entityWorkflowManager = $this->createMock(EntityWorkflowManager::class);
$entityWorkflowManager->method('getAssociatedStoredObject')->willReturn($associatedStoredObject);
return $entityWorkflowManager;
}
private function buildStoredObjectManager(StoredObject $expectedStoredObject, string $expectedContent): StoredObjectManagerInterface
{
$storedObjectManager = $this->createMock(StoredObjectManagerInterface::class);
$storedObjectManager->expects($this->once())
->method('write')
->with($this->identicalTo($expectedStoredObject), $expectedContent);
return $storedObjectManager;
}
}

View File

@ -13,14 +13,18 @@ namespace Chill\DocStoreBundle\Workflow;
use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument;
use Chill\DocStoreBundle\Repository\AccompanyingCourseDocumentRepository;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowWithStoredObjectHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Symfony\Contracts\Translation\TranslatorInterface;
readonly class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandlerInterface
/**
* @implements EntityWorkflowWithStoredObjectHandlerInterface<AccompanyingCourseDocument>
*/
readonly class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowWithStoredObjectHandlerInterface
{
public function __construct(
private TranslatorInterface $translator,
@ -67,8 +71,6 @@ readonly class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkfl
}
/**
* @param AccompanyingCourseDocument $object
*
* @return array[]
*/
public function getRelatedObjects(object $object): array
@ -116,6 +118,11 @@ readonly class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkfl
return AccompanyingCourseDocument::class === $entityWorkflow->getRelatedEntityClass();
}
public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject
{
return $this->getRelatedEntity($entityWorkflow)?->getObject();
}
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return false;

View File

@ -25,6 +25,7 @@ use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\HttpFoundation\Request;
@ -39,7 +40,18 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class WorkflowController extends AbstractController
{
public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager, private readonly EntityWorkflowRepository $entityWorkflowRepository, private readonly ValidatorInterface $validator, private readonly PaginatorFactory $paginatorFactory, private readonly Registry $registry, private readonly EntityManagerInterface $entityManager, private readonly TranslatorInterface $translator, private readonly ChillSecurity $security, private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry) {}
public function __construct(
private readonly EntityWorkflowManager $entityWorkflowManager,
private readonly EntityWorkflowRepository $entityWorkflowRepository,
private readonly ValidatorInterface $validator,
private readonly PaginatorFactory $paginatorFactory,
private readonly Registry $registry,
private readonly EntityManagerInterface $entityManager,
private readonly TranslatorInterface $translator,
private readonly ChillSecurity $security,
private readonly \Doctrine\Persistence\ManagerRegistry $managerRegistry,
private readonly ClockInterface $clock,
) {}
#[Route(path: '/{_locale}/main/workflow/create', name: 'chill_main_workflow_create')]
public function create(Request $request): Response
@ -310,7 +322,14 @@ class WorkflowController extends AbstractController
throw $this->createAccessDeniedException(sprintf("not allowed to apply transition {$transition}: %s", implode(', ', $msgs)));
}
$workflow->apply($entityWorkflow, $transition, ['context' => $stepDTO]);
$byUser = $this->security->getUser();
$workflow->apply($entityWorkflow, $transition, [
'context' => $stepDTO,
'byUser' => $byUser,
'transition' => $transition,
'transitionAt' => $this->clock->now(),
]);
$this->entityManager->flush();

View File

@ -413,8 +413,20 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
*
* @return $this
*/
public function setStep(string $step, WorkflowTransitionContextDTO $transitionContextDTO): self
{
public function setStep(
string $step,
WorkflowTransitionContextDTO $transitionContextDTO,
string $transition,
\DateTimeImmutable $transitionAt,
?User $byUser = null
): self {
$previousStep = $this->getCurrentStep();
$previousStep
->setTransitionAfter($transition)
->setTransitionAt($transitionAt)
->setTransitionBy($byUser);
$newStep = new EntityWorkflowStep();
$newStep->setCurrentStep($step);
@ -430,6 +442,14 @@ class EntityWorkflow implements TrackCreationInterface, TrackUpdateInterface
$newStep->addDestEmail($email);
}
if (null !== $transitionContextDTO->futureUserSignature) {
new EntityWorkflowStepSignature($newStep, $transitionContextDTO->futureUserSignature);
} else {
foreach ($transitionContextDTO->futurePersonSignatures as $personSignature) {
new EntityWorkflowStepSignature($newStep, $personSignature);
}
}
// copy the freeze
if ($this->isFreeze()) {
$newStep->setFreezeAfter(true);

View File

@ -12,13 +12,14 @@ declare(strict_types=1);
namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class WorkflowEntityDeletionVoter extends Voter
{
/**
* @param \Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface[] $handlers
* @param EntityWorkflowHandlerInterface[] $handlers
*/
public function __construct(private $handlers, private readonly EntityWorkflowRepository $entityWorkflowRepository) {}
@ -30,7 +31,7 @@ class WorkflowEntityDeletionVoter extends Voter
foreach ($this->handlers as $handler) {
if ($handler->isObjectSupported($subject)
&& \in_array($attribute, $handler->getDeletionRoles($subject), true)) {
&& \in_array($attribute, $handler->getDeletionRoles(), true)) {
return true;
}
}

View File

@ -11,8 +11,11 @@ declare(strict_types=1);
namespace Chill\MainBundle\Tests\Entity\Workflow;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Chill\PersonBundle\Entity\Person;
use PHPUnit\Framework\TestCase;
/**
@ -26,7 +29,7 @@ final class EntityWorkflowTest extends TestCase
{
$entityWorkflow = new EntityWorkflow();
$entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow), 'finalize', new \DateTimeImmutable());
$entityWorkflow->getCurrentStep()->setIsFinal(true);
$this->assertTrue($entityWorkflow->isFinal());
@ -38,16 +41,16 @@ final class EntityWorkflowTest extends TestCase
$this->assertFalse($entityWorkflow->isFinal());
$entityWorkflow->setStep('two', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('two', new WorkflowTransitionContextDTO($entityWorkflow), 'two', new \DateTimeImmutable());
$this->assertFalse($entityWorkflow->isFinal());
$entityWorkflow->setStep('previous_final', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('previous_final', new WorkflowTransitionContextDTO($entityWorkflow), 'three', new \DateTimeImmutable());
$this->assertFalse($entityWorkflow->isFinal());
$entityWorkflow->getCurrentStep()->setIsFinal(true);
$entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('final', new WorkflowTransitionContextDTO($entityWorkflow), 'four', new \DateTimeImmutable());
$this->assertTrue($entityWorkflow->isFinal());
}
@ -58,23 +61,81 @@ final class EntityWorkflowTest extends TestCase
$this->assertFalse($entityWorkflow->isFreeze());
$entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_one', new \DateTimeImmutable());
$this->assertFalse($entityWorkflow->isFreeze());
$entityWorkflow->setStep('step_three', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('step_three', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_three', new \DateTimeImmutable());
$this->assertFalse($entityWorkflow->isFreeze());
$entityWorkflow->setStep('freezed', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('freezed', new WorkflowTransitionContextDTO($entityWorkflow), 'to_freezed', new \DateTimeImmutable());
$entityWorkflow->getCurrentStep()->setFreezeAfter(true);
$this->assertTrue($entityWorkflow->isFreeze());
$entityWorkflow->setStep('after_freeze', new WorkflowTransitionContextDTO($entityWorkflow));
$entityWorkflow->setStep('after_freeze', new WorkflowTransitionContextDTO($entityWorkflow), 'to_after_freeze', new \DateTimeImmutable());
$this->assertTrue($entityWorkflow->isFreeze());
$this->assertTrue($entityWorkflow->getCurrentStep()->isFreezeAfter());
}
public function testPreviousStepMetadataAreFilled()
{
$entityWorkflow = new EntityWorkflow();
$initialStep = $entityWorkflow->getCurrentStep();
$entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_one', new \DateTimeImmutable('2024-01-01'), $user1 = new User());
$previous = $entityWorkflow->getCurrentStep();
$entityWorkflow->setStep('step_one', new WorkflowTransitionContextDTO($entityWorkflow), 'to_step_two', new \DateTimeImmutable('2024-01-02'), $user2 = new User());
$final = $entityWorkflow->getCurrentStep();
$stepsChained = $entityWorkflow->getStepsChained();
self::assertCount(3, $stepsChained);
self::assertSame($initialStep, $stepsChained[0]);
self::assertSame($previous, $stepsChained[1]);
self::assertSame($final, $stepsChained[2]);
self::assertEquals($user1, $initialStep->getTransitionBy());
self::assertEquals('2024-01-01', $initialStep->getTransitionAt()?->format('Y-m-d'));
self::assertEquals('to_step_one', $initialStep->getTransitionAfter());
self::assertEquals($user2, $previous->getTransitionBy());
self::assertEquals('2024-01-02', $previous->getTransitionAt()?->format('Y-m-d'));
self::assertEquals('to_step_two', $previous->getTransitionAfter());
}
public function testSetStepSignatureForUserIsCreated()
{
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futureUserSignature = $user = new User();
$entityWorkflow->setStep('new', $dto, 'to_new', new \DateTimeImmutable());
$actual = $entityWorkflow->getCurrentStep();
self::assertCount(1, $actual->getSignatures());
self::assertSame($user, $actual->getSignatures()->first()->getSigner());
}
public function testSetStepSignatureForPersonIsCreated()
{
$entityWorkflow = new EntityWorkflow();
$dto = new WorkflowTransitionContextDTO($entityWorkflow);
$dto->futurePersonSignatures[] = $person1 = new Person();
$dto->futurePersonSignatures[] = $person2 = new Person();
$entityWorkflow->setStep('new', $dto, 'to_new', new \DateTimeImmutable());
$actual = $entityWorkflow->getCurrentStep();
$persons = $actual->getSignatures()->map(fn (EntityWorkflowStepSignature $signature) => $signature->getSigner());
self::assertCount(2, $actual->getSignatures());
self::assertContains($person1, $persons);
self::assertContains($person2, $persons);
}
}

View File

@ -39,19 +39,29 @@ class EntityWorkflowMarkingStoreTest extends TestCase
{
$markingStore = $this->buildMarkingStore();
$workflow = new EntityWorkflow();
$previousStep = $workflow->getCurrentStep();
$dto = new WorkflowTransitionContextDTO($workflow);
$dto->futureCcUsers[] = $user1 = new User();
$dto->futureDestUsers[] = $user2 = new User();
$dto->futureDestEmails[] = $email = 'test@example.com';
$markingStore->setMarking($workflow, new Marking(['foo' => 1]), ['context' => $dto]);
$markingStore->setMarking($workflow, new Marking(['foo' => 1]), [
'context' => $dto,
'transition' => 'bar_transition',
'byUser' => $user3 = new User(),
'transitionAt' => $at = new \DateTimeImmutable(),
]);
$currentStep = $workflow->getCurrentStep();
self::assertEquals('foo', $currentStep->getCurrentStep());
self::assertContains($email, $currentStep->getDestEmail());
self::assertContains($user1, $currentStep->getCcUser());
self::assertContains($user2, $currentStep->getDestUser());
self::assertSame($user3, $previousStep->getTransitionBy());
self::assertSame($at, $previousStep->getTransitionAt());
self::assertEquals('bar_transition', $previousStep->getTransitionAfter());
}
private function buildMarkingStore(): EntityWorkflowMarkingStore

View File

@ -14,6 +14,9 @@ namespace Chill\MainBundle\Workflow;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
/**
* @template T of object
*/
interface EntityWorkflowHandlerInterface
{
/**
@ -25,6 +28,9 @@ interface EntityWorkflowHandlerInterface
public function getEntityTitle(EntityWorkflow $entityWorkflow, array $options = []): string;
/**
* @return T|null
*/
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?object;
public function getRelatedObjects(object $object): array;

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\MainBundle\Workflow;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\Exception\HandlerNotFoundException;
use Symfony\Component\Workflow\Registry;
@ -38,6 +39,17 @@ class EntityWorkflowManager
return $this->registry->all($entityWorkflow);
}
public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject
{
foreach ($this->handlers as $handler) {
if ($handler instanceof EntityWorkflowWithStoredObjectHandlerInterface && $handler->supports($entityWorkflow)) {
return $handler->getAssociatedStoredObject($entityWorkflow);
}
}
return null;
}
/**
* @return list<EntityWorkflow>
*/

View File

@ -40,10 +40,14 @@ final readonly class EntityWorkflowMarkingStore implements MarkingStoreInterface
$next = array_keys($places)[0];
$transitionDTO = $context['context'] ?? null;
$transition = $context['transition'];
$byUser = $context['byUser'] ?? null;
$at = $context['transitionAt'];
if (!$transitionDTO instanceof WorkflowTransitionContextDTO) {
throw new \UnexpectedValueException(sprintf('Expected instance of %s', WorkflowTransitionContextDTO::class));
}
$subject->setStep($next, $transitionDTO);
$subject->setStep($next, $transitionDTO, $transition, $at, $byUser);
}
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Workflow;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
/**
* Add methods to handle workflows associated with @see{StoredObject}.
*
* @template T of object
*
* @template-extends EntityWorkflowHandlerInterface<T>
*/
interface EntityWorkflowWithStoredObjectHandlerInterface extends EntityWorkflowHandlerInterface
{
public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject;
}

View File

@ -108,12 +108,6 @@ final readonly class EntityWorkflowTransitionEventSubscriber implements EventSub
/** @var EntityWorkflow $entityWorkflow */
$entityWorkflow = $event->getSubject();
$step = $entityWorkflow->getCurrentStep();
$step
->setTransitionAfter($event->getTransition()->getName())
->setTransitionAt(new \DateTimeImmutable('now'))
->setTransitionBy($this->security->getUser());
$this->chillLogger->info('[workflow] apply transition on entityWorkflow', [
'relatedEntityClass' => $entityWorkflow->getRelatedEntityClass(),

View File

@ -13,6 +13,7 @@ namespace Chill\MainBundle\Workflow;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Workflow\Transition;
@ -51,6 +52,18 @@ class WorkflowTransitionContextDTO
*/
public array $futureDestEmails = [];
/**
* A list of future @see{Person} with will sign the next step.
*
* @var list<Person>
*/
public array $futurePersonSignatures = [];
/**
* An eventual user which is requested to apply a signature.
*/
public ?User $futureUserSignature = null;
public ?Transition $transition = null;
public string $comment = '';

View File

@ -11,16 +11,20 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Workflow;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\MainBundle\Workflow\EntityWorkflowWithStoredObjectHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocumentRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationDocumentVoter;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityWorkflowHandlerInterface
/**
* @implements EntityWorkflowWithStoredObjectHandlerInterface<AccompanyingPeriodWorkEvaluationDocument>
*/
class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityWorkflowWithStoredObjectHandlerInterface
{
public function __construct(
private readonly AccompanyingPeriodWorkEvaluationDocumentRepository $repository,
@ -73,8 +77,6 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
}
/**
* @param AccompanyingPeriodWorkEvaluationDocument $object
*
* @return array[]
*/
public function getRelatedObjects(object $object): array
@ -130,6 +132,11 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
return AccompanyingPeriodWorkEvaluationDocument::class === $entityWorkflow->getRelatedEntityClass();
}
public function getAssociatedStoredObject(EntityWorkflow $entityWorkflow): ?StoredObject
{
return $this->getRelatedEntity($entityWorkflow)?->getStoredObject();
}
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return false;

View File

@ -21,6 +21,9 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvalu
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @implements EntityWorkflowHandlerInterface<AccompanyingPeriodWorkEvaluation>
*/
readonly class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowHandlerInterface
{
public function __construct(
@ -59,9 +62,6 @@ readonly class AccompanyingPeriodWorkEvaluationWorkflowHandler implements Entity
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingPeriodWorkEvaluation $object
*/
public function getRelatedObjects(object $object): array
{
$relateds = [];

View File

@ -22,13 +22,16 @@ use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepos
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInterface
/**
* @implements EntityWorkflowHandlerInterface<AccompanyingPeriodWork>
*/
readonly class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInterface
{
public function __construct(
private readonly AccompanyingPeriodWorkRepository $repository,
private readonly EntityWorkflowRepository $workflowRepository,
private readonly TranslatableStringHelperInterface $translatableStringHelper,
private readonly TranslatorInterface $translator
private AccompanyingPeriodWorkRepository $repository,
private EntityWorkflowRepository $workflowRepository,
private TranslatableStringHelperInterface $translatableStringHelper,
private TranslatorInterface $translator
) {}
public function getDeletionRoles(): array
@ -61,9 +64,6 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingPeriodWork $object
*/
public function getRelatedObjects(object $object): array
{
$relateds = [];