Completed
Pull Request — master (#1)
by Greg
06:16
created

SiteAliasName::__toString()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 3
nc 4
nop 0
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 basename matches 'location'. Location terms
14
 *       may only be used when both the sitename and env are also provided.
15
 *
16
 *   - @env: Look up a named environment in instances where the site root
17
 *       is known (e.g. via cwd). In this form, there is an implicit sitename
18
 *       'self' which is replaced by the actual site alias name once known.
19
 *
20
 *   - @sitename: Provides only the sitename; uses the 'default' environment,
21
 *       or 'dev' if there is no 'default' (or whatever is there if there is
22
 *       only one). With this form, the site alias name has no environment
23
 *       until the appropriate default environment is looked up. This form
24
 *       is checked only after `@env` returns no matches. This form can NOT
25
 *       be filtered with a `location.` term.
26
 *
27
 * There are also two special aliases that are recognized:
28
 *
29
 *   - @self: The current bootstrapped site.
30
 *
31
 *   - @none: No alias ('root' and 'uri' unset).
32
 *
33
 * The special alias forms have no environment component.
34
 *
35
 * When provided to an API, the '@' is optional.
36
 *
37
 * Note that @sitename and @env are ambiguous. Aliases in this form
38
 * (that are not one of the special aliases) will first be assumed
39
 * to be @env, and may be converted to @sitename later.
40
 *
41
 * Note that:
42
 *
43
 * - 'sitename' and 'env' MUST NOT contain a '.' (unlike previous
44
 *     versions of Drush).
45
 * - Users SHOULD NOT create any environments that have the same name
46
 *     as any site name (and visa-versa).
47
 * - All environments in one site record SHOULD be different versions
48
 *     of the same site (e.g. dev / test / live).
49
 */
50
class SiteAliasName
51
{
52
    protected $location;
53
    protected $sitename;
54
    protected $env;
55
56
    /**
57
     * Match the parts of a regex name.
58
     */
59
    const ALIAS_NAME_REGEX = '%^@?([a-zA-Z0-9_-]+)(\.[a-zA-Z0-9_-]+)?(\.[a-zA-Z0-9_-]+)?$%';
60
61
    /**
62
     * Create a new site alias name
63
     *
64
     * @param string $item
65
     * @return SiteAliasName
66
     */
67
    public static function parse($item)
68
    {
69
        $aliasName = new self();
70
        $aliasName->doParse($item);
71
        return $aliasName;
72
    }
73
74
    /**
75
     * Creae a SiteAliasName object from an alias name string.
76
     *
77
     * @param string $sitename The alias name for the site.
78
     * @param string $env The name for the site's environment.
79
     * @param string $location The location filter for the site.
80
     */
81
    public function __construct($sitename = null, $env = null, $location = null)
82
    {
83
        $this->location = $location;
84
        $this->sitename = $sitename;
85
        $this->env = $env;
86
    }
87
88
    /**
89
     * Convert an alias name back to a string.
90
     *
91
     * @return string
92
     */
93
    public function __toString()
94
    {
95
        $parts = [ $this->sitename() ];
96
        if ($this->hasLocation()) {
97
            array_unshift($parts, $this->location());
98
        }
99
        if ($this->hasEnv()) {
100
            $parts[] = $this->env();
101
        }
102
        return '@' . implode('.', $parts);
103
    }
104
105
    /**
106
     * Determine whether or not the provided name is an alias name.
107
     *
108
     * @param string $aliasName
109
     * @return bool
110
     */
111
    public static function isAliasName($aliasName)
112
    {
113
        // Alias names provided by users must begin with '@'
114
        if (empty($aliasName) || ($aliasName[0] != '@')) {
115
            return false;
116
        }
117
        return preg_match(self::ALIAS_NAME_REGEX, $aliasName);
118
    }
119
120
    /**
121
     * Return the sitename portion of the alias name. By definition,
122
     * every alias must have a sitename. If the site name is implicit,
123
     * then 'self' is assumed.
124
     *
125
     * @return string
126
     */
127
    public function sitename()
128
    {
129
        if (empty($this->sitename)) {
130
            return 'self';
131
        }
132
        return $this->sitename;
133
    }
134
135
    /**
136
     * Return the sitename portion of the alias name. By definition,
137
     * every alias must have a sitename. If the site name is implicit,
138
     * then 'self' is assumed.
139
     *
140
     * @return string
141
     */
142
    public function sitenameWithLocation()
143
    {
144
        if (empty($this->sitename)) {
145
            return 'self';
146
        }
147
        return (empty($this->location) ? '' : $this->location . '.') . $this->sitename;
148
    }
149
150
    /**
151
     * Set the sitename portion of the alias name
152
     *
153
     * @param string $sitename
154
     */
155
    public function setSitename($sitename)
156
    {
157
        $this->sitename = $sitename;
158
        return $this;
159
    }
160
161
    /**
162
     * In general, all aliases have a sitename. The time when one will not
163
     * is when an environment name `@env` is used as a shortcut for `@self.env`
164
     *
165
     * @return bool
166
     */
167
    public function hasSitename()
168
    {
169
        return !empty($this->sitename);
170
    }
171
172
    /**
173
     * Return true if this alias name contains an 'env' portion.
174
     *
175
     * @return bool
176
     */
177
    public function hasEnv()
178
    {
179
        return !empty($this->env);
180
    }
181
182
    /**
183
     * Set the environment portion of the alias name.
184
     *
185
     * @param string
186
     */
187
    public function setEnv($env)
188
    {
189
        $this->env = $env;
190
        return $this;
191
    }
192
193
    /**
194
     * Return the 'env' portion of the alias name.
195
     *
196
     * @return string
197
     */
198
    public function env()
199
    {
200
        return $this->env;
201
    }
202
203
    /**
204
     * Return true if this alias name contains a 'location' portion
205
     * @return bool
206
     */
207
    public function hasLocation()
208
    {
209
        return !empty($this->location);
210
    }
211
212
    /**
213
     * Set the 'loation' portion of the alias name.
214
     * @param string $location
215
     */
216
    public function setLocation($location)
217
    {
218
        $this->location = $location;
219
        return $this;
220
    }
221
222
    /**
223
     * Return the 'location' portion of the alias name.
224
     *
225
     * @param string
226
     */
227
    public function location()
228
    {
229
        return $this->location;
230
    }
231
232
    /**
233
     * Return true if this alias name is the 'self' alias.
234
     *
235
     * @return bool
236
     */
237
    public function isSelf()
238
    {
239
        return ($this->sitename == 'self') && !isset($this->env);
240
    }
241
242
    /**
243
     * Return true if this alias name is the 'none' alias.
244
     */
245
    public function isNone()
246
    {
247
        return ($this->sitename == 'none') && !isset($this->env);
248
    }
249
250
    /**
251
     * Convert the parts of an alias name to its various component parts.
252
     *
253
     * @param string $aliasName a string representation of an alias name.
254
     */
255
    protected function doParse($aliasName)
256
    {
257
        // Example contents of $matches:
258
        //
259
        // - a.b:
260
        //     [
261
        //       0 => 'a.b',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
262
        //       1 => 'a',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
263
        //       2 => '.b',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
264
        //     ]
265
        //
266
        // - a:
267
        //     [
268
        //       0 => 'a',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
269
        //       1 => 'a',
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
270
        //     ]
271
        if (!preg_match(self::ALIAS_NAME_REGEX, $aliasName, $matches)) {
272
            return false;
273
        }
274
275
        // Get rid of $matches[0]
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
276
        array_shift($matches);
277
278
        // If $matches contains only one item1, then assume the alias name
279
        // contains only the environment.
280
        if (count($matches) == 1) {
281
            return $this->processSingleItem($matches[0]);
282
        }
283
284
        // If there are three items, then the first is the location.
285
        if (count($matches) == 3) {
286
            $this->location = trim(array_shift($matches), '.');
287
        }
288
289
        // The sitename and env follow the location.
290
        $this->sitename = trim(array_shift($matches), '.');
291
        $this->env = trim(array_shift($matches), '.');
292
        return true;
293
    }
294
295
    /**
296
     * Process an alias name provided as '@sitename'.
297
     *
298
     * @param string $sitename
0 ignored issues
show
Bug introduced by
There is no parameter named $sitename. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
299
     * @return true
300
     */
301
    protected function processSingleItem($item)
302
    {
303
        if ($this->isSpecialAliasName($item)) {
304
            $this->setSitename($item);
305
            return true;
306
        }
307
        $this->sitename = '';
308
        $this->env = $item;
309
        return true;
310
    }
311
312
    /**
313
     * Determine whether the requested name is a special alias name.
314
     *
315
     * @param string $item
316
     * @return boolean
317
     */
318
    protected function isSpecialAliasName($item)
319
    {
320
        return ($item == 'self') || ($item == 'none');
321
    }
322
}
323