Completed
Push — master ( 7f3b40...87527d )
by Jan
05:23
created

CleanAttachmentsCommand   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 44
dl 0
loc 92
rs 10
c 1
b 0
f 0
wmc 11

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A execute() 0 50 5
A configure() 0 6 1
A removeEmptySubFolders() 0 8 4
1
<?php
2
3
namespace App\Command;
4
5
use App\Services\AttachmentHelper;
6
use App\Services\AttachmentReverseSearch;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Helper\Table;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
use Symfony\Component\Console\Style\SymfonyStyle;
14
use Symfony\Component\Filesystem\Filesystem;
15
use Symfony\Component\Finder\Finder;
16
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
17
use Symfony\Component\Mime\MimeTypes;
18
use Symfony\Component\Mime\MimeTypesInterface;
19
20
class CleanAttachmentsCommand extends Command
21
{
22
    protected static $defaultName = 'app:clean-attachments';
23
24
    protected $attachment_helper;
25
    protected $reverseSearch;
26
    protected $mimeTypeGuesser;
27
28
    public function __construct(AttachmentHelper $attachmentHelper, AttachmentReverseSearch $reverseSearch)
29
    {
30
        $this->attachment_helper = $attachmentHelper;
31
        $this->reverseSearch = $reverseSearch;
32
        $this->mimeTypeGuesser = new MimeTypes();
33
        parent::__construct();
34
    }
35
36
    protected function configure()
37
    {
38
        $this
39
            ->setDescription('Lists (and deletes if wanted) attachments files that are not used anymore (abandoned files).')
40
            ->setHelp('This command allows to find all files in the media folder which are not associated with an attachment anymore.'.
41
                ' These files are not needed and can eventually deleted.');
42
    }
43
44
    protected function execute(InputInterface $input, OutputInterface $output)
45
    {
46
        $io = new SymfonyStyle($input, $output);
47
48
        $mediaPath = $this->attachment_helper->getMediaPath();
49
        $io->note("The media path is " . $mediaPath);
50
51
        $finder = new Finder();
52
        //We look for files in the media folder only
53
        $finder->files()->in($mediaPath);
54
        $fs = new Filesystem();
55
56
        $file_list = array();
57
58
        $table = new Table($output);
59
        $table->setHeaders(['Filename', 'MIME Type', 'Last modified date']);
60
        $dateformatter = \IntlDateFormatter::create(null, \IntlDateFormatter::SHORT, \IntlDateFormatter::SHORT);
61
62
        foreach ($finder as $file)
63
        {
64
            //If not attachment object uses this file, print it
65
            if (count($this->reverseSearch->findAttachmentsByFile($file)) == 0) {
66
                $file_list[] = $file;
67
                $table->addRow([
68
                    $fs->makePathRelative($file->getPathname(), $mediaPath),
69
                    $this->mimeTypeGuesser->guessMimeType($file->getPathname()),
70
                    $dateformatter->format($file->getMTime())
71
                ]);
72
            }
73
        }
74
75
        if (count($file_list) > 0) {
76
            $table->render();
77
78
            $continue = $io->confirm(sprintf("Found %d abandoned files. Do you want to delete them? This can not be undone!", count($file_list)), false);
79
80
            if (!$continue) {
81
                //We are finished here, when no files should be deleted
82
                return;
83
            }
84
85
            //Delete the files
86
            $fs->remove($file_list);
87
            //Delete empty folders:
88
            $this->removeEmptySubFolders($mediaPath);
89
90
            $io->success("All abandoned files were removed.");
91
92
        } else {
93
            $io->success("No abandoned files found.");
94
        }
95
96
97
    }
98
99
    /**
100
     * This function removes all empty folders inside $path. Taken from https://stackoverflow.com/a/1833681
101
     * @param string $path The path in which the empty folders should be deleted
102
     * @return bool
103
     */
104
    protected function removeEmptySubFolders($path)
105
    {
106
        $empty=true;
107
        foreach (glob($path . DIRECTORY_SEPARATOR . "*") as $file)
108
        {
109
            $empty &= is_dir($file) && $this->removeEmptySubFolders($file);
110
        }
111
        return $empty && rmdir($path);
112
    }
113
}
114