/** * @inheritdoc */ protected function execute(InputInterface $input, OutputInterface $output) { if (null === $this->command) { $this->command = $this->getApplication()->find($input->getArgument('command_name')); } $config = new CliConfig(); $helper = new DescriptorHelper(); $helper->register('txt', new CustomTextDescriptor($config->get('application.executable'))); $helper->register('md', new CustomMarkdownDescriptor($config->get('application.executable'))); $helper->describe($output, $this->command, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw')]); }
/** * Test that selected user config can override initial config. */ public function testUserConfigOverrides() { $config = new CliConfig([], __DIR__ . '/data/mock-cli-config.yaml', true); $this->assertFalse($config->has('experimental.test')); $home = getenv('HOME'); putenv('HOME=' . __DIR__ . '/data'); $config = new CliConfig([], __DIR__ . '/data/mock-cli-config.yaml', true); putenv('HOME=' . $home); $this->assertTrue($config->has('experimental.test')); $this->assertTrue($config->get('experimental.test')); $this->assertNotEquals($config->get('application.name'), 'Attempted override'); }
/** * Get a user's account info. * * @param ProjectAccess $user * @param bool $reset * * @return array * An array containing 'email' and 'display_name'. */ public function getAccount(ProjectAccess $user, $reset = false) { $cacheKey = 'account:' . $user->id; if ($reset || !($details = self::$cache->fetch($cacheKey))) { $details = $user->getAccount()->getProperties(); self::$cache->save($cacheKey, $details, $this->config->get('api.users_ttl')); } return $details; }
/** * {@inheritdoc} */ public function renderException(\Exception $e, OutputInterface $output) { $output->writeln('', OutputInterface::VERBOSITY_QUIET); do { $exceptionName = get_class($e); if (($pos = strrpos($exceptionName, '\\')) !== false) { $exceptionName = substr($exceptionName, $pos + 1); } $title = sprintf(' [%s] ', $exceptionName); $len = strlen($title); $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX; // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 if (defined('HHVM_VERSION') && $width > 1 << 31) { $width = 1 << 31; } $formatter = $output->getFormatter(); $lines = array(); foreach (preg_split('/\\r?\\n/', $e->getMessage()) as $line) { foreach (str_split($line, $width - 4) as $chunk) { // pre-format lines to get the right string length $lineLength = strlen(preg_replace('/\\[[^m]*m/', '', $formatter->format($chunk))) + 4; $lines[] = array($chunk, $lineLength); $len = max($lineLength, $len); } } $messages = array(); $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len))); $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - strlen($title))))); foreach ($lines as $line) { $messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1]))); } $messages[] = $emptyLine; $messages[] = ''; $output->writeln($messages, OutputInterface::OUTPUT_RAW | OutputInterface::VERBOSITY_QUIET); if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET); // exception related properties $trace = $e->getTrace(); array_unshift($trace, array('function' => '', 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a', 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a', 'args' => array())); for ($i = 0, $count = count($trace); $i < $count; ++$i) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; $function = $trace[$i]['function']; $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET); } $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } while ($e = $e->getPrevious()); if (null !== $this->currentCommand && $this->currentCommand->getName() !== 'welcome') { $output->writeln(sprintf('Usage: <info>%s</info>', $this->currentCommand->getSynopsis()), OutputInterface::VERBOSITY_QUIET); $output->writeln('', OutputInterface::VERBOSITY_QUIET); $output->writeln(sprintf('For more information, type: <info>%s help %s</info>', $this->cliConfig->get('application.executable'), $this->currentCommand->getName()), OutputInterface::VERBOSITY_QUIET); $output->writeln('', OutputInterface::VERBOSITY_QUIET); } }
/** * {@inheritdoc} */ public function getSynopsis($short = false) { $key = $short ? 'short' : 'long'; if (!isset($this->synopsis[$key])) { $aliases = $this->getAliases(); $name = $this->getName(); $shortName = count($aliases) === 1 ? reset($aliases) : $name; $this->synopsis[$key] = trim(sprintf('%s %s %s', self::$config->get('application.executable'), $shortName, $this->getDefinition()->getSynopsis($short))); } return $this->synopsis[$key]; }
/** * Create a settings.local.php for a Drupal site. * * This helps with database setup, etc. */ protected function installDrupalSettingsLocal() { $sitesDefault = $this->getWebRoot() . '/sites/default'; $shared = $this->getSharedDir(); $settingsLocal = $sitesDefault . '/settings.local.php'; if ($shared !== false && is_dir($sitesDefault) && !file_exists($settingsLocal)) { $sharedSettingsLocal = $shared . '/settings.local.php'; $relative = $this->config->get('local.shared_dir') . '/settings.local.php'; if (!file_exists($sharedSettingsLocal)) { $this->output->writeln("Creating file: <info>{$relative}</info>"); $this->fsHelper->copy(CLI_ROOT . '/resources/drupal/settings.local.php.dist', $sharedSettingsLocal); $this->output->writeln('Edit this file to add your database credentials and other Drupal configuration.'); } else { $this->output->writeln("Symlinking <info>{$relative}</info> into sites/default"); } $this->fsHelper->symlink($sharedSettingsLocal, $settingsLocal); } }
/** * Remove old build archives. * * @param string $projectRoot * @param int $maxAge * @param int $keepMax * @param bool $quiet * * @return int[] * The numbers of deleted and kept builds. */ public function cleanArchives($projectRoot, $maxAge = null, $keepMax = 10, $quiet = true) { return $this->cleanDirectory($projectRoot . '/' . $this->config->get('local.archive_dir'), $maxAge, $keepMax, [], $quiet); }
/** * Create Drush aliases for the provided project and environments. * * @param Project $project The project * @param string $projectRoot The project root * @param Environment[] $environments The environments * @param string $original The original group name * @param bool $merge Whether to merge existing alias settings * * @throws \Exception * * @return bool Whether any aliases have been created. */ public function createAliases(Project $project, $projectRoot, $environments, $original = null, $merge = true) { $localProject = new LocalProject(); $config = $localProject->getProjectConfig($projectRoot); $group = !empty($config['alias-group']) ? $config['alias-group'] : $project['id']; $autoRemoveKey = $this->getAutoRemoveKey(); // Ensure the existence of the .drush directory. $drushDir = $this->homeDir . '/.drush'; if (!is_dir($drushDir)) { mkdir($drushDir); } $filename = $drushDir . '/' . $group . '.aliases.drushrc.php'; if (!is_writable($drushDir) || file_exists($filename) && !is_writable($filename)) { throw new \Exception("Drush alias file not writable: {$filename}"); } // Include the previous alias file(s) so that the user's own // modifications can be merged. This may create a PHP parse error for // invalid syntax, but in that case the user could not run Drush anyway. $aliases = []; $originalFiles = [$filename]; if ($original) { array_unshift($originalFiles, $drushDir . '/' . $original . '.aliases.drushrc.php'); } if ($merge) { foreach ($originalFiles as $originalFile) { if (file_exists($originalFile)) { include $originalFile; } } } // Gather applications. $apps = LocalApplication::getApplications($projectRoot, $this->config); $drupalApps = $apps; $multiApp = false; if (count($apps) > 1) { $multiApp = true; // Remove non-Drupal applications. foreach ($drupalApps as $key => $app) { if (!Drupal::isDrupal($app->getRoot())) { unset($drupalApps[$key]); } } } // Generate aliases for the remote environments and applications. $autoGenerated = ''; foreach ($environments as $environment) { foreach ($drupalApps as $app) { $newAlias = $this->generateRemoteAlias($environment, $app, $multiApp); if (!$newAlias) { continue; } $aliasName = $environment->id; if (count($drupalApps) > 1) { $aliasName .= '--' . $app->getId(); } // If the alias already exists, recursively replace existing // settings with new ones. if (isset($aliases[$aliasName])) { $newAlias = array_replace_recursive($aliases[$aliasName], $newAlias); unset($aliases[$aliasName]); } $autoGenerated .= sprintf("\n// Automatically generated alias for the environment \"%s\", application \"%s\".\n", $environment->title, $app->getId()); $autoGenerated .= $this->exportAlias($aliasName, $newAlias); } } // Generate an alias for the local environment, for each app. $localAlias = ''; $localWebRoot = $this->config->get('local.web_root'); foreach ($drupalApps as $app) { $appId = $app->getId(); $localAliasName = '_local'; $webRoot = $projectRoot . '/' . $localWebRoot; if (count($drupalApps) > 1) { $localAliasName .= '--' . $appId; } if ($multiApp) { $webRoot .= '/' . $appId; } $local = ['root' => $webRoot, $autoRemoveKey => true]; if (isset($aliases[$localAliasName])) { $local = array_replace_recursive($aliases[$localAliasName], $local); unset($aliases[$localAliasName]); } $localAlias .= sprintf("\n// Automatically generated alias for the local environment, application \"%s\".\n", $appId) . $this->exportAlias($localAliasName, $local); } // Add any user-defined (pre-existing) aliases. $userDefined = ''; foreach ($aliases as $name => $alias) { if (!empty($alias[$autoRemoveKey])) { // This is probably for a deleted environment. continue; } $userDefined .= $this->exportAlias($name, $alias) . "\n"; } if ($userDefined) { $userDefined = "\n// User-defined aliases.\n" . $userDefined; } $header = "<?php\n" . "/**\n * @file" . "\n * Drush aliases for the " . $this->config->get('service.name') . " project \"{$project->title}\"." . "\n *" . "\n * This file is auto-generated by the " . $this->config->get('application.name') . "." . "\n *" . "\n * WARNING" . "\n * This file may be regenerated at any time." . "\n * - User-defined aliases will be preserved." . "\n * - Aliases for active environments (including any custom additions) will be preserved." . "\n * - Aliases for deleted or inactive environments will be deleted." . "\n * - All other information will be deleted." . "\n */\n\n"; $export = $header . $userDefined . $localAlias . $autoGenerated; $this->writeAliasFile($filename, $export); return true; }