diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index b82dc3cfe..456bdeea2 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -34,6 +34,6 @@ jobs: with: context: . push: true - build-args: GITHUB_RELEASE=1.3.6 - tags: docker.io/koillection/koillection:latest,docker.io/koillection/koillection:1.3.6 + build-args: GITHUB_RELEASE=1.3.7 + tags: docker.io/koillection/koillection:latest,docker.io/koillection/koillection:1.3.7 platforms: linux/amd64,linux/arm64 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 54cb6b868..45feac37f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Changelog All notable changes to this project will be documented in this file. +## [1.3.7] / 2022-07-27 +### Features +- Add possibility to choose which columns to display in collection list view based on items metadata (Benjamin Jonard) +- Add new choice list type (Benjamin Jonard) +- Add possibility to order s collection's items on text, list and country metadata types (Benjamin Jonard) + +### Miscellaneous +- Update JS dependencies, fix CVE-2022-25858 (Benjamin Jonard) +- Remove update logs, add create/delete logs for more entities (Benjamin Jonard) + ## [1.3.6] / 2022-07-20 ### Features - Add sorting feature on collections; sorting is available on item name and data of type Date, Number and Rating (Benjamin Jonard) diff --git a/config/services.yaml b/config/services.yaml index 61ed1c2df..c5789b8b1 100755 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,5 +1,5 @@ parameters: - release: '1.3.6' + release: '1.3.7' locale: 'en-GB' uuid_regex: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' @@ -87,6 +87,7 @@ services: tags: - { name: doctrine.event_listener, event: prePersist, lazy: true, priority: -5 } - { name: doctrine.event_listener, event: preRemove, lazy: true, priority: -5 } + - { name: doctrine.event_listener, event: postRemove, lazy: true, priority: -5 } App\EventListener\VisibilityListener: tags: diff --git a/fixtures/loans.yaml b/fixtures/loans.yaml index 3131d46ec..d0f9135f6 100644 --- a/fixtures/loans.yaml +++ b/fixtures/loans.yaml @@ -2,11 +2,11 @@ App\Entity\Loan: loan_admin_{1..5}: item: "@item_admin_" lentTo: "" - lentAt: <(new \DateTime())> + lentAt: <(new \DateTimeImmutable())> owner: "@admin" loan_user_{1..5}: item: "@item_user_" lentTo: "" - lentAt: <(new \DateTime())> + lentAt: <(new \DateTimeImmutable())> owner: "@user" \ No newline at end of file diff --git a/migrations/Mysql/Version20220725204054.php b/migrations/Mysql/Version20220725204054.php new file mode 100644 index 000000000..38d9ab6b8 --- /dev/null +++ b/migrations/Mysql/Version20220725204054.php @@ -0,0 +1,42 @@ +skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'mysql\'.'); + + $this->addSql('ALTER TABLE koi_album CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_choice_list CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_collection CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_datum CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_inventory CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_item CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_loan CHANGE lent_at lent_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE returned_at returned_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_log CHANGE logged_at logged_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_photo CHANGE taken_at taken_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_tag CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_tag_category CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_template CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_user CHANGE last_date_of_activity last_date_of_activity DATE DEFAULT NULL COMMENT \'(DC2Type:date_immutable)\', CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE automatic_dark_mode_start_at automatic_dark_mode_start_at TIME DEFAULT NULL COMMENT \'(DC2Type:time_immutable)\', CHANGE automatic_dark_mode_end_at automatic_dark_mode_end_at TIME DEFAULT NULL COMMENT \'(DC2Type:time_immutable)\''); + $this->addSql('ALTER TABLE koi_wish CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_wishlist CHANGE created_at created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', CHANGE updated_at updated_at DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\''); + } + + public function down(Schema $schema): void + { + $this->skipIf(true, 'Always move forward.'); + } +} diff --git a/migrations/Postgresql/Version20220725195801.php b/migrations/Postgresql/Version20220725195801.php new file mode 100644 index 000000000..ede8628d0 --- /dev/null +++ b/migrations/Postgresql/Version20220725195801.php @@ -0,0 +1,127 @@ +skipIf('postgresql' !== $this->connection->getDatabasePlatform()->getName(), 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE koi_album ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_album ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_album ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_album ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_album.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_album.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_choice_list ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_choice_list ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_choice_list ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_choice_list ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_choice_list.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_choice_list.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_collection ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_collection ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_collection ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_collection ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_collection.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_collection.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_datum ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_datum ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_datum ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_datum ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_datum.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_datum.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_inventory ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_inventory ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_inventory ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_inventory ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_inventory.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_inventory.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_item ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_item ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_item ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_item ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_item.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_item.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_loan ALTER lent_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_loan ALTER lent_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_loan ALTER returned_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_loan ALTER returned_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_loan.lent_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_loan.returned_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_log DROP payload'); + $this->addSql('ALTER TABLE koi_log ALTER logged_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_log ALTER logged_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_log.logged_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_photo ALTER taken_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_photo ALTER taken_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_photo ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_photo ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_photo ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_photo ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_photo.taken_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_photo.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_photo.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_tag ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_tag ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_tag ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_tag ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_tag.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_tag.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_tag_category ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_tag_category ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_tag_category ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_tag_category ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_tag_category.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_tag_category.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_template ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_template ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_template ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_template ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_template.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_template.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_user ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_user ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_user ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_user ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_user.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_user.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_wish ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_wish ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_wish ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_wish ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_wish.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_wish.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_wishlist ALTER created_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_wishlist ALTER created_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_wishlist ALTER updated_at TYPE TIMESTAMP(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_wishlist ALTER updated_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_wishlist.created_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_wishlist.updated_at IS \'(DC2Type:datetime_immutable)\''); + $this->addSql('ALTER TABLE koi_user ALTER automatic_dark_mode_start_at TYPE TIME(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_user ALTER automatic_dark_mode_start_at DROP DEFAULT'); + $this->addSql('ALTER TABLE koi_user ALTER automatic_dark_mode_end_at TYPE TIME(0) WITHOUT TIME ZONE'); + $this->addSql('ALTER TABLE koi_user ALTER automatic_dark_mode_end_at DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_user.automatic_dark_mode_start_at IS \'(DC2Type:time_immutable)\''); + $this->addSql('COMMENT ON COLUMN koi_user.automatic_dark_mode_end_at IS \'(DC2Type:time_immutable)\''); + $this->addSql('ALTER TABLE koi_user ALTER last_date_of_activity TYPE DATE'); + $this->addSql('ALTER TABLE koi_user ALTER last_date_of_activity DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN koi_user.last_date_of_activity IS \'(DC2Type:date_immutable)\''); + } + + public function down(Schema $schema): void + { + $this->skipIf(true, 'Always move forward.'); + } +} diff --git a/src/Command/RegenerateLogsCommand.php b/src/Command/RegenerateLogsCommand.php index bf1fcc45d..efa0ccb4e 100644 --- a/src/Command/RegenerateLogsCommand.php +++ b/src/Command/RegenerateLogsCommand.php @@ -83,6 +83,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int $output->writeln($this->translator->trans('message.logs_generated', ['%count%' => $counter])); + $results = $this->managerRegistry->getManager()->createQueryBuilder() + ->select('l.objectId') + ->distinct() + ->from(Log::class, 'l') + ->where('l.type = ?1') + ->setParameter(1, LogTypeEnum::TYPE_DELETE) + ->getQuery() + ->execute() + ; + + $ids = array_map(function ($result) { + return $result['objectId']; + }, $results); + + $this->managerRegistry->getManager()->createQueryBuilder() + ->update(Log::class, 'l') + ->set('l.objectDeleted', '?1') + ->where('l.objectId IN (?2)') + ->setParameter(1, true) + ->setParameter(2, $ids) + ->getQuery() + ->execute() + ; + return Command::SUCCESS; } } diff --git a/src/Controller/Admin/AdminController.php b/src/Controller/Admin/AdminController.php index 20b66731c..f73ff08d5 100755 --- a/src/Controller/Admin/AdminController.php +++ b/src/Controller/Admin/AdminController.php @@ -73,7 +73,7 @@ public function index( )] public function exportSql(DatabaseDumper $databaseDumper): FileResponse { - return new FileResponse($databaseDumper->dump(), (new \DateTime())->format('YmdHis').'-koillection-database.sql'); + return new FileResponse($databaseDumper->dump(), (new \DateTimeImmutable())->format('YmdHis').'-koillection-database.sql'); } #[Route( @@ -91,7 +91,7 @@ public function exportImages(DatabaseDumper $databaseDumper, UserRepository $use $options->setFlushOutput(true); $options->setSendHttpHeaders(true); - $zipFilename = (new \DateTime())->format('YmdHis').'-koillection-images.zip'; + $zipFilename = (new \DateTimeImmutable())->format('YmdHis').'-koillection-images.zip'; $zip = new ZipStream($zipFilename, $options); foreach ($users as $user) { diff --git a/src/Controller/CollectionController.php b/src/Controller/CollectionController.php index b6f9c2b48..f22e4035e 100755 --- a/src/Controller/CollectionController.php +++ b/src/Controller/CollectionController.php @@ -8,6 +8,7 @@ use App\Form\Type\Entity\CollectionType; use App\Form\Type\Model\BatchTaggerType; use App\Model\BatchTagger; +use App\Repository\ChoiceListRepository; use App\Repository\CollectionRepository; use App\Repository\DatumRepository; use App\Repository\ItemRepository; @@ -53,7 +54,13 @@ public function index(CollectionRepository $collectionRepository): Response name: 'app_collection_add', methods: ['GET', 'POST'] )] - public function add(Request $request, TranslatorInterface $translator, CollectionRepository $collectionRepository, ManagerRegistry $managerRegistry): Response + public function add( + Request $request, + TranslatorInterface $translator, + CollectionRepository $collectionRepository, + ChoiceListRepository $choiceListRepository, + ManagerRegistry $managerRegistry + ): Response { $collection = new Collection(); @@ -87,6 +94,7 @@ public function add(Request $request, TranslatorInterface $translator, Collectio 'form' => $form->createView(), 'suggestedItemsTitles' => $collectionRepository->suggestItemsTitles($collection), 'suggestedChildrenTitles' => $collectionRepository->suggestChildrenTitles($collection), + 'choiceLists' => $choiceListRepository->findAll(), ]); } @@ -141,7 +149,14 @@ public function items(Collection $collection, ItemRepository $itemRepository): R requirements: ['id' => '%uuid_regex%'], methods: ['GET', 'POST'] )] - public function edit(Request $request, Collection $collection, TranslatorInterface $translator, CollectionRepository $collectionRepository, ManagerRegistry $managerRegistry): Response + public function edit( + Request $request, + Collection $collection, + TranslatorInterface $translator, + CollectionRepository $collectionRepository, + ChoiceListRepository $choiceListRepository, + ManagerRegistry $managerRegistry + ): Response { $form = $this->createForm(CollectionType::class, $collection); $form->handleRequest($request); @@ -157,6 +172,7 @@ public function edit(Request $request, Collection $collection, TranslatorInterfa 'collection' => $collection, 'suggestedItemsTitles' => $collectionRepository->suggestItemsTitles($collection), 'suggestedChildrenTitles' => $collectionRepository->suggestChildrenTitles($collection), + 'choiceLists' => $choiceListRepository->findAll(), ]); } diff --git a/src/Controller/LoanController.php b/src/Controller/LoanController.php index a5377594f..5e70e5154 100755 --- a/src/Controller/LoanController.php +++ b/src/Controller/LoanController.php @@ -63,7 +63,7 @@ public function returned(Loan $loan, TranslatorInterface $translator, ManagerReg { $this->denyAccessUnlessFeaturesEnabled(['loans']); - $loan->setReturnedAt(new \DateTime()); + $loan->setReturnedAt(new \DateTimeImmutable()); $managerRegistry->getManager()->flush(); $this->addFlash('notice', $translator->trans('message.item_returned', ['%item%' => ' '.$loan->getItem()->getName().' '])); diff --git a/src/Controller/ToolsController.php b/src/Controller/ToolsController.php index fb8796e14..92592fd41 100644 --- a/src/Controller/ToolsController.php +++ b/src/Controller/ToolsController.php @@ -60,7 +60,7 @@ public function exportCsv(CollectionRepository $collectionRepository): CsvRespon } } - return new CsvResponse($rows, (new \DateTime())->format('YmdHis').'-koillection-export.csv'); + return new CsvResponse($rows, (new \DateTimeImmutable())->format('YmdHis').'-koillection-export.csv'); } #[Route( @@ -70,7 +70,7 @@ public function exportCsv(CollectionRepository $collectionRepository): CsvRespon )] public function exportSql(DatabaseDumper $databaseDumper): FileResponse { - return new FileResponse($databaseDumper->dump(), (new \DateTime())->format('YmdHis').'-koillection-export.sql'); + return new FileResponse($databaseDumper->dump(), (new \DateTimeImmutable())->format('YmdHis').'-koillection-export.sql'); } #[Route( @@ -86,7 +86,7 @@ public function exportImages(): StreamedResponse $options->setFlushOutput(true); $options->setSendHttpHeaders(true); - $zipFilename = (new \DateTime())->format('YmdHis').'-koillection-images.zip'; + $zipFilename = (new \DateTimeImmutable())->format('YmdHis').'-koillection-images.zip'; $zip = new ZipStream($zipFilename, $options); $path = $this->getParameter('kernel.project_dir').'/public/uploads/'.$this->getUser()->getId(); diff --git a/src/Entity/Album.php b/src/Entity/Album.php index c5303dc4b..e404ff0b0 100755 --- a/src/Entity/Album.php +++ b/src/Entity/Album.php @@ -103,13 +103,13 @@ class Album implements BreadcrumbableInterface, LoggableInterface, CacheableInte #[Groups(['album:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['album:read'])] - private ?\DateTimeInterface $createdAt = null; + private ?\DateTimeImmutable $createdAt = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['album:read'])] - private ?\DateTimeInterface $updatedAt = null; + private ?\DateTimeImmutable $updatedAt = null; public function __construct() { @@ -167,24 +167,24 @@ public function setSeenCounter(int $seenCounter): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -293,7 +293,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/ChoiceList.php b/src/Entity/ChoiceList.php index 7caebff1a..dff8f318c 100644 --- a/src/Entity/ChoiceList.php +++ b/src/Entity/ChoiceList.php @@ -38,13 +38,13 @@ class ChoiceList implements BreadcrumbableInterface, LoggableInterface #[Groups(['choiceList:read'])] private ?User $owner = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['choiceList:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['choiceList:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -128,24 +128,24 @@ public function setOwner(?User $owner): ChoiceList return $this; } - public function getCreatedAt(): \DateTimeInterface + public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): ChoiceList + public function setCreatedAt(\DateTimeImmutable $createdAt): ChoiceList { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): ChoiceList + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): ChoiceList { $this->updatedAt = $updatedAt; diff --git a/src/Entity/Collection.php b/src/Entity/Collection.php index 76f93a595..57d32a1fb 100755 --- a/src/Entity/Collection.php +++ b/src/Entity/Collection.php @@ -143,13 +143,13 @@ class Collection implements LoggableInterface, BreadcrumbableInterface, Cacheabl #[Groups(['collection:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['collection:read'])] - private ?\DateTimeInterface $createdAt = null; + private ?\DateTimeImmutable $createdAt = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['collection:read'])] - private ?\DateTimeInterface $updatedAt = null; + private ?\DateTimeImmutable $updatedAt = null; public function __construct() { @@ -243,24 +243,24 @@ public function setSeenCounter(int $seenCounter): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -369,7 +369,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/Datum.php b/src/Entity/Datum.php index af1bcc555..8fe9ae873 100755 --- a/src/Entity/Datum.php +++ b/src/Entity/Datum.php @@ -110,13 +110,13 @@ class Datum #[Groups(['datum:read'])] private ?User $owner = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['datum:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['datum:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -181,24 +181,24 @@ public function setPosition(?int $position): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -239,7 +239,7 @@ public function setFileImage(?File $fileImage): self $this->fileImage = $fileImage; // Force Doctrine to trigger an update if ($fileImage instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; @@ -315,7 +315,7 @@ public function setFileFile(?File $fileFile): Datum $this->fileFile = $fileFile; // Force Doctrine to trigger an update if ($fileFile instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/Inventory.php b/src/Entity/Inventory.php index 8f7b9c82b..0e16146cc 100644 --- a/src/Entity/Inventory.php +++ b/src/Entity/Inventory.php @@ -40,13 +40,13 @@ class Inventory implements BreadcrumbableInterface, LoggableInterface #[Groups(['inventory:read'])] private ?User $owner = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['inventory:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['inventory:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; private array $contentAsArray = []; @@ -124,24 +124,24 @@ public function setContent(string $content): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; diff --git a/src/Entity/Item.php b/src/Entity/Item.php index 3a74740fc..e06522ffe 100755 --- a/src/Entity/Item.php +++ b/src/Entity/Item.php @@ -131,13 +131,13 @@ class Item implements BreadcrumbableInterface, LoggableInterface, CacheableInter #[Groups(['item:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['item:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['item:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; private ?string $orderingValue = null; @@ -246,24 +246,24 @@ public function setSeenCounter(int $seenCounter): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -426,7 +426,7 @@ public function setFile(?File $file): self // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/Loan.php b/src/Entity/Loan.php index a8d6a9e9e..c31e840ee 100755 --- a/src/Entity/Loan.php +++ b/src/Entity/Loan.php @@ -37,14 +37,14 @@ class Loan #[Groups(['loan:read', 'loan:write'])] private ?string $lentTo = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Assert\NotBlank] #[Groups(['loan:read', 'loan:write'])] - private ?\DateTimeInterface $lentAt = null; + private ?\DateTimeImmutable $lentAt = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['loan:read', 'loan:write'])] - private ?\DateTimeInterface $returnedAt; + private ?\DateTimeImmutable $returnedAt; #[ORM\ManyToOne(targetEntity: User::class)] #[Groups(['loan:read'])] @@ -72,24 +72,24 @@ public function setLentTo(string $lentTo): self return $this; } - public function getLentAt(): ?\DateTimeInterface + public function getLentAt(): ?\DateTimeImmutable { return $this->lentAt; } - public function setLentAt(\DateTimeInterface $lentAt): self + public function setLentAt(\DateTimeImmutable $lentAt): self { $this->lentAt = $lentAt; return $this; } - public function getReturnedAt(): ?\DateTimeInterface + public function getReturnedAt(): ?\DateTimeImmutable { return $this->returnedAt; } - public function setReturnedAt(?\DateTimeInterface $returnedAt): self + public function setReturnedAt(?\DateTimeImmutable $returnedAt): self { $this->returnedAt = $returnedAt; diff --git a/src/Entity/Log.php b/src/Entity/Log.php index f7a784fe9..0ed7bde45 100755 --- a/src/Entity/Log.php +++ b/src/Entity/Log.php @@ -30,9 +30,9 @@ class Log #[Groups(['log:read'])] private ?string $type; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['log:read'])] - private ?\DateTimeInterface $loggedAt = null; + private ?\DateTimeImmutable $loggedAt = null; #[ORM\Column(type: Types::STRING, length: 36)] #[Groups(['log:read'])] @@ -77,12 +77,12 @@ public function setType(?string $type): self return $this; } - public function getLoggedAt(): ?\DateTimeInterface + public function getLoggedAt(): ?\DateTimeImmutable { return $this->loggedAt; } - public function setLoggedAt(\DateTimeInterface $loggedAt): self + public function setLoggedAt(\DateTimeImmutable $loggedAt): self { $this->loggedAt = $loggedAt; diff --git a/src/Entity/Photo.php b/src/Entity/Photo.php index 95e2485e9..d1cf655da 100755 --- a/src/Entity/Photo.php +++ b/src/Entity/Photo.php @@ -73,9 +73,9 @@ class Photo implements CacheableInterface, LoggableInterface #[Groups(['photo:read'])] private ?string $imageSmallThumbnail = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['photo:read'])] - private ?\DateTimeInterface $takenAt = null; + private ?\DateTimeImmutable $takenAt = null; #[ORM\Column(type: Types::STRING, length: 10)] #[Groups(['photo:read', 'photo:write'])] @@ -90,13 +90,13 @@ class Photo implements CacheableInterface, LoggableInterface #[Groups(['photo:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['photo:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['photo:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -150,36 +150,36 @@ public function setPlace(?string $place): self return $this; } - public function getTakenAt(): ?\DateTimeInterface + public function getTakenAt(): ?\DateTimeImmutable { return $this->takenAt; } - public function setTakenAt(?\DateTimeInterface $takenAt): self + public function setTakenAt(?\DateTimeImmutable $takenAt): self { $this->takenAt = $takenAt; return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -220,7 +220,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/Tag.php b/src/Entity/Tag.php index 34070f5b8..e6b190d8c 100755 --- a/src/Entity/Tag.php +++ b/src/Entity/Tag.php @@ -90,13 +90,13 @@ class Tag implements BreadcrumbableInterface, LoggableInterface #[Assert\Choice(choices: VisibilityEnum::VISIBILITIES)] private string $visibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['tag:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['tag:read'])] - private ?\DateTimeInterface $updatedAt = null; + private ?\DateTimeImmutable $updatedAt = null; public function __construct() { @@ -165,24 +165,24 @@ public function setVisibility(string $visibility): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -199,7 +199,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/TagCategory.php b/src/Entity/TagCategory.php index a9eb63713..5d47cb6ed 100644 --- a/src/Entity/TagCategory.php +++ b/src/Entity/TagCategory.php @@ -51,13 +51,13 @@ class TagCategory implements BreadcrumbableInterface, LoggableInterface #[ApiSubresource(maxDepth: 1)] private DoctrineCollection $tags; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['tagCategory:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['tagCategory:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -111,24 +111,24 @@ public function setColor(string $color): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; diff --git a/src/Entity/Template.php b/src/Entity/Template.php index d994da407..e437fee24 100755 --- a/src/Entity/Template.php +++ b/src/Entity/Template.php @@ -46,13 +46,13 @@ class Template implements BreadcrumbableInterface, LoggableInterface #[Groups(['template:read'])] private ?User $owner = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['template:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['template:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -82,24 +82,24 @@ public function setName(string $name): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; diff --git a/src/Entity/User.php b/src/Entity/User.php index 6e3052c5e..62af236cc 100755 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -12,7 +12,7 @@ use App\Enum\RoleEnum; use App\Enum\VisibilityEnum; use App\Repository\UserRepository; -use DateTimeInterface; +use DateTimeImmutable; use Doctrine\Common\Collections\Collection as DoctrineCollection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; @@ -128,21 +128,21 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Breadcr #[ORM\OneToMany(targetEntity: Inventory::class, mappedBy: 'owner', cascade: ['remove'])] private DoctrineCollection $inventories; - #[ORM\Column(type: Types::DATE_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATE_IMMUTABLE, nullable: true)] #[Groups(['user:read'])] - private ?DateTimeInterface $lastDateOfActivity = null; + private ?DateTimeImmutable $lastDateOfActivity = null; #[ORM\Column(type: Types::BOOLEAN, options: ['default' => 0])] #[Groups(['user:read', 'user:write'])] private bool $darkModeEnabled; - #[ORM\Column(type: Types::TIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::TIME_IMMUTABLE, nullable: true)] #[Groups(['user:read', 'user:write'])] - private ?\DateTime $automaticDarkModeStartAt; + private ?\DateTimeImmutable $automaticDarkModeStartAt; - #[ORM\Column(type: Types::TIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::TIME_IMMUTABLE, nullable: true)] #[Groups(['user:read', 'user:write'])] - private ?\DateTime $automaticDarkModeEndAt; + private ?\DateTimeImmutable $automaticDarkModeEndAt; #[ORM\Column(type: Types::BOOLEAN, options: ['default' => 1])] #[Groups(['user:read', 'user:write'])] @@ -176,13 +176,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Breadcr #[Groups(['user:read', 'user:write'])] private bool $statisticsFeatureEnabled; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['user:read'])] - private DateTimeInterface $createdAt; + private DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['user:read'])] - private ?DateTimeInterface $updatedAt; + private ?DateTimeImmutable $updatedAt; public function __construct() { @@ -248,7 +248,7 @@ public function isInDarkMode(): bool if ($this->getAutomaticDarkModeStartAt() && $this->getAutomaticDarkModeEndAt()) { // Apply timezone to get current time for the user $timezone = new \DateTimeZone('Europe/Paris'); - $currentTime = strtotime((new \DateTime())->setTimezone($timezone)->format('H:i')); + $currentTime = strtotime((new \DateTimeImmutable())->setTimezone($timezone)->format('H:i')); $startTime = strtotime($this->getAutomaticDarkModeStartAt()->format('H:i')); $endTime = strtotime($this->getAutomaticDarkModeEndAt()->format('H:i')); @@ -476,36 +476,36 @@ public function setVisibility(string $visibility): self return $this; } - public function getLastDateOfActivity(): ?DateTimeInterface + public function getLastDateOfActivity(): ?DateTimeImmutable { return $this->lastDateOfActivity; } - public function setLastDateOfActivity(?DateTimeInterface $lastDateOfActivity): self + public function setLastDateOfActivity(?DateTimeImmutable $lastDateOfActivity): self { $this->lastDateOfActivity = $lastDateOfActivity; return $this; } - public function getCreatedAt(): ?DateTimeInterface + public function getCreatedAt(): ?DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(DateTimeInterface $createdAt): self + public function setCreatedAt(DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?DateTimeInterface + public function getUpdatedAt(): ?DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?DateTimeInterface $updatedAt): self + public function setUpdatedAt(?DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -534,7 +534,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; @@ -648,24 +648,24 @@ public function setDarkModeEnabled(bool $darkModeEnabled): User return $this; } - public function getAutomaticDarkModeStartAt(): ?\DateTime + public function getAutomaticDarkModeStartAt(): ?\DateTimeImmutable { return $this->automaticDarkModeStartAt; } - public function setAutomaticDarkModeStartAt(?\DateTime $automaticDarkModeStartAt): User + public function setAutomaticDarkModeStartAt(?\DateTimeImmutable $automaticDarkModeStartAt): User { $this->automaticDarkModeStartAt = $automaticDarkModeStartAt; return $this; } - public function getAutomaticDarkModeEndAt(): ?\DateTime + public function getAutomaticDarkModeEndAt(): ?\DateTimeImmutable { return $this->automaticDarkModeEndAt; } - public function setAutomaticDarkModeEndAt(?\DateTime $automaticDarkModeEndAt): User + public function setAutomaticDarkModeEndAt(?\DateTimeImmutable $automaticDarkModeEndAt): User { $this->automaticDarkModeEndAt = $automaticDarkModeEndAt; diff --git a/src/Entity/Wish.php b/src/Entity/Wish.php index a59227083..c3b57bee2 100755 --- a/src/Entity/Wish.php +++ b/src/Entity/Wish.php @@ -95,13 +95,13 @@ class Wish implements CacheableInterface, LoggableInterface #[Groups(['wish:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['wish:read'])] - private \DateTimeInterface $createdAt; + private \DateTimeImmutable $createdAt; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['wish:read'])] - private ?\DateTimeInterface $updatedAt; + private ?\DateTimeImmutable $updatedAt; public function __construct() { @@ -179,24 +179,24 @@ public function setComment(?string $comment): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -237,7 +237,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/Entity/Wishlist.php b/src/Entity/Wishlist.php index 8d86071f9..a198d5cba 100755 --- a/src/Entity/Wishlist.php +++ b/src/Entity/Wishlist.php @@ -98,13 +98,13 @@ class Wishlist implements BreadcrumbableInterface, CacheableInterface, LoggableI #[Groups(['wishlist:read'])] private string $finalVisibility; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] #[Groups(['wishlist:read'])] - private ?\DateTimeInterface $createdAt = null; + private ?\DateTimeImmutable $createdAt = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + #[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)] #[Groups(['wishlist:read'])] - private ?\DateTimeInterface $updatedAt = null; + private ?\DateTimeImmutable $updatedAt = null; public function __construct() { @@ -161,24 +161,24 @@ public function setSeenCounter(int $seenCounter): self return $this; } - public function getCreatedAt(): ?\DateTimeInterface + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(\DateTimeInterface $createdAt): self + public function setCreatedAt(\DateTimeImmutable $createdAt): self { $this->createdAt = $createdAt; return $this; } - public function getUpdatedAt(): ?\DateTimeInterface + public function getUpdatedAt(): ?\DateTimeImmutable { return $this->updatedAt; } - public function setUpdatedAt(?\DateTimeInterface $updatedAt): self + public function setUpdatedAt(?\DateTimeImmutable $updatedAt): self { $this->updatedAt = $updatedAt; @@ -287,7 +287,7 @@ public function setFile(?File $file): self $this->file = $file; // Force Doctrine to trigger an update if ($file instanceof UploadedFile) { - $this->setUpdatedAt(new \DateTime()); + $this->setUpdatedAt(new \DateTimeImmutable()); } return $this; diff --git a/src/EventListener/ActivityListener.php b/src/EventListener/ActivityListener.php index e9555c43c..97868ebda 100644 --- a/src/EventListener/ActivityListener.php +++ b/src/EventListener/ActivityListener.php @@ -19,7 +19,7 @@ public function __construct( public function onKernelRequest() { $user = $this->security->getUser(); - $now = (new \DateTime())->setTime(0, 0, 0, 0); + $now = (new \DateTimeImmutable())->setTime(0, 0, 0, 0); if (!$user instanceof User || $user->getLastDateOfActivity() == $now) { return null; diff --git a/src/EventListener/LoggableListener.php b/src/EventListener/LoggableListener.php index 9a7b5fbac..191a680e7 100755 --- a/src/EventListener/LoggableListener.php +++ b/src/EventListener/LoggableListener.php @@ -46,4 +46,21 @@ public function preRemove(LifecycleEventArgs $args): void $args->getEntityManager()->persist($log); } } + + public function postRemove(LifecycleEventArgs $args): void + { + $entity = $args->getEntity(); + + if ($entity instanceof LoggableInterface) { + $args->getEntityManager()->createQueryBuilder() + ->update(Log::class, 'l') + ->set('l.objectDeleted', '?1') + ->where('l.objectId = ?2') + ->setParameter(1, true) + ->setParameter(2, $entity->getId()) + ->getQuery() + ->execute() + ; + } + } } diff --git a/src/EventListener/TimestampableListener.php b/src/EventListener/TimestampableListener.php index c5ede78e2..dbe261652 100755 --- a/src/EventListener/TimestampableListener.php +++ b/src/EventListener/TimestampableListener.php @@ -12,11 +12,11 @@ public function prePersist(LifecycleEventArgs $args): void { $entity = $args->getEntity(); if (true === property_exists($entity, 'createdAt')) { - $entity->setCreatedAt(new \DateTime()); + $entity->setCreatedAt(new \DateTimeImmutable()); } if (true === property_exists($entity, 'loggedAt') && null === $entity->getLoggedAt()) { - $entity->setLoggedAt(new \DateTime()); + $entity->setLoggedAt(new \DateTimeImmutable()); } } @@ -24,7 +24,7 @@ public function preUpdate(LifecycleEventArgs $args): void { $entity = $args->getEntity(); if (true === property_exists($entity, 'updatedAt')) { - $entity->setUpdatedAt(new \DateTime()); + $entity->setUpdatedAt(new \DateTimeImmutable()); } } } diff --git a/src/Form/Type/Entity/DatumType.php b/src/Form/Type/Entity/DatumType.php index e3aad2356..e559f1fc2 100755 --- a/src/Form/Type/Entity/DatumType.php +++ b/src/Form/Type/Entity/DatumType.php @@ -72,16 +72,17 @@ function (FormEvent $event) { case DatumTypeEnum::TYPE_DATE: $form ->add('value', DateType::class, [ + 'input' => 'datetime_immutable', 'required' => false, 'html5' => false, 'widget' => 'single_text', 'format' => $this->security->getUser()->getDateFormatForForm(), 'model_transformer' => new CallbackTransformer( function ($string) { - return null !== $string ? new \DateTime($string) : null; + return null !== $string ? new \DateTimeImmutable($string) : null; }, function ($date) { - return $date instanceof \DateTime ? $date->format('Y-m-d') : null; + return $date instanceof \DateTimeImmutable ? $date->format('Y-m-d') : null; } ), ]) diff --git a/src/Form/Type/Entity/LoanType.php b/src/Form/Type/Entity/LoanType.php index 66ac5b74a..c6c47bb7b 100755 --- a/src/Form/Type/Entity/LoanType.php +++ b/src/Form/Type/Entity/LoanType.php @@ -23,6 +23,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('lentAt', DateType::class, [ + 'input' => 'datetime_immutable', 'required' => true, 'html5' => false, 'widget' => 'single_text', diff --git a/src/Form/Type/Entity/PhotoType.php b/src/Form/Type/Entity/PhotoType.php index 5947dcd0a..2f98d787c 100755 --- a/src/Form/Type/Entity/PhotoType.php +++ b/src/Form/Type/Entity/PhotoType.php @@ -42,6 +42,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'required' => false, ]) ->add('takenAt', DateType::class, [ + 'input' => 'datetime_immutable', 'required' => false, 'html5' => false, 'widget' => 'single_text', diff --git a/src/Form/Type/Model/SearchType.php b/src/Form/Type/Model/SearchType.php index bd83d5a2c..d454bd39a 100644 --- a/src/Form/Type/Model/SearchType.php +++ b/src/Form/Type/Model/SearchType.php @@ -30,6 +30,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'required' => false, ]) ->add('createdAt', DateType::class, [ + 'input' => 'datetime_immutable', 'label' => false, 'required' => false, 'html5' => false, diff --git a/src/Form/Type/Model/SettingsType.php b/src/Form/Type/Model/SettingsType.php index dcfdba1ab..afcfc1839 100644 --- a/src/Form/Type/Model/SettingsType.php +++ b/src/Form/Type/Model/SettingsType.php @@ -45,11 +45,13 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'required' => false, ]) ->add('automaticDarkModeStartAt', TimeType::class, [ + 'input' => 'datetime_immutable', 'required' => false, 'widget' => 'single_text', 'html5' => false, ]) ->add('automaticDarkModeEndAt', TimeType::class, [ + 'input' => 'datetime_immutable', 'required' => false, 'widget' => 'single_text', 'html5' => false, diff --git a/src/Model/Search/Search.php b/src/Model/Search/Search.php index 0b91f751d..56c51115b 100644 --- a/src/Model/Search/Search.php +++ b/src/Model/Search/Search.php @@ -12,7 +12,7 @@ class Search #[Assert\Length(min: 2, minMessage: 'error.search.too_short')] private ?string $term = null; - private ?\DateTime $createdAt = null; + private ?\DateTimeImmutable $createdAt = null; private bool $searchInItems = true; @@ -36,12 +36,12 @@ public function setTerm(string $term): Search return $this; } - public function getCreatedAt(): ?\DateTime + public function getCreatedAt(): ?\DateTimeImmutable { return $this->createdAt; } - public function setCreatedAt(?\DateTime $createdAt): Search + public function setCreatedAt(?\DateTimeImmutable $createdAt): Search { $this->createdAt = $createdAt; diff --git a/src/Repository/AlbumRepository.php b/src/Repository/AlbumRepository.php index 8ada20a5c..fff3f86cd 100644 --- a/src/Repository/AlbumRepository.php +++ b/src/Repository/AlbumRepository.php @@ -69,7 +69,7 @@ public function findForSearch(Search $search): array ; } - if ($search->getCreatedAt() instanceof \DateTime) { + if ($search->getCreatedAt() instanceof \DateTimeImmutable) { $createdAt = $search->getCreatedAt(); $qb ->andWhere('a.createdAt BETWEEN :start AND :end') diff --git a/src/Repository/CollectionRepository.php b/src/Repository/CollectionRepository.php index 4104e632d..9e55f9d61 100755 --- a/src/Repository/CollectionRepository.php +++ b/src/Repository/CollectionRepository.php @@ -119,7 +119,7 @@ public function findForSearch(Search $search): array ; } - if ($search->getCreatedAt() instanceof \DateTime) { + if ($search->getCreatedAt() instanceof \DateTimeImmutable) { $createdAt = $search->getCreatedAt(); $qb ->andWhere('c.createdAt BETWEEN :start AND :end') diff --git a/src/Repository/ItemRepository.php b/src/Repository/ItemRepository.php index 16e72ab28..e85e27380 100755 --- a/src/Repository/ItemRepository.php +++ b/src/Repository/ItemRepository.php @@ -103,7 +103,7 @@ public function findForSearch(Search $search): array ->setParameter('term', '%'.$search->getTerm().'%'); } - if ($search->getCreatedAt() instanceof \DateTime) { + if ($search->getCreatedAt() instanceof \DateTimeImmutable) { $createdAt = $search->getCreatedAt(); $qb ->andWhere('i.createdAt BETWEEN :start AND :end') @@ -152,9 +152,8 @@ public function findAllByCollection(Collection $collection): array if ($collection->getItemsDisplayMode() === DisplayModeEnum::DISPLAY_MODE_LIST) { $qb - ->leftJoin('i.data', 'data') + ->leftJoin('i.data', 'data', 'WITH', 'data.label IN (:labels) OR data IS NULL') ->addSelect('partial data.{id, label, type, value}') - ->andWhere('data.label IN (:labels) OR data IS NULL') ->setParameter('labels', $collection->getItemsDisplayModeListColumns()) ; } diff --git a/src/Repository/TagRepository.php b/src/Repository/TagRepository.php index 43c4cf123..0338fd32e 100755 --- a/src/Repository/TagRepository.php +++ b/src/Repository/TagRepository.php @@ -164,7 +164,7 @@ public function findForSearch(Search $search): array ; } - if ($search->getCreatedAt() instanceof \DateTime) { + if ($search->getCreatedAt() instanceof \DateTimeImmutable) { $createdAt = $search->getCreatedAt(); $qb ->andWhere('t.createdAt BETWEEN :start AND :end') diff --git a/src/Repository/WishlistRepository.php b/src/Repository/WishlistRepository.php index c8454fe06..d7268ffd3 100755 --- a/src/Repository/WishlistRepository.php +++ b/src/Repository/WishlistRepository.php @@ -90,7 +90,7 @@ public function findForSearch(Search $search): array ; } - if ($search->getCreatedAt() instanceof \DateTime) { + if ($search->getCreatedAt() instanceof \DateTimeImmutable) { $createdAt = $search->getCreatedAt(); $qb ->andWhere('w.createdAt BETWEEN :start AND :end') diff --git a/src/Twig/DateRuntime.php b/src/Twig/DateRuntime.php index 20b3fc843..88c3d5299 100644 --- a/src/Twig/DateRuntime.php +++ b/src/Twig/DateRuntime.php @@ -14,9 +14,9 @@ public function __construct( ) { } - public function timeAgo(\DateTime $ago): string + public function timeAgo(\DateTimeImmutable $ago): string { - $now = new \DateTime(); + $now = new \DateTimeImmutable(); $diff = $now->diff($ago); $diff->w = floor($diff->d / 7); @@ -44,7 +44,7 @@ public function timeAgo(\DateTime $ago): string $this->translator->trans('global.time.ago', ['%time%' => implode(', ', $string)]) : $this->translator->trans('global.time.just_now'); } - public function timeDiff(\DateTime $start, \DateTime $end): string + public function timeDiff(\DateTimeImmutable $start, \DateTimeImmutable $end): string { $diff = $start->diff($end); @@ -72,9 +72,9 @@ public function timeDiff(\DateTime $start, \DateTime $end): string return $string ? implode(', ', $string) : ''; } - public function dateAgo(\DateTime $ago): string + public function dateAgo(\DateTimeImmutable $ago): string { - $now = new \DateTime(); + $now = new \DateTimeImmutable(); $diff = $now->diff($ago); $diff->w = floor($diff->d / 7); diff --git a/src/Twig/LogRuntime.php b/src/Twig/LogRuntime.php index 20a8d6ff0..359b14543 100644 --- a/src/Twig/LogRuntime.php +++ b/src/Twig/LogRuntime.php @@ -30,6 +30,8 @@ public function getLogMessages(Log $log): array $class = strtolower($class); if ('tagcategory' == $class) { $class = 'tag_category'; + } elseif ('choicelist' == $class) { + $class = 'choice_list'; } $objectLabel = $log->getObjectLabel(); diff --git a/templates/App/Collection/_form_data_block.html.twig b/templates/App/Collection/_form_data_block.html.twig index 606424a40..6feb9df41 100644 --- a/templates/App/Collection/_form_data_block.html.twig +++ b/templates/App/Collection/_form_data_block.html.twig @@ -6,19 +6,20 @@
- {% for key, datum in data|filter(datum => datum.type in ([constant('App\\Enum\\DatumTypeEnum::TYPE_TEXT'), constant('App\\Enum\\DatumTypeEnum::TYPE_COUNTRY'), constant('App\\Enum\\DatumTypeEnum::TYPE_FILE'), constant('App\\Enum\\DatumTypeEnum::TYPE_DATE'), constant('App\\Enum\\DatumTypeEnum::TYPE_NUMBER')])) %} + {% for key, datum in data %} {% include 'App/Datum/_datum.html.twig' with { datum: datum, iteration: key, type: datum.type, entity: 'collection', - label: datum.label + label: datum.label, + choiceList: datum.choiceList } only %} {% endfor %}
-
+ + +{% if choiceLists is defined and choiceLists is not empty %} +
+ + {% for choiceList in choiceLists %} + {{ choiceList.name }} + {% endfor %} +
+{% endif %} diff --git a/templates/App/Collection/show.html.twig b/templates/App/Collection/show.html.twig index 5c6868d63..7ed271324 100755 --- a/templates/App/Collection/show.html.twig +++ b/templates/App/Collection/show.html.twig @@ -93,20 +93,7 @@ {% for datum in collection.data %}
{{ datum.label }} : - {% if datum.type == constant('App\\Enum\\DatumTypeEnum::TYPE_TEXT') %} - {% for value in datum.value|split(',') %} - {{ underlinedTags[value|trim] is defined ? underlinedTags[value|trim]|raw : value }}{{ not loop.last ? ',' }} - {% endfor %} - {% elseif datum.type == constant('App\\Enum\\DatumTypeEnum::TYPE_NUMBER') %} - {{ datum.value }} - {% elseif datum.type == constant('App\\Enum\\DatumTypeEnum::TYPE_COUNTRY') %} - {{ getCountryFlag(datum.value) }} - ({{ getCountryName(datum.value) }}) - {% elseif datum.type == constant('App\\Enum\\DatumTypeEnum::TYPE_FILE') %} - {{ datum.originalFilename }} - {% elseif datum.type == constant('App\\Enum\\DatumTypeEnum::TYPE_DATE') %} - {{ datum.value|date(app.user.dateFormat|default('Y-m-d')) }} - {% endif %} + {{ include('App/Datum/_display_value/_' ~ datum.type ~ '.html.twig', {'datum': datum}) }}
{% endfor %}