CommandDirectoryChecker::ensureDirectoryExists()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
nc 2
cc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of AppName.
5
 *
6
 * (c) Monofony
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace App\Installer\Checker;
13
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Filesystem\Exception\IOException;
16
use Symfony\Component\Filesystem\Filesystem;
17
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;
18
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
19
20
final class CommandDirectoryChecker
21
{
22
    /**
23
     * @var string
24
     */
25
    private $name;
26
27
    /**
28
     * @var Filesystem
29
     */
30
    private $filesystem;
31
32
    /**
33
     * @param Filesystem $filesystem
34
     */
35
    public function __construct(Filesystem $filesystem)
36
    {
37
        $this->filesystem = $filesystem;
38
    }
39
40
    public function ensureDirectoryExists($directory, OutputInterface $output): void
41
    {
42
        if (!is_dir($directory)) {
43
            $this->createDirectory($directory, $output);
44
        }
45
    }
46
47
    public function ensureDirectoryIsWritable($directory, OutputInterface $output): void
48
    {
49
        try {
50
            $this->changePermissionsRecursively($directory, $output);
51
        } catch (AccessDeniedException $exception) {
52
            $output->writeln($this->createBadPermissionsMessage($exception->getMessage()));
53
54
            throw new \RuntimeException('Failed while trying to change directory permissions.');
55
        }
56
    }
57
58
    public function setCommandName($name): void
59
    {
60
        $this->name = $name;
61
    }
62
63
    /**
64
     * @param string          $directory
65
     * @param OutputInterface $output
66
     */
67
    private function createDirectory($directory, OutputInterface $output): void
68
    {
69
        try {
70
            $this->filesystem->mkdir($directory, 0755);
71
        } catch (IOException $exception) {
72
            $output->writeln($this->createUnexistingDirectoryMessage(getcwd().'/'.$directory));
73
74
            throw new \RuntimeException('Failed while trying to create directory.');
75
        }
76
77
        $output->writeln(sprintf('<comment>Created "%s" directory.</comment>', $directory));
78
    }
79
80
    /**
81
     * @param string          $directory
82
     * @param OutputInterface $output
83
     */
84
    private function changePermissionsRecursively($directory, OutputInterface $output): void
85
    {
86
        if (is_file($directory) && is_writable($directory)) {
87
            return;
88
        }
89
90
        if (!is_writable($directory)) {
91
            $this->changePermissions($directory, $output);
92
93
            return;
94
        }
95
96
        foreach (new RecursiveDirectoryIterator($directory, \FilesystemIterator::CURRENT_AS_FILEINFO) as $subdirectory) {
97
            if ('.' !== $subdirectory->getFilename()[0]) {
98
                $this->changePermissionsRecursively($subdirectory->getPathname(), $output);
99
            }
100
        }
101
    }
102
103
    /**
104
     * @param string          $directory
105
     * @param OutputInterface $output
106
     *
107
     * @throws AccessDeniedException if directory/file permissions cannot be changed
108
     */
109
    private function changePermissions($directory, OutputInterface $output): void
110
    {
111
        try {
112
            $this->filesystem->chmod($directory, 0755, 0000, true);
113
114
            $output->writeln(sprintf('<comment>Changed "%s" permissions to 0755.</comment>', $directory));
115
        } catch (IOException $exception) {
116
            throw new AccessDeniedException(dirname($directory));
117
        }
118
    }
119
120
    /**
121
     * @param string $directory
122
     *
123
     * @return string
124
     */
125
    private function createUnexistingDirectoryMessage($directory)
126
    {
127
        return
128
            '<error>Cannot run command due to unexisting directory (tried to create it automatically, failed).</error>'.PHP_EOL.
129
            sprintf('Create directory "%s" and run command "<comment>%s</comment>"', $directory, $this->name)
130
        ;
131
    }
132
133
    /**
134
     * @param string $directory
135
     *
136
     * @return string
137
     */
138
    private function createBadPermissionsMessage($directory)
139
    {
140
        return
141
            '<error>Cannot run command due to bad directory permissions (tried to change permissions to 0755).</error>'.PHP_EOL.
142
            sprintf('Set "%s" writable recursively and run command "<comment>%s</comment>"', $directory, $this->name)
143
        ;
144
    }
145
}
146