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 ( 49671e...b33618 )
by Anton
02:31
created

Deployer::collectAnonymousStats()   F

Complexity

Conditions 11
Paths 257

Size

Total Lines 35
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
cc 11
eloc 23
nc 257
nop 1
dl 0
loc 35
ccs 0
cts 0
cp 0
crap 132
rs 3.8181
c 0
b 0
f 0

How to fix   Complexity   

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 Deployer\Task;
28
use Deployer\Utility\ProcessOutputPrinter;
29
use Deployer\Utility\ProcessRunner;
30
use Deployer\Utility\Reporter;
31
use Deployer\Utility\Rsync;
32
use Pimple\Container;
33
use Symfony\Component\Console;
34
use Symfony\Component\Console\Input\ArgvInput;
35
use Symfony\Component\Console\Output\ConsoleOutput;
36
use Symfony\Component\Console\Style\SymfonyStyle;
37
use function Deployer\Support\array_merge_alternate;
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 29
    public function __construct(Application $console)
70
    {
71 29
        parent::__construct();
72
73
        /******************************
74
         *           Console          *
75
         ******************************/
76
77
        $this['console'] = function () use ($console) {
78 14
            $console->catchIO(function ($input, $output) {
79 14
                $this['input'] = $input;
80 14
                $this['output'] =  new OutputWatcher($output);
81 14
                return [$this['input'], $this['output']];
82 14
            });
83 14
            return $console;
84
        };
85
86
        /******************************
87
         *           Config           *
88
         ******************************/
89
90 29
        $this['config'] = function () {
91 29
            return new Collection();
92
        };
93 29
        $this->config['ssh_multiplexing'] = true;
94 29
        $this->config['default_stage'] = null;
95
96
        /******************************
97
         *            Core            *
98
         ******************************/
99
100 10
        $this['pop'] = function ($c) {
101 10
            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 10
        $this['processRunner'] = function ($c) {
110 10
            return new ProcessRunner($c['pop']);
111
        };
112 18
        $this['tasks'] = function () {
113 18
            return new Task\TaskCollection();
114
        };
115 18
        $this['hosts'] = function () {
116 18
            return new Host\HostCollection();
117
        };
118 16
        $this['scriptManager'] = function ($c) {
119 16
            return new Task\ScriptManager($c['tasks']);
120
        };
121 14
        $this['hostSelector'] = function ($c) {
122 14
            $defaultStage = $c['config']['default_stage'];
123 14
            if (is_object($defaultStage) && ($defaultStage instanceof \Closure)) {
124
                $defaultStage = call_user_func($defaultStage);
125
            }
126 14
            return new Host\HostSelector($c['hosts'], $defaultStage);
127
        };
128 9
        $this['fail'] = function () {
129 9
            return new Collection();
130
        };
131 14
        $this['informer'] = function ($c) {
132 14
            return new Informer($c['output']);
133
        };
134 11
        $this['seriesExecutor'] = function ($c) {
135 11
            return new SeriesExecutor($c['input'], $c['output'], $c['informer']);
136
        };
137 3
        $this['parallelExecutor'] = function ($c) {
138 3
            return new ParallelExecutor($c['input'], $c['output'], $c['informer'], $c['console']);
139
        };
140
141
        /******************************
142
         *           Logger           *
143
         ******************************/
144
145 11
        $this['log_handler'] = function () {
146 11
            return !empty($this->config['log_file'])
147
                ? new FileHandler($this->config['log_file'])
148 11
                : new NullHandler();
149
        };
150 11
        $this['logger'] = function () {
151 11
            return new Logger($this['log_handler']);
152
        };
153
154
        /******************************
155
         *        Init command        *
156
         ******************************/
157
158 14
        $this['init_command'] = function () {
159 14
            return new InitCommand();
160
        };
161
162 29
        self::$instance = $this;
163 29
    }
164
165
    /**
166
     * @return Deployer
167
     */
168 31
    public static function get()
169
    {
170 31
        return self::$instance;
171
    }
172
173
    /**
174
     * @param string $name
175
     * @param mixed $value
176
     */
177 13
    public static function setDefault($name, $value)
178
    {
179 13
        Deployer::get()->config[$name] = $value;
180 13
    }
181
182
    /**
183
     * @param string $name
184
     * @param mixed $default
185
     * @return mixed
186
     */
187 15
    public static function getDefault($name, $default = null)
188
    {
189 15
        return self::hasDefault($name) ? Deployer::get()->config[$name] : $default;
190
    }
191
192
    /**
193
     * @param string $name
194
     * @return boolean
195
     */
196 15
    public static function hasDefault($name)
197
    {
198 15
        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 14
    public function init()
222
    {
223 14
        $this->addConsoleCommands();
224 14
        $this->getConsole()->add(new WorkerCommand($this));
225 14
        $this->getConsole()->add($this['init_command']);
226 14
        $this->getConsole()->add(new SshCommand($this));
227 14
        $this->getConsole()->add(new RunCommand($this));
228 14
        $this->getConsole()->add(new DebugCommand($this));
229 14
        $this->getConsole()->add(new AutocompleteCommand());
230 14
        $this->getConsole()->afterRun([$this, 'collectAnonymousStats']);
231 14
    }
232
233
    /**
234
     * Transform tasks to console commands.
235
     */
236 14
    public function addConsoleCommands()
237
    {
238 14
        $this->getConsole()->addUserArgumentsAndOptions();
239
240 14
        foreach ($this->tasks as $name => $task) {
241 14
            if ($task->isPrivate()) {
242 9
                continue;
243
            }
244
245 14
            $this->getConsole()->add(new TaskCommand($name, $task->getDescription(), $this));
246
        }
247 14
    }
248
249
    /**
250
     * @param string $name
251
     * @return mixed
252
     * @throws \InvalidArgumentException
253
     */
254 34
    public function __get($name)
255
    {
256 34
        if (isset($this[$name])) {
257 34
            return $this[$name];
258
        } else {
259 1
            throw new \InvalidArgumentException("Property \"$name\" does not exist.");
260
        }
261
    }
262
263
    /**
264
     * @return Application
265
     */
266 14
    public function getConsole()
267
    {
268 14
        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
        if (is_readable($deployFile)) {
323
            // Prevent variable leak into deploy.php file
324
            call_user_func(function () use ($deployFile) {
325
                require $deployFile;
326
            });
327
        }
328
329
        // Run Deployer
330
        $deployer->init();
331
        $console->run($input, $output);
332
    }
333
334
    /**
335
     * Collect anonymous stats about Deployer usage for improving developer experience.
336
     * If you are not comfortable with this, you will always be able to disable this
337
     * by setting `allow_anonymous_stats` to false in your deploy.php file.
338
     *
339
     * @param CommandEvent $commandEvent
340
     * @codeCoverageIgnore
341
     */
342
    public function collectAnonymousStats(CommandEvent $commandEvent)
343
    {
344
        if ($this->config->has('allow_anonymous_stats') && $this->config['allow_anonymous_stats'] === false) {
345
            return;
346
        }
347
348
        $stats = [
349
            'status' => 'success',
350
            'command_name' => $commandEvent->getCommand()->getName(),
351
            'project_hash' => empty($this->config['repository']) ? null : sha1($this->config['repository']),
352
            'hosts_count' => $this->hosts->count(),
353
            'deployer_version' => $this->getConsole()->getVersion(),
354
            'deployer_phar' => $this->getConsole()->isPharArchive(),
355
            'php_version' => phpversion(),
356
            'extension_pcntl' => extension_loaded('pcntl'),
357
            'extension_curl' => extension_loaded('curl'),
358
            '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))),
359
            'exception' => null,
360
        ];
361
362
        if ($commandEvent->getException() !== null) {
363
            $stats['status'] = 'error';
364
            $stats['exception'] = get_class($commandEvent->getException());
365
        }
366
367
        if ($stats['command_name'] === 'init') {
368
            $stats['allow_anonymous_stats'] = $GLOBALS['allow_anonymous_stats'] ?? false;
369
        }
370
371
        if (in_array($stats['command_name'], ['worker', 'list', 'help'], true)) {
372
            return;
373
        }
374
375
        Reporter::report($stats);
376
    }
377
}
378