2 namespace Consolidation\SiteAlias;
4 use Symfony\Component\Finder\Finder;
7 * Discover alias files named:
9 * - sitename.site.yml: contains multiple aliases, one for each of the
10 * environments of 'sitename'.
12 * Drush aliases that contain both a site name and an environment
13 * (e.g. @site.env) will cause Drush to find the file named after
14 * the respective site name and retrieve the specified environment
17 * Sites may also define a special alias file self.site.yml, which
18 * may be stored in the drush/sites directory relative to either
19 * the Drupal root or the Composer root of the site. The environments
20 * in this file will be merged with the available environments for
21 * the element @self, however it is defined.
23 class SiteAliasFileDiscovery
25 protected $searchLocations;
26 protected $locationFilter;
29 public function __construct($searchLocations = [], $depth = '<= 1', $locationFilter = null)
31 $this->locationFilter = $locationFilter;
32 $this->searchLocations = $searchLocations;
33 $this->depth = $depth;
37 * Add a location that alias files may be found.
42 public function addSearchLocation($paths)
44 foreach ((array)$paths as $path) {
46 $this->searchLocations[] = $path;
53 * Return all of the paths where alias files may be found.
56 public function searchLocations()
58 return $this->searchLocations;
61 public function locationFilter()
63 return $this->locationFilter;
67 * Set the search depth for finding alias files
69 * @param string|int $depth (@see \Symfony\Component\Finder\Finder::depth)
72 public function depth($depth)
74 $this->depth = $depth;
79 * Only search for aliases that are in alias files stored in directories
80 * whose basename or key matches the specified location.
82 public function filterByLocation($location)
84 if (empty($location)) {
88 return new SiteAliasFileDiscovery($this->searchLocations(), $this->depth, $location);
92 * Find an alias file SITENAME.site.yml in one
93 * of the specified search locations.
95 * @param string $siteName
98 public function find($siteName)
100 return $this->searchForAliasFiles("$siteName.site.yml");
104 * Find an alias file SITENAME.site.yml in one
105 * of the specified search locations.
107 * @param string $siteName
108 * @return string|bool
110 public function findSingleSiteAliasFile($siteName)
112 $matches = $this->find($siteName);
113 if (empty($matches)) {
116 return reset($matches);
120 * Return a list of all SITENAME.site.yml files in any of
121 * the search locations.
125 public function findAllSingleAliasFiles()
127 return $this->searchForAliasFiles('*.site.yml');
131 * Return all of the legacy alias files used in previous Drush versions.
135 public function findAllLegacyAliasFiles()
138 $this->searchForAliasFiles('*.alias.drushrc.php'),
139 $this->searchForAliasFiles('*.aliases.drushrc.php'),
140 $this->searchForAliasFiles('aliases.drushrc.php')
145 * Create a Symfony Finder object to search all available search locations
146 * for the specified search pattern.
148 * @param string $searchPattern
151 protected function createFinder($searchPattern)
153 $finder = new Finder();
155 ->name($searchPattern)
156 ->in($this->searchLocations)
157 ->depth($this->depth);
162 * Return a list of all alias files matching the provided pattern.
164 * @param string $searchPattern
167 protected function searchForAliasFiles($searchPattern)
169 if (empty($this->searchLocations)) {
172 list($match, $site) = $this->splitLocationFromSite($this->locationFilter);
174 $searchPattern = str_replace('*', $site, $searchPattern);
176 $finder = $this->createFinder($searchPattern);
178 foreach ($finder as $file) {
179 $path = $file->getRealPath();
182 // Find every location where the parent directory name matches
183 // with the first part of the search pattern.
184 // In theory we can use $finder->path() instead. That didn't work well,
185 // in practice, though; had trouble correctly escaping the path separators.
186 if (!empty($this->locationFilter)) {
187 $result = array_filter($result, function ($path) use ($match) {
188 return SiteAliasName::locationFromPath($path) === $match;
196 * splitLocationFromSite returns the part of 'site' before the first
197 * '.' as the "path match" component, and the part after the first
198 * '.' as the "site" component.
200 protected function splitLocationFromSite($site)
202 $parts = explode('.', $site, 3) + ['', '', ''];
204 return array_slice($parts, 0, 2);
208 // TODO: Seems like this could just be basename()
209 protected function extractKey($basename, $filenameExensions)
211 return str_replace($filenameExensions, '', $basename);