|
5 | 5 | namespace Mammatus\Queue\Composer; |
6 | 6 |
|
7 | 7 | use Composer\Composer; |
8 | | -use Composer\Config; |
9 | 8 | use Composer\EventDispatcher\EventSubscriberInterface; |
10 | 9 | use Composer\IO\IOInterface; |
11 | | -use Composer\Package\PackageInterface; |
12 | | -use Composer\Package\RootPackageInterface; |
13 | 10 | use Composer\Plugin\PluginInterface; |
14 | 11 | use Composer\Script\Event; |
15 | 12 | use Composer\Script\ScriptEvents; |
16 | | -use Illuminate\Support\Collection; |
17 | | -use Mammatus\Kubernetes\Attributes\SplitOut; |
18 | | -use Mammatus\Queue\Attributes\Consumer; |
19 | | -use Mammatus\Queue\Contracts\Worker; |
20 | | -use Roave\BetterReflection\BetterReflection; |
21 | | -use Roave\BetterReflection\Reflection\ReflectionClass; |
22 | | -use Roave\BetterReflection\Reflector\DefaultReflector; |
23 | | -use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; |
24 | | -use Roave\BetterReflection\SourceLocator\Type\Composer\Factory\MakeLocatorForComposerJsonAndInstalledJson; |
25 | | -use Roave\BetterReflection\SourceLocator\Type\Composer\Psr\Exception\InvalidPrefixMapping; |
26 | | -use RuntimeException; |
27 | | - |
28 | | -use function array_key_exists; |
29 | | -use function count; |
30 | | -use function dirname; |
31 | | -use function explode; |
32 | | -use function file_exists; |
33 | | -use function is_array; |
34 | | -use function is_string; |
35 | | -use function microtime; |
36 | | -use function round; |
37 | | -use function rtrim; |
38 | | -use function Safe\chmod; |
39 | | -use function Safe\file_get_contents; |
40 | | -use function Safe\file_put_contents; |
41 | | -use function Safe\mkdir; |
42 | | -use function Safe\spl_autoload_register; |
43 | | -use function sprintf; |
44 | | -use function str_replace; |
45 | | -use function strlen; |
46 | | -use function strpos; |
47 | | -use function substr; |
48 | | -use function WyriHaximus\getIn; |
49 | | -use function WyriHaximus\listClassesInDirectories; |
50 | | -use function WyriHaximus\Twig\render; |
51 | | - |
52 | | -use const DIRECTORY_SEPARATOR; |
| 13 | +use WyriHaximus\Composer\GenerativePluginTooling\GenerativePluginExecutioner; |
53 | 14 |
|
54 | 15 | final class Installer implements PluginInterface, EventSubscriberInterface |
55 | 16 | { |
@@ -79,214 +40,6 @@ public function uninstall(Composer $composer, IOInterface $io): void |
79 | 40 | */ |
80 | 41 | public static function findActions(Event $event): void |
81 | 42 | { |
82 | | - $start = microtime(true); |
83 | | - $io = $event->getIO(); |
84 | | - $composer = $event->getComposer(); |
85 | | - $vendorDir = $composer->getConfig()->get('vendor-dir'); |
86 | | - if (! is_string($vendorDir)) { |
87 | | - throw new RuntimeException('Vendor dir must be a string'); |
88 | | - } |
89 | | - |
90 | | - // Composer is bugged and doesn't handle root package autoloading properly yet |
91 | | - if (array_key_exists('psr-4', $composer->getPackage()->getAutoload())) { |
92 | | - foreach ($composer->getPackage()->getAutoload()['psr-4'] as $ns => $p) { |
93 | | - /** @phpstan-ignore-next-line */ |
94 | | - $p = dirname($vendorDir) . '/' . $p; |
95 | | - spl_autoload_register(static function ($class) use ($ns, $p): void { |
96 | | - if (strpos($class, $ns) !== 0) { |
97 | | - return; |
98 | | - } |
99 | | - |
100 | | - $fileName = $p . str_replace('\\', DIRECTORY_SEPARATOR, substr($class, strlen($ns))) . '.php'; |
101 | | - /** @phpstan-ignore-next-line */ |
102 | | - if (! file_exists($fileName)) { |
103 | | - return; |
104 | | - } |
105 | | - |
106 | | - include $fileName; |
107 | | - }); |
108 | | - } |
109 | | - } |
110 | | - |
111 | | - /** @psalm-suppress UnresolvableInclude */ |
112 | | - require_once $composer->getConfig()->get('vendor-dir') . '/wyrihaximus/list-classes-in-directory/src/functions_include.php'; |
113 | | - /** @psalm-suppress UnresolvableInclude */ |
114 | | - require_once $composer->getConfig()->get('vendor-dir') . '/wyrihaximus/string-get-in/src/functions_include.php'; |
115 | | - /** @psalm-suppress UnresolvableInclude */ |
116 | | - require_once $composer->getConfig()->get('vendor-dir') . '/wyrihaximus/constants/src/Numeric/constants_include.php'; |
117 | | - /** @psalm-suppress UnresolvableInclude */ |
118 | | - require_once $composer->getConfig()->get('vendor-dir') . '/igorw/get-in/src/get_in.php'; |
119 | | - /** @psalm-suppress UnresolvableInclude */ |
120 | | - require_once $composer->getConfig()->get('vendor-dir') . '/jetbrains/phpstorm-stubs/PhpStormStubsMap.php'; |
121 | | - /** @psalm-suppress UnresolvableInclude */ |
122 | | - require_once $composer->getConfig()->get('vendor-dir') . '/thecodingmachine/safe/generated/filesystem.php'; |
123 | | - /** @psalm-suppress UnresolvableInclude */ |
124 | | - require_once $composer->getConfig()->get('vendor-dir') . '/thecodingmachine/safe/generated/strings.php'; |
125 | | - /** @psalm-suppress UnresolvableInclude */ |
126 | | - require_once $composer->getConfig()->get('vendor-dir') . '/wyrihaximus/simple-twig/src/functions_include.php'; |
127 | | - /** @psalm-suppress UnresolvableInclude */ |
128 | | - |
129 | | - $io->write('<info>mammatus/queue:</info> Locating actions'); |
130 | | - |
131 | | - $actions = self::findAllActions($composer, $io); |
132 | | - |
133 | | - $io->write(sprintf('<info>mammatus/queue:</info> Found %s action(s)', count($actions))); |
134 | | - |
135 | | - $classContentsList = render( |
136 | | - file_get_contents( |
137 | | - self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage()) . '/etc/generated_templates/AbstractList_.php.twig', |
138 | | - ), |
139 | | - ['workers' => $actions], |
140 | | - ); |
141 | | - |
142 | | - $installPathList = self::locateRootPackageInstallPath($composer->getConfig(), $composer->getPackage()) |
143 | | - . '/src/Generated/AbstractList_.php'; |
144 | | - |
145 | | - file_put_contents($installPathList, $classContentsList); |
146 | | - chmod($installPathList, 0664); |
147 | | - |
148 | | - $io->write(sprintf( |
149 | | - '<info>mammatus/queue:</info> Generated static abstract queue manager and queue list in %s second(s)', |
150 | | - round(microtime(true) - $start, 2), |
151 | | - )); |
152 | | - } |
153 | | - |
154 | | - /** |
155 | | - * Find the location where to put the generate PHP class in. |
156 | | - */ |
157 | | - private static function locateRootPackageInstallPath( |
158 | | - Config $composerConfig, |
159 | | - RootPackageInterface $rootPackage, |
160 | | - ): string { |
161 | | - $vendorDir = $composerConfig->get('vendor-dir'); |
162 | | - if (! is_string($vendorDir)) { |
163 | | - throw new RuntimeException('Vendor dir must be a string'); |
164 | | - } |
165 | | - |
166 | | - // You're on your own |
167 | | - if ($rootPackage->getName() === 'mammatus/queue') { |
168 | | - return dirname($vendorDir); |
169 | | - } |
170 | | - |
171 | | - return $vendorDir . '/mammatus/queue'; |
172 | | - } |
173 | | - |
174 | | - /** @return array<mixed> */ |
175 | | - private static function findAllActions(Composer $composer, IOInterface $io): array |
176 | | - { |
177 | | - $vendorDir = $composer->getConfig()->get('vendor-dir'); |
178 | | - if (! is_string($vendorDir)) { |
179 | | - throw new RuntimeException('Vendor dir must be a string'); |
180 | | - } |
181 | | - |
182 | | - retry: |
183 | | - try { |
184 | | - $classReflector = new DefaultReflector( |
185 | | - (new MakeLocatorForComposerJsonAndInstalledJson())(dirname($vendorDir), (new BetterReflection())->astLocator()), |
186 | | - ); |
187 | | - } catch (InvalidPrefixMapping $invalidPrefixMapping) { |
188 | | - mkdir(explode('" is not a', explode('" for prefix "', $invalidPrefixMapping->getMessage())[1])[0]); |
189 | | - goto retry; |
190 | | - } |
191 | | - |
192 | | - $packages = $composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages(); |
193 | | - $packages[] = $composer->getPackage(); |
194 | | - |
195 | | - return (new Collection($packages))->filter(static function (PackageInterface $package): bool { |
196 | | - return count($package->getAutoload()) > 0; |
197 | | - })->filter(static function (PackageInterface $package): bool { |
198 | | - /** @phpstan-ignore-next-line */ |
199 | | - return getIn($package->getExtra(), 'mammatus.queue.has-workers', false); |
200 | | - })->filter(static function (PackageInterface $package): bool { |
201 | | - return array_key_exists('classmap', $package->getAutoload()) || array_key_exists('psr-4', $package->getAutoload()); |
202 | | - })->flatMap(static function (PackageInterface $package) use ($vendorDir): array { |
203 | | - $packageName = $package->getName(); |
204 | | - $autoload = $package->getAutoload(); |
205 | | - $paths = []; |
206 | | - foreach (['classmap', 'psr-4'] as $item) { |
207 | | - if (! array_key_exists($item, $autoload)) { |
208 | | - continue; |
209 | | - } |
210 | | - |
211 | | - foreach ($autoload[$item] as $path) { |
212 | | - if (is_string($path)) { |
213 | | - if ($package instanceof RootPackageInterface) { |
214 | | - $paths[] = dirname($vendorDir) . DIRECTORY_SEPARATOR . $path; |
215 | | - } else { |
216 | | - $paths[] = $vendorDir . DIRECTORY_SEPARATOR . $packageName . DIRECTORY_SEPARATOR . $path; |
217 | | - } |
218 | | - } |
219 | | - |
220 | | - if (! is_array($path)) { |
221 | | - continue; |
222 | | - } |
223 | | - |
224 | | - foreach ($path as $p) { |
225 | | - if ($package instanceof RootPackageInterface) { |
226 | | - $paths[] = dirname($vendorDir) . DIRECTORY_SEPARATOR . $p; |
227 | | - } else { |
228 | | - $paths[] = $vendorDir . DIRECTORY_SEPARATOR . $packageName . DIRECTORY_SEPARATOR . $p; |
229 | | - } |
230 | | - } |
231 | | - } |
232 | | - } |
233 | | - |
234 | | - return $paths; |
235 | | - })->map(static function (string $path): string { |
236 | | - return rtrim($path, '/'); |
237 | | - })->filter(static function (string $path): bool { |
238 | | - /** @phpstan-ignore-next-line */ |
239 | | - return file_exists($path); |
240 | | - })->flatMap(static function (string $path): array { |
241 | | - return [...listClassesInDirectories($path)]; |
242 | | - /** @phpstan-ignore-next-line */ |
243 | | - })->flatMap(static function (string $class) use ($classReflector, $io): array { |
244 | | - try { |
245 | | - /** @psalm-suppress PossiblyUndefinedVariable */ |
246 | | - return [ |
247 | | - (static function (ReflectionClass $reflectionClass): ReflectionClass { |
248 | | - $reflectionClass->getInterfaces(); |
249 | | - $reflectionClass->getMethods(); |
250 | | - |
251 | | - return $reflectionClass; |
252 | | - })($classReflector->reflectClass($class)), |
253 | | - ]; |
254 | | - } catch (IdentifierNotFound $identifierNotFound) { |
255 | | - $io->write(sprintf( |
256 | | - '<info>mammatus/queue:</info> Error while reflecting "<fg=cyan>%s</>": <fg=yellow>%s</>', |
257 | | - $class, |
258 | | - $identifierNotFound->getMessage(), |
259 | | - )); |
260 | | - } |
261 | | - |
262 | | - return []; |
263 | | - })->filter(static function (ReflectionClass $class): bool { |
264 | | - return $class->isInstantiable(); |
265 | | - })->filter(static function (ReflectionClass $class): bool { |
266 | | - return $class->implementsInterface(Worker::class); |
267 | | - })->flatMap(static function (ReflectionClass $class): array { |
268 | | - $attributes = []; |
269 | | - foreach ((new \ReflectionClass($class->getName()))->getAttributes() as $attributeReflection) { |
270 | | - $attribute = $attributeReflection->newInstance(); |
271 | | - $attributes[$attribute::class] = $attribute; |
272 | | - } |
273 | | - |
274 | | - return [ |
275 | | - [ |
276 | | - 'class' => $class->getName(), |
277 | | - 'attributes' => $attributes, |
278 | | - ], |
279 | | - ]; |
280 | | - })->filter(static function (array $classNattributes): bool { |
281 | | - return array_key_exists(Consumer::class, $classNattributes['attributes']); |
282 | | - })->flatMap(static function (array $classNattributes): array { |
283 | | - return [ |
284 | | - [ |
285 | | - 'class' => $classNattributes['class'], |
286 | | - 'consumer' => $classNattributes['attributes'][Consumer::class], |
287 | | - 'split_out' => array_key_exists(SplitOut::class, $classNattributes['attributes']), |
288 | | - ], |
289 | | - ]; |
290 | | - })->toArray(); |
| 43 | + GenerativePluginExecutioner::execute($event->getComposer(), $event->getIO(), new Plugin()); |
291 | 44 | } |
292 | 45 | } |
0 commit comments