GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Host   D
last analyzed

Complexity

Total Complexity 59

Size/Duplication

Total Lines 303
Duplicated Lines 0 %

Test Coverage

Coverage 57.14%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 97
c 2
b 0
f 0
dl 0
loc 303
rs 4.08
ccs 88
cts 154
cp 0.5714
wmc 59

42 Methods

Rating   Name   Duplication   Size   Complexity  
A set() 0 10 3
A setHostname() 0 4 1
A getRemoteUser() 0 3 1
A getShell() 0 3 1
A __construct() 0 9 2
A getSshMultiplexing() 0 3 1
A getTag() 0 3 1
A getIdentityFile() 0 3 1
A getHostname() 0 3 1
A setShell() 0 4 1
A getConfigFile() 0 3 1
A hasOwn() 0 3 1
A setRemoteUser() 0 4 1
A add() 0 4 1
A get() 0 3 1
A setTag() 0 4 1
A setSshMultiplexing() 0 4 1
A has() 0 3 1
A __toString() 0 3 1
A setForwardAgent() 0 4 1
A setConfigFile() 0 4 1
A setIdentityFile() 0 4 1
A getAlias() 0 3 1
A getForwardAgent() 0 3 1
A config() 0 3 1
A getPort() 0 3 1
A setPort() 0 4 1
A getShellPath() 0 3 1
A addLabels() 0 5 1
A generateControlPath() 0 16 5
A connectionString() 0 6 2
A getSshArguments() 0 3 1
A getDeployPath() 0 3 1
A getSshControlPath() 0 3 1
B connectionOptionsArray() 0 28 10
A setLabels() 0 4 1
A getLabels() 0 3 1
A setShellPath() 0 4 1
A setSshArguments() 0 4 1
A setSshControlPath() 0 4 1
A setDeployPath() 0 4 1
A connectionOptionsString() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Host often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Host, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
/* (c) Anton Medvedev <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Deployer\Host;
12
13
use Deployer\Configuration;
14
use Deployer\Deployer;
15
use Deployer\Exception\ConfigurationException;
16
use Deployer\Exception\Exception;
17
use Deployer\Task\Context;
18
19
use function Deployer\Support\colorize_host;
20 25
use function Deployer\Support\parse_home_dir;
21
22 25
class Host
23 25
{
24 23
    /**
25
     * @var Configuration $config
26 25
     */
27 25
    private $config;
28 25
29 25
    public function __construct(string $hostname)
30 25
    {
31
        $parent = null;
32 12
        if (Deployer::get()) {
33
            $parent = Deployer::get()->config;
34 12
        }
35
        $this->config = new Configuration($parent);
36
        $this->set('#alias', $hostname);
37 25
        $this->set('hostname', preg_replace('/\/.+$/', '', $hostname));
38
    }
39 25
40 25
    public function __toString(): string
41
    {
42
        return $this->getTag();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getTag() could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
43 1
    }
44
45 1
    public function config(): Configuration
46 1
    {
47
        return $this->config;
48
    }
49
50
    /**
51
     * @param mixed $value
52
     */
53
    public function set(string $name, $value): self
54 19
    {
55
        if ($name === 'alias') {
56 19
            throw new ConfigurationException("Can not update alias of the host.\nThis will change only host own alias,\nbut not the key it is stored in HostCollection.");
57
        }
58
        if ($name === '#alias') {
59 19
            $name = 'alias';
60
        }
61 19
        $this->config->set($name, $value);
62
        return $this;
63
    }
64
65
    public function add(string $name, array $value): self
66
    {
67
        $this->config->add($name, $value);
68
        return $this;
69
    }
70 11
71
    public function has(string $name): bool
72 11
    {
73
        return $this->config->has($name);
74
    }
75 1
76
    public function hasOwn(string $name): bool
77 1
    {
78 1
        return $this->config->hasOwn($name);
79
    }
80
81 3
    /**
82
     * @param mixed|null $default
83 3
     * @return mixed|null
84
     */
85
    public function get(string $name, $default = null)
86 1
    {
87
        return $this->config->get($name, $default);
88 1
    }
89 1
90
    public function getAlias(): ?string
91
    {
92 2
        return $this->config->get('alias', null);
93
    }
94 2
95
    public function setTag(string $tag): self
96
    {
97 1
        $this->config->set('tag', $tag);
98
        return $this;
99 1
    }
100 1
101
    public function getTag(): ?string
102
    {
103 3
        return $this->config->get('tag', colorize_host($this->getAlias()));
0 ignored issues
show
Bug introduced by
It seems like $this->getAlias() can also be of type null; however, parameter $alias of Deployer\Support\colorize_host() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

103
        return $this->config->get('tag', colorize_host(/** @scrutinizer ignore-type */ $this->getAlias()));
Loading history...
104
    }
105 3
106
    public function setHostname(string $hostname): self
107
    {
108 1
        $this->config->set('hostname', $hostname);
109
        return $this;
110 1
    }
111 1
112
    public function getHostname(): ?string
113
    {
114 3
        return $this->config->get('hostname', null);
115
    }
116 3
117
    public function setRemoteUser(string $user): self
118
    {
119 1
        $this->config->set('remote_user', $user);
120
        return $this;
121 1
    }
122 1
123
    public function getRemoteUser(): ?string
124
    {
125 4
        return $this->config->get('remote_user', null);
126
    }
127 4
128
    /**
129
     * @param string|int|null $port
130 1
     * @return $this
131
     */
132 1
    public function setPort($port): self
133 1
    {
134
        $this->config->set('port', $port);
135
        return $this;
136 3
    }
137
138 3
    /**
139
     * @return string|int|null
140
     */
141 1
    public function getPort()
142
    {
143 1
        return $this->config->get('port', null);
144 1
    }
145
146
    public function setConfigFile(string $file): self
147 2
    {
148
        $this->config->set('config_file', $file);
149 2
        return $this;
150
    }
151
152
    public function getConfigFile(): ?string
153
    {
154
        return $this->config->get('config_file', null);
155
    }
156
157
    public function setIdentityFile(string $file): self
158
    {
159
        $this->config->set('identity_file', $file);
160
        return $this;
161
    }
162
163
    public function getIdentityFile(): ?string
164
    {
165
        return $this->config->get('identity_file', null);
166
    }
167
168
    public function setForwardAgent(bool $on): self
169
    {
170
        $this->config->set('forward_agent', $on);
171
        return $this;
172
    }
173
174 2
    public function getForwardAgent(): ?bool
175
    {
176 2
        return $this->config->get('forward_agent', null);
177
    }
178
179 2
    public function setSshMultiplexing(bool $on): self
180
    {
181
        $this->config->set('ssh_multiplexing', $on);
182 3
        return $this;
183
    }
184 3
185 3
    public function getSshMultiplexing(): ?bool
186
    {
187
        return $this->config->get('ssh_multiplexing', null);
188
    }
189
190 2
    public function setShell(string $command): self
191
    {
192 2
        $this->config->set('shell', $command);
193 2
        return $this;
194
    }
195
196
    public function getShell(): ?string
197
    {
198 2
        return $this->config->get('shell', null);
199
    }
200 2
201 2
    public function setShellPath(string $path): self
202
    {
203
        $this->config->set('shell_path', $path);
204 3
        return $this;
205
    }
206 3
207 3
    public function getShellPath(): ?string
208
    {
209
        return $this->config->get('shell_path', null);
210 3
    }
211 2
212
    public function setDeployPath(string $path): self
213
    {
214 3
        $this->config->set('deploy_path', $path);
215 2
        return $this;
216
    }
217
218 3
    public function getDeployPath(): ?string
219 3
    {
220
        return $this->config->get('deploy_path', null);
221 3
    }
222
223 11
    public function setLabels(array $labels): self
224
    {
225 11
        $this->config->set('labels', $labels);
226 10
        return $this;
227
    }
228
229 1
    public function addLabels(array $labels): self
230
    {
231
        $existingLabels = $this->getLabels() ?? [];
232
        $this->setLabels(array_replace_recursive($existingLabels, $labels));
233 1
        return $this;
234
    }
235
236
    public function getLabels(): ?array
237
    {
238
        return $this->config->get('labels', null);
239
    }
240
241
    public function setSshArguments(array $args): self
242
    {
243
        $this->config->set('ssh_arguments', $args);
244
        return $this;
245
    }
246
247
    public function getSshArguments(): ?array
248
    {
249
        return $this->config->get('ssh_arguments', null);
250
    }
251
252
    public function setSshControlPath(string $path): self
253
    {
254
        $this->config->set('ssh_control_path', $path);
255
        return $this;
256
    }
257
258
    public function getSshControlPath(): string
259
    {
260
        return $this->config->get('ssh_control_path', $this->generateControlPath());
261
    }
262
263
    private function generateControlPath(): string
264
    {
265
        $C = $this->getHostname();
266
        if ($this->has('remote_user')) {
267
            $C = $this->getRemoteUser() . '@' . $C;
268
        }
269
        if ($this->has('port')) {
270
            $C .= ':' . $this->getPort();
271
        }
272
273
        // In case of CI environment, lets use shared memory.
274
        if (getenv('CI') && is_writable('/dev/shm')) {
275
            return "/dev/shm/$C";
276
        }
277
278
        return "~/.ssh/$C";
279
    }
280
281
    public function connectionString(): string
282
    {
283
        if ($this->get('remote_user', '') !== '') {
284
            return $this->get('remote_user') . '@' . $this->get('hostname');
285
        }
286
        return $this->get('hostname');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get('hostname') could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
287
    }
288
289
    public function connectionOptionsString(): string
290
    {
291
        return implode(' ', array_map('escapeshellarg', $this->connectionOptionsArray()));
292
    }
293 1
294
    /**
295
     * @return string[]
296
     */
297
    public function connectionOptionsArray(): array
298
    {
299
        $options = [];
300
        if ($this->has('ssh_arguments')) {
301
            foreach ($this->getSshArguments() as $arg) {
302
                $options = array_merge($options, explode(' ', $arg));
303
            }
304
        }
305 1
        if ($this->has('port')) {
306 1
            $options = array_merge($options, ['-p', $this->getPort()]);
307
        }
308 1
        if ($this->has('config_file')) {
309
            $options = array_merge($options, ['-F', parse_home_dir($this->getConfigFile())]);
0 ignored issues
show
Bug introduced by
It seems like $this->getConfigFile() can also be of type null; however, parameter $path of Deployer\Support\parse_home_dir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

309
            $options = array_merge($options, ['-F', parse_home_dir(/** @scrutinizer ignore-type */ $this->getConfigFile())]);
Loading history...
310
        }
311
        if ($this->has('identity_file')) {
312
            $options = array_merge($options, ['-i', parse_home_dir($this->getIdentityFile())]);
313
        }
314
        if ($this->has('forward_agent') && $this->getForwardAgent()) {
315
            $options = array_merge($options, ['-A']);
316
        }
317
        if ($this->has('ssh_multiplexing') && $this->getSshMultiplexing()) {
318
            $options = array_merge($options, [
319
                '-o', 'ControlMaster=auto',
320
                '-o', 'ControlPersist=60',
321
                '-o', 'ControlPath=' . $this->getSshControlPath(),
322
            ]);
323
        }
324
        return $options;
325
    }
326
}
327