diff --git a/Command/CheckCommand.php b/Command/CheckCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..a883bd6b0270c380738992b4976db28496f15e8a --- /dev/null +++ b/Command/CheckCommand.php @@ -0,0 +1,65 @@ +<?php + +/* + * Copyright (C) 2015 IRSTEA + * All rights reserved. + */ + +namespace Irstea\FileUploadBundle\Command; + +use Irstea\FileUploadBundle\Model\FileManagerInterface; +use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Description of GarbageCollectorCommand + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class CheckCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('irstea:file-upload:check') + ->setDescription("Vérifie l'intégrité des fichiers.") + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + /* @var $manager FileManagerInterface */ + $manager = $this->getContainer()->get('irstea_file_upload.file_manager'); + + $em = $this->getContainer()->get('doctrine.orm.entity_manager'); + + $files = $manager->findFilesToValidate(); + + if(count($files) == 0) { + $output->writeln('Aucun fichier à vérifier.'); + return; + } + + $output->writeln('Vérification des fichiers'); + + $progress = new ProgressBar($output, count($files)); + $progress->start(); + + foreach($files as $file){ + $file->validate(); + if(!$file->isValid()) { + $output->writeln(sprintf("\nFichier %s: %s", $file->getEtat(), $file->getPath())); + $em->persist($file); + } + $progress->advance(); + } + + $progress->finish(); + + $em->flush(); + $output->writeln(''); + } +} diff --git a/Command/CollectGarbageCommand.php b/Command/CollectGarbageCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..dcab1c3a90d48194434f7d509cf7130f23bb1f89 --- /dev/null +++ b/Command/CollectGarbageCommand.php @@ -0,0 +1,63 @@ +<?php + +/* + * Copyright (C) 2015 IRSTEA + * All rights reserved. + */ + +namespace Irstea\FileUploadBundle\Command; + +use Irstea\FileUploadBundle\Model\FileManagerInterface; +use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Description of GarbageCollectorCommand + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class CollectGarbageCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('irstea:file-upload:collect-garbage') + ->setDescription("Nettoie les fichiers orphelins et partiels.") + ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Affiche ce qui devrait être fait, sans le faire') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + /* @var $manager FileManagerInterface */ + $manager = $this->getContainer()->get('irstea_file_upload.file_manager'); + + $files = $manager->findGarbage(); + + if(count($files) == 0) { + $output->writeln('Aucun fichier à supprimer.'); + return; + } + + if($input->getOption('dry-run')) { + $output->writeln(sprintf('%d fichier(s) à supprimer.', count($files))); + return; + } + + $output->writeln("Suppression des fichiers"); + + $progress = new ProgressBar($output, count($files)); + $progress->start(); + + foreach($files as $file){ + $manager->delete($file); + $progress->advance(); + } + + $progress->finish(); + $output->writeln(''); + } +} diff --git a/Entity/Repository/UploadedFileRepository.php b/Entity/Repository/UploadedFileRepository.php index b49e2891c078ccedb0bc426cf6b6d2eb166fd4d3..434ffb6f3ae62d004ad8738cf3fc455361edc9de 100644 --- a/Entity/Repository/UploadedFileRepository.php +++ b/Entity/Repository/UploadedFileRepository.php @@ -7,6 +7,7 @@ namespace Irstea\FileUploadBundle\Entity\Repository; +use DateTime; use Doctrine\ORM\EntityRepository; use Gaufrette\Filesystem; use Irstea\FileUploadBundle\Entity\UploadedFile; @@ -136,4 +137,26 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte $this->logger->log($level, $message, $context); } } + + public function findGarbage() + { + $files = $this->findBy(['etat' => [UploadedFileInterface::ETAT_EN_COURS, UploadedFileInterface::ETAT_ORPHELIN]]); + + $limit = new DateTime('now'); + $limit->modify('- 1 hour'); + + return array_filter( + $files, + function(UploadedFileInterface $file) use($limit) { + $mtime = $file->getLastModified(); + return $mtime === null || $mtime < $limit; + } + ); + } + + public function findFilesToValidate() + { + return $this->findBy(['etat' => [UploadedFileInterface::ETAT_ORPHELIN, UploadedFileInterface::ETAT_NORMAL]]); + } + } diff --git a/Entity/UploadedFile.php b/Entity/UploadedFile.php index 53b083d524191b071604f0079fbb58c958401563..9002066cebf616d051ca250467d67e10ce6b7cc7 100644 --- a/Entity/UploadedFile.php +++ b/Entity/UploadedFile.php @@ -9,9 +9,11 @@ namespace Irstea\FileUploadBundle\Entity; use DateTime; use Doctrine\ORM\Mapping as ORM; +use Gaufrette\Exception\FileNotFound; use Gaufrette\Filesystem; use Gaufrette\StreamMode; use InvalidArgumentException; +use Irstea\FileUploadBundle\Entity\Repository\UploadedFileRepository; use Irstea\FileUploadBundle\Model\UploadedFileInterface; use Irstea\FileUploadBundle\Utils\MimeTypeIcon; use Rhumsaa\Uuid\Uuid; @@ -361,7 +363,7 @@ class UploadedFile implements UploadedFileInterface public function validate() { - if (self::ETAT_EN_COURS !== $this->getEtat()) { + if (self::ETAT_EN_COURS === $this->getEtat()) { return; } @@ -403,7 +405,11 @@ class UploadedFile implements UploadedFileInterface */ public function getLastModified() { - return new \DateTime(sprintf('@%d', $this->filesystem->mtime($this->getPath()))); + try { + return new \DateTime(sprintf('@%d', $this->filesystem->mtime($this->getPath()))); + } catch(FileNotFound $ex) { + return null; + } } /** Retourne le contenu du fichier. diff --git a/Model/FileManagerInterface.php b/Model/FileManagerInterface.php index 84a4b524fc5e91f05e43537a2885211a7b5d2f39..f2d48cb6cce2b68ad8a2ef063dedfc6fef94cda7 100644 --- a/Model/FileManagerInterface.php +++ b/Model/FileManagerInterface.php @@ -37,4 +37,17 @@ interface FileManagerInterface * @param UploadedFileInterface $file */ public function completed(UploadedFileInterface $file); + + + /** Retourne un tableau de fichiers à nettoyer. + * + * @return UploadedFileInterface[] + */ + public function findGarbage(); + + /** Retourne des fichiers à valider. + * + * @return UploadedFileInterface[] + */ + public function findFilesToValidate(); }