Completed
Push — master ( c4223d...e3af10 )
by Nikita
03:25
created

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