Skip to content

Commit

Permalink
[RE] Adherent formations (#7902)
Browse files Browse the repository at this point in the history
* [RE] Adherent formations

* Add downloadsCount

* Add formation file download

* Fix admin form

* Add visibility & fix file upload

* Fix lint

* Enhance admin view

* Add tests

* update formations ui design (#7917)

* Fix fixtures

* Show full description

* Enhance download action

* Fix required file validation

* Create new ROLE_ADHERENT_RENAISSANCE

* Make new role as voter

* Voter attributes can not beging with ROLE_

Co-authored-by: Arthur Monney <[email protected]>
  • Loading branch information
Remg and mckenziearts authored Dec 7, 2022
1 parent c8334f0 commit acd25bd
Show file tree
Hide file tree
Showing 17 changed files with 591 additions and 5 deletions.
1 change: 1 addition & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ security:
- ROLE_APP_ADMIN_RENAISSANCE_HOME_BLOCK_ALL
- ROLE_APP_ADMIN_RENAISSANCE_BIOGRAPHY_EXECUTIVE_OFFICE_MEMBER_ALL
- ROLE_APP_ADMIN_COMMITMENT_ALL
- ROLE_APP_ADMIN_ADHERENT_FORMATION_ALL

ROLE_ADMIN_DASHBOARD:
- ROLE_APP_ADMIN_GEO_ZONE_ALL
Expand Down
8 changes: 8 additions & 0 deletions config/services/admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@
<argument />
</service>

<service id="app.admin.adherent_formation" class="App\Admin\FormationAdmin">
<tag name="sonata.admin" manager-type="orm" label="Formations" group="Re site web"/>

<argument />
<argument>App\Entity\AdherentFormation\Formation</argument>
<argument />
</service>

<!--
######################################################
# Communication
Expand Down
45 changes: 45 additions & 0 deletions migrations/Version20221207092223.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20221207092223 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('CREATE TABLE adherent_formation (
id BIGINT AUTO_INCREMENT NOT NULL,
file_id INT UNSIGNED DEFAULT NULL,
title VARCHAR(255) NOT NULL,
description LONGTEXT DEFAULT NULL,
visible TINYINT(1) DEFAULT \'0\' NOT NULL,
downloads_count SMALLINT UNSIGNED NOT NULL,
position SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
UNIQUE INDEX UNIQ_2D97408B2B36786B (title),
UNIQUE INDEX UNIQ_2D97408B93CB796C (file_id),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE adherent_formation_file (
id INT UNSIGNED AUTO_INCREMENT NOT NULL,
title VARCHAR(255) NOT NULL,
slug VARCHAR(255) NOT NULL,
path VARCHAR(255) NOT NULL,
extension VARCHAR(255) NOT NULL,
UNIQUE INDEX adherent_formation_file_slug_extension (slug, extension),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE
adherent_formation
ADD
CONSTRAINT FK_2D97408B93CB796C FOREIGN KEY (file_id) REFERENCES adherent_formation_file (id)');
}

public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE adherent_formation DROP FOREIGN KEY FK_2D97408B93CB796C');
$this->addSql('DROP TABLE adherent_formation');
$this->addSql('DROP TABLE adherent_formation_file');
}
}
92 changes: 92 additions & 0 deletions src/Admin/FormationAdmin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace App\Admin;

use App\Entity\AdherentFormation\File;
use App\Form\Admin\BaseFileType;
use App\Form\PositionType;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class FormationAdmin extends AbstractAdmin
{
protected function configureFormOptions(array &$formOptions): void
{
if ($this->isCurrentRoute('create')) {
$formOptions['validation_groups'] = ['Default', 'adherent_formation_create'];
}
}

protected function configureFormFields(FormMapper $formMapper): void
{
$formMapper
->with('Méta-données', ['class' => 'col-md-6'])
->add('title', TextType::class, [
'label' => 'Titre',
])
->add('description', TextareaType::class, [
'label' => 'Description',
'required' => false,
])
->end()
->with('Visibilité', ['class' => 'col-md-6'])
->add('visible', CheckboxType::class, [
'label' => 'Visible',
'required' => false,
])
->add('position', PositionType::class, [
'label' => 'Position sur la page',
])
->end()
->with('Fichier attaché', ['class' => 'col-md-12'])
->add('file', BaseFileType::class, [
'label' => false,
'required' => $this->isCurrentRoute('create'),
'data_class' => File::class,
'can_update_file' => true,
'attr' => ['accept' => 'application/pdf'],
])
->end()
;
}

protected function configureDatagridFilters(DatagridMapper $datagridMapper): void
{
$datagridMapper
->add('title', null, [
'label' => 'Titre',
'show_filter' => true,
])
;
}

protected function configureListFields(ListMapper $listMapper): void
{
$listMapper
->addIdentifier('title', null, [
'label' => 'Titre',
])
->add('downloadsCount', null, [
'label' => 'Téléchargements',
])
->add('position', null, [
'label' => 'Position',
])
->add('visible', null, [
'label' => 'Visible',
])
->add(ListMapper::NAME_ACTIONS, null, [
'virtual_field' => true,
'actions' => [
'edit' => [],
'delete' => [],
],
])
;
}
}
35 changes: 35 additions & 0 deletions src/Controller/Renaissance/Formation/DownloadController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace App\Controller\Renaissance\Formation;

use App\Entity\Adherent;
use App\Entity\AdherentFormation\Formation;
use App\Storage\FileRequestHandler;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
* @Route("/espace-adherent/formations/{id}/telecharger", name="app_renaissance_adherent_formation_download", methods={"GET"})
* @Entity("formation", expr="repository.findOneVisible(id)")
* @IsGranted("RENAISSANCE_ADHERENT")
*/
class DownloadController extends AbstractController
{
public function __construct(
private readonly FileRequestHandler $fileRequestHandler,
private readonly EntityManagerInterface $entityManager
) {
}

public function __invoke(Formation $formation): Response
{
$formation->incrementDownloadsCount();
$this->entityManager->flush();

return $this->fileRequestHandler->createResponse($formation->getFile());
}
}
28 changes: 28 additions & 0 deletions src/Controller/Renaissance/Formation/ListController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Controller\Renaissance\Formation;

use App\Entity\Adherent;
use App\Repository\AdherentFormation\FormationRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
* @Route("/espace-adherent/formations", name="app_renaissance_adherent_formation_list", methods={"GET"})
* @IsGranted("RENAISSANCE_ADHERENT")
*/
class ListController extends AbstractController
{
public function __construct(private readonly FormationRepository $formationRepository)
{
}

public function __invoke(): Response
{
return $this->render('renaissance/formation/list.html.twig', [
'formations' => $this->formationRepository->findAllVisible(),
]);
}
}
56 changes: 56 additions & 0 deletions src/DataFixtures/ORM/LoadAdherentFormationData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\DataFixtures\ORM;

use App\Entity\AdherentFormation\File;
use App\Entity\AdherentFormation\Formation;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use Faker\Factory;
use Faker\Generator;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class LoadAdherentFormationData extends Fixture
{
private Generator $faker;

public function __construct()
{
$this->faker = Factory::create('fr_FR');
}

public function load(ObjectManager $manager)
{
$manager->persist($this->createFormation('Première formation'));
$manager->persist($this->createFormation('Formation sans description', false));
$manager->persist($this->createFormation('Formation non visible', true, false));

$manager->flush();
}

private function createFormation(string $title, bool $description = true, bool $visible = true): Formation
{
$formation = new Formation();
$formation->setTitle($title);
$formation->setDescription($description ? $this->faker->text('200') : null);
$formation->setVisible($visible);
$formation->setFile($this->createFile($title));

return $formation;
}

private function createFile(string $title): File
{
$file = new File();
$file->setTitle($title);
$file->setFile(new UploadedFile(
__DIR__.'/../adherent_formations/formation.pdf',
"$title.pdf",
'application/pdf',
null,
true
));

return $file;
}
}
Binary file not shown.
36 changes: 36 additions & 0 deletions src/Entity/AdherentFormation/File.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace App\Entity\AdherentFormation;

use App\Entity\BaseFile;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

/**
* @ORM\Entity
* @ORM\Table(
* name="adherent_formation_file",
* uniqueConstraints={@ORM\UniqueConstraint(name="adherent_formation_file_slug_extension", columns={"slug", "extension"})}
* )
*/
class File extends BaseFile
{
public const PREFIX_PATH = 'files/adherent_formations';

/**
* @var UploadedFile|null
*
* @Assert\NotBlank(groups={"adherent_formation_create"})
* @Assert\File(
* maxSize="5M",
* mimeTypes={"application/pdf", "application/x-pdf"}
* )
*/
protected $file;

public function getPrefixPath(): string
{
return self::PREFIX_PATH;
}
}
Loading

0 comments on commit acd25bd

Please sign in to comment.