mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 11:18:25 +00:00 
			
		
		
		
	Add export generation creation from saved export endpoint
Introduce a new controller for creating export generations from saved exports using a POST endpoint. Updates include a new route, serialization groups, and a corresponding test to validate functionality.
This commit is contained in:
		@@ -0,0 +1,62 @@
 | 
			
		||||
<?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\Controller;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Entity\ExportGeneration;
 | 
			
		||||
use Chill\MainBundle\Entity\SavedExport;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Chill\MainBundle\Export\Messenger\ExportRequestGenerationMessage;
 | 
			
		||||
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Symfony\Component\Clock\ClockInterface;
 | 
			
		||||
use Symfony\Component\HttpFoundation\JsonResponse;
 | 
			
		||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 | 
			
		||||
use Symfony\Component\Messenger\MessageBusInterface;
 | 
			
		||||
use Symfony\Component\Routing\Annotation\Route;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
use Symfony\Component\Serializer\SerializerInterface;
 | 
			
		||||
 | 
			
		||||
class ExportGenerationCreateFromSavedExportController
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        private Security $security,
 | 
			
		||||
        private EntityManagerInterface $entityManager,
 | 
			
		||||
        private MessageBusInterface $messageBus,
 | 
			
		||||
        private ClockInterface $clock,
 | 
			
		||||
        private SerializerInterface $serializer,
 | 
			
		||||
    ) {}
 | 
			
		||||
 | 
			
		||||
    #[Route('/api/1.0/main/export/export-generation/create-from-saved-export/{id}', methods: ['POST'])]
 | 
			
		||||
    public function __invoke(SavedExport $export): JsonResponse
 | 
			
		||||
    {
 | 
			
		||||
        if (!$this->security->isGranted(SavedExportVoter::GENERATE, $export)) {
 | 
			
		||||
            throw new AccessDeniedHttpException('Not allowed to generate an export from this saved export');
 | 
			
		||||
        }
 | 
			
		||||
        $user = $this->security->getUser();
 | 
			
		||||
 | 
			
		||||
        if (!$user instanceof User) {
 | 
			
		||||
            throw new AccessDeniedHttpException('Only users can create exports');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $exportGeneration = ExportGeneration::fromSavedExport($export, $this->clock->now()->add(new \DateInterval('P6M')));
 | 
			
		||||
 | 
			
		||||
        $this->entityManager->persist($exportGeneration);
 | 
			
		||||
        $this->entityManager->flush();
 | 
			
		||||
 | 
			
		||||
        $this->messageBus->dispatch(new ExportRequestGenerationMessage($exportGeneration, $user));
 | 
			
		||||
 | 
			
		||||
        return new JsonResponse(
 | 
			
		||||
            $this->serializer->serialize($exportGeneration, 'json', ['groups' => ['read']]),
 | 
			
		||||
            json: true,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -17,6 +17,7 @@ use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
use Ramsey\Uuid\Uuid;
 | 
			
		||||
use Ramsey\Uuid\UuidInterface;
 | 
			
		||||
use Symfony\Component\Serializer\Annotation as Serializer;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Contains the single execution of an export.
 | 
			
		||||
@@ -29,21 +30,25 @@ use Ramsey\Uuid\UuidInterface;
 | 
			
		||||
 */
 | 
			
		||||
#[ORM\Entity()]
 | 
			
		||||
#[ORM\Table('chill_main_export_generation')]
 | 
			
		||||
#[Serializer\DiscriminatorMap('type', ['export_generation' => ExportGeneration::class])]
 | 
			
		||||
class ExportGeneration implements TrackCreationInterface
 | 
			
		||||
{
 | 
			
		||||
    use TrackCreationTrait;
 | 
			
		||||
 | 
			
		||||
    #[ORM\Id]
 | 
			
		||||
    #[ORM\Column(type: 'uuid', unique: true)]
 | 
			
		||||
    #[Serializer\Groups(['read'])]
 | 
			
		||||
    private UuidInterface $id;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #[ORM\ManyToOne(targetEntity: StoredObject::class, cascade: ['persist', 'refresh'])]
 | 
			
		||||
    #[ORM\JoinColumn(nullable: false)]
 | 
			
		||||
    #[Serializer\Groups(['read'])]
 | 
			
		||||
    private StoredObject $storedObject;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, nullable: false, options: ['default' => ''])]
 | 
			
		||||
        #[Serializer\Groups(['read'])]
 | 
			
		||||
        private string $exportAlias,
 | 
			
		||||
        #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON, nullable: false, options: ['default' => '[]'])]
 | 
			
		||||
        private array $options = [],
 | 
			
		||||
@@ -103,6 +108,9 @@ class ExportGeneration implements TrackCreationInterface
 | 
			
		||||
 | 
			
		||||
    public static function fromSavedExport(SavedExport $savedExport, ?\DateTimeImmutable $deletedAt = null): self
 | 
			
		||||
    {
 | 
			
		||||
        return new self($savedExport->getExportAlias(), $savedExport->getOptions(), $deletedAt, $savedExport);
 | 
			
		||||
        $generation = new self($savedExport->getExportAlias(), $savedExport->getOptions(), $deletedAt, $savedExport);
 | 
			
		||||
        $generation->getStoredObject()->setTitle($savedExport->getTitle());
 | 
			
		||||
 | 
			
		||||
        return $generation;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,81 @@
 | 
			
		||||
<?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\Tests\Authorization;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Controller\ExportGenerationCreateFromSavedExportController;
 | 
			
		||||
use Chill\MainBundle\Entity\ExportGeneration;
 | 
			
		||||
use Chill\MainBundle\Entity\SavedExport;
 | 
			
		||||
use Chill\MainBundle\Entity\User;
 | 
			
		||||
use Chill\MainBundle\Export\Messenger\ExportRequestGenerationMessage;
 | 
			
		||||
use Chill\MainBundle\Security\Authorization\SavedExportVoter;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
use Prophecy\Argument;
 | 
			
		||||
use Prophecy\PhpUnit\ProphecyTrait;
 | 
			
		||||
use Symfony\Component\Clock\MockClock;
 | 
			
		||||
use Symfony\Component\HttpFoundation\JsonResponse;
 | 
			
		||||
use Symfony\Component\Messenger\Envelope;
 | 
			
		||||
use Symfony\Component\Messenger\MessageBusInterface;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
use Symfony\Component\Serializer\SerializerInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * @coversNothing
 | 
			
		||||
 */
 | 
			
		||||
class ExportGenerationCreateFromSavedExportControllerTest extends TestCase
 | 
			
		||||
{
 | 
			
		||||
    use ProphecyTrait;
 | 
			
		||||
 | 
			
		||||
    public function testInvoke(): void
 | 
			
		||||
    {
 | 
			
		||||
        $savedExport = new SavedExport();
 | 
			
		||||
        $savedExport->setOptions($exportOptions = ['test' => 'content'])->setExportAlias('dummy_export_alias');
 | 
			
		||||
 | 
			
		||||
        $user = new User();
 | 
			
		||||
        $reflection = new \ReflectionClass($user);
 | 
			
		||||
        $id = $reflection->getProperty('id');
 | 
			
		||||
        $id->setValue($user, 1);
 | 
			
		||||
 | 
			
		||||
        $security = $this->prophesize(Security::class);
 | 
			
		||||
        $security->isGranted(SavedExportVoter::GENERATE, $savedExport)->shouldBeCalled()->willReturn(true);
 | 
			
		||||
        $security->getUser()->willReturn($user);
 | 
			
		||||
 | 
			
		||||
        $entityManager = $this->prophesize(EntityManagerInterface::class);
 | 
			
		||||
        $entityManager->persist(Argument::that(
 | 
			
		||||
            static fn ($arg) => $arg instanceof ExportGeneration && $arg->getOptions() === $exportOptions && $arg->getSavedExport() === $savedExport,
 | 
			
		||||
        ))->shouldBeCalled();
 | 
			
		||||
        $entityManager->flush()->shouldBeCalled();
 | 
			
		||||
 | 
			
		||||
        $messenger = $this->prophesize(MessageBusInterface::class);
 | 
			
		||||
        $messenger->dispatch(Argument::type(ExportRequestGenerationMessage::class))->shouldBeCalled()->will(
 | 
			
		||||
            static fn (array $args): Envelope => new Envelope($args[0]),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $serializer = $this->prophesize(SerializerInterface::class);
 | 
			
		||||
        $serializer->serialize(Argument::type(ExportGeneration::class), 'json', ['groups' => ['read']])->shouldBeCalled()->willReturn('{"test": "export-generation"}');
 | 
			
		||||
 | 
			
		||||
        $controller = new ExportGenerationCreateFromSavedExportController(
 | 
			
		||||
            $security->reveal(),
 | 
			
		||||
            $entityManager->reveal(),
 | 
			
		||||
            $messenger->reveal(),
 | 
			
		||||
            new MockClock(),
 | 
			
		||||
            $serializer->reveal()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $response = $controller($savedExport);
 | 
			
		||||
 | 
			
		||||
        self::assertInstanceOf(JsonResponse::class, $response);
 | 
			
		||||
        self::assertEquals('{"test": "export-generation"}', $response->getContent());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1123,3 +1123,25 @@ paths:
 | 
			
		||||
                        application/json:
 | 
			
		||||
                            schema:
 | 
			
		||||
                                type: object
 | 
			
		||||
    /1.0/main/export/export-generation/create-from-saved-export/{id}:
 | 
			
		||||
        post:
 | 
			
		||||
            tags:
 | 
			
		||||
                - export
 | 
			
		||||
            summary: Create an export generation from an existing saved export
 | 
			
		||||
            parameters:
 | 
			
		||||
                -   name: id
 | 
			
		||||
                    in: path
 | 
			
		||||
                    required: true
 | 
			
		||||
                    description: The entity saved export's id
 | 
			
		||||
                    schema:
 | 
			
		||||
                        type: string
 | 
			
		||||
                        format: uuid
 | 
			
		||||
            responses:
 | 
			
		||||
                403:
 | 
			
		||||
                    description: Access denied
 | 
			
		||||
                200:
 | 
			
		||||
                    description: "ok"
 | 
			
		||||
                    content:
 | 
			
		||||
                        application/json:
 | 
			
		||||
                            schema:
 | 
			
		||||
                                type: object
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user