|
13 | 13 |
|
14 | 14 | use Symfony\Component\Console\ConsoleEvents;
|
15 | 15 | use Symfony\Component\Console\Event\ConsoleErrorEvent;
|
| 16 | +use Symfony\Component\Console\Exception\CommandNotFoundException; |
16 | 17 | use Symfony\Component\Console\Exception\NamespaceNotFoundException;
|
17 | 18 | use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
18 | 19 |
|
|
24 | 25 | */
|
25 | 26 | final class SuggestMissingPackageSubscriber implements EventSubscriberInterface
|
26 | 27 | {
|
27 |
| - /** |
28 |
| - * Mappings between namespaces of Symfony commands and packages required to run these commands. |
29 |
| - * |
30 |
| - * @var array |
31 |
| - */ |
32 |
| - private static $suggestedPackages = [ |
| 28 | + const PACKAGES = [ |
33 | 29 | 'doctrine' => [
|
34 |
| - 'Doctrine ORM', |
35 |
| - 'symfony/orm-pack', |
| 30 | + 'fixtures' => ['DoctrineFixturesBundle', 'doctrine/doctrine-fixtures-bundle --dev'], |
| 31 | + 'mongodb' => ['DoctrineMongoDBBundle', 'doctrine/mongodb-odm-bundle'], |
| 32 | + '_default' => ['Doctrine ORM', 'symfony/orm-pack'], |
36 | 33 | ],
|
37 | 34 | 'generate' => [
|
38 |
| - 'SensioGeneratorBundle', |
39 |
| - 'sensio/generator-bundle', |
| 35 | + '_default' => ['SensioGeneratorBundle', 'sensio/generator-bundle'], |
40 | 36 | ],
|
41 | 37 | 'make' => [
|
42 |
| - 'MakerBundle', |
43 |
| - 'symfony/maker-bundle --dev', |
| 38 | + '_default' => ['MakerBundle', 'symfony/maker-bundle --dev'], |
44 | 39 | ],
|
45 | 40 | 'server' => [
|
46 |
| - 'Symfony Web Server', |
47 |
| - 'symfony/web-server-bundle --dev', |
| 41 | + 'dump' => ['VarDumper Component', 'symfony/var-dumper --dev'], |
| 42 | + '_default' => ['WebServerBundle', 'symfony/web-server-bundle --dev'], |
48 | 43 | ],
|
49 | 44 | ];
|
50 | 45 |
|
51 |
| - public function onConsoleError(ConsoleErrorEvent $event) |
| 46 | + public function onConsoleError(ConsoleErrorEvent $event) : void |
52 | 47 | {
|
53 |
| - if ($event->getError() instanceof NamespaceNotFoundException) { |
54 |
| - if (null !== $event->getInput()->getFirstArgument()) { |
55 |
| - $namespace = explode(':', $event->getInput()->getFirstArgument())[0]; |
| 48 | + if (!$event->getError() instanceof CommandNotFoundException || empty($input = $event->getInput()->getFirstArgument())) { |
| 49 | + return; |
| 50 | + } |
| 51 | + |
| 52 | + $input = explode(':', $input); |
| 53 | + $namespace = $input[0]; |
| 54 | + $command = $input[1] ?? ''; |
| 55 | + |
| 56 | + if (!isset(self::PACKAGES[$namespace])) { |
| 57 | + return; |
| 58 | + } |
56 | 59 |
|
57 |
| - if (isset(self::$suggestedPackages[$namespace])) { |
58 |
| - $suggestion = self::$suggestedPackages[$namespace]; |
59 |
| - $message = sprintf("It seems that you are trying to run a command from '%s' bundle/package, but you do not have it installed. You may try installing the missing bundle/package by running:\n\n composer require %s", $suggestion[0], $suggestion[1]); |
60 |
| - $event->setError(new NamespaceNotFoundException($message)); |
61 |
| - } |
62 |
| - } |
| 60 | + if (isset(self::PACKAGES[$namespace][$command]) && '' !== $command) { |
| 61 | + $suggestion = self::PACKAGES[$namespace][$command]; |
| 62 | + $exact = true; |
| 63 | + } else { |
| 64 | + $suggestion = self::PACKAGES[$namespace]['_default']; |
| 65 | + $exact = false; |
63 | 66 | }
|
| 67 | + |
| 68 | + $error = $event->getError(); |
| 69 | + |
| 70 | + if (!empty($error->getAlternatives()) && !$exact) { |
| 71 | + return; |
| 72 | + } |
| 73 | + |
| 74 | + $message = sprintf("%s\n\nYou may be looking for a command provided by the \"%s\" which is currently not installed. Try running \"composer require %s\".", $error->getMessage(), $suggestion[0], $suggestion[1]); |
| 75 | + $event->setError(new CommandNotFoundException($message)); |
64 | 76 | }
|
65 | 77 |
|
66 |
| - public static function getSubscribedEvents() |
| 78 | + public static function getSubscribedEvents() : array |
67 | 79 | {
|
68 | 80 | return [
|
69 | 81 | ConsoleEvents::ERROR => ['onConsoleError', 0],
|
|
0 commit comments