Completed
Push — master ( 139edb...3490f3 )
by Andreas
28:06
created

blobdircleanup::cleanup_corrupted()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 10
c 2
b 0
f 0
nc 5
nop 2
dl 0
loc 14
ccs 0
cts 12
cp 0
crap 56
rs 8.8333
1
<?php
2
/**
3
 * @package midcom.console
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\console\command;
10
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
16
/**
17
 * Cleanup the blobdir
18
 * Search for corrupted (0 bytes) files
19
 *
20
 * @package midcom.console
21
 */
22
class blobdircleanup extends Command
23
{
24
    /**
25
     * @var int
26
     */
27
    private $_file_counter = 0;
28
29
    /**
30
     * @var string
31
     */
32
    private $_dir = "";
33
34
    private $dry = false;
35
36
    private $findings = [
37
        'corrupted' => [],
38
        'orphaned' => []
39
    ];
40
41
    protected function configure()
42
    {
43
        $this->setName('midcom:blobdircleanup')
44
            ->setAliases(['blobdircleanup'])
45
            ->setDescription('Cleanup the blobdir')
46
            ->addOption('dry', 'd', InputOption::VALUE_NONE, 'If set, files and attachments will not be deleted');
47
    }
48
49
    public function check_dir($outerDir)
50
    {
51
        $outerDir = rtrim($outerDir, "/");
52
        $dirs = array_diff(scandir($outerDir), [".", ".."]);
0 ignored issues
show
Bug introduced by
It seems like scandir($outerDir) can also be of type false; however, parameter $array1 of array_diff() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

52
        $dirs = array_diff(/** @scrutinizer ignore-type */ scandir($outerDir), [".", ".."]);
Loading history...
53
        foreach ($dirs as $d) {
54
            if (is_dir($outerDir . "/" . $d)) {
55
                $this->check_dir($outerDir . "/" . $d);
56
            } else {
57
                // got something
58
                $file = $outerDir . "/" . $d;
59
                if (filesize($file) == 0) {
60
                    $this->findings['corrupted'][] = $file;
61
                } elseif ($this->get_attachment($file) === false) {
62
                    $this->findings['orphaned'][] = $file;
63
                }
64
                $this->_file_counter++;
65
            }
66
        }
67
    }
68
69
    private function _determine_location(string $path) : string
70
    {
71
        return ltrim(str_replace($this->_dir, "", $path), "/");
72
    }
73
74
    private function get_attachment(string $file)
75
    {
76
        $location = $this->_determine_location($file);
77
        // get attachments
78
        $qb = \midcom_db_attachment::new_query_builder();
79
        $qb->add_constraint("location", "=", $location);
80
        $attachments = $qb->execute();
81
        if (empty($attachments)) {
82
            return false;
83
        }
84
        if (count($attachments) === 1) {
85
            return $attachments[0];
86
        }
87
        throw new \midcom_error('Multiple attachments share location ' . $location);
88
    }
89
90
    private function cleanup_corrupted(OutputInterface $output, array $files)
91
    {
92
        $i = 0;
93
        foreach ($files as $file) {
94
            $i++;
95
            // cleanup file
96
            $output->writeln($i . ") " . $file);
97
            $this->cleanup_file($output, $file);
98
99
            if ($att = $this->get_attachment($file)) {
100
                if (!$this->dry) {
101
                    $stat = $att->purge();
102
                    if (!$stat || $output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
103
                        $output->writeln(($stat) ? "<info>Purge OK</info>" : "<comment>Purge FAILED, reason: " . \midcom_connection::get_error_string() . "</comment>");
104
                    }
105
                }
106
            }
107
        }
108
    }
109
110
    private function cleanup_file(OutputInterface $output, string $file)
111
    {
112
        if (!$this->dry) {
113
            $stat = unlink($file);
114
            if (!$stat || $output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
115
                $output->writeln(($stat) ? "<info>Cleanup OK</info>" : "<comment>Cleanup FAILED</comment>");
116
            }
117
        }
118
    }
119
120
    protected function execute(InputInterface $input, OutputInterface $output)
121
    {
122
        $dir = \midgard_connection::get_instance()->config->blobdir;
123
        if (!is_dir($dir)) {
124
            $output->writeln("<comment>Unable to detect blobdir</comment>");
125
            return;
126
        }
127
        $this->_dir = $dir;
128
        $this->dry = $input->getOption("dry");
129
        if ($this->dry) {
130
            $output->writeln("<comment>Running in dry mode!</comment>");
131
        }
132
133
        $output->writeln("Start scanning dir: <comment>" . $dir . "</comment>");
134
135
        $this->check_dir($dir);
136
137
        $output->writeln("Scanned <info>" . $this->_file_counter . "</info> files");
138
        $output->writeln("Found <info>" . count($this->findings['corrupted']) . "</info> corrupted files:");
139
        $output->writeln("Found <info>" . count($this->findings['orphaned']) . "</info> orphaned files:");
140
141
        $this->cleanup_corrupted($output, $this->findings['corrupted']);
142
143
        foreach ($this->findings['orphaned'] as $file) {
144
            $this->cleanup_file($output, $file);
145
        }
146
147
        $output->writeln("<comment>Done</comment>");
148
    }
149
}
150