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.
Passed
Push — master ( f968f3...d9c744 )
by Anton
02:00
created

Deployer::__construct()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 95

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 4.0609

Importance

Changes 0
Metric Value
cc 4
nc 1
nop 1
dl 0
loc 95
ccs 27
cts 32
cp 0.8438
crap 4.0609
rs 8.109
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* (c) Anton Medvedev <[email protected]>
3
 *
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace Deployer;
9
10
use Deployer\Collection\Collection;
11
use Deployer\Console\Application;
12
use Deployer\Console\AutocompleteCommand;
13
use Deployer\Console\CommandEvent;
14
use Deployer\Console\DebugCommand;
15
use Deployer\Console\InitCommand;
16
use Deployer\Console\Output\Informer;
17
use Deployer\Console\Output\OutputWatcher;
18
use Deployer\Console\RunCommand;
19
use Deployer\Console\SshCommand;
20
use Deployer\Console\TaskCommand;
21
use Deployer\Console\WorkerCommand;
22
use Deployer\Executor\ParallelExecutor;
23
use Deployer\Executor\SeriesExecutor;
24
use Deployer\Logger\Handler\FileHandler;
25
use Deployer\Logger\Handler\NullHandler;
26
use Deployer\Logger\Logger;
27
use function Deployer\Support\array_merge_alternate;
28
use Deployer\Task;
29
use Deployer\Utility\ProcessOutputPrinter;
30
use Deployer\Utility\ProcessRunner;
31
use Deployer\Utility\Reporter;
32
use Deployer\Utility\Rsync;
33
use Pimple\Container;
34
use Symfony\Component\Console;
35
use Symfony\Component\Console\Input\ArgvInput;
36
use Symfony\Component\Console\Output\ConsoleOutput;
37
use Symfony\Component\Console\Style\SymfonyStyle;
38
39
/**
40
 * Deployer class represents DI container for configuring
41
 *
42
 * @property Application $console
43
 * @property Task\TaskCollection|Task\Task[] $tasks
44
 * @property Host\HostCollection|Collection|Host\Host[] $hosts
45
 * @property Collection $config
46
 * @property Rsync $rsync
47
 * @property Ssh\Client $sshClient
48
 * @property ProcessRunner $processRunner
49
 * @property Task\ScriptManager $scriptManager
50
 * @property Host\HostSelector $hostSelector
51
 * @property SeriesExecutor $seriesExecutor
52
 * @property ParallelExecutor $parallelExecutor
53
 * @property Informer $informer
54
 * @property Logger $logger
55
 * @property ProcessOutputPrinter $pop
56
 * @property Collection $fail
57
 */
58
class Deployer extends Container
59
{
60
    /**
61
     * Global instance of deployer. It's can be accessed only after constructor call.
62
     * @var Deployer
63
     */
64
    private static $instance;
65
66
    /**
67
     * @param Application $console
68
     */
69 27
    public function __construct(Application $console)
70
    {
71 27
        parent::__construct();
72
73
        /******************************
74
         *           Console          *
75
         ******************************/
76
77
        $this['console'] = function () use ($console) {
78
            $console->catchIO(function ($input, $output) {
79 11
                $this['input'] = $input;
80 11
                $this['output'] =  new OutputWatcher($output);
81 11
                return [$this['input'], $this['output']];
82 12
            });
83 12
            return $console;
84
        };
85
86
        /******************************
87
         *           Config           *
88
         ******************************/
89
90
        $this['config'] = function () {
91 27
            return new Collection();
92
        };
93 27
        $this->config['ssh_multiplexing'] = true;
94 27
        $this->config['default_stage'] = null;
95
96
        /******************************
97
         *            Core            *
98
         ******************************/
99
100
        $this['pop'] = function ($c) {
101 9
            return new ProcessOutputPrinter($c['output'], $c['logger']);
102
        };
103
        $this['sshClient'] = function ($c) {
104
            return new Ssh\Client($c['output'], $c['pop'], $c['config']['ssh_multiplexing']);
105
        };
106
        $this['rsync'] = function ($c) {
107
            return new Rsync($c['pop']);
108
        };
109
        $this['processRunner'] = function ($c) {
110 9
            return new ProcessRunner($c['pop']);
111
        };
112
        $this['tasks'] = function () {
113 16
            return new Task\TaskCollection();
114
        };
115
        $this['hosts'] = function () {
116 16
            return new Host\HostCollection();
117
        };
118
        $this['scriptManager'] = function ($c) {
119 13
            return new Task\ScriptManager($c['tasks']);
120
        };
121
        $this['hostSelector'] = function ($c) {
122 11
            $defaultStage = $c['config']['default_stage'];
123 11
            if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) {
124
                $defaultStage = call_user_func($defaultStage);
125
            }
126 11
            return new Host\HostSelector($c['hosts'], $defaultStage);
127
        };
128
        $this['fail'] = function () {
129 8
            return new Collection();
130
        };
131
        $this['informer'] = function ($c) {
132 11
            return new Informer($c['output']);
133
        };
134
        $this['seriesExecutor'] = function ($c) {
135 11
            return new SeriesExecutor($c['input'], $c['output'], $c['informer']);
136
        };
137
        $this['parallelExecutor'] = function ($c) {
138
            return new ParallelExecutor($c['input'], $c['output'], $c['informer'], $c['console']);
139
        };
140
141
        /******************************
142
         *           Logger           *
143
         ******************************/
144
145
        $this['log_handler'] = function () {
146 9
            return !empty($this->config['log_file'])
147
                ? new FileHandler($this->config['log_file'])
148 9
                : new NullHandler();
149
        };
150
        $this['logger'] = function () {
151 9
            return new Logger($this['log_handler']);
152
        };
153
154
        /******************************
155
         *        Init command        *
156
         ******************************/
157
158
        $this['init_command'] = function () {
159 12
            return new InitCommand();
160
        };
161
162 27
        self::$instance = $this;
163 27
    }
