nineskeletor/src/Controller/FileController.php

722 lines
28 KiB
PHP

<?php
namespace App\Controller;
use App\Service\MinioService;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
class FileController extends AbstractController
{
private $minio;
public function __construct(MinioService $minio)
{
$this->minio = $minio;
}
public function list($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
// Récupération des paramètres
$folder = $request->query->get('folder');
$usage = $request->query->get('usage');
$view = $request->get('view');
$sort = $request->get('sort');
$order = $request->get('order');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
// Récupérer les files icons
$tbicons = json_decode(file_get_contents($this->getParameter('kernel.project_dir').'/public/medias/file/files.json'), true);
// Récupérer les préférences utilisateur
if (!$this->getUser()) {
$preference['widgetfolder'][$id] = ['folder' => null, 'sort' => null, 'order' => null, 'view' => null];
} else {
$preference = $this->getUser()->getPreference();
if (is_null($preference)) {
$preference = [];
}
// Initalisation des préférences si aucune
if (!array_key_exists('widgetfolder', $preference) || !array_key_exists($id, $preference['widgetfolder'])) {
$preference['widgetfolder'][$id] = ['folder' => null, 'sort' => null, 'order' => null, 'view' => null];
}
}
// Si aucun folder on récupére la preference
if (!$folder && $preference['widgetfolder'][$id]['folder']) {
$folder = $preference['widgetfolder'][$id]['folder'];
}
// On s'assure que le folder existe toujours
if ($folder && 0 == $this->minio->countKeys($folder)) {
$folder = null;
}
// On s'assure qu'il est bien dans le folder de base
if (false === stripos($folder, 'file/pagewidget/'.$id.'/')) {
$folder = null;
}
// Si pas de folder on est sur la racine
if (!$folder) {
$folder = 'file/pagewidget/'.$id.'/';
}
// Trie
if (!$order) {
$order = $preference['widgetfolder'][$id]['order'];
}
if (!$order) {
$order = 'SORT_ASC';
}
if (!$sort) {
$sort = $preference['widgetfolder'][$id]['sort'];
}
if (!$sort) {
$sort = 'name';
}
// View
if (!$view) {
$view = $preference['widgetfolder'][$id]['view'];
}
// Récuperer les files et folders du folder en cours
$files = $this->minio->listFiles($folder, '/');
$folders = $this->minio->listFolders($folder, '/');
// Ajouter basename et thumb des entrées récupérées
if ($files) {
foreach ($files as $key => $value) {
if ('.dir' == pathinfo($value['Key'], PATHINFO_BASENAME)) {
unset($files[$key]);
continue;
}
$files[$key]['basename'] = pathinfo($value['Key'], PATHINFO_BASENAME);
$files[$key]['dirname'] = pathinfo($value['Key'], PATHINFO_DIRNAME);
$files[$key]['extention'] = pathinfo($value['Key'], PATHINFO_EXTENSION);
// thumb ?
if (1 == $this->minio->countKeys($files[$key]['dirname'].'/.thumb/'.$files[$key]['basename'])) {
$files[$key]['thumb'] = $this->generateUrl('app_minio_image', ['file' => $files[$key]['dirname'].'/.thumb/'.$files[$key]['basename']]);
}
// file icon ?
elseif (array_key_exists($files[$key]['extention'], $tbicons)) {
$files[$key]['thumb'] = $tbicons[$files[$key]['extention']];
}
// blank file icon
else {
$files[$key]['thumb'] = $tbicons['blank'];
}
}
$filesdate = array_column($files, 'LastModified');
$filesname = array_column($files, 'basename');
switch ($sort) {
case 'name':
array_multisort($filesname, 'SORT_ASC' == $order ? SORT_ASC : SORT_DESC, $files);
break;
case 'date':
array_multisort($filesdate, 'SORT_ASC' == $order ? SORT_ASC : SORT_DESC, $files);
break;
}
}
if ($folders) {
foreach ($folders as $key => $value) {
if ('.thumb' == pathinfo($value['Prefix'], PATHINFO_BASENAME) || '.trash' == pathinfo($value['Prefix'], PATHINFO_BASENAME)) {
unset($folders[$key]);
continue;
}
$folders[$key]['basename'] = pathinfo($value['Prefix'], PATHINFO_BASENAME);
$folders[$key]['thumb'] = $tbicons['dir'];
}
$foldersname = array_column($folders, 'basename');
array_multisort($foldersname, 'SORT_ASC' == $order ? SORT_ASC : SORT_DESC, $folders);
}
// Mise à jour des préférences
$preference['widgetfolder'][$id] = ['folder' => $folder, 'sort' => $sort, 'order' => $order, 'view' => $view];
if ($this->getUser()) {
$this->getUser()->setPreference($preference);
$em->getManager()->flush();
}
// Construction de la navigation des folers
$basefolder = 'file/pagewidget/'.$id;
$parents = [['basename' => 'Home', 'folder' => $basefolder.'/']];
$tmp = explode('/', $folder);
unset($tmp[0]);
unset($tmp[1]);
unset($tmp[2]);
array_pop($tmp);
foreach ($tmp as $value) {
$basefolder = $basefolder.'/'.$value;
array_push($parents, ['basename' => $value, 'folder' => $basefolder.'/']);
}
// Flag poubelle
$fgtrash = false;
if (stripos($folder, '.trash') >= 1) {
$fgtrash = true;
}
return $this->render('File\list.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'access' => $access,
'category' => $category,
'id' => $id,
'folder' => $folder,
'usage' => $usage,
'view' => $view,
'sort' => $sort,
'order' => $order,
'canadd' => $canadd,
'fgtrash' => $fgtrash,
'parents' => $parents,
'folders' => $folders,
'files' => $files,
]);
}
public function upload($access, $category, $id, $type, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$folder = urldecode($request->get('folder'));
if (!$folder) {
$folder = 'file/'.$category.'/'.$id.'/';
}
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($folder, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
return $this->render('File\upload.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'maxsize' => ('all' == $access ? 1200 : null),
'access' => $access,
'category' => $category,
'id' => $id,
'type' => $type,
'folder' => $folder,
'forcereload' => ('pagewidget' == $category),
]);
}
public function folder($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$infolder = $usage = $request->query->get('folder');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($infolder, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
$folder = $request->get('folder');
$form = $this->createFormBuilder()
->add('folder', TextType::class, ['label' => 'Répertoire'])
->add('submit', SubmitType::class, ['label' => 'Valider', 'attr' => ['class' => 'btn btn-success']])
->getForm();
$form->handleRequest($request);
$toclose = false;
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
if ('.thumb' == $data['folder'] || '.dir' == $data['folder'] || '.trash' == $data['folder']) {
$form->addError(new FormError('Nom de répertoire réservé, merci de choisir un autre nom de répertoire'));
$request->getSession()->getFlashBag()->clear();
$request->getSession()->getFlashBag()->add('error', 'Nom de répertoire réservé, merci de choisir un autre nom de répertoire');
} else {
$filesystem = new Filesystem();
$filesystem->dumpFile($this->getParameter('kernel.project_dir').'/var/tmp/.dir', '');
$this->minio->upload($this->getParameter('kernel.project_dir').'/var/tmp/.dir', $infolder.$data['folder'].'/.dir');
$toclose = true;
}
}
return $this->render('File\folder.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'access' => $access,
'id' => $id,
'folder' => $folder,
'form' => $form->createView(),
'toclose' => $toclose,
]);
}
public function rename($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$oldfile = $usage = $request->query->get('file');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($oldfile, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
$form = $this->createFormBuilder()
->add('folder', TextType::class, ['label' => 'Renommer'])
->add('submit', SubmitType::class, ['label' => 'Valider', 'attr' => ['class' => 'btn btn-success']])
->getForm();
$form->handleRequest($request);
$toclose = false;
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
if ('.thumb' == $data['folder'] || '.dir' == $data['folder'] || '.trash' == $data['folder']) {
$form->addError(new FormError('Nom réservé, merci de choisir un autre nom'));
$this->get('session')->getFlashBag()->clear();
$request->getSession()->getFlashBag()->add('error', 'Nom réservé, merci de choisir un autre nom');
} else {
$newfile = pathinfo($oldfile, PATHINFO_DIRNAME).'/'.$data['folder'];
if ('/' == substr($oldfile, -1)) {
$newfile = $newfile.'/';
}
$files = $this->minio->listFiles($oldfile);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
// Déplacer le fichier dans .trash
try {
$this->minio->move($file, str_replace($oldfile, $newfile, $file), true);
} catch (\Exception $e) {
}
// Déplacer le thumb dans .trash
try {
$oldthumb = pathinfo($oldfile, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($oldfile, PATHINFO_BASENAME);
$newthumb = pathinfo($newfile, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($newfile, PATHINFO_BASENAME);
$this->minio->move($oldthumb, $newthumb, true);
} catch (\Exception $e) {
}
}
$toclose = true;
}
} else {
$form->get('folder')->setData(basename($oldfile));
}
return $this->render('File\folder.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'access' => $access,
'id' => $id,
'folder' => $oldfile,
'form' => $form->createView(),
'toclose' => $toclose,
]);
}
public function trash($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$file = $usage = $request->query->get('file');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($file, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
$files = $this->minio->listFiles($file);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
// Déplacer le fichier dans .trash
try {
$this->minio->move($file, str_replace($basefolder, $basefolder.'.trash/', $file), true);
} catch (\Exception $e) {
}
// Déplacer le thumb dans .trash
try {
$thumb = pathinfo($file, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($file, PATHINFO_BASENAME);
$this->minio->move($thumb, str_replace($basefolder, $basefolder.'.trash/', $thumb), true);
} catch (\Exception $e) {
}
}
return new JsonResponse();
}
public function restaure($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$file = $usage = $request->query->get('file');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($file, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
$files = $this->minio->listFiles($file);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
// Déplacer le fichier de .trash vers sa cible d'origine
try {
$this->minio->move($file, str_replace('/.trash/', '/', $file), true);
} catch (\Exception $e) {
}
// Déplacer le thumb dans .trash
try {
$thumb = pathinfo($file, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($file, PATHINFO_BASENAME);
$this->minio->move($thumb, str_replace('/.trash/', '/', $thumb), true);
} catch (\Exception $e) {
}
}
return new JsonResponse();
}
public function purgetrash($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/.trash';
$files = $this->minio->listFiles($basefolder);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
try {
$this->minio->delete($file);
} catch (\Exception $e) {
}
}
return $this->redirectToRoute('app_'.$access.'_file_list', ['category' => $category, 'id' => $id]);
}
public function delete($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$file = $usage = $request->query->get('file');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($file, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
// Si en mode naviation rechercher le prochain fichier à afficher
if (!$request->isXmlHttpRequest()) {
$files = $this->minio->listFiles(dirname($file).'/', '/');
dump($files);
if ($files) {
$basename = basename($file);
$date = array_column($files, 'LastModified');
array_multisort($date, SORT_DESC, $files);
foreach ($files as $key => $tbfile) {
if ($basename == basename($tbfile['Key'])) {
$next = (array_key_exists($key + 1, $files) ? $files[$key + 1] : $files[0]);
if ($next['Key'] == $file) {
unset($next);
}
}
}
}
}
$files = $this->minio->listFiles($file);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
// Supprimer le fichier
try {
$this->minio->delete($file);
} catch (\Exception $e) {
}
// Supprimer le thumb
try {
$thumb = pathinfo($file, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($file, PATHINFO_BASENAME);
$this->minio->delete($thumb);
} catch (\Exception $e) {
}
}
// Appel ajax
if ($request->isXmlHttpRequest()) {
return new JsonResponse();
} else {
if (isset($next)) {
return $this->redirectToRoute(str_replace('_admin_', '_'.$access.'_', 'app_admin_file_view'), ['category' => $category, 'id' => $id, 'usage' => $usage, 'file' => $next['Key']]);
} else {
return $this->render('File\redirect.html.twig');
}
}
}
public function move($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$usage = $request->query->get('usage');
$source = $usage = $request->query->get('source');
$destination = $usage = $request->query->get('destination');
// Permission
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
if (!$canadd) {
throw $this->createAccessDeniedException('Permission denied');
}
$basefolder = 'file/'.$category.'/'.$id.'/';
if (false === stripos($source, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
if (false === stripos($destination, $basefolder)) {
throw $this->createAccessDeniedException('Permission denied');
}
$isdirdest = false;
if ('/' == substr($source, -1)) {
$isdirdest = true;
$destination = $destination.basename($source).'/';
// On ne peut déplacer un répertoire vers un répertoire enfant
if (0 === stripos($destination, $source)) {
return new JsonResponse();
}
}
$files = $this->minio->listFiles($source);
foreach ($files as $tbfile) {
$file = $tbfile['Key'];
if ($isdirdest) {
$dest = str_replace($source, $destination, $file);
} else {
$dest = str_replace(pathinfo($source, PATHINFO_DIRNAME).'/', $destination, $file);
}
// Déplacer le fichier
try {
$this->minio->move($file, $dest, true);
} catch (\Exception $e) {
}
// Thumb
if (!$isdirdest) {
$oldthumb = pathinfo($source, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($source, PATHINFO_BASENAME);
$newthumb = pathinfo($dest, PATHINFO_DIRNAME).'/.thumb/'.pathinfo($dest, PATHINFO_BASENAME);
// Déplacer le thumb
try {
$this->minio->move($oldthumb, $newthumb, true);
} catch (\Exception $e) {
}
}
}
exit;
return new JsonResponse();
}
public function view($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$file = $request->query->get('file');
$basename = basename($file);
$path = dirname($file);
$usage = $request->query->get('usage');
$navigation = boolval($request->query->get('navigation'));
$canadd = $this->getPermission($em, $access, $category, $id, $usage);
// Si en mode navigation on recherche le fichier précédent ou suivant
$next = [];
$prev = [];
if ($navigation) {
$files = $this->minio->listFiles($path.'/', '/');
if ($files) {
$date = array_column($files, 'LastModified');
array_multisort($date, SORT_DESC, $files);
foreach ($files as $key => $value) {
if ($basename == basename($value['Key'])) {
$next = (array_key_exists($key + 1, $files) ? $files[$key + 1] : $files[0]);
$prev = (array_key_exists($key - 1, $files) ? $files[$key - 1] : end($files));
}
}
}
}
$tmpfile = $this->minio->download($file, basename($file));
if (str_starts_with(mime_content_type($tmpfile), 'image/') || 'application/pdf' == mime_content_type($tmpfile) || 'text/plain' == mime_content_type($tmpfile)) {
return $this->render('File\view.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'access' => $access,
'category' => $category,
'id' => $id,
'usage' => $usage,
'navigation' => $navigation,
'file' => $file,
'basename' => basename($file),
'canadd' => $canadd,
'prev' => $prev,
'next' => $next,
'isimage' => str_starts_with(mime_content_type($tmpfile), 'image/'),
]);
} else {
$response = new BinaryFileResponse($tmpfile);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, basename($file));
return $response;
}
}
public function show($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$file = $request->query->get('file');
$usage = $request->query->get('usage');
$this->getPermission($em, $access, $category, $id, $usage);
$tmpfile = $this->minio->download($file, basename($file));
if (str_starts_with(mime_content_type($tmpfile), 'image/') || 'application/pdf' == mime_content_type($tmpfile) || 'text/plain' == mime_content_type($tmpfile)) {
$response = new BinaryFileResponse($tmpfile);
$response->headers->set('Content-Type', mime_content_type($tmpfile));
} else {
$response = new BinaryFileResponse($tmpfile);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, basename($file));
}
return $response;
}
public function download($access, $category, $id, Request $request, ManagerRegistry $em): Response
{
$file = $request->query->get('file');
$usage = $request->query->get('usage');
$this->getPermission($em, $access, $category, $id, $usage);
$tmpfile = $this->minio->download($file, basename($file));
$response = new BinaryFileResponse($tmpfile);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, basename($file));
return $response;
}
public function getPermission($em, $access, $category, $id, $usage = '')
{
if ('all' == $access) {
switch ($category) {
case 'pagewidget':
// Récupération du widget
$pagewidget = $em->getRepository("App\Entity\Pagewidget")->find($id);
// Vérifier que l'on peut voir
if ('all' == $access) {
if (!$em->getRepository("App\Entity\Pagewidget")->getCansee($this->getUser(), $pagewidget)) {
throw $this->createAccessDeniedException('Permission denied');
}
}
// Retourner la permission d'ajout
return $em->getRepository("App\Entity\Pagewidget")->getCanadd($this->getUser(), $pagewidget, $usage);
break;
case 'projecttask':
// Récupération de la tache
$projecttask = $em->getRepository('CadolesPortalBundle:Projecttask')->find($id);
if (!$projecttask) {
throw $this->createNotFoundException('Unable to find entity.');
}
// On s'assure que l'utilisateur à la permission de voir
$project = $projecttask->getProject();
$user = $this->getUser();
$em->getRepository('CadolesPortalBundle:Project')->getPermission($user, $project, $cansee, $canupdate, $canadd);
if (!$cansee) {
throw $this->createAccessDeniedException('Permission denied');
}
return $canupdate;
break;
case 'calendarevent':
// Récupération de l'event'
$calendarevent = $em->getRepository('CadolesPortalBundle:Calendarevent')->find($id);
if (!$calendarevent) {
throw $this->createNotFoundException('Unable to find entity.');
}
// On s'assure que l'utilisateur à la permission de voir
$calendar = $calendarevent->getCalendar();
$user = $this->getUser();
$em->getRepository('CadolesPortalBundle:Calendar')->getPermission($user, $calendar, $cansee, $canupdate, $canadd);
if (!$cansee) {
throw $this->createAccessDeniedException('Permission denied');
}
return $canadd;
break;
}
} else {
return true;
}
}
}