diff --git a/composer.json b/composer.json index 9811cd2..d81d89a 100755 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "symfony/translation": "8.0.*", "symfony/twig-bundle": "8.0.*", "symfony/validator": "8.0.*", - "symfony/yaml": "8.0.*" + "symfony/yaml": "8.0.*", + "vich/uploader-bundle": "^2.9" }, "require-dev": { "symfony/maker-bundle": "^1.65", diff --git a/composer.lock b/composer.lock index 3d8d930..95c1257 100755 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a65a9ed16594341ca6c22d4c6316bce1", + "content-hash": "754cd146956f25fd7cf8b7b7a01e4aa3", "packages": [ { "name": "doctrine/collections", @@ -1120,6 +1120,70 @@ }, "time": "2025-10-26T09:35:14+00:00" }, + { + "name": "jms/metadata", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "554319d2e5f0c5d8ccaeffe755eac924e14da330" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/554319d2e5f0c5d8ccaeffe755eac924e14da330", + "reference": "554319d2e5f0c5d8ccaeffe755eac924e14da330", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "require-dev": { + "doctrine/cache": "^1.0|^2.0", + "doctrine/coding-standard": "^8.0", + "mikey179/vfsstream": "^1.6.7", + "phpunit/phpunit": "^8.5.42|^9.6.23", + "psr/container": "^1.0|^2.0", + "symfony/cache": "^3.1|^4.0|^5.0|^6.0|^7.0|^8.0", + "symfony/dependency-injection": "^3.1|^4.0|^5.0|^6.0|^7.0|^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Metadata\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Class/method/property metadata management in PHP", + "keywords": [ + "annotations", + "metadata", + "xml", + "yaml" + ], + "support": { + "issues": "https://github.com/schmittjoh/metadata/issues", + "source": "https://github.com/schmittjoh/metadata/tree/2.9.0" + }, + "time": "2025-11-30T20:12:26+00:00" + }, { "name": "psr/cache", "version": "3.0.0", @@ -3057,6 +3121,92 @@ ], "time": "2025-12-08T07:59:34+00:00" }, + { + "name": "symfony/mime", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40", + "reference": "7576ce3b2b4d3a2a7fe7020a07a392065d6ffd40", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v8.0.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-11-16T10:17:21+00:00" + }, { "name": "symfony/options-resolver", "version": "v8.0.0", @@ -3371,6 +3521,93 @@ ], "time": "2025-06-20T22:24:30+00:00" }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.33.0", @@ -5395,6 +5632,114 @@ } ], "time": "2025-12-14T11:28:47+00:00" + }, + { + "name": "vich/uploader-bundle", + "version": "v2.9.1", + "source": { + "type": "git", + "url": "https://github.com/dustin10/VichUploaderBundle.git", + "reference": "945939a04a33c0b78c5fbb7ead31533d85112df5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/945939a04a33c0b78c5fbb7ead31533d85112df5", + "reference": "945939a04a33c0b78c5fbb7ead31533d85112df5", + "shasum": "" + }, + "require": { + "doctrine/persistence": "^3.0 || ^4.0", + "ext-simplexml": "*", + "jms/metadata": "^2.4", + "php": "^8.1", + "symfony/config": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/event-dispatcher-contracts": "^3.1", + "symfony/http-foundation": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/mime": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/property-access": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/string": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "league/flysystem": "<2.0" + }, + "require-dev": { + "dg/bypass-finals": "^1.9", + "doctrine/common": "^3.0", + "doctrine/doctrine-bundle": "^2.7 || ^3.0", + "doctrine/mongodb-odm": "^2.4", + "doctrine/orm": "^2.13 || ^3.0", + "ext-sqlite3": "*", + "knplabs/knp-gaufrette-bundle": "dev-master", + "league/flysystem-bundle": "^2.4 || ^3.0", + "league/flysystem-memory": "^2.0 || ^3.0", + "matthiasnoback/symfony-dependency-injection-test": "^5.1 || ^6.0", + "mikey179/vfsstream": "^1.6.11", + "phpunit/phpunit": "^10.5 || ^11.5 || ^12.2", + "symfony/asset": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/browser-kit": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/doctrine-bridge": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/form": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/phpunit-bridge": "^7.3", + "symfony/security-csrf": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/translation": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/twig-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/validator": "^5.4.22 || ^6.0 || ^7.0 || ^8.0", + "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "suggest": { + "doctrine/doctrine-bundle": "For integration with Doctrine", + "doctrine/mongodb-odm-bundle": "For integration with Doctrine ODM", + "doctrine/orm": "For integration with Doctrine ORM", + "doctrine/phpcr-odm": "For integration with Doctrine PHPCR", + "knplabs/knp-gaufrette-bundle": "For integration with Gaufrette", + "league/flysystem-bundle": "For integration with Flysystem", + "liip/imagine-bundle": "To generate image thumbnails", + "oneup/flysystem-bundle": "For integration with Flysystem", + "symfony/asset": "To generate better links", + "symfony/form": "To handle uploads in forms", + "symfony/yaml": "To use YAML mapping" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Vich\\UploaderBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dustin Dobervich", + "email": "ddobervich@gmail.com" + } + ], + "description": "Ease file uploads attached to entities", + "homepage": "https://github.com/dustin10/VichUploaderBundle", + "keywords": [ + "file uploads", + "upload" + ], + "support": { + "issues": "https://github.com/dustin10/VichUploaderBundle/issues", + "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.9.1" + }, + "time": "2025-12-10T08:23:38+00:00" } ], "packages-dev": [ diff --git a/config/bundles.php b/config/bundles.php index ceed9f1..a64513a 100755 --- a/config/bundles.php +++ b/config/bundles.php @@ -8,4 +8,5 @@ return [ Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Vich\UploaderBundle\VichUploaderBundle::class => ['all' => true], ]; diff --git a/config/packages/csrf.yaml b/config/packages/csrf.yaml old mode 100644 new mode 100755 diff --git a/config/packages/vich_uploader.yaml b/config/packages/vich_uploader.yaml new file mode 100755 index 0000000..e5c3a6c --- /dev/null +++ b/config/packages/vich_uploader.yaml @@ -0,0 +1,15 @@ +vich_uploader: + db_driver: orm + + mappings: + attachments: + uri_prefix: /uploads/questions + upload_destination: '%kernel.project_dir%/public/uploads/questions' + namer: Vich\UploaderBundle\Naming\UniqidNamer + directory_namer: ~ + + inject_on_load: false + delete_on_update: true + delete_on_remove: true + # Optionnel : pour générer des URLs absolues + # uri_prefix_absolute: true \ No newline at end of file diff --git a/config/reference.php b/config/reference.php index 6508d97..c4c008c 100755 --- a/config/reference.php +++ b/config/reference.php @@ -1242,6 +1242,44 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * intercept_redirects?: bool, // Default: false * excluded_ajax_paths?: scalar|null, // Default: "^/((index|app(_[\\w]+)?)\\.php/)?_wdt" * } + * @psalm-type VichUploaderConfig = array{ + * default_filename_attribute_suffix?: scalar|null, // Default: "_name" + * db_driver: scalar|null, + * storage?: scalar|null, // Default: "file_system" + * use_flysystem_to_resolve_uri?: bool, // Default: false + * twig?: scalar|null, // twig requires templating // Default: true + * form?: scalar|null, // Default: true + * metadata?: array{ + * cache?: scalar|null, // Default: "file" + * type?: scalar|null, // Default: "attribute" + * file_cache?: array{ + * dir?: scalar|null, // Default: "%kernel.cache_dir%/vich_uploader" + * }, + * auto_detection?: bool, // Default: true + * directories?: list, + * }, + * mappings?: array, + * } * @psalm-type ConfigType = array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -1251,6 +1289,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * doctrine?: DoctrineConfig, * doctrine_migrations?: DoctrineMigrationsConfig, * security?: SecurityConfig, + * vich_uploader?: VichUploaderConfig, * "when@dev"?: array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -1262,6 +1301,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * doctrine_migrations?: DoctrineMigrationsConfig, * security?: SecurityConfig, * web_profiler?: WebProfilerConfig, + * vich_uploader?: VichUploaderConfig, * }, * "when@prod"?: array{ * imports?: ImportsConfig, @@ -1272,6 +1312,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * doctrine?: DoctrineConfig, * doctrine_migrations?: DoctrineMigrationsConfig, * security?: SecurityConfig, + * vich_uploader?: VichUploaderConfig, * }, * "when@test"?: array{ * imports?: ImportsConfig, @@ -1283,6 +1324,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; * doctrine_migrations?: DoctrineMigrationsConfig, * security?: SecurityConfig, * web_profiler?: WebProfilerConfig, + * vich_uploader?: VichUploaderConfig, * }, * ...getData(); $investigation->setCreateBy($this->getUser()); + ; + foreach($investigation->getQuestions() as $question){ + foreach ($question->getAttachments() as $attachment) { + if ($attachment->getFile()) { + // Optionnel : calculer les dimensions pour les images + $attachment->setDimensionsFromFile($attachment->getFile()); + } + } + } + $this->em->persist($investigation); $this->em->flush(); @@ -80,6 +90,31 @@ final class InvestigationController extends AbstractController ]); } + private function handleAttachments($form, Question $question): void + { + // Récupérer le champ attachments du formulaire + $attachmentsForm = $form->get('attachments'); + + // Parcourir tous les attachments du formulaire + foreach ($attachmentsForm as $attachmentForm) { + /** @var Attachment $attachment */ + $attachment = $attachmentForm->getData(); + + // Récupérer le fichier uploadé + $file = $attachmentForm->get('file')->getData(); + + if ($file) { + // Définir le fichier sur l'entité Attachment + $attachment->setFile($file); + + // Associer l'attachment à la question + if (!$attachment->getQuestion()) { + $attachment->setQuestion($question); + } + } + } + } + #[Route('/show/{id}', name: 'app_investigation_show')] public function show(Investigation $investigation): Response { diff --git a/src/Entity/Attachment.php b/src/Entity/Attachment.php new file mode 100644 index 0000000..fed5d07 --- /dev/null +++ b/src/Entity/Attachment.php @@ -0,0 +1,174 @@ +id; + } + + public function setFile(?File $file = null): void + { + $this->file = $file; + + if (null !== $file) { + $this->updatedAt = new \DateTimeImmutable(); + } + } + + public function getFile(): ?File + { + return $this->file; + } + + public function setFileName(?string $fileName): void + { + $this->fileName = $fileName; + } + + public function getFileName(): ?string + { + return $this->fileName; + } + + public function setFileSize(?int $fileSize): void + { + $this->fileSize = $fileSize; + } + + public function getFileSize(): ?int + { + return $this->fileSize; + } + + public function setMimeType(?string $mimeType): void + { + $this->mimeType = $mimeType; + } + + public function getMimeType(): ?string + { + return $this->mimeType; + } + + public function setOriginalName(?string $originalName): void + { + $this->originalName = $originalName; + } + + public function getOriginalName(): ?string + { + return $this->originalName; + } + + public function setDimensions(?array $dimensions): void + { + $this->dimensions = $dimensions; + } + + public function getDimensions(): ?array + { + return $this->dimensions; + } + + public function getQuestion(): ?Question + { + return $this->question; + } + + public function setQuestion(?Question $question): void + { + $this->question = $question; + } + + public function getUpdatedAt(): ?\DateTimeImmutable + { + return $this->updatedAt; + } + + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): void + { + $this->updatedAt = $updatedAt; + } + + // Méthode utilitaire pour afficher la taille en format lisible + public function getReadableFileSize(): string + { + $bytes = $this->fileSize; + $units = ['B', 'KB', 'MB', 'GB']; + + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + + $bytes /= (1 << (10 * $pow)); + + return round($bytes, 2) . ' ' . $units[$pow]; + } + + public function __toString(): string + { + return $this->originalName ?? $this->fileName ?? ''; + } + + // Si vous utilisez les dimensions (pour les images) + public function setDimensionsFromFile(File $file): void + { + if (str_starts_with($file->getMimeType(), 'image/')) { + try { + $size = getimagesize($file->getPathname()); + if ($size) { + $this->dimensions = [$size[0], $size[1]]; + } + } catch (\Exception $e) { + // Ignorer l'erreur si ce n'est pas une image + } + } + } +} \ No newline at end of file diff --git a/src/Entity/Question.php b/src/Entity/Question.php index ec251df..661ad38 100644 --- a/src/Entity/Question.php +++ b/src/Entity/Question.php @@ -56,6 +56,12 @@ class Question #[ORM\JoinColumn(nullable: false)] private ?Investigation $investigation = null; + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: Attachment::class, mappedBy: 'question', cascade: ['persist', 'remove'], orphanRemoval: true)] + private Collection $attachments; + public function __construct() { @@ -64,6 +70,7 @@ class Question $this->choice = false; $this->amount = 0; $this->max_participant = 0; + $this->attachments = new ArrayCollection(); } public function __clone() @@ -254,6 +261,36 @@ class Question return $this; } + /** + * @return Collection + */ + public function getAttachments(): Collection + { + return $this->attachments; + } + + public function addAttachment(Attachment $attachment): static + { + if (!$this->attachments->contains($attachment)) { + $this->attachments->add($attachment); + $attachment->setQuestion($this); + } + + return $this; + } + + public function removeAttachment(Attachment $attachment): static + { + if ($this->attachments->removeElement($attachment)) { + // set the owning side to null (unless already changed) + if ($attachment->getQuestion() === $this) { + $attachment->setQuestion(null); + } + } + + return $this; + } + } diff --git a/src/Form/AttachmentType.php b/src/Form/AttachmentType.php new file mode 100644 index 0000000..3eacbb1 --- /dev/null +++ b/src/Form/AttachmentType.php @@ -0,0 +1,33 @@ +add('file', VichFileType::class, [ // Utilisez VichFileType au lieu de FileType + 'label' => 'Fichier', + 'required' => false, + 'allow_delete' => true, + 'delete_label' => 'Supprimer', + 'download_label' => 'Télécharger', + 'download_uri' => true, + 'asset_helper' => true, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Attachment::class, + ]); + } +} \ No newline at end of file diff --git a/src/Form/QuestionType.php b/src/Form/QuestionType.php index 34d8872..0653997 100644 --- a/src/Form/QuestionType.php +++ b/src/Form/QuestionType.php @@ -12,6 +12,8 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; +use Symfony\Component\Form\Extension\Core\Type\FileType; + class QuestionType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void @@ -59,6 +61,17 @@ class QuestionType extends AbstractType 'prototype' => true, 'by_reference' => false )) + ->add('attachments', CollectionType::class, [ + 'label' => 'Pièces jointes', + 'entry_type' => AttachmentType::class, + 'entry_options' => ['label' => false], + 'allow_add' => true, + 'allow_delete' => true, + 'by_reference' => false, + 'prototype' => true, + 'prototype_name' => '__attachment_prot__', + 'required' => false, + ]); ; } diff --git a/src/Repository/AttachmentRepository.php b/src/Repository/AttachmentRepository.php new file mode 100644 index 0000000..58b74f2 --- /dev/null +++ b/src/Repository/AttachmentRepository.php @@ -0,0 +1,43 @@ + + */ +class AttachmentRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Attachment::class); + } + + // /** + // * @return Attachment[] Returns an array of Attachment objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('a') + // ->andWhere('a.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('a.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Attachment + // { + // return $this->createQueryBuilder('a') + // ->andWhere('a.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/symfony.lock b/symfony.lock index 50e44a6..0816ec6 100755 --- a/symfony.lock +++ b/symfony.lock @@ -189,5 +189,17 @@ "config/packages/web_profiler.yaml", "config/routes/web_profiler.yaml" ] + }, + "vich/uploader-bundle": { + "version": "2.9", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "1.13", + "ref": "1b3064c2f6b255c2bc2f56461aaeb76b11e07e36" + }, + "files": [ + "config/packages/vich_uploader.yaml" + ] } } diff --git a/templates/investigation/add-index.html.twig b/templates/investigation/add-index.html.twig index d66b626..8f6b2de 100644 --- a/templates/investigation/add-index.html.twig +++ b/templates/investigation/add-index.html.twig @@ -42,7 +42,7 @@

