Completed
Push — master ( 3ae743...2bdd9e )
by Nikita
03:21 queued 01:07
created

RebuildCacheCommand::rebuildCommandsCache()   C

Complexity

Conditions 8
Paths 20

Size

Total Lines 28
Code Lines 19

Duplication

Lines 28
Ratio 100 %

Importance

Changes 0
Metric Value
dl 28
loc 28
rs 5.3846
c 0
b 0
f 0
cc 8
eloc 19
nc 20
nop 1
1
<?php
2
3
namespace Taisiya\CoreBundle\Command;
4
5
use Symfony\Component\Console\Input\InputInterface;
6
use Symfony\Component\Console\Output\OutputInterface;
7
use Symfony\Component\Finder\Finder;
8
use Taisiya\CoreBundle\Composer\Event\EventSubscriberInterface;
9
use Taisiya\CoreBundle\Console\Style\TaisiyaStyle;
10
use Taisiya\CoreBundle\Exception\InvalidArgumentException;
11
use Taisiya\CoreBundle\Exception\NotReadableException;
12
use Taisiya\CoreBundle\Exception\RuntimeException;
13
use Taisiya\CoreBundle\Provider\ServiceProvider;
14
15
class RebuildCacheCommand extends Command
16
{
17
    /**
18
     * {@inheritdoc}
19
     */
20
    protected function configure()
21
    {
22
        $this->setName('cache:rebuild')
23
            ->setDescription('Rebuild internal application cache');
24
    }
25
26
    /**
27
     * @param InputInterface $input
28
     * @param OutputInterface $output
29
     */
30
    protected function execute(InputInterface $input, OutputInterface $output):
31
    {
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '{'
Loading history...
32
        $io = new TaisiyaStyle($input, $output);
33
34
        $this->rebuildComposerSubscribersCache($io);
35
        $this->rebuildBundlesCache($io);
36
        $this->rebuildCommandsCache($io);
37
    }
38
39
    /**
40
     * @param TaisiyaStyle $io
41
     */
42
    final protected function rebuildComposerSubscribersCache(TaisiyaStyle $io): void
43
    {
44
        $io->isVerbose() && $io->writeln('Rebuild Composer subscribers cache');
45
46
        $subscribers = [];
47
48
        $finder = Finder::create()
49
            ->in(TAISIYA_ROOT)
50
            ->path('/(src|vendor)/')
51
            ->files()
52
            ->name('*Subscriber.php');
53
54
        foreach ($finder as $k => $file) {
55
            $subscriberClass = $this->extractClassNameFromFile($file->getPathname());
56
            try {
57
                $reflectionClass = new \ReflectionClass($subscriberClass);
58
            } catch (\ReflectionException $e) {
59
                continue;
60
            }
61
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(EventSubscriberInterface::class)) {
62
                $io->isVerbose() && $io->writeln('  + '.$subscriberClass);
63
                $subscribers[] = $subscriberClass;
64
            }
65
        }
66
67
        $this->putDataToCacheFile('composer_subscribers.cache.php', $subscribers);
68
        $io->isVerbose() && $io->writeln('  Subscribers saved to <info>composer_subscribers.cache.php</info>');
69
    }
70
71
    /**
72
     * @param TaisiyaStyle $io
73
     */
74
    final protected function rebuildBundlesCache(TaisiyaStyle $io): void
75
    {
76
        $io->isVerbose() && $io->writeln('Rebuild bundles cache');
77
78
        $bundles = [];
79
80
        $finder = Finder::create()
81
            ->in(TAISIYA_ROOT)
82
            ->path('/(src|vendor)/')
83
            ->files()
84
            ->name('*ServiceProvider.php');
85
86
        foreach ($finder as $k => $file) {
87
            $bundleServiceProvider = $this->extractClassNameFromFile($file->getPathname());
88
            $reflectionClass = new \ReflectionClass($bundleServiceProvider);
89
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(ServiceProvider::class)) {
90
                $io->isVerbose() && $io->writeln('  + '.$bundleServiceProvider);
91
                $bundles[] = $bundleServiceProvider;
92
            }
93
        }
