PHPConsoleHandler::initConnector()   F
last analyzed

Complexity

Conditions 17
Paths 3078

Size

Total Lines 53
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 35
c 0
b 0
f 0
nc 3078
nop 1
dl 0
loc 53
rs 1.0499

How to fix   Long Method    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
3
/*
4
 * This file is part of the Monolog package.
5
 *
6
 * (c) Jordi Boggiano <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Monolog\Handler;
13
14
use Exception;
15
use Monolog\Formatter\LineFormatter;
16
use Monolog\Logger;
17
use PhpConsole\Connector;
0 ignored issues
show
Bug introduced by
The type PhpConsole\Connector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use PhpConsole\Handler;
0 ignored issues
show
Bug introduced by
The type PhpConsole\Handler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use PhpConsole\Helper;
0 ignored issues
show
Bug introduced by
The type PhpConsole\Helper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
21
/**
22
 * Monolog handler for Google Chrome extension "PHP Console"
23
 *
24
 * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
25
 *
26
 * Usage:
27
 * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
28
 * 2. See overview https://github.com/barbushin/php-console#overview
29
 * 3. Install PHP Console library https://github.com/barbushin/php-console#installation
30
 * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
31
 *
32
 *      $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
33
 *      \Monolog\ErrorHandler::register($logger);
34
 *      echo $undefinedVar;
35
 *      $logger->addDebug('SELECT * FROM users', array('db', 'time' => 0.012));
36
 *      PC::debug($_SERVER); // PHP Console debugger for any type of vars
37
 *
38
 * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
39
 */
40
class PHPConsoleHandler extends AbstractProcessingHandler
41
{
42
    private $options = array(
43
        'enabled' => true, // bool Is PHP Console server enabled
44
        'classesPartialsTraceIgnore' => array('Monolog\\'), // array Hide calls of classes started with...
45
        'debugTagsKeysInContext' => array(0, 'tag'), // bool Is PHP Console server enabled
46
        'useOwnErrorsHandler' => false, // bool Enable errors handling
47
        'useOwnExceptionsHandler' => false, // bool Enable exceptions handling
48
        'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths
49
        'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
50
        'serverEncoding' => null, // string|null Server internal encoding
51
        'headersLimit' => null, // int|null Set headers size limit for your web-server
52
        'password' => null, // string|null Protect PHP Console connection by password
53
        'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed
54
        'ipMasks' => array(), // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
55
        'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
56
        'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
57
        'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level
58
        'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number
59
        'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item
60
        'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON
61
        'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug
62
        'dataStorage' => null, // PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ)
63
    );
64
65
    /** @var Connector */
66
    private $connector;
67
68
    /**
69
     * @param  array          $options   See \Monolog\Handler\PHPConsoleHandler::$options for more details
70
     * @param  Connector|null $connector Instance of \PhpConsole\Connector class (optional)
71
     * @param  int            $level
72
     * @param  bool           $bubble
73
     * @throws Exception
74
     */
75
    public function __construct(array $options = array(), Connector $connector = null, $level = Logger::DEBUG, $bubble = true)
76
    {
77
        if (!class_exists('PhpConsole\Connector')) {
78
            throw new Exception('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
79
        }
80
        parent::__construct($level, $bubble);
81
        $this->options = $this->initOptions($options);
82
        $this->connector = $this->initConnector($connector);
83
    }
84
85
    private function initOptions(array $options)
86
    {
87
        $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
88
        if ($wrongOptions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $wrongOptions of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
89
            throw new Exception('Unknown options: ' . implode(', ', $wrongOptions));
90
        }
91
92
        return array_replace($this->options, $options);
93
    }
94
95
    private function initConnector(Connector $connector = null)
96
    {
97
        if (!$connector) {
98
            if ($this->options['dataStorage']) {
99
                Connector::setPostponeStorage($this->options['dataStorage']);
100
            }
101
            $connector = Connector::getInstance();
102
        }
103
104
        if ($this->options['registerHelper'] && !Helper::isRegistered()) {
105
            Helper::register();
106
        }
107
108
        if ($this->options['enabled'] && $connector->isActiveClient()) {
109
            if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
110
                $handler = Handler::getInstance();
111
                $handler->setHandleErrors($this->options['useOwnErrorsHandler']);
112
                $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
113
                $handler->start();
114
            }
115
            if ($this->options['sourcesBasePath']) {
116
                $connector->setSourcesBasePath($this->options['sourcesBasePath']);
117
            }
118
            if ($this->options['serverEncoding']) {
119
                $connector->setServerEncoding($this->options['serverEncoding']);
120
            }
121
            if ($this->options['password']) {
122
                $connector->setPassword($this->options['password']);
123
            }
124
            if ($this->options['enableSslOnlyMode']) {
125
                $connector->enableSslOnlyMode();
126
            }
127
            if ($this->options['ipMasks']) {
128
                $connector->setAllowedIpMasks($this->options['ipMasks']);
129
            }
130
            if ($this->options['headersLimit']) {
131
                $connector->setHeadersLimit($this->options['headersLimit']);
132
            }
133
            if ($this->options['detectDumpTraceAndSource']) {
134
                $connector->getDebugDispatcher()->detectTraceAndSource = true;
135
            }
136
            $dumper = $connector->getDumper();
137
            $dumper->levelLimit = $this->options['dumperLevelLimit'];
138
            $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
139
            $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
140
            $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
141
            $dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
142
            if ($this->options['enableEvalListener']) {
143
                $connector->startEvalRequestsListener();
144
            }
145
        }
146
147
        return $connector;
148
    }
149
150
    public function getConnector()
151
    {
152
        return $this->connector;
153
    }
154
155
    public function getOptions()
156
    {
157
        return $this->options;
158
    }
159
160
    public function handle(array $record)
161
    {
162
        if ($this->options['enabled'] && $this->connector->isActiveClient()) {
163
            return parent::handle($record);
164
        }
165
166
        return !$this->bubble;
167
    }
168
169
    /**
170
     * Writes the record down to the log of the implementing handler
171
     *
172
     * @param  array $record
173
     * @return void
174
     */
175
    protected function write(array $record)
176
    {
177
        if ($record['level'] < Logger::NOTICE) {
178
            $this->handleDebugRecord($record);
179
        } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof Exception) {
180
            $this->handleExceptionRecord($record);
181
        } else {
182
            $this->handleErrorRecord($record);
183
        }
184
    }
185
186
    private function handleDebugRecord(array $record)
187
    {
188
        $tags = $this->getRecordTags($record);
189
        $message = $record['message'];
190
        if ($record['context']) {
191
            $message .= ' ' . json_encode($this->connector->getDumper()->dump(array_filter($record['context'])));
192
        }
193
        $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
194
    }
195
196
    private function handleExceptionRecord(array $record)
197
    {
198
        $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
199
    }
200
201
    private function handleErrorRecord(array $record)
202
    {
203
        $context = $record['context'];
204
205
        $this->connector->getErrorsDispatcher()->dispatchError(
206
            isset($context['code']) ? $context['code'] : null,
207
            isset($context['message']) ? $context['message'] : $record['message'],
208
            isset($context['file']) ? $context['file'] : null,
209
            isset($context['line']) ? $context['line'] : null,
210
            $this->options['classesPartialsTraceIgnore']
211
        );
212
    }
213
214
    private function getRecordTags(array &$record)
215
    {
216
        $tags = null;
217
        if (!empty($record['context'])) {
218
            $context = & $record['context'];
219
            foreach ($this->options['debugTagsKeysInContext'] as $key) {
220
                if (!empty($context[$key])) {
221
                    $tags = $context[$key];
222
                    if ($key === 0) {
223
                        array_shift($context);
224
                    } else {
225
                        unset($context[$key]);
226
                    }
227
                    break;
228
                }
229
            }
230
        }
231
232
        return $tags ?: strtolower($record['level_name']);
233
    }
234
235
    /**
236
     * {@inheritDoc}
237
     */
238
    protected function getDefaultFormatter()
239
    {
240
        return new LineFormatter('%message%');
241
    }
242
}
243