Ajout du renommage des fichiers/dossiers + fix urls quand sous dossiers + ajout création de dossiers

This commit is contained in:
Melaine Gérard 2025-01-11 19:25:42 +01:00
parent 7c574fc9a5
commit 327c354ac4
8 changed files with 225 additions and 15 deletions

View File

@ -2,19 +2,19 @@
namespace App\Controller; namespace App\Controller;
use App\Form\CreateDirectoryType;
use App\Form\RenameType;
use League\Flysystem\Filesystem; use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException; use League\Flysystem\FilesystemException;
use League\Flysystem\FilesystemReader;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Attribute\MapQueryParameter; use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;
use Symfony\Component\HttpKernel\Attribute\MapUploadedFile;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/files', 'app_files_')] #[Route('/files', 'app_files_')]
@ -38,7 +38,8 @@ class FilesController extends AbstractController
$realFiles = []; $realFiles = [];
foreach ($files as $file) { foreach ($files as $file) {
if (!str_starts_with($file['path'], '.')) { $filename = basename($file['path']);
if (!str_starts_with($filename, '.')) {
$realFiles[] = [ $realFiles[] = [
'type' => $file['type'], 'type' => $file['type'],
'path' => $file['path'], 'path' => $file['path'],
@ -46,7 +47,7 @@ class FilesController extends AbstractController
'size' => $file['fileSize'] ?? null, 'size' => $file['fileSize'] ?? null,
'url' => $file['type'] === 'file' 'url' => $file['type'] === 'file'
? $this->generateUrl('app_files_app_file_proxy', ['filename' => $file['path']], UrlGeneratorInterface::ABSOLUTE_URL) ? $this->generateUrl('app_files_app_file_proxy', ['filename' => $file['path']], UrlGeneratorInterface::ABSOLUTE_URL)
: $this->generateUrl('app_files_index', ['path' => $path . '/' . $file['path']]), : $this->generateUrl('app_files_index', ['path' => $file['path']]),
]; ];
} }
} }
@ -99,7 +100,7 @@ class FilesController extends AbstractController
{ {
$file = $this->normalizePath($filename); $file = $this->normalizePath($filename);
if ($file !== '' && $defaultAdapter->fileExists($file)) { if ($file !== '' && !str_starts_with($file, '.') && $defaultAdapter->fileExists($file)) {
$defaultAdapter->delete($file); $defaultAdapter->delete($file);
$this->addFlash('success', 'Le fichier a bien été supprimé.'); $this->addFlash('success', 'Le fichier a bien été supprimé.');
@ -119,7 +120,7 @@ class FilesController extends AbstractController
$path = $this->normalizePath($path); $path = $this->normalizePath($path);
if ($path !== '' && $defaultAdapter->directoryExists($path)) { if ($path !== '' && !str_starts_with($path, '.') && $defaultAdapter->directoryExists($path)) {
$defaultAdapter->deleteDirectory($path); $defaultAdapter->deleteDirectory($path);
$this->addFlash('success', 'Le dossier a bien été supprimé.'); $this->addFlash('success', 'Le dossier a bien été supprimé.');
@ -130,6 +131,124 @@ class FilesController extends AbstractController
return $this->redirectToRoute('app_files_index'); return $this->redirectToRoute('app_files_index');
} }
/**
* @throws FilesystemException
*/
#[Route('/rename', name: 'rename')]
public function rename(#[MapQueryParameter('path')] string $filepath, Request $request, Filesystem $defaultAdapter): Response
{
$filepath = $this->normalizePath($filepath);
if ($filepath === '' || str_starts_with($filepath, '.') || !$defaultAdapter->fileExists($filepath)) {
throw $this->createNotFoundException("Ce fichier n'existe pas !");
}
$data = [
'newName' => pathinfo($filepath, PATHINFO_BASENAME),
];
$form = $this->createForm(RenameType::class, $data);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$newName = $data['newName'];
$newPath = dirname($filepath) . '/' . $newName;
$defaultAdapter->move($filepath, $newPath);
$this->addFlash('success', 'Le fichier a bien été renommé.');
return $this->redirectToRoute('app_files_index', [
'path' => dirname($filepath),
]);
}
return $this->render('files/rename.html.twig', [
'form' => $form->createView(),
'filepath' => $filepath,
'type' => 'fichier',
]);
}
/**
* @throws FilesystemException
*/
#[Route('/create-directory', name: 'create_directory')]
public function createDirectory(Request $request, Filesystem $defaultAdapter, #[MapQueryParameter('base')] string $basePath): Response
{
$basePath = $this->normalizePath($basePath);
$form = $this->createForm(CreateDirectoryType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$name = $data['name'];
$defaultAdapter->createDirectory($basePath . '/' . $name);
$defaultAdapter->write($basePath . '/' . $name . '/.gitkeep', '');
$this->addFlash('success', 'Le dossier a bien été créé.');
return $this->redirectToRoute('app_files_index', [
'path' => $basePath,
]);
}
return $this->render('files/create_directory.html.twig', [
'form' => $form->createView(),
'basePath' => $basePath,
]);
}
/**
* @throws FilesystemException
*/
#[Route('/rename-directory', name: 'rename-directory')]
public function renameDirectory(#[MapQueryParameter('path')] string $filepath, Request $request, Filesystem $defaultAdapter): Response
{
$filepath = $this->normalizePath($filepath);
if ($filepath === '' || str_starts_with($filepath, '.') || !$defaultAdapter->directoryExists($filepath)) {
throw $this->createNotFoundException("Ce dossier n'existe pas !");
}
$data = [
'newName' => pathinfo($filepath, PATHINFO_BASENAME),
];
$form = $this->createForm(RenameType::class, $data);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$newName = $data['newName'];
$newPath = dirname($filepath) . '/' . $newName;
$defaultAdapter->move($filepath, $newPath);
$this->addFlash('success', 'Le dossier a bien été renommé.');
return $this->redirectToRoute('app_files_index', [
'path' => dirname($filepath),
]);
}
return $this->render('files/rename.html.twig', [
'form' => $form->createView(),
'filepath' => $filepath,
'type' => 'dossier',
]);
}
private function normalizePath(string $path): string private function normalizePath(string $path): string
{ {
// On retire les slashs en début et fin de chaîne // On retire les slashs en début et fin de chaîne

View File

@ -0,0 +1,22 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
class CreateDirectoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', null, [
'label' => 'Nom du dossier',
])
->add('submit', SubmitType::class, [
'label' => 'Créer',
])
;
}
}

29
src/Form/RenameType.php Normal file
View File

@ -0,0 +1,29 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RenameType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('newName', null, [
'label' => 'Nouveau nom',
])
->add('submit', SubmitType::class, [
'label' => 'Renommer',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
]);
}
}

View File

@ -0,0 +1,15 @@
{% extends 'base.html.twig' %}
{% block body %}
<div class="container mx-auto px-16 mt-4">
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h3 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Créer un dossier dans /{{ basePath }}</h3>
{{ form(form) }}
</div>
</div>
{% endblock %}
{% block title %}
Créer un dossier
{% endblock %}

View File

@ -8,6 +8,11 @@
<div class="mt-4"> <div class="mt-4">
{{ include('partials/alerts.html.twig') }} {{ include('partials/alerts.html.twig') }}
</div> </div>
<div class="flex justify-end">
<a href="{{ path('app_files_create_directory', {
base: path
}) }}" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Créer un dossier</a>
</div>
<div class="mt-4"> <div class="mt-4">
{% include 'partials/breadbrumb.html.twig' %} {% include 'partials/breadbrumb.html.twig' %}
</div> </div>
@ -51,19 +56,22 @@
</td> </td>
<td class="px-6 py-4 flex gap-2 light:text-black"> <td class="px-6 py-4 flex gap-2 light:text-black">
{% if file.type == 'file' %} {% if file.type == 'file' %}
<a href="{{ file.url }}" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:download" /></a> <a title="Permet de télécharger le fichier" href="{{ file.url }}" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:download" /></a>
<a href="#" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:pencil" /></a> <a title="Permet de renommer le fichier" href="{{ path('app_files_rename', {
<a href="{{ path: file.path
}) }}" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:pencil" /></a>
<a title="Permet de supprimer le fichier" href="{{
path('app_files_delete', { path('app_files_delete', {
filename: file.path filename: file.path
}) })
}}" class="hover:text-red-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:trash-can" /></a> }}" class="hover:text-red-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:trash-can" /></a>
{% else %} {% else %}
<a href="{{ file.url }}" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:link" /></a> <a href="{{ path('app_files_rename-directory', {
<a href="#" class="hover:text-blue-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:pencil" /></a> path: file.path
}) }}" class="hover:text-blue-700 duration-300" title="Permet de renommer le dossier"><twig:ux:icon class="w-6 h-6" name="fa6-solid:pencil" /></a>
<a href="{{ path('app_files_delete_directory', { <a href="{{ path('app_files_delete_directory', {
path: file.path path: file.path
}) }}" class="hover:text-red-700 duration-300"><twig:ux:icon class="w-6 h-6" name="fa6-solid:trash-can" /></a> }) }}" class="hover:text-red-700 duration-300" title="Permet de supprimer le dossier"><twig:ux:icon class="w-6 h-6" name="fa6-solid:trash-can" /></a>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>

View File

@ -0,0 +1,15 @@
{% extends 'base.html.twig' %}
{% block body %}
<div class="container mx-auto px-16 mt-4">
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h3 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Renommer le {{ type }} {{ filepath }}</h3>
{{ form(form) }}
</div>
</div>
{% endblock %}
{% block title %}
Renommer un {{ type }}
{% endblock %}

View File

@ -8,7 +8,9 @@
</li> </li>
{% if path != '' %} {% if path != '' %}
{% set pathSplitted = path|split('/') %} {% set pathSplitted = path|split('/') %}
{% set base = '' %}
{% for pa in pathSplitted %} {% for pa in pathSplitted %}
{% set base = base ~ '/' ~ pa %}
{% if loop.last %} {% if loop.last %}
<li aria-current="page"> <li aria-current="page">
<div class="flex items-center"> <div class="flex items-center">
@ -22,7 +24,7 @@
<div class="flex items-center"> <div class="flex items-center">
<twig:ux:icon class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1" <twig:ux:icon class="rtl:rotate-180 w-3 h-3 text-gray-400 mx-1"
name="fa6-solid:chevron-right"/> name="fa6-solid:chevron-right"/>
<a href="#" <a href="{{ path('app_files_index', {path: base}) }}"
class="ms-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ms-2 dark:text-gray-400 dark:hover:text-white">{{ pa }}</a> class="ms-1 text-sm font-medium text-gray-700 hover:text-blue-600 md:ms-2 dark:text-gray-400 dark:hover:text-white">{{ pa }}</a>
</div> </div>
</li> </li>

0
uploads/.gitkeep Normal file
View File