Passed
Push — master ( 304892...44e430 )
by Raffael
04:59
created

Cli   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 17
lcom 1
cbo 1
dl 0
loc 162
ccs 0
cts 88
cp 0
rs 10
c 1
b 1
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
B process() 0 25 3
A executeCommand() 0 9 2
A routeCommand() 0 14 2
B reduceLogLevel() 0 14 6
A configureLogger() 0 21 2
A setExceptionHandler() 0 11 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * balloon
7
 *
8
 * @copyright   Copryright (c) 2012-2018 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Balloon\Bootstrap;
13
14
use Bramus\Monolog\Formatter\ColoredLineFormatter;
15
use GetOpt\GetOpt;
16
use Monolog\Handler\FilterHandler;
17
use Monolog\Handler\StreamHandler;
18
use Monolog\Logger;
19
use Psr\Container\ContainerInterface;
20
use Psr\Log\LoggerInterface;
21
22
class Cli extends AbstractBootstrap
23
{
24
    /**
25
     * Getopt.
26
     *
27
     * @var GetOpt
28
     */
29
    protected $getopt;
30
31
    /**
32
     * Container.
33
     *
34
     * @var ContainerInterface
35
     */
36
    protected $container;
37
38
    /**
39
     * Cli.
40
     *
41
     * @param LoggerInterface    $logger
42
     * @param Getopt             $getopt
43
     * @param ContainerInterface $container
44
     */
45
    public function __construct(LoggerInterface $logger, GetOpt $getopt, ContainerInterface $container)
46
    {
47
        $this->logger = $logger;
48
        $this->getopt = $getopt;
49
        $this->container = $container;
50
        $this->reduceLogLevel();
51
52
        $this->setExceptionHandler();
53
        $this->setErrorHandler();
54
    }
55
56
    /**
57
     * Process.
58
     *
59
     * @return Cli
60
     */
61
    public function process(): Cli
62
    {
63
        $this->getopt->addOption(['v', 'verbose', GetOpt::NO_ARGUMENT, 'Verbose']);
64
        $this->getopt->addOption(['h', 'help', GetOpt::NO_ARGUMENT, 'Help']);
65
66
        try {
67
            $this->getopt->process();
68
        } catch (\Exception $e) {
69
            $this->logger->debug('Some cli input failed', [
70
                'category' => get_class($this),
71
                'exception' => $e,
72
            ]);
73
        }
74
75
        if ($this->getopt->getOption('help')) {
76
            echo $this->getopt->getHelpText();
77
78
            return $this;
79
        }
80
81
        $this->configureLogger($this->getopt->getOption('verbose'));
82
        $this->routeCommand();
83
84
        return $this;
85
    }
86
87
    /**
88
     * Execute class action.
89
     *
90
     * @param object $command
91
     */
92
    protected function executeCommand($command)
93
    {
94
        $action = $this->getopt->getOperand('action');
95
        if (is_callable([&$command, $action])) {
96
            return call_user_func_array([&$command, $action], []);
97
        }
98
99
        return call_user_func_array([&$command, 'help'], []);
100
    }
101
102
    /**
103
     * Route command.
104
     */
105
    protected function routeCommand()
106
    {
107
        $cmd = $this->getopt->getCommand();
108
        if ($cmd === null) {
109
            echo $this->getopt->getHelpText();
110
111
            return null;
112
        }
113
114
        $handler = $cmd->getHandler();
115
        $class = $this->container->get($handler);
116
117
        return $this->executeCommand($class);
118
    }
119
120
    /**
121
     * Remove logger.
122
     *
123
     * @return Cli
124
     */
125
    protected function reduceLogLevel(): self
126
    {
127
        foreach ($this->logger->getHandlers() as $handler) {
128
            if ($handler instanceof StreamHandler) {
0 ignored issues
show
Bug introduced by
The class Monolog\Handler\StreamHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
129
                if ($handler->getUrl() === 'php://stderr' || $handler->getUrl() === 'php://stdout') {
130
                    $handler->setLevel(600);
131
                }
132
            } elseif ($handler instanceof FilterHandler) {
0 ignored issues
show
Bug introduced by
The class Monolog\Handler\FilterHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
133
                $handler->setAcceptedLevels(1000, 1000);
134
            }
135
        }
136
137
        return $this;
138
    }
139
140
    /**
141
     * Configure cli logger.
142
     *
143
     * @return Cli
144
     */
145
    protected function configureLogger(?int $level = null): self
146
    {
147
        if (null === $level) {
148
            $level = 400;
149
        } else {
150
            $level = (4 - $level) * 100;
151
        }
152
153
        $formatter = new ColoredLineFormatter();
154
        $handler = new StreamHandler('php://stderr', Logger::EMERGENCY);
155
        $handler->setFormatter($formatter);
156
        $this->logger->pushHandler($handler);
157
158
        $handler = new StreamHandler('php://stdout', $level);
159
        $filter = new FilterHandler($handler, $level, Logger::ERROR);
160
        $handler->setFormatter($formatter);
161
162
        $this->logger->pushHandler($filter);
163
164
        return $this;
165
    }
166
167
    /**
168
     * Set exception handler.
169
     *
170
     * @return Cli
171
     */
172
    protected function setExceptionHandler(): self
173
    {
174
        set_exception_handler(function ($e) {
175
            $this->logger->emergency('uncaught exception: '.$e->getMessage(), [
176
                'category' => get_class($this),
177
                'exception' => $e,
178
            ]);
179
        });
180
181
        return $this;
182
    }
183
}
184