|
3 | 3 |
|
4 | 4 | /** |
5 | 5 | * @file |
| 6 | + * Acquia CLI command line front file. |
| 7 | + * |
| 8 | + * This is largely based on the default bin/console command that ships with a |
| 9 | + * Symfony app. However, it's been modified to not rely on the Framework Bundle, |
| 10 | + * which spares us from unnecessary dependencies such as the routing layer. |
| 11 | + * |
| 12 | + * ORCA does something similar. |
| 13 | + * |
| 14 | + * @see https://github.com/TravisCarden/stackoverflow-a-50356503 |
6 | 15 | */ |
7 | 16 |
|
8 | | -use Acquia\Cli\AcquiaCliApplication; |
9 | | -use Acquia\Cli\Command\Api\ApiListCommand; |
10 | | -use Acquia\Cli\Command\AuthCommand; |
11 | | -use Acquia\Cli\Command\Ide\IdeCreateCommand; |
12 | | -use Acquia\Cli\Command\Ide\IdeDeleteCommand; |
13 | | -use Acquia\Cli\Command\Ide\IdeListCommand; |
14 | | -use Acquia\Cli\Command\Ide\IdeOpenCommand; |
15 | | -use Acquia\Cli\Command\Ide\Wizard\IdeWizardCreateSshKeyCommand; |
16 | | -use Acquia\Cli\Command\Ide\Wizard\IdeWizardDeleteSshKeyCommand; |
17 | | -use Acquia\Cli\Command\LinkCommand; |
18 | | -use Acquia\Cli\Command\LogTailCommand; |
19 | | -use Acquia\Cli\Command\NewCommand; |
20 | | -use Acquia\Cli\Command\RefreshCommand; |
21 | | -use Acquia\Cli\Command\Remote\AliasesDownloadCommand; |
22 | | -use Acquia\Cli\Command\Remote\AliasListCommand; |
23 | | -use Acquia\Cli\Command\Remote\DrushCommand; |
24 | | -use Acquia\Cli\Command\Remote\SshCommand; |
25 | | -use Acquia\Cli\Command\Ssh\SshKeyCreateCommand; |
26 | | -use Acquia\Cli\Command\Ssh\SshKeyCreateUploadCommand; |
27 | | -use Acquia\Cli\Command\Ssh\SshKeyDeleteCommand; |
28 | | -use Acquia\Cli\Command\Ssh\SshKeyListCommand; |
29 | | -use Acquia\Cli\Command\Ssh\SshKeyUploadCommand; |
30 | | -use Acquia\Cli\Command\TelemetryCommand; |
31 | | -use Acquia\Cli\Command\UnlinkCommand; |
32 | | -use Acquia\Cli\Command\UpdateCommand; |
33 | | -use Acquia\Cli\Helpers\ClientService; |
34 | | -use Acquia\Cli\Helpers\LocalMachineHelper; |
35 | | -use Acquia\Cli\Helpers\TelemetryHelper; |
36 | | -use Symfony\Component\Console\Helper\QuestionHelper; |
37 | | -use AcquiaLogstream\LogstreamManager; |
| 17 | +namespace Acquia\Cli; |
| 18 | + |
| 19 | +use Acquia\Cli\Command\Api\ApiCommandHelper; |
| 20 | +use Acquia\Cli\Exception\AcquiaCliException; |
| 21 | +use League\OAuth2\Client\Provider\Exception\IdentityProviderException; |
| 22 | +use Symfony\Component\Console\Application; |
| 23 | +use Symfony\Component\Console\ConsoleEvents; |
| 24 | +use Symfony\Component\Console\Event\ConsoleErrorEvent; |
38 | 25 | use Symfony\Component\Console\Input\ArgvInput; |
39 | | -use Symfony\Component\Console\Logger\ConsoleLogger; |
40 | | -use Symfony\Component\Console\Output\ConsoleOutput; |
41 | | -use Symfony\Component\DependencyInjection\Reference; |
42 | | -use Webmozart\KeyValueStore\JsonFileStore; |
43 | | -use Webmozart\PathUtil\Path; |
44 | | -use Zumba\Amplitude\Amplitude; |
| 26 | +use Symfony\Component\Dotenv\Dotenv; |
| 27 | +use Symfony\Component\ErrorHandler\Debug; |
| 28 | +use Symfony\Component\EventDispatcher\EventDispatcher; |
| 29 | +use Symfony\Component\Filesystem\Filesystem; |
45 | 30 |
|
46 | | -$pharPath = Phar::running(TRUE); |
47 | | -if ($pharPath) { |
48 | | - require_once "$pharPath/vendor/autoload.php"; |
| 31 | +if (!in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { |
| 32 | + echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL; |
49 | 33 | } |
50 | | -else { |
51 | | - require_once __DIR__ . '/../vendor/autoload.php'; |
52 | | -} |
53 | | - |
54 | | -// Create the input and output objects for Acquia CLI to run against. |
55 | | -$input = new ArgvInput($_SERVER['argv']); |
56 | | -$output = new ConsoleOutput(); |
57 | | -$logger = new ConsoleLogger($output); |
58 | | -$container = new Symfony\Component\DependencyInjection\ContainerBuilder(); |
59 | | -$container->setParameter('repo_root', find_repo_root()); |
60 | | -$container->setParameter('data_dir', LocalMachineHelper::getHomeDir() . '/.acquia'); |
61 | | -AcquiaCliApplication::configureContainer($container, $input, $output, $logger); |
62 | 34 |
|
63 | | -/** |
64 | | - * Running Acquia CLI. |
65 | | - */ |
66 | | -$application = new AcquiaCliApplication($container, $logger, $input, $output, '@package_version@'); |
67 | | -$application->addCommands([ |
68 | | - new AliasesDownloadCommand(), |
69 | | - new AliasListCommand(), |
70 | | - new AuthCommand(), |
71 | | - new ApiListCommand(), |
72 | | - new DrushCommand(), |
73 | | - new IdeCreateCommand(), |
74 | | - new IdeDeleteCommand(), |
75 | | - new IdeListCommand(), |
76 | | - new IdeOpenCommand(), |
77 | | - new IdeWizardCreateSshKeyCommand(), |
78 | | - new IdeWizardDeleteSshKeyCommand(), |
79 | | - new LinkCommand(), |
80 | | - new LogTailCommand(), |
81 | | - new NewCommand(), |
82 | | - new RefreshCommand(), |
83 | | - new SshCommand(), |
84 | | - new SshKeyCreateCommand(), |
85 | | - new SshKeyDeleteCommand(), |
86 | | - new SshKeyListCommand(), |
87 | | - new SshKeyUploadCommand(), |
88 | | - new SshKeyCreateUploadCommand(), |
89 | | - new TelemetryCommand(), |
90 | | - new UnlinkCommand(), |
91 | | - new UpdateCommand(), |
92 | | -]); |
| 35 | +set_time_limit(0); |
93 | 36 |
|
94 | | -$status_code = $application->run($input, $output); |
95 | | -exit($status_code); |
| 37 | +require dirname(__DIR__).'/vendor/autoload.php'; |
96 | 38 |
|
97 | | -/** |
98 | | - * Finds the root directory for the repository. |
99 | | - * |
100 | | - * @return null|string |
101 | | - * Root. |
102 | | - */ |
103 | | -function find_repo_root() { |
104 | | - $possible_repo_roots = [ |
105 | | - getcwd(), |
106 | | - ]; |
107 | | - // Check for PWD - some local environments will not have this key. |
108 | | - if (isset($_SERVER['PWD']) && !in_array($_SERVER['PWD'], $possible_repo_roots, TRUE)) { |
109 | | - array_unshift($possible_repo_roots, $_SERVER['PWD']); |
110 | | - } |
111 | | - foreach ($possible_repo_roots as $possible_repo_root) { |
112 | | - if ($repo_root = find_directory_containing_files($possible_repo_root, ['docroot/index.php'])) { |
113 | | - return realpath($repo_root); |
114 | | - } |
115 | | - } |
| 39 | +$input = new ArgvInput(); |
| 40 | +if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) { |
| 41 | + putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); |
| 42 | +} |
116 | 43 |
|
117 | | - return NULL; |
| 44 | +if ($input->hasParameterOption('--no-debug', true)) { |
| 45 | + putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); |
118 | 46 | } |
119 | 47 |
|
120 | | -/** |
121 | | - * Traverses file system upwards in search of a given file. |
122 | | - * |
123 | | - * Begins searching for $file in $working_directory and climbs up directories |
124 | | - * $max_height times, repeating search. |
125 | | - * |
126 | | - * @param string $working_directory |
127 | | - * Working directory. |
128 | | - * @param array $files |
129 | | - * Files. |
130 | | - * @param int $max_height |
131 | | - * Max Height. |
132 | | - * |
133 | | - * @return bool|string |
134 | | - * FALSE if file was not found. Otherwise, the directory path containing the |
135 | | - * file. |
136 | | - */ |
137 | | -function find_directory_containing_files($working_directory, array $files, $max_height = 10) { |
138 | | - // Find the root directory of the git repository containing BLT. |
139 | | - // We traverse the file tree upwards $max_height times until we find |
140 | | - // vendor/bin/blt. |
141 | | - $file_path = $working_directory; |
142 | | - for ($i = 0; $i <= $max_height; $i++) { |
143 | | - if (files_exist($file_path, $files)) { |
144 | | - return $file_path; |
145 | | - } |
| 48 | +(new Dotenv())->bootEnv(dirname(__DIR__).'/.env'); |
| 49 | + |
| 50 | +if ($_SERVER['APP_DEBUG']) { |
| 51 | + umask(0000); |
146 | 52 |
|
147 | | - $file_path = dirname($file_path) . ''; |
| 53 | + if (class_exists(Debug::class)) { |
| 54 | + Debug::enable(); |
148 | 55 | } |
| 56 | +} |
149 | 57 |
|
150 | | - return FALSE; |
| 58 | +$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); |
| 59 | + |
| 60 | +// Handle a cache:clear pseudo command. This isn't implemented as a true console |
| 61 | +// command because a stale or corrupted cache would render it unusable-- |
| 62 | +// precisely when it is needed. |
| 63 | +if (in_array($input->getFirstArgument(), ['cache:clear', 'cc'])) { |
| 64 | + $filesystem = new Filesystem(); |
| 65 | + $cache_dir = $kernel->getCacheDir(); |
| 66 | + $filesystem->remove($cache_dir); |
| 67 | + $filesystem->mkdir($cache_dir); |
| 68 | + $filesystem->touch("{$cache_dir}/.gitkeep"); |
| 69 | + exit; |
151 | 70 | } |
152 | 71 |
|
153 | | -/** |
154 | | - * Determines if an array of files exist in a particular directory. |
155 | | - * |
156 | | - * @param string $dir |
157 | | - * Dir. |
158 | | - * @param array $files |
159 | | - * Files. |
160 | | - * |
161 | | - * @return bool |
162 | | - * Exists. |
163 | | - */ |
164 | | -function files_exist($dir, array $files) { |
165 | | - foreach ($files as $file) { |
166 | | - if (file_exists(Path::join($dir, $file))) { |
167 | | - return TRUE; |
168 | | - } |
| 72 | +$kernel->boot(); |
| 73 | +$container = $kernel->getContainer(); |
| 74 | +/** @var Application $application */ |
| 75 | +$application = $container->get(Application::class); |
| 76 | +$application->setName('Acquia CLI'); |
| 77 | +$application->setVersion('@package_version@'); |
| 78 | +/** @var \Acquia\Cli\Command\Api\ApiCommandHelper $helper */ |
| 79 | +$helper = $container->get(ApiCommandHelper::class); |
| 80 | +$application->addCommands($helper->getApiCommands()); |
| 81 | +// Clean up exceptions thrown during commands. |
| 82 | +$dispatcher = new EventDispatcher(); |
| 83 | +$dispatcher->addListener(ConsoleEvents::ERROR, function (ConsoleErrorEvent $event) { |
| 84 | + $exitCode = $event->getExitCode(); |
| 85 | + $error = $event->getError(); |
| 86 | + // Make OAuth server errors more human-friendly. |
| 87 | + if ($error instanceof IdentityProviderException && $error->getMessage() === 'invalid_client') { |
| 88 | + $event->setError(new AcquiaCliException('Your Cloud API credentials are invalid. Run acli auth:login to reset them.', [], $exitCode)); |
169 | 89 | } |
| 90 | +}); |
| 91 | +$application->setDispatcher($dispatcher); |
170 | 92 |
|
171 | | - return FALSE; |
172 | | -} |
| 93 | +$application->run(); |
0 commit comments