94
95
        $this->putDataToCacheFile('bundles.cache.php', $bundles);
96
        $io->isVerbose() && $io->writeln('  Bundles saved to <info>bundles.cache.php</info>');
97
    }
98
99
    /**
100
     * @param TaisiyaStyle $io
101
     */
102
    final protected function rebuildCommandsCache(TaisiyaStyle $io): void
103
    {
104
        $io->isVerbose() && $io->writeln('Rebuild commands cache');
105
106
        $commands = [];
107
108
        $finder = Finder::create()
109
            ->in(TAISIYA_ROOT)
110
            ->path('/(src|vendor)/')
111
            ->files()
112
            ->name('*Command.php');
113
114
        foreach ($finder as $k => $file) {
115
            $commandClass = $this->extractClassNameFromFile($file->getPathname());
116
            try {
117
                $reflectionClass = new \ReflectionClass($commandClass);
118
            } catch (\ReflectionException $e) {
119
                continue;
120
            }
121
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(Command::class)) {
122
                $io->isVerbose() && $io->writeln('  + '.$commandClass);
123
                $commands[] = $commandClass;
124
            }
125
        }
126
127
        $this->putDataToCacheFile('commands.cache.php', $commands);
128
        $io->isVerbose() && $io->writeln('  Commands saved to <info>commands.cache.php</info>');
129
    }
130
131
    /**
132
     * @param string $filepath
133
     * @throws RuntimeException
134
     * @return string
135
     */
136
    final protected function extractClassNameFromFile(string $filepath): string
137
    {
138
        $contents = $this->getFileContents($filepath);
139
140
        preg_match('/namespace\s+(.+?)\;/', $contents, $namespace);
141
        if (!is_array($namespace) || !array_key_exists(1, $namespace)) {
142
            $namespace = null;
143
        } else {
144
            $namespace = $namespace[1];
145
        }
146
147
        preg_match('/class\s+(\w+)/', $contents, $class);
148
        if (!array_key_exists(1, $class)) {
149
            throw new RuntimeException('Couldn\'t extract class from file '.$filepath);
150
        }
151
        $class = $class[1];
152
153
        return preg_replace('/\\+/', '\\', implode('\\', ['', $namespace, $class]));
154
    }
155
156
    /**
157
     * @param string $filepath
158
     * @throws InvalidArgumentException
159
     * @throws NotReadableException
160
     * @throws RuntimeException
161
     * @return string
162
     */
163
    final protected function getFileContents(string $filepath): string
164
    {
165
        if (!file_exists($filepath)) {
166
            throw new InvalidArgumentException('File '.$filepath.' not exists');
167
        } elseif (!is_file($filepath)) {
168
            throw new InvalidArgumentException('The '.$filepath.' is not a regular file');
169
        } elseif (!is_readable($filepath)) {
170
            throw new NotReadableException('File '.$filepath.' not readable');
171
        }
172
173
        $contents = file_get_contents($filepath);
174
175
        if ($contents === false) {
176
            throw new RuntimeException('Couldn\'t get contents from file '.$filepath);
177
        }
178
179
        return $contents;
180
    }
181
182
    /**
183
     * @param string $filename
184
     * @param array $data
185
     * @throws RuntimeException
186
     */
187
    final protected function putDataToCacheFile(string $filename, array $data): void
188
    {
189
        $cacheDir = TAISIYA_ROOT.'/var/cache';
190
        if (!file_exists($cacheDir)) {
191
            if (!mkdir($cacheDir, 0777, true)) {
192
                throw new RuntimeException('Couldn\'t create directory '.$cacheDir);
193
            }
194
        }
195
        if (!file_put_contents($cacheDir.'/'.$filename, "<?php\n\nreturn ".var_export($data, true).";\n")) {
196
            throw new RuntimeException('Couldn\'t write contents to file '.$cacheDir.'/'.$filename);
197
        }
198
    }
199
}
200