Completed
Push — master ( 86928f...ccdb85 )
by Nikita
06:11
created

rebuildEventsSubscribersCache()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 6.7272
cc 7
eloc 16
nc 16
nop 1
1
<?php
2
3
namespace Taisiya\CoreBundle\Console\Command\Cache;
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\Console\Command\Command;
9
use Taisiya\CoreBundle\Console\Style\TaisiyaStyle;
10
use Taisiya\CoreBundle\Event\EventSubscriberInterface;
11
use Taisiya\CoreBundle\Exception\InvalidArgumentException;
12
use Taisiya\CoreBundle\Exception\NotReadableException;
13
use Taisiya\CoreBundle\Exception\RuntimeException;
14
use Taisiya\CoreBundle\Provider\ServiceProvider;
15
16
final class RebuildInternalCacheCommand extends Command
17
{
18
    /**
19
     * {@inheritdoc}
20
     */
21
    protected function configure()
22
    {
23
        $this->setName('cache:rebuild-internal')
24
            ->setDescription('Rebuild internal application cache');
25
    }
26
27
    /**
28
     * @param InputInterface $input
29
     * @param OutputInterface $output
30
     */
31
    protected function execute(InputInterface $input, OutputInterface $output)
32
    {
33
        $io = new TaisiyaStyle($input, $output);
34
35
        $this->rebuildEventsSubscribersCache($io);
36
        $this->rebuildBundlesCache($io);
37
        $this->rebuildCommandsCache($io);
38
    }
39
40
    /**
41
     * @param TaisiyaStyle $io
42
     */
43
    final protected function rebuildEventsSubscribersCache(TaisiyaStyle $io): void
0 ignored issues
show
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
44
    {
45
        $io->isVerbose() && $io->writeln('Rebuild events subscribers cache');
46
47
        $bundles = [];
48
49
        $finder = Finder::create()
50
            ->in(TAISIYA_ROOT)
51
            ->path('/(src|vendor)/')
52
            ->files()
53
            ->name('*Subscriber.php');
54
55
        foreach ($finder as $k => $file) {
56
            $bundleServiceProvider = $this->extractClassNameFromFile($file->getPathname());
57
            $reflectionClass = new \ReflectionClass($bundleServiceProvider);
58
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(EventSubscriberInterface::class)) {
59
                $io->isVerbose() && $io->writeln('  + '.$bundleServiceProvider);
60
                $bundles[] = $bundleServiceProvider;
61
            }
62
        }
63
64
        $this->putDataToCacheFile('events_subscribers.cache.php', $bundles);
65
        $io->isVerbose() && $io->writeln('  Subscribers saved to <info>events_subscribers.cache.php</info>');
66
    }
67
68
    /**
69
     * @param TaisiyaStyle $io
70
     */
71 View Code Duplication
    final protected function rebuildBundlesCache(TaisiyaStyle $io): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
72
    {
73
        $io->isVerbose() && $io->writeln('Rebuild bundles cache');
74
75
        $bundles = [];
76
77
        $finder = Finder::create()
78
            ->in(TAISIYA_ROOT)
79
            ->path('/(src|vendor)/')
80
            ->files()
81
            ->name('*ServiceProvider.php');
82
83
        foreach ($finder as $k => $file) {
84
            $bundleServiceProvider = $this->extractClassNameFromFile($file->getPathname());
85
            $reflectionClass = new \ReflectionClass($bundleServiceProvider);
86
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(ServiceProvider::class)) {
87
                $io->isVerbose() && $io->writeln('  + '.$bundleServiceProvider);
88
                $bundles[] = $bundleServiceProvider;
89
            }
90
        }
91
92
        $this->putDataToCacheFile('bundles.cache.php', $bundles);
93
        $io->isVerbose() && $io->writeln('  Bundles saved to <info>bundles.cache.php</info>');
94
    }
95
96
    /**
97
     * @param TaisiyaStyle $io
98
     */
99 View Code Duplication
    final protected function rebuildCommandsCache(TaisiyaStyle $io): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
100
    {
101
        $io->isVerbose() && $io->writeln('Rebuild commands cache');
102
103
        $commands = [];
104
105
        $finder = Finder::create()
106
            ->in(TAISIYA_ROOT)
107
            ->path('/(src|vendor)/')
108
            ->files()
109
            ->name('*Command.php');
110
111
        foreach ($finder as $k => $file) {
112
            $commandClass = $this->extractClassNameFromFile($file->getPathname());
113
            try {
114
                $reflectionClass = new \ReflectionClass($commandClass);
115
            } catch (\ReflectionException $e) {
116
                continue;
117
            }
118
            if (!$reflectionClass->isAbstract() && $reflectionClass->isSubclassOf(Command::class)) {
119
                $io->isVerbose() && $io->writeln('  + '.$commandClass);
120
                $commands[] = $commandClass;
121
            }
122
        }
123
124
        $this->putDataToCacheFile('commands.cache.php', $commands);
125
        $io->isVerbose() && $io->writeln('  Commands saved to <info>commands.cache.php</info>');
126
    }
127
128
    /**
129
     * @param string $filepath
130
     * @throws RuntimeException
131
     * @return string
132
     */
133
    final protected function extractClassNameFromFile(string $filepath): string
0 ignored issues
show
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
134
    {
135
        $contents = $this->getFileContents($filepath);
136
137
        preg_match('/namespace\s+(.+?)\;/', $contents, $namespace);
138
        if (!is_array($namespace) || !array_key_exists(1, $namespace)) {
139
            $namespace = null;
140
        } else {
141
            $namespace = $namespace[1];
142
        }
143
144
        preg_match('/class\s+(\w+)/', $contents, $class);
145
        if (!array_key_exists(1, $class)) {
146
            throw new RuntimeException('Couldn\'t extract class from file '.$filepath);
147
        }
148
        $class = $class[1];
149
150
        return preg_replace('/\\+/', '\\', implode('\\', ['', $namespace, $class]));
151
    }
152
153
    /**
154
     * @param string $filepath
155
     * @throws InvalidArgumentException
156
     * @throws NotReadableException
157
     * @throws RuntimeException
158
     * @return string
159
     */
160
    final protected function getFileContents(string $filepath): string
0 ignored issues
show
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
161
    {
162
        if (!file_exists($filepath)) {
163
            throw new InvalidArgumentException('File '.$filepath.' not exists');
164
        } elseif (!is_file($filepath)) {
165
            throw new InvalidArgumentException('The '.$filepath.' is not a regular file');
166
        } elseif (!is_readable($filepath)) {
167
            throw new NotReadableException('File '.$filepath.' not readable');
168
        }
169
170
        $contents = file_get_contents($filepath);
171
172
        if ($contents === false) {
173
            throw new RuntimeException('Couldn\'t get contents from file '.$filepath);
174
        }
175
176
        return $contents;
177
    }
178
179
    /**
180
     * @param string $filename
181
     * @param array $data
182
     * @throws RuntimeException
183
     */
184
    final protected function putDataToCacheFile(string $filename, array $data): void
0 ignored issues
show
Coding Style introduced by
Unnecessary FINAL modifier in FINAL class
Loading history...
185
    {
186
        $cacheDir = TAISIYA_ROOT.'/var/cache';
187
        if (!file_exists($cacheDir)) {
188
            if (!mkdir($cacheDir, 0777, true)) {
189
                throw new RuntimeException('Couldn\'t create directory '.$cacheDir);
190
            }
191
        }
192
        if (!file_put_contents($cacheDir.'/'.$filename, "<?php\n\nreturn ".var_export($data, true).";\n")) {
193
            throw new RuntimeException('Couldn\'t write contents to file '.$cacheDir.'/'.$filename);
194
        }
195
    }
196
}
197