vendor/artgris/filemanager-bundle/Controller/ManagerController.php line 322

Open in your IDE?
  1. <?php
  2. namespace Artgris\Bundle\FileManagerBundle\Controller;
  3. use Artgris\Bundle\FileManagerBundle\Event\FileManagerEvents;
  4. use Artgris\Bundle\FileManagerBundle\Helpers\File;
  5. use Artgris\Bundle\FileManagerBundle\Helpers\FileManager;
  6. use Artgris\Bundle\FileManagerBundle\Helpers\UploadHandler;
  7. use Artgris\Bundle\FileManagerBundle\Service\FilemanagerService;
  8. use Artgris\Bundle\FileManagerBundle\Service\FileTypeService;
  9. use Artgris\Bundle\FileManagerBundle\Twig\OrderExtension;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  12. use Symfony\Component\EventDispatcher\GenericEvent;
  13. use Symfony\Component\Filesystem\Exception\IOException;
  14. use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
  15. use Symfony\Component\Filesystem\Filesystem;
  16. use Symfony\Component\Finder\Finder;
  17. use Symfony\Component\Finder\SplFileInfo;
  18. use Symfony\Component\Form\Extension\Core\Type\FormType;
  19. use Symfony\Component\Form\Extension\Core\Type\HiddenType;
  20. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  21. use Symfony\Component\Form\Extension\Core\Type\TextType;
  22. use Symfony\Component\Form\Form;
  23. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  24. use Symfony\Component\HttpFoundation\JsonResponse;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpKernel\KernelInterface;
  28. use Symfony\Component\Routing\Annotation\Route;
  29. use Symfony\Component\Validator\Constraints\NotBlank;
  30. use Symfony\Contracts\Translation\TranslatorInterface;
  31. /**
  32.  * @author Arthur Gribet <a.gribet@gmail.com>
  33.  */
  34. class ManagerController extends AbstractController
  35. {
  36.     /**
  37.      * @var FileManager
  38.      */
  39.     protected $fileManager;
  40.     /**
  41.      * @var FilemanagerService
  42.      */
  43.     private $filemanagerService;
  44.     /**
  45.      * @var KernelInterface
  46.      */
  47.     private $kernel;
  48.     /**
  49.      * @var EventDispatcherInterface
  50.      */
  51.     private $dispatcher;
  52.     /**
  53.      * @var TranslatorInterface
  54.      */
  55.     private $translator;
  56.     /**
  57.      * ManagerController constructor.
  58.      */
  59.     public function __construct(FilemanagerService $filemanagerServiceKernelInterface $kernelEventDispatcherInterface $dispatcherTranslatorInterface $translator)
  60.     {
  61.         $this->filemanagerService $filemanagerService;
  62.         $this->kernel $kernel;
  63.         $this->dispatcher $dispatcher;
  64.         $this->translator $translator;
  65.     }
  66.     /**
  67.      * @Route("/", name="file_manager")
  68.      *
  69.      * @throws \Exception
  70.      *
  71.      * @return Response
  72.      */
  73.     public function indexAction(Request $requestFileTypeService $fileTypeService)
  74.     {
  75.         $queryParameters $request->query->all();
  76.         $isJson $request->get('json') ? true false;
  77.         if ($isJson) {
  78.             unset($queryParameters['json']);
  79.         }
  80.         $fileManager $this->newFileManager($queryParameters);
  81.         // Folder search
  82.         $directoriesArbo $this->retrieveSubDirectories($fileManager$fileManager->getDirName(), \DIRECTORY_SEPARATOR$fileManager->getBaseName());
  83.         // File search
  84.         $finderFiles = new Finder();
  85.         $finderFiles->in($fileManager->getCurrentPath())->depth(0);
  86.         $regex $fileManager->getRegex();
  87.         $orderBy $fileManager->getQueryParameter('orderby');
  88.         $orderDESC OrderExtension::DESC === $fileManager->getQueryParameter('order');
  89.         if (!$orderBy) {
  90.             $finderFiles->sortByType();
  91.         }
  92.         switch ($orderBy) {
  93.             case 'name':
  94.                 $finderFiles->sort(function (SplFileInfo $aSplFileInfo $b) {
  95.                     return strcmp(mb_strtolower($b->getFilename()), mb_strtolower($a->getFilename()));
  96.                 });
  97.                 break;
  98.             case 'date':
  99.                 $finderFiles->sortByModifiedTime();
  100.                 break;
  101.             case 'size':
  102.                 $finderFiles->sort(function (\SplFileInfo $a\SplFileInfo $b) {
  103.                     return $a->getSize() - $b->getSize();
  104.                 });
  105.                 break;
  106.         }
  107.         if ($fileManager->getTree()) {
  108.             $finderFiles->files()->name($regex)->filter(function (SplFileInfo $file) {
  109.                 return $file->isReadable();
  110.             });
  111.         } else {
  112.             $finderFiles->filter(function (SplFileInfo $file) use ($regex) {
  113.                 if ('file' === $file->getType()) {
  114.                     if (preg_match($regex$file->getFilename())) {
  115.                         return $file->isReadable();
  116.                     }
  117.                     return false;
  118.                 }
  119.                 return $file->isReadable();
  120.             });
  121.         }
  122.         $this->dispatch(FileManagerEvents::POST_FILE_FILTER_CONFIGURATION, ['finder' => $finderFiles]);
  123.         $formDelete $this->createDeleteForm()->createView();
  124.         $fileArray = [];
  125.         foreach ($finderFiles as $file) {
  126.             $fileArray[] = new File($file$this->translator$fileTypeService$fileManager);
  127.         }
  128.         if ('dimension' === $orderBy) {
  129.             usort($fileArray, function (File $aFile $b) {
  130.                 $aDimension $a->getDimension();
  131.                 $bDimension $b->getDimension();
  132.                 if ($aDimension && !$bDimension) {
  133.                     return 1;
  134.                 }
  135.                 if (!$aDimension && $bDimension) {
  136.                     return -1;
  137.                 }
  138.                 if (!$aDimension && !$bDimension) {
  139.                     return 0;
  140.                 }
  141.                 return ($aDimension[0] * $aDimension[1]) - ($bDimension[0] * $bDimension[1]);
  142.             });
  143.         }
  144.         if ($orderDESC) {
  145.             $fileArray array_reverse($fileArray);
  146.         }
  147.         $parameters = [
  148.             'fileManager' => $fileManager,
  149.             'fileArray' => $fileArray,
  150.             'formDelete' => $formDelete,
  151.         ];
  152.         if ($isJson) {
  153.             $fileList $this->renderView('@ArtgrisFileManager/views/_manager_view.html.twig'$parameters);
  154.             return new JsonResponse(['data' => $fileList'badge' => $finderFiles->count(), 'treeData' => $directoriesArbo]);
  155.         }
  156.         $parameters['treeData'] = json_encode($directoriesArbo);
  157.         $form $this->get('form.factory')->createNamedBuilder('rename'FormType::class)
  158.             ->add('name'TextType::class, [
  159.                 'constraints' => [
  160.                     new NotBlank(),
  161.                 ],
  162.                 'label' => false,
  163.                 'data' => $this->translator->trans('input.default'),
  164.             ])
  165.             ->add('send'SubmitType::class, [
  166.                 'attr' => [
  167.                     'class' => 'btn btn-primary',
  168.                 ],
  169.                 'label' => $this->translator->trans('button.save'),
  170.             ])
  171.             ->getForm();
  172.         /* @var Form $form */
  173.         $form->handleRequest($request);
  174.         /** @var Form $formRename */
  175.         $formRename $this->createRenameForm();
  176.         if ($form->isSubmitted() && $form->isValid()) {
  177.             $data $form->getData();
  178.             $fs = new Filesystem();
  179.             $directory $directorytmp $fileManager->getCurrentPath().\DIRECTORY_SEPARATOR.$data['name'];
  180.             $i 1;
  181.             while ($fs->exists($directorytmp)) {
  182.                 $directorytmp "{$directory} ({$i})";
  183.                 ++$i;
  184.             }
  185.             $directory $directorytmp;
  186.             try {
  187.                 $fs->mkdir($directory);
  188.                 $this->addFlash('success'$this->translator->trans('folder.add.success'));
  189.             } catch (IOExceptionInterface $e) {
  190.                 $this->addFlash('danger'$this->translator->trans('folder.add.danger', ['%message%' => $data['name']]));
  191.             }
  192.             return $this->redirectToRoute('file_manager'$fileManager->getQueryParameters());
  193.         }
  194.         $parameters['form'] = $form->createView();
  195.         $parameters['formRename'] = $formRename->createView();
  196.         return $this->render('@ArtgrisFileManager/manager.html.twig'$parameters);
  197.     }
  198.     /**
  199.      * @Route("/rename/{fileName}", name="file_manager_rename")
  200.      *
  201.      * @param $fileName
  202.      *
  203.      * @throws \Exception
  204.      *
  205.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  206.      */
  207.     public function renameFileAction(Request $request$fileName)
  208.     {
  209.         $queryParameters $request->query->all();
  210.         $formRename $this->createRenameForm();
  211.         /* @var Form $formRename */
  212.         $formRename->handleRequest($request);
  213.         if ($formRename->isSubmitted() && $formRename->isValid()) {
  214.             $data $formRename->getData();
  215.             $extension $data['extension'] ? '.'.$data['extension'] : '';
  216.             $newfileName $data['name'].$extension;
  217.             if ($newfileName !== $fileName && isset($data['name'])) {
  218.                 $fileManager $this->newFileManager($queryParameters);
  219.                 $NewfilePath $fileManager->getCurrentPath().\DIRECTORY_SEPARATOR.$newfileName;
  220.                 $OldfilePath realpath($fileManager->getCurrentPath().\DIRECTORY_SEPARATOR.$fileName);
  221.                 if (!== mb_strpos($NewfilePath$fileManager->getCurrentPath())) {
  222.                     $this->addFlash('danger'$this->translator->trans('file.renamed.unauthorized'));
  223.                 } else {
  224.                     $fs = new Filesystem();
  225.                     try {
  226.                         $fs->rename($OldfilePath$NewfilePath);
  227.                         $this->addFlash('success'$this->translator->trans('file.renamed.success'));
  228.                         //File has been renamed successfully
  229.                     } catch (IOException $exception) {
  230.                         $this->addFlash('danger'$this->translator->trans('file.renamed.danger'));
  231.                     }
  232.                 }
  233.             } else {
  234.                 $this->addFlash('warning'$this->translator->trans('file.renamed.nochanged'));
  235.             }
  236.         }
  237.         return $this->redirectToRoute('file_manager'$queryParameters);
  238.     }
  239.     /**
  240.      * @Route("/upload/", name="file_manager_upload")
  241.      *
  242.      * @throws \Exception
  243.      *
  244.      * @return Response
  245.      */
  246.     public function uploadFileAction(Request $request)
  247.     {
  248.         $fileManager $this->newFileManager($request->query->all());
  249.         $options = [
  250.             'upload_dir' => $fileManager->getCurrentPath().\DIRECTORY_SEPARATOR,
  251.             'upload_url' => $fileManager->getImagePath(),
  252.             'accept_file_types' => $fileManager->getRegex(),
  253.             'print_response' => false,
  254.         ];
  255.         if (isset($fileManager->getConfiguration()['upload'])) {
  256.             $options += $fileManager->getConfiguration()['upload'];
  257.         }
  258.         $this->dispatch(FileManagerEvents::PRE_UPDATE, ['options' => &$options]);
  259.         $uploadHandler = new UploadHandler($options);
  260.         $response $uploadHandler->response;
  261.         foreach ($response['files'] as $file) {
  262.             if (isset($file->error)) {
  263.                 $file->error $this->translator->trans($file->error);
  264.             } else {
  265.                 if (!$fileManager->getImagePath()) {
  266.                     $file->url $this->generateUrl('file_manager_file'array_merge($fileManager->getQueryParameters(), ['fileName' => $file->url]));
  267.                 }
  268.             }
  269.         }
  270.         $this->dispatch(FileManagerEvents::POST_UPDATE, ['response' => &$response]);
  271.         return new JsonResponse($response);
  272.     }
  273.     /**
  274.      * @Route("/file/{fileName}", name="file_manager_file")
  275.      *
  276.      * @param $fileName
  277.      *
  278.      * @throws \Exception
  279.      *
  280.      * @return BinaryFileResponse
  281.      */
  282.     public function binaryFileResponseAction(Request $request$fileName)
  283.     {
  284.         $fileManager $this->newFileManager($request->query->all());
  285.         $file $fileManager->getCurrentPath() . \DIRECTORY_SEPARATOR urldecode($fileName);
  286.         $this->dispatch(FileManagerEvents::FILE_ACCESS, ['path' => $file]);
  287.         return new BinaryFileResponse($file);
  288.     }
  289.     /**
  290.      * @Route("/delete/", name="file_manager_delete")
  291.      *
  292.      * @throws \Exception
  293.      *
  294.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  295.      */
  296.     public function deleteAction(Request $request)
  297.     {
  298.         $form $this->createDeleteForm();
  299.         $form->handleRequest($request);
  300.         $queryParameters $request->query->all();
  301.         if ($form->isSubmitted() && $form->isValid()) {
  302.             // remove file
  303.             $fileManager $this->newFileManager($queryParameters);
  304.             $fs = new Filesystem();
  305.             if (isset($queryParameters['delete'])) {
  306.                 $is_delete false;
  307.                 foreach ($queryParameters['delete'] as $fileName) {
  308.                     $filePath realpath($fileManager->getCurrentPath().\DIRECTORY_SEPARATOR.$fileName);
  309.                     if (!== mb_strpos($filePath$fileManager->getCurrentPath())) {
  310.                         $this->addFlash('danger''file.deleted.danger');
  311.                     } else {
  312.                         $this->dispatch(FileManagerEvents::PRE_DELETE_FILE);
  313.                         try {
  314.                             $fs->remove($filePath);
  315.                             $is_delete true;
  316.                         } catch (IOException $exception) {
  317.                             $this->addFlash('danger''file.deleted.unauthorized');
  318.                         }
  319.                         $this->dispatch(FileManagerEvents::POST_DELETE_FILE);
  320.                     }
  321.                 }
  322.                 if ($is_delete) {
  323.                     $this->addFlash('success''file.deleted.success');
  324.                 }
  325.                 unset($queryParameters['delete']);
  326.             } else {
  327.                 $this->dispatch(FileManagerEvents::PRE_DELETE_FOLDER);
  328.                 try {
  329.                     $fs->remove($fileManager->getCurrentPath());
  330.                     $this->addFlash('success''folder.deleted.success');
  331.                 } catch (IOException $exception) {
  332.                     $this->addFlash('danger''folder.deleted.unauthorized');
  333.                 }
  334.                 $this->dispatch(FileManagerEvents::POST_DELETE_FOLDER);
  335.                 $queryParameters['route'] = \dirname($fileManager->getCurrentRoute());
  336.                 if ($queryParameters['route'] = '/') {
  337.                     unset($queryParameters['route']);
  338.                 }
  339.                 return $this->redirectToRoute('file_manager'$queryParameters);
  340.             }
  341.         }
  342.         return $this->redirectToRoute('file_manager'$queryParameters);
  343.     }
  344.     /**
  345.      * @return Form|\Symfony\Component\Form\FormInterface
  346.      */
  347.     private function createDeleteForm()
  348.     {
  349.         return $this->get('form.factory')->createNamedBuilder('delete_f')
  350.             ->add('DELETE'SubmitType::class, [
  351.                 'translation_domain' => 'messages',
  352.                 'attr' => [
  353.                     'class' => 'btn btn-danger',
  354.                 ],
  355.                 'label' => 'button.delete.action',
  356.             ])
  357.             ->getForm();
  358.     }
  359.     /**
  360.      * @return mixed
  361.      */
  362.     private function createRenameForm()
  363.     {
  364.         return $this->get('form.factory')->createNamedBuilder('rename_f')
  365.             ->add('name'TextType::class, [
  366.                 'constraints' => [
  367.                     new NotBlank(),
  368.                 ],
  369.                 'label' => false,
  370.             ])->add('extension'HiddenType::class)
  371.             ->add('send'SubmitType::class, [
  372.                 'attr' => [
  373.                     'class' => 'btn btn-primary',
  374.                 ],
  375.                 'label' => 'button.rename.action',
  376.             ])
  377.             ->getForm();
  378.     }
  379.     /**
  380.      * @param $path
  381.      * @param string $parent
  382.      * @param bool   $baseFolderName
  383.      *
  384.      * @return array|null
  385.      */
  386.     private function retrieveSubDirectories(FileManager $fileManager$path$parent \DIRECTORY_SEPARATOR$baseFolderName false)
  387.     {
  388.         $directories = new Finder();
  389.         $directories->in($path)->ignoreUnreadableDirs()->directories()->depth(0)->sortByType()->filter(function (SplFileInfo $file) {
  390.             return $file->isReadable();
  391.         });
  392.         $this->dispatch(FileManagerEvents::POST_DIRECTORY_FILTER_CONFIGURATION, ['finder' => $directories]);
  393.         if ($baseFolderName) {
  394.             $directories->name($baseFolderName);
  395.         }
  396.         $directoriesList null;
  397.         foreach ($directories as $directory) {
  398.             /** @var SplFileInfo $directory */
  399.             $fileName $baseFolderName '' $parent.$directory->getFilename();
  400.             $queryParameters $fileManager->getQueryParameters();
  401.             $queryParameters['route'] = $fileName;
  402.             $queryParametersRoute $queryParameters;
  403.             unset($queryParametersRoute['route']);
  404.             $filesNumber $this->retrieveFilesNumber($directory->getPathname(), $fileManager->getRegex());
  405.             $fileSpan $filesNumber " <span class='label label-default'>{$filesNumber}</span>" '';
  406.             $directoriesList[] = [
  407.                 'text' => $directory->getFilename().$fileSpan,
  408.                 'icon' => 'far fa-folder-open',
  409.                 'children' => $this->retrieveSubDirectories($fileManager$directory->getPathname(), $fileName.\DIRECTORY_SEPARATOR),
  410.                 'a_attr' => [
  411.                     'href' => $fileName $this->generateUrl('file_manager'$queryParameters) : $this->generateUrl('file_manager'$queryParametersRoute),
  412.                 ], 'state' => [
  413.                     'selected' => $fileManager->getCurrentRoute() === $fileName,
  414.                     'opened' => true,
  415.                 ],
  416.             ];
  417.         }
  418.         return $directoriesList;
  419.     }
  420.     /**
  421.      * Tree Iterator.
  422.      *
  423.      * @param $path
  424.      * @param $regex
  425.      *
  426.      * @return int
  427.      */
  428.     private function retrieveFilesNumber($path$regex)
  429.     {
  430.         $files = new Finder();
  431.         $files->in($path)->files()->depth(0)->name($regex);
  432.         $this->dispatch(FileManagerEvents::POST_FILE_FILTER_CONFIGURATION, ['finder' => $files]);
  433.         return iterator_count($files);
  434.     }
  435.     /**
  436.      * @return mixed
  437.      */
  438.     private function getKernelRoute()
  439.     {
  440.         return $this->kernel->getProjectDir();
  441.     }
  442.     /**
  443.      * @param $queryParameters
  444.      *
  445.      * @throws \Exception
  446.      *
  447.      * @return FileManager
  448.      */
  449.     private function newFileManager($queryParameters)
  450.     {
  451.         if (!isset($queryParameters['conf'])) {
  452.             throw new \RuntimeException('Please define a conf parameter in your route');
  453.         }
  454.         $webDir $this->getParameter('artgris_file_manager')['web_dir'];
  455.         $this->fileManager = new FileManager($queryParameters$this->filemanagerService->getBasePath($queryParameters), $this->getKernelRoute(), $this->get('router'), $this->dispatcher$webDir);
  456.         return $this->fileManager;
  457.     }
  458.     protected function dispatch($eventName, array $arguments = [])
  459.     {
  460.         $arguments array_replace([
  461.             'filemanager' => $this->fileManager,
  462.         ], $arguments);
  463.         $subject $arguments['filemanager'];
  464.         $event = new GenericEvent($subject$arguments);
  465.         $this->dispatcher->dispatch($event$eventName);
  466.     }
  467. }