Créer une nouvelle enquête

- {{ form_start(form) }} + {{ form_start(form, {'attr': {'enctype': 'multipart/form-data'}}) }}
+ {# modalities #}

Modalité

@@ -242,9 +243,38 @@
{% endfor %}
+ + + + + + + +
+
+ {% for attachment in formQuestion.attachments %} +
+ {{ form_row(attachment.file, { 'row_attr': {'class': 'mb-0'} }) }} + +
+ {% else %} +

Aucun fichier ajouté

+ {% endfor %} +
+
+ + + + + + +
- + +
@@ -337,6 +367,50 @@ $(document).on('click', '.remove-modality', function() { $(this).closest('.modality-item').remove(); }); + + + + + + + + + + + + // 1. Ajouter un fichier + $(document).on('click', '.add-attachment', function(e) { + e.preventDefault(); + + // On remonte au parent pour trouver le conteneur spécifique à cette question + var $container = $(this).closest('.row').find('.attachments-container'); + var prototype = $container.data('prototype'); + var index = $container.data('index'); + + // On remplace le prototype par l'index actuel + var newForm = prototype.replace(/__attachment_prot__/g, index); + + // On crée l'élément HTML + var $newItem = $('
').append(newForm); + + // On ajoute un bouton de suppression au nouvel élément + $newItem.append(''); + + // On ajoute au DOM et on incrémente l'index + $container.append($newItem); + $container.data('index', index + 1); + + // Supprimer le message "Aucun fichier" s'il existe + $container.find('p.text-muted').remove(); + }); + + // 2. Supprimer un fichier (existant ou nouveau) + $(document).on('click', '.remove-attachment', function(e) { + e.preventDefault(); + $(this).closest('.attachment-item').remove(); + }); + + }); {% endblock %} diff --git a/templates/investigation/form-question.html.twig b/templates/investigation/form-question.html.twig index f94613b..8501a85 100644 --- a/templates/investigation/form-question.html.twig +++ b/templates/investigation/form-question.html.twig @@ -168,10 +168,29 @@ {% endfor %} + + + +
+
+ {% for attachment in formQtn.attachments %} +
+ {{ form_row(attachment.file, { 'row_attr': {'class': 'mb-0'} }) }} + +
+ {% else %} +

Aucun fichier ajouté

+ {% endfor %} +
+
+
+