2 namespace Drush\Commands\core;
4 use Drush\Commands\DrushCommands;
6 use Drush\SiteAlias\LegacyAliasConverter;
7 use Consolidation\SiteAlias\SiteAliasFileDiscovery;
8 use Consolidation\SiteAlias\SiteAliasManagerAwareInterface;
9 use Consolidation\SiteAlias\SiteAliasManagerAwareTrait;
10 use Consolidation\OutputFormatters\StructuredData\ListDataFromKeys;
11 use Drush\Utils\StringUtils;
12 use Symfony\Component\Console\Input\Input;
13 use Symfony\Component\Console\Output\Output;
14 use Webmozart\PathUtil\Path;
16 class SiteCommands extends DrushCommands implements SiteAliasManagerAwareInterface
18 use SiteAliasManagerAwareTrait;
21 * Set a site alias that will persist for the current session.
23 * Stores the site alias being used in the current session in a temporary
28 * @param string $site Site specification to use, or "-" for previous site. Omit this argument to unset.
31 * @handle-remote-commands
32 * @validate-php-extension posix
33 * @usage drush site:set @dev
34 * Set the current session to use the @dev alias.
35 * @usage drush site:set user@server/path/to/drupal#sitename
36 * Set the current session to use a remote site via site specification.
37 * @usage drush site:set /path/to/drupal#sitename
38 * Set the current session to use a local site via site specification.
39 * @usage drush site:set -
40 * Go back to the previously-set site (like `cd -`).
41 * @usage drush site:set
42 * Without an argument, any existing site becomes unset.
43 * @aliases use,site-set
45 public function siteSet($site = '@none')
47 $filename = $this->getConfig()->get('runtime.site-file-current');
49 $last_site_filename = $this->getConfig()->get('runtime.site-file-previous');
51 if (file_exists($last_site_filename)) {
52 $site = file_get_contents($last_site_filename);
57 if ($site == '@self') {
58 // TODO: Add a method of SiteAliasManager to find a local
59 // alias by directory / by env.cwd.
60 // $path = drush_cwd();
61 // $site_record = drush_sitealias_lookup_alias_by_path($path, true);
62 $site_record = []; // This should be returned as an AliasRecord, not an array.
63 if (isset($site_record['#name'])) {
64 $site = '@' . $site_record['#name']; // $site_record->name();
68 // Using 'site:set @self' is quiet if there is no change.
69 $current = is_file($filename) ? trim(file_get_contents($filename)) : "@none";
70 if ($current == $site) {
74 // Alias record lookup exists.
75 $aliasRecord = $this->siteAliasManager()->get($site);
77 if (file_exists($filename)) {
78 @unlink($last_site_filename);
79 @rename($filename, $last_site_filename);
81 $success_message = dt('Site set to @site', ['@site' => $site]);
82 if ($site == '@none' || $site == '') {
83 if (drush_delete_dir($filename)) {
84 $this->logger()->success(dt('Site unset.'));
86 } elseif (drush_mkdir(dirname($filename), true)) {
87 if (file_put_contents($filename, $site)) {
88 $this->logger()->success($success_message);
89 $this->logger()->info(dt('Site information stored in @file', ['@file' => $filename]));
93 throw new \Exception(dt('Could not find a site definition for @site.', ['@site' => $site]));
99 * Show site alias details, or a list of available site aliases.
101 * @command site:alias
103 * @param string $site Site alias or site specification.
104 * @param array $options
106 * @return \Consolidation\OutputFormatters\StructuredData\ListDataFromKeys
109 * @usage drush site:alias
110 * List all alias records known to drush.
111 * @usage drush site:alias @dev
112 * Print an alias record for the alias 'dev'.
113 * @topics docs:aliases
116 public function siteAlias($site = null, $options = ['format' => 'yaml'])
118 // First check to see if the user provided a specification that matches
120 $aliasList = $this->siteAliasManager()->getMultiple($site);
121 if (is_array($aliasList) && !empty($aliasList)) {
122 return new ListDataFromKeys($this->siteAliasExportList($aliasList, $options));
125 // Next check for a specific alias or a site specification.
126 $aliasRecord = $this->siteAliasManager()->get($site);
127 if ($aliasRecord !== false) {
128 return new ListDataFromKeys([$aliasRecord->name() => $aliasRecord->export()]);
132 throw new \Exception('Site alias not found.');
134 $this->logger()->success('No site aliases found.');
139 * Convert legacy site alias files to the new yml format.
141 * @command site:alias-convert
142 * @param $destination An absolute path to a directory for writing new alias files.If omitted, user will be prompted.
143 * @option sources A comma delimited list of paths to search. Overrides the default paths.
144 * @usage drush site:alias-convert
145 * Find legacy alias files and convert them to yml. You will be prompted for a destination directory.
146 * @usage drush site:alias-convert --simulate
147 * List the files to be converted but do not actually do anything.
149 * @aliases sa-convert,sac
152 public function siteAliasConvert($destination, $options = ['format' => 'yaml', 'sources' => self::REQ])
156 * - remove checksum system?
158 $config = $this->getConfig();
159 if (!$paths = StringUtils::csvToArray($options['sources'])) {
161 $config->get('drush.user-dir'),
162 $config->get('drush.system-dir'),
164 if ($siteRoot = Drush::bootstrapManager()->getRoot()) {
165 $paths = array_merge($paths, [ dirname($siteRoot) . '/drush', "$siteRoot/drush", "$siteRoot/sites/all/drush" ]);
169 // Configure legacy converter.
170 $discovery = new SiteAliasFileDiscovery();
171 array_map([$discovery, 'addSearchLocation'], $paths);
172 $discovery->depth('< 9');
173 $legacyAliasConverter = new LegacyAliasConverter($discovery);
174 $legacyAliasConverter->setTargetDir($destination);
175 $legacyAliasConverter->setSimulate(Drush::simulate());
178 drush_mkdir($destination, true);
179 $legacyFiles = $discovery->findAllLegacyAliasFiles();
180 if ($convertedFiles = $legacyAliasConverter->convert()) {
181 $args = ['!num' => count($convertedFiles), '!dest' => $destination];
182 $message = dt('Created !num file(s) at !dest. Usually, one commits them to /drush/sites in your Composer project.', $args);
183 $this->logger()->success($message);
187 'legacy_files' => $legacyFiles,
188 'converted_files' => $convertedFiles,
194 * @hook interact site:alias-convert
196 public function interactSiteAliasConvert(Input $input, Output $output)
198 if (!$input->getArgument('destination')) {
199 $default = Path::join($this->getConfig()->home(), '.drush/sites');
200 if ($composerRoot = Drush::bootstrapManager()->getComposerRoot()) {
201 $default = Path::join($composerRoot, 'drush/sites');
203 $destination = $this->io()->ask('Absolute path to a directory for writing new alias files', $default);
204 $input->setArgument('destination', $destination);
209 * @param array $aliasList
213 protected function siteAliasExportList($aliasList, $options)
216 function ($aliasRecord) {
217 return $aliasRecord->export();