164
165
    /**
166
     * @return Deployer
167
     */
168 29
    public static function get()
169
    {
170 29
        return self::$instance;
171
    }
172
173
    /**
174
     * @param string $name
175
     * @param mixed $value
176
     */
177 11
    public static function setDefault($name, $value)
178
    {
179 11
        Deployer::get()->config[$name] = $value;
180 11
    }
181
182
    /**
183
     * @param string $name
184
     * @param mixed $default
185
     * @return mixed
186
     */
187 14
    public static function getDefault($name, $default = null)
188
    {
189 14
        return self::hasDefault($name) ? Deployer::get()->config[$name] : $default;
190
    }
191
192
    /**
193
     * @param string $name
194
     * @return boolean
195
     */
196 14
    public static function hasDefault($name)
197
    {
198 14
        return isset(Deployer::get()->config[$name]);
199
    }
200
201
    /**
202
     * @param string $name
203
     * @param array $array
204
     */
205 2
    public static function addDefault($name, $array)
206
    {
207 2
        if (self::hasDefault($name)) {
208 2
            $config = self::getDefault($name);
209 2
            if (!is_array($config)) {
210 1
                throw new \RuntimeException("Configuration parameter `$name` isn't array.");
211
            }
212 1
            self::setDefault($name, array_merge_alternate($config, $array));
213
        } else {
214
            self::setDefault($name, $array);
215
        }
216 1
    }
217
218
    /**
219
     * Init console application
220
     */
221 12
    public function init()
222
    {
223 12
        $this->addConsoleCommands();
224 12
        $this->getConsole()->add(new WorkerCommand($this));
225 12
        $this->getConsole()->add($this['init_command']);
226 12
        $this->getConsole()->add(new SshCommand($this));
227 12
        $this->getConsole()->add(new RunCommand($this));
228 12
        $this->getConsole()->add(new DebugCommand($this));
229 12
        $this->getConsole()->add(new AutocompleteCommand());
230 12
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
231 12
    }
232
233
    /**
234
     * Transform tasks to console commands.
235
     */
236 12
    public function addConsoleCommands()
237
    {
238 12
        $this->getConsole()->addUserArgumentsAndOptions();
239
240 12
        foreach ($this->tasks as $name => $task) {
241 12
            if ($task->isPrivate()) {
242 8
                continue;
243
            }
244
245 12
            $this->getConsole()->add(new TaskCommand($name, $task->getDescription(), $this));
246
        }
247 12
    }
248
249
    /**
250
     * @param string $name
251
     * @return mixed
252
     * @throws \InvalidArgumentException
253
     */
254 32
    public function __get($name)
255
    {
256 32
        if (isset($this[$name])) {
257 32
            return $this[$name];
258
        } else {
259 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
260
        }
261
    }
262
263
    /**
264
     * @return Application
265
     */
266 12
    public function getConsole()
267
    {
268 12
        return $this['console'];
269
    }
270
271
    /**
272
     * @return Console\Input\InputInterface
273
     */
274
    public function getInput()
275
    {
276
        return $this['input'];
277
    }
278
279
    /**
280
     * @return Console\Output\OutputInterface
281
     */
282
    public function getOutput()
283
    {
284
        return $this['output'];
285
    }
286
287
    /**
288
     * @param string $name
289
     * @return Console\Helper\HelperInterface
290
     */
291
    public function getHelper($name)
292
    {
293
        return $this->getConsole()->getHelperSet()->get($name);
294
    }
295
296
    /**
297
     * Run Deployer
298
     *
299
     * @param string $version
300
     * @param string $deployFile
301
     */
302
    public static function run($version, $deployFile)
303
    {
304
        // Init Deployer
305
        $console = new Application('Deployer', $version);
306
        $input = new ArgvInput();
307
        $output = new ConsoleOutput();
308
        $deployer = new self($console);
309
310
        // Pretty-print uncaught exceptions in symfony-console
311
        set_exception_handler(function ($e) use ($input, $output, $deployer) {
312
            $io = new SymfonyStyle($input, $output);
313
            $io->block($e->getMessage(), get_class($e), 'fg=white;bg=red', ' ', true);
314
            $io->block($e->getTraceAsString());
315
316
            $deployer->logger->log('['. get_class($e) .'] '. $e->getMessage());
317
            $deployer->logger->log($e->getTraceAsString());
318
            exit(1);
319
        });
320
321
        // Require deploy.php file
322
        self::loadRecipe($deployFile);
323
324
        // Run Deployer
325
        $deployer->init();
326
        $console->run($input, $output);
327
    }
328
329
    /**
330
     * Collect anonymous stats about Deployer usage for improving developer experience.
331
     * If you are not comfortable with this, you will always be able to disable this
332
     * by setting `allow_anonymous_stats` to false in your deploy.php file.
333
     *
334
     * @param CommandEvent $commandEvent
335
     * @codeCoverageIgnore
336
     */
337
    public function collectAnonymousStats(CommandEvent $commandEvent)
338
    {
339
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
340
            return;
341
        }
342
343
        $stats = [
344
            'status' => 'success',
345
            'command_name' => $commandEvent->getCommand()->getName(),
346
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
347
            'hosts_count' => $this->hosts->count(),
348
            'deployer_version' => $this->getConsole()->getVersion(),
349
            'deployer_phar' => $this->getConsole()->isPharArchive(),
350
            'php_version' => phpversion(),
351
            'extension_pcntl' => extension_loaded('pcntl'),
352
            'extension_curl' => extension_loaded('curl'),
353
            'os' => defined('PHP_OS_FAMILY') ? PHP_OS_FAMILY : (stristr(PHP_OS, 'DAR') ? 'OSX' : (stristr(PHP_OS, 'WIN') ? 'WIN' : (stristr(PHP_OS, 'LINUX') ? 'LINUX' : PHP_OS))),
354
            'exception' => null,
355
        ];
356
357
        if ($commandEvent->getException() !== null) {
358
            $stats['status'] = 'error';
359
            $stats['exception'] = get_class($commandEvent->getException());
360
        }
361
362
        if ($stats['command_name'] === 'init') {
363
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
364
        }
365
366
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
367
            return;
368
        }
369
370
        Reporter::report($stats);
371
    }
372
373
    /**
374
     * Load recipe file
375
     *
376
     * @param string $deployFile
377
     *
378
     * @return void
379
     * @codeCoverageIgnore
380
     */
381
    public static function loadRecipe($deployFile)
382
    {
383
        if (is_readable($deployFile)) {
384
            // Prevent variable leak into deploy.php file
385
            call_user_func(function () use ($deployFile) {
386
                // reorder autoload stack.
387
                $originStack = spl_autoload_functions();
388
                require $deployFile;
389
                $newStack = spl_autoload_functions();
390
                if ($originStack[0] !== $newStack[0]) {
391
                    foreach (array_reverse($originStack) as $loader) {
392
                        spl_autoload_unregister($loader);
393
                        spl_autoload_register($loader, true, true);
394
                    }
395
                }
396
            });
397
        }
398
    }
399
}
400