Pull merge.
[yaffs-website] / vendor / consolidation / site-alias / src / SiteAliasFileDiscovery.php
1 <?php
2 namespace Consolidation\SiteAlias;
3
4 use Symfony\Component\Finder\Finder;
5
6 /**
7  * Discover alias files named:
8  *
9  * - sitename.site.yml: contains multiple aliases, one for each of the
10  *     environments of 'sitename'.
11  *
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
15  * record.
16  *
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.
22  */
23 class SiteAliasFileDiscovery
24 {
25     protected $searchLocations;
26     protected $locationFilter;
27     protected $depth;
28
29     public function __construct($searchLocations = [], $depth = '<= 1', $locationFilter = null)
30     {
31         $this->locationFilter = $locationFilter;
32         $this->searchLocations = $searchLocations;
33         $this->depth = $depth;
34     }
35
36     /**
37      * Add a location that alias files may be found.
38      *
39      * @param string $path
40      * @return $this
41      */
42     public function addSearchLocation($paths)
43     {
44         foreach ((array)$paths as $path) {
45             if (is_dir($path)) {
46                 $this->searchLocations[] = $path;
47             }
48         }
49         return $this;
50     }
51
52     /**
53      * Return all of the paths where alias files may be found.
54      * @return string[]
55      */
56     public function searchLocations()
57     {
58         return $this->searchLocations;
59     }
60
61     public function locationFilter()
62     {
63         return $this->locationFilter;
64     }
65
66     /**
67      * Set the search depth for finding alias files
68      *
69      * @param string|int $depth (@see \Symfony\Component\Finder\Finder::depth)
70      * @return $this
71      */
72     public function depth($depth)
73     {
74         $this->depth = $depth;
75         return $this;
76     }
77
78     /**
79      * Only search for aliases that are in alias files stored in directories
80      * whose basename or key matches the specified location.
81      */
82     public function filterByLocation($location)
83     {
84         if (empty($location)) {
85             return $this;
86         }
87
88         return new SiteAliasFileDiscovery($this->searchLocations(), $this->depth, $location);
89     }
90
91     /**
92      * Find an alias file SITENAME.site.yml in one
93      * of the specified search locations.
94      *
95      * @param string $siteName
96      * @return string[]
97      */
98     public function find($siteName)
99     {
100         return $this->searchForAliasFiles("$siteName.site.yml");
101     }
102
103     /**
104      * Find an alias file SITENAME.site.yml in one
105      * of the specified search locations.
106      *
107      * @param string $siteName
108      * @return string|bool
109      */
110     public function findSingleSiteAliasFile($siteName)
111     {
112         $matches = $this->find($siteName);
113         if (empty($matches)) {
114             return false;
115         }
116         return reset($matches);
117     }
118
119     /**
120      * Return a list of all SITENAME.site.yml files in any of
121      * the search locations.
122      *
123      * @return string[]
124      */
125     public function findAllSingleAliasFiles()
126     {
127         return $this->searchForAliasFiles('*.site.yml');
128     }
129
130     /**
131      * Return all of the legacy alias files used in previous Drush versions.
132      *
133      * @return string[]
134      */
135     public function findAllLegacyAliasFiles()
136     {
137         return array_merge(
138             $this->searchForAliasFiles('*.alias.drushrc.php'),
139             $this->searchForAliasFiles('*.aliases.drushrc.php'),
140             $this->searchForAliasFiles('aliases.drushrc.php')
141         );
142     }
143
144     /**
145      * Create a Symfony Finder object to search all available search locations
146      * for the specified search pattern.
147      *
148      * @param string $searchPattern
149      * @return Finder
150      */
151     protected function createFinder($searchPattern)
152     {
153         $finder = new Finder();
154         $finder->files()
155             ->name($searchPattern)
156             ->in($this->searchLocations)
157             ->depth($this->depth);
158         return $finder;
159     }
160
161     /**
162      * Return a list of all alias files matching the provided pattern.
163      *
164      * @param string $searchPattern
165      * @return string[]
166      */
167     protected function searchForAliasFiles($searchPattern)
168     {
169         if (empty($this->searchLocations)) {
170             return [];
171         }
172         list($match, $site) = $this->splitLocationFromSite($this->locationFilter);
173         if (!empty($site)) {
174             $searchPattern = str_replace('*', $site, $searchPattern);
175         }
176         $finder = $this->createFinder($searchPattern);
177         $result = [];
178         foreach ($finder as $file) {
179             $path = $file->getRealPath();
180             $result[] = $path;
181         }
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;
189             });
190         }
191
192         return $result;
193     }
194
195     /**
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.
199      */
200     protected function splitLocationFromSite($site)
201     {
202         $parts = explode('.', $site, 3) + ['', '', ''];
203
204         return array_slice($parts, 0, 2);
205     }
206
207
208     // TODO: Seems like this could just be basename()
209     protected function extractKey($basename, $filenameExensions)
210     {
211         return str_replace($filenameExensions, '', $basename);
212     }
213 }