From 2467082a585f952088cec3e7188df4f42945ea5c Mon Sep 17 00:00:00 2001 From: Sebastian Castro <sebastian.castro@protonmail.com> Date: Fri, 7 May 2021 13:38:29 +0200 Subject: [PATCH] files: ability to upload and manage files --- config/packages/vich_uploader.yaml | 28 +----------- config/services.yaml | 12 ++++++ src/Admin/FileAdmin.php | 44 +++++++++++++++++++ src/Document/AbstractFile.php | 10 ++++- src/Document/EmbeddedImage.php | 2 +- src/Document/File.php | 62 +++++++++++++++++++++++++++ src/Services/UploadDirectoryNamer.php | 11 ++--- src/Services/UploadFileNamer.php | 27 ++++++++++++ translations/admin+intl-icu.fr.yaml | 13 ++++++ 9 files changed, 174 insertions(+), 35 deletions(-) create mode 100644 src/Admin/FileAdmin.php create mode 100755 src/Document/File.php create mode 100755 src/Services/UploadFileNamer.php diff --git a/config/packages/vich_uploader.yaml b/config/packages/vich_uploader.yaml index 6d5709c7d..dcf635fa7 100755 --- a/config/packages/vich_uploader.yaml +++ b/config/packages/vich_uploader.yaml @@ -4,31 +4,5 @@ vich_uploader: default_file: upload_destination: '%kernel.root_dir%/../web' directory_namer: App\Services\UploadDirectoryNamer - namer: vich_uploader.namer_origname - import_file: - upload_destination: '%kernel.root_dir%/../web' - directory_namer: App\Services\UploadDirectoryNamer - image: - upload_destination: '%kernel.root_dir%/../web' - # inject_on_load: true - directory_namer: App\Services\UploadDirectoryNamer - namer: vich_uploader.namer_origname - element_image: - upload_destination: '%kernel.root_dir%/../web' - directory_namer: App\Services\UploadDirectoryNamer - namer: vich_uploader.namer_origname - delete_on_remove: true - element_file: - upload_destination: '%kernel.root_dir%/../web' - directory_namer: App\Services\UploadDirectoryNamer - namer: vich_uploader.namer_origname - delete_on_remove: true - partner_image: - upload_destination: '%kernel.root_dir%/../web' - directory_namer: App\Services\UploadDirectoryNamer - namer: ~ - config_image: - upload_destination: '%kernel.root_dir%/../web' - directory_namer: App\Services\UploadDirectoryNamer - namer: ~ + namer: App\Services\UploadFileNamer # if you add new image class, don't forget to add the relevant service in services_admin.yml \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index f312cd9ee..6e85e3dfd 100755 --- a/config/services.yaml +++ b/config/services.yaml @@ -35,6 +35,11 @@ services: public: true arguments: [] + App\Services\UploadFileNamer: + class: App\Services\UploadFileNamer + public: true + arguments: [] + App\Services\AsyncService: arguments: $rootDir: '%kernel.root_dir%' @@ -167,6 +172,13 @@ services: tags: - { name: sonata.admin, manager_type: doctrine_mongodb, group: "contents", label: abouts._label } + admin.files: + class: App\Admin\FileAdmin + arguments: [~, App\Document\File, ''] + calls: [ [ setGoGoTranslator, ['@translator'] ] ] + tags: + - { name: sonata.admin, manager_type: doctrine_mongodb, group: "contents", label: files._label } + # --------- CONFIGURATION ----------- diff --git a/src/Admin/FileAdmin.php b/src/Admin/FileAdmin.php new file mode 100644 index 000000000..059e75dc5 --- /dev/null +++ b/src/Admin/FileAdmin.php @@ -0,0 +1,44 @@ +<?php + +namespace App\Admin; + +use Sonata\AdminBundle\Datagrid\DatagridMapper; +use Sonata\AdminBundle\Datagrid\ListMapper; +use Sonata\AdminBundle\Form\FormMapper; +use Symfony\Component\Form\Extension\Core\Type\FileType; + +class FileAdmin extends GoGoAbstractAdmin +{ + protected $datagridValues = [ + '_page' => 1, + '_sort_order' => 'DESC', + '_sort_by' => 'updatedAt', + ]; + + protected function configureFormFields(FormMapper $formMapper) + { + $disable = $this->getSubject()->getId(); + $formMapper + ->add('file', FileType::class) + ->add('fileName', null, ['disabled' => $disable]) + ->add('customDirectory', null, ['disabled' => $disable]) + ; + } + + protected function configureDatagridFilters(DatagridMapper $datagridMapper) + { + $datagridMapper->add('fileName'); + } + + protected function configureListFields(ListMapper $listMapper) + { + $listMapper + ->addIdentifier('fileName') + ->add('fileUrl') + ->add('_action', 'actions', [ + 'actions' => [ + 'delete' => [], + ], + ]); + } +} diff --git a/src/Document/AbstractFile.php b/src/Document/AbstractFile.php index 489be30b3..b22d1d48b 100755 --- a/src/Document/AbstractFile.php +++ b/src/Document/AbstractFile.php @@ -6,6 +6,7 @@ use App\Services\UploadDirectoryNamer; use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB; use Symfony\Component\HttpFoundation\File\UploadedFile; use Vich\UploaderBundle\Mapping\Annotation as Vich; +use Vich\UploaderBundle\Mapping\PropertyMapping; /** * Represent a common File. Need to be extended by real Document @@ -44,7 +45,7 @@ class AbstractFile implements \Serializable public function __toString() { - return $this->getFileUrl(); + return $this->getFileName(); } /** @@ -129,7 +130,7 @@ class AbstractFile implements \Serializable global $kernel; $container = $kernel->getContainer(); $uploadDirHelper = $container->get(UploadDirectoryNamer::class); - $filePath = $uploadDirHelper->getDirectoryPathFromKey($this->vichUploadFileKey).'/'.$this->fileName; + $filePath = $uploadDirHelper->getDirectoryPath($this).'/'.$this->fileName; if ($suffix) { return preg_replace( '/(\.jpe?g|\.png)$/', @@ -156,6 +157,11 @@ class AbstractFile implements \Serializable return $url; } + public function getCustomDirectory() + { + return ''; + } + public function getFile() { return $this->file; diff --git a/src/Document/EmbeddedImage.php b/src/Document/EmbeddedImage.php index 408f7d37d..e90bc1b34 100755 --- a/src/Document/EmbeddedImage.php +++ b/src/Document/EmbeddedImage.php @@ -22,7 +22,7 @@ class EmbeddedImage extends AbstractFile public function __toString() { - return $this->getImageUrl(); + return $this->isExternalFile() ? $this->getExternalImageUrl() : $this->getFileName(); } public function toJson() diff --git a/src/Document/File.php b/src/Document/File.php new file mode 100755 index 000000000..b856afb09 --- /dev/null +++ b/src/Document/File.php @@ -0,0 +1,62 @@ +<?php + +namespace App\Document; + +use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB; +use Vich\UploaderBundle\Mapping\Annotation as Vich; + +/** + * @MongoDB\Document + * @Vich\Uploadable + */ +class File extends AbstractFile +{ + /** + * @var int + * + * @MongoDB\Id(strategy="INCREMENT") + */ + private $id; + + /** @MongoDB\Field(type="string") */ + private $customDirectory = ''; + + protected $vichUploadFileKey = 'general_file'; + + /** + * Get the value of customDirectory + */ + public function getCustomDirectory() + { + return $this->customDirectory; + } + + public function setFileName($fileName) + { + // Prevent resetting fileName to null, so we can edit the file without changing fileName + if ($fileName) $this->fileName = $fileName; + return $this; + } + + /** + * Set the value of customDirectory + * + * @return self + */ + public function setCustomDirectory($customDirectory) + { + $this->customDirectory = $customDirectory; + + return $this; + } + + /** + * Get the value of id + * + * @return int + */ + public function getId() + { + return $this->id; + } +} diff --git a/src/Services/UploadDirectoryNamer.php b/src/Services/UploadDirectoryNamer.php index 000c882db..38ad63fec 100755 --- a/src/Services/UploadDirectoryNamer.php +++ b/src/Services/UploadDirectoryNamer.php @@ -22,6 +22,7 @@ class UploadDirectoryNamer implements DirectoryNamerInterface 'partner_image' => '/images/partners', 'config_image' => '/images/config', 'import_file' => '/imports', + 'general_file' => '/files', 'default_file' => '/default', ]; @@ -32,13 +33,13 @@ class UploadDirectoryNamer implements DirectoryNamerInterface public function directoryName($object, PropertyMapping $mapping): string { - $name = $this->getDirectoryPathFromKey($object->getVichUploadFileKey()); - - return $name; + return $this->getDirectoryPath($object); } - public function getDirectoryPathFromKey($key) + public function getDirectoryPath($object) { - return $this->BASE_PATH . $this->dmFactory->getCurrentDbName() . $this->PATHS[$key]; + $path = $this->BASE_PATH . $this->dmFactory->getCurrentDbName() . $this->PATHS[$object->getVichUploadFileKey()]; + $path .= $object->getCustomDirectory(); + return $path; } } diff --git a/src/Services/UploadFileNamer.php b/src/Services/UploadFileNamer.php new file mode 100755 index 000000000..840968977 --- /dev/null +++ b/src/Services/UploadFileNamer.php @@ -0,0 +1,27 @@ +<?php + +namespace App\Services; + +use Vich\UploaderBundle\Mapping\PropertyMapping; +use Vich\UploaderBundle\Naming\NamerInterface; +use Vich\UploaderBundle\Util\Transliterator; + +/** + * Directory namer wich can create subfolder depends on generated filename. + * + * @author Konstantin Myakshin <koc-dp@yandex.ru> + */ +class UploadFileNamer implements NamerInterface +{ + public function name($object, PropertyMapping $mapping): string + { + if ($object->getFileName()) return $object->getFileName(); + + $file = $mapping->getFile($object); + $name = $file->getClientOriginalName(); + + $name = Transliterator::transliterate($name); + + return $name; + } +} diff --git a/translations/admin+intl-icu.fr.yaml b/translations/admin+intl-icu.fr.yaml index 92ee1edef..0ec1f1dd2 100755 --- a/translations/admin+intl-icu.fr.yaml +++ b/translations/admin+intl-icu.fr.yaml @@ -643,6 +643,19 @@ duplicates: merge: "Fusionnez les doublons" wantMore: "J'en veux encore ! (Plus que {count} doublons à traiter)" +files: + _label: Uploader des fichiers + fields: + file: Fichier + fileName: Nom du fichier + fileUrl: Url + form: + fileName: Changer le nom du fichier (optionel) + fileName_placeholder: "nouveau_nom.png" + customDirectory: Changer le répertoire d'upload + customDirectory_help: Dans certains cas, par l'exemple pour l'upload d'une police d'icones, vous devez respecter une arborescence de fichier précise (le fichier CSS à la racine, et les fichiers polices dans un répertoire fonts par exemple) + customDirectory_placeholder: "/fonts" + categories: _label: "Catégories" list: -- GitLab