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 |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
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 |
|
|
|
|
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
|
|
|
|
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.