1
|
|
|
<?php |
2
|
|
|
namespace Consolidation\SiteAlias; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* Parse a string that contains a site alias name, and provide convenience |
6
|
|
|
* methods to access the parts. |
7
|
|
|
* |
8
|
|
|
* When provided by users, aliases must be in one of the following forms: |
9
|
|
|
* |
10
|
|
|
* - @sitename.env: List only sitename and environment. |
11
|
|
|
* |
12
|
|
|
* - @location.sitename.env: List only sitename and environment. Search |
13
|
|
|
* only those paths where the name of the folder holding the alias |
14
|
|
|
* files matches 'location'. Location terms may only be used when both |
15
|
|
|
* the sitename and env are also provided. |
16
|
|
|
* |
17
|
|
|
* - @env: Look up a named environment in instances where the site root |
18
|
|
|
* is known (e.g. via cwd). In this form, there is an implicit sitename |
19
|
|
|
* 'self' which is replaced by the actual site alias name once known. |
20
|
|
|
* |
21
|
|
|
* - @sitename: Provides only the sitename; uses the 'default' environment, |
22
|
|
|
* or 'dev' if there is no 'default' (or whatever is there if there is |
23
|
|
|
* only one). With this form, the site alias name has no environment |
24
|
|
|
* until the appropriate default environment is looked up. This form |
25
|
|
|
* is checked only after `@env` returns no matches. This form can NOT |
26
|
|
|
* be filtered with a `location.` term. |
27
|
|
|
* |
28
|
|
|
* There are also two special aliases that are recognized: |
29
|
|
|
* |
30
|
|
|
* - @self: The current bootstrapped site. |
31
|
|
|
* |
32
|
|
|
* - @none: No alias ('root' and 'uri' unset). |
33
|
|
|
* |
34
|
|
|
* The special alias forms have no environment component. |
35
|
|
|
* |
36
|
|
|
* When provided to an API, the '@' is optional. |
37
|
|
|
* |
38
|
|
|
* Note that @sitename and @env are ambiguous. Aliases in this form |
39
|
|
|
* (that are not one of the special aliases) will first be assumed |
40
|
|
|
* to be @env, and may be converted to @sitename later. |
41
|
|
|
* |
42
|
|
|
* Note that: |
43
|
|
|
* |
44
|
|
|
* - 'sitename' and 'env' MUST NOT contain a '.' (unlike previous |
45
|
|
|
* versions of Drush). |
46
|
|
|
* - Users SHOULD NOT create any environments that have the same name |
47
|
|
|
* as any site name (and visa-versa). |
48
|
|
|
* - All environments in one site record SHOULD be different versions |
49
|
|
|
* of the same site (e.g. dev / test / live). |
50
|
|
|
*/ |
51
|
|
|
class SiteAliasName |
52
|
|
|
{ |
53
|
|
|
protected $location; |
54
|
|
|
protected $sitename; |
55
|
|
|
protected $env; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Match the parts of a regex name. |
59
|
|
|
*/ |
60
|
|
|
const ALIAS_NAME_REGEX = '%^@?([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+)?(\.[a-zA-Z0-9_-]+)?$%'; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Create a new site alias name |
64
|
|
|
* |
65
|
|
|
* @param string $item |
66
|
|
|
* @return SiteAliasName |
67
|
|
|
*/ |
68
|
|
|
public static function parse($item) |
69
|
|
|
{ |
70
|
|
|
$aliasName = new self(); |
71
|
|
|
$aliasName->doParse($item); |
72
|
|
|
return $aliasName; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* The 'location' of an alias file is defined as being the name |
77
|
|
|
* of the immediate parent of the alias file. e.g. the path |
78
|
|
|
* '$HOME/.drush/sites/isp/mysite.site.yml' would have a location |
79
|
|
|
* of 'isp' and a sitename of 'mysite'. The environments of the site |
80
|
|
|
* are defined by the alias contents. |
81
|
|
|
* |
82
|
|
|
* @param type $path |
83
|
|
|
* @return type |
84
|
|
|
*/ |
85
|
|
|
public static function locationFromPath($path) |
86
|
|
|
{ |
87
|
|
|
$location = ltrim(basename(dirname($path)), '.'); |
88
|
|
|
if (($location === 'sites') || ($location === 'drush')) { |
89
|
|
|
return ''; |
90
|
|
|
} |
91
|
|
|
return $location; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Creae a SiteAliasName object from an alias name string. |
96
|
|
|
* |
97
|
|
|
* @param string $sitename The alias name for the site. |
98
|
|
|
* @param string $env The name for the site's environment. |
99
|
|
|
* @param string $location The location filter for the site. |
100
|
|
|
*/ |
101
|
|
|
public function __construct($sitename = null, $env = null, $location = null) |
102
|
|
|
{ |
103
|
|
|
$this->location = $location; |
104
|
|
|
$this->sitename = $sitename; |
105
|
|
|
$this->env = $env; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Convert an alias name back to a string. |
110
|
|
|
* |
111
|
|
|
* @return string |
112
|
|
|
*/ |
113
|
|
|
public function __toString() |
114
|
|
|
{ |
115
|
|
|
$parts = [ $this->sitename() ]; |
116
|
|
|
if ($this->hasLocation()) { |
117
|
|
|
array_unshift($parts, $this->location()); |
118
|
|
|
} |
119
|
|
|
if ($this->hasEnv()) { |
120
|
|
|
$parts[] = $this->env(); |
121
|
|
|
} |
122
|
|
|
return '@' . implode('.', $parts); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Determine whether or not the provided name is an alias name. |
127
|
|
|
* |
128
|
|
|
* @param string $aliasName |
129
|
|
|
* @return bool |
130
|
|
|
*/ |
131
|
|
|
public static function isAliasName($aliasName) |
132
|
|
|
{ |
133
|
|
|
// Alias names provided by users must begin with '@' |
134
|
|
|
if (empty($aliasName) || ($aliasName[0] != '@')) { |
135
|
|
|
return false; |
136
|
|
|
} |
137
|
|
|
return preg_match(self::ALIAS_NAME_REGEX, $aliasName); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Return the sitename portion of the alias name. By definition, |
142
|
|
|
* every alias must have a sitename. If the site name is implicit, |
143
|
|
|
* then 'self' is assumed. |
144
|
|
|
* |
145
|
|
|
* @return string |
146
|
|
|
*/ |
147
|
|
|
public function sitename() |
148
|
|
|
{ |
149
|
|
|
if (empty($this->sitename)) { |
150
|
|
|
return 'self'; |
151
|
|
|
} |
152
|
|
|
return $this->sitename; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Return the sitename portion of the alias name. By definition, |
157
|
|
|
* every alias must have a sitename. If the site name is implicit, |
158
|
|
|
* then 'self' is assumed. |
159
|
|
|
* |
160
|
|
|
* @return string |
161
|
|
|
*/ |
162
|
|
|
public function sitenameWithLocation() |
163
|
|
|
{ |
164
|
|
|
if (empty($this->sitename)) { |
165
|
|
|
return 'self'; |
166
|
|
|
} |
167
|
|
|
return (empty($this->location) ? '' : $this->location . '.') . $this->sitename; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Set the sitename portion of the alias name |
172
|
|
|
* |
173
|
|
|
* @param string $sitename |
174
|
|
|
*/ |
175
|
|
|
public function setSitename($sitename) |
176
|
|
|
{ |
177
|
|
|
$this->sitename = $sitename; |
178
|
|
|
return $this; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* In general, all aliases have a sitename. The time when one will not |
183
|
|
|
* is when an environment name `@env` is used as a shortcut for `@self.env` |
184
|
|
|
* |
185
|
|
|
* @return bool |
186
|
|
|
*/ |
187
|
|
|
public function hasSitename() |
188
|
|
|
{ |
189
|
|
|
return !empty($this->sitename); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Return true if this alias name contains an 'env' portion. |
194
|
|
|
* |
195
|
|
|
* @return bool |
196
|
|
|
*/ |
197
|
|
|
public function hasEnv() |
198
|
|
|
{ |
199
|
|
|
return !empty($this->env); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Set the environment portion of the alias name. |
204
|
|
|
* |
205
|
|
|
* @param string |
206
|
|
|
*/ |
207
|
|
|
public function setEnv($env) |
208
|
|
|
{ |
209
|
|
|
$this->env = $env; |
210
|
|
|
return $this; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Return the 'env' portion of the alias name. |
215
|
|
|
* |
216
|
|
|
* @return string |
217
|
|
|
*/ |
218
|
|
|
public function env() |
219
|
|
|
{ |
220
|
|
|
return $this->env; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Return true if this alias name contains a 'location' portion |
225
|
|
|
* @return bool |
226
|
|
|
*/ |
227
|
|
|
public function hasLocation() |
228
|
|
|
{ |
229
|
|
|
return !empty($this->location); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Set the 'loation' portion of the alias name. |
234
|
|
|
* @param string $location |
235
|
|
|
*/ |
236
|
|
|
public function setLocation($location) |
237
|
|
|
{ |
238
|
|
|
$this->location = $location; |
239
|
|
|
return $this; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Return the 'location' portion of the alias name. |
244
|
|
|
* |
245
|
|
|
* @param string |
246
|
|
|
*/ |
247
|
|
|
public function location() |
248
|
|
|
{ |
249
|
|
|
return $this->location; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Return true if this alias name is the 'self' alias. |
254
|
|
|
* |
255
|
|
|
* @return bool |
256
|
|
|
*/ |
257
|
|
|
public function isSelf() |
258
|
|
|
{ |
259
|
|
|
return ($this->sitename == 'self') && !isset($this->env); |
260
|
|
|
} |
261
|
|
|
|
262
|
|
|
/** |
263
|
|
|
* Return true if this alias name is the 'none' alias. |
264
|
|
|
*/ |
265
|
|
|
public function isNone() |
266
|
|
|
{ |
267
|
|
|
return ($this->sitename == 'none') && !isset($this->env); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Convert the parts of an alias name to its various component parts. |
272
|
|
|
* |
273
|
|
|
* @param string $aliasName a string representation of an alias name. |
274
|
|
|
*/ |
275
|
|
|
protected function doParse($aliasName) |
276
|
|
|
{ |
277
|
|
|
// Example contents of $matches: |
278
|
|
|
// |
279
|
|
|
// - a.b: |
280
|
|
|
// [ |
281
|
|
|
// 0 => 'a.b', |
|
|
|
|
282
|
|
|
// 1 => 'a', |
|
|
|
|
283
|
|
|
// 2 => '.b', |
|
|
|
|
284
|
|
|
// ] |
285
|
|
|
// |
286
|
|
|
// - a: |
287
|
|
|
// [ |
288
|
|
|
// 0 => 'a', |
|
|
|
|
289
|
|
|
// 1 => 'a', |
|
|
|
|
290
|
|
|
// ] |
291
|
|
|
if (!preg_match(self::ALIAS_NAME_REGEX, $aliasName, $matches)) { |
292
|
|
|
return false; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
// Get rid of $matches[0] |
|
|
|
|
296
|
|
|
array_shift($matches); |
297
|
|
|
|
298
|
|
|
// If $matches contains only one item1, then assume the alias name |
299
|
|
|
// contains only the environment. |
300
|
|
|
if (count($matches) == 1) { |
301
|
|
|
return $this->processSingleItem($matches[0]); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
// If there are three items, then the first is the location. |
305
|
|
|
if (count($matches) == 3) { |
306
|
|
|
$this->location = trim(array_shift($matches), '.'); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
// The sitename and env follow the location. |
310
|
|
|
$this->sitename = trim(array_shift($matches), '.'); |
311
|
|
|
$this->env = trim(array_shift($matches), '.'); |
312
|
|
|
return true; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Process an alias name provided as '@sitename'. |
317
|
|
|
* |
318
|
|
|
* @param string $sitename |
|
|
|
|
319
|
|
|
* @return true |
320
|
|
|
*/ |
321
|
|
|
protected function processSingleItem($item) |
322
|
|
|
{ |
323
|
|
|
if ($this->isSpecialAliasName($item)) { |
324
|
|
|
$this->setSitename($item); |
325
|
|
|
return true; |
326
|
|
|
} |
327
|
|
|
$this->sitename = ''; |
328
|
|
|
$this->env = $item; |
329
|
|
|
return true; |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Determine whether the requested name is a special alias name. |
334
|
|
|
* |
335
|
|
|
* @param string $item |
336
|
|
|
* @return boolean |
337
|
|
|
*/ |
338
|
|
|
protected function isSpecialAliasName($item) |
339
|
|
|
{ |
340
|
|
|
return ($item == 'self') || ($item == 'none'); |
341
|
|
|
} |
342
|
|
|
} |
343
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.