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.

Issues (910)

framework/log/Target.php (2 issues)

1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\log;
9
10
use Yii;
11
use yii\base\Component;
12
use yii\base\InvalidConfigException;
13
use yii\helpers\ArrayHelper;
14
use yii\helpers\VarDumper;
15
use yii\web\Request;
16
17
/**
18
 * Target is the base class for all log target classes.
19
 *
20
 * A log target object will filter the messages logged by [[Logger]] according
21
 * to its [[levels]] and [[categories]] properties. It may also export the filtered
22
 * messages to specific destination defined by the target, such as emails, files.
23
 *
24
 * Level filter and category filter are combinatorial, i.e., only messages
25
 * satisfying both filter conditions will be handled. Additionally, you
26
 * may specify [[except]] to exclude messages of certain categories.
27
 *
28
 * @property bool $enabled Indicates whether this log target is enabled. Defaults to true. Note that the type
29
 * of this property differs in getter and setter. See [[getEnabled()]] and [[setEnabled()]] for details.
30
 * @property int $levels The message levels that this target is interested in. This is a bitmap of level
31
 * values. Defaults to 0, meaning all available levels. Note that the type of this property differs in getter and
32
 * setter. See [[getLevels()]] and [[setLevels()]] for details.
33
 *
34
 * For more details and usage information on Target, see the [guide article on logging & targets](guide:runtime-logging).
35
 *
36
 * @author Qiang Xue <[email protected]>
37
 * @since 2.0
38
 */
39
abstract class Target extends Component
40
{
41
    /**
42
     * @var array list of message categories that this target is interested in. Defaults to empty, meaning all categories.
43
     * You can use an asterisk at the end of a category so that the category may be used to
44
     * match those categories sharing the same common prefix. For example, 'yii\db\*' will match
45
     * categories starting with 'yii\db\', such as 'yii\db\Connection'.
46
     */
47
    public $categories = [];
48
    /**
49
     * @var array list of message categories that this target is NOT interested in. Defaults to empty, meaning no uninteresting messages.
50
     * If this property is not empty, then any category listed here will be excluded from [[categories]].
51
     * You can use an asterisk at the end of a category so that the category can be used to
52
     * match those categories sharing the same common prefix. For example, 'yii\db\*' will match
53
     * categories starting with 'yii\db\', such as 'yii\db\Connection'.
54
     * @see categories
55
     */
56
    public $except = [];
57
    /**
58
     * @var array list of the PHP predefined variables that should be logged in a message.
59
     * Note that a variable must be accessible via `$GLOBALS`. Otherwise it won't be logged.
60
     *
61
     * Defaults to `['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER']`.
62
     *
63
     * Since version 2.0.9 additional syntax can be used:
64
     * Each element could be specified as one of the following:
65
     *
66
     * - `var` - `var` will be logged.
67
     * - `var.key` - only `var[key]` key will be logged.
68
     * - `!var.key` - `var[key]` key will be excluded.
69
     *
70
     * Note that if you need $_SESSION to logged regardless if session was used you have to open it right at
71
     * the start of your request.
72
     *
73
     * @see \yii\helpers\ArrayHelper::filter()
74
     */
75
    public $logVars = [
76
        '_GET',
77
        '_POST',
78
        '_FILES',
79
        '_COOKIE',
80
        '_SESSION',
81
        '_SERVER',
82
    ];
83
    /**
84
     * @var array list of the PHP predefined variables that should NOT be logged "as is" and should always be replaced
85
     * with a mask `***` before logging, when exist.
86
     *
87
     * Defaults to `[ '_SERVER.HTTP_AUTHORIZATION', '_SERVER.PHP_AUTH_USER', '_SERVER.PHP_AUTH_PW']`
88
     *
89
     * Each element could be specified as one of the following:
90
     *
91
     * - `var` - `var` will be logged as `***`
92
     * - `var.key` - only `var[key]` will be logged as `***`
93
     *
94
     * @since 2.0.16
95
     */
96
    public $maskVars = [
97
        '_SERVER.HTTP_AUTHORIZATION',
98
        '_SERVER.PHP_AUTH_USER',
99
        '_SERVER.PHP_AUTH_PW',
100
    ];
101
    /**
102
     * @var callable|null a PHP callable that returns a string to be prefixed to every exported message.
103
     *
104
     * If not set, [[getMessagePrefix()]] will be used, which prefixes the message with context information
105
     * such as user IP, user ID and session ID.
106
     *
107
     * The signature of the callable should be `function ($message)`.
108
     */
109
    public $prefix;
110
    /**
111
     * @var int how many messages should be accumulated before they are exported.
112
     * Defaults to 1000. Note that messages will always be exported when the application terminates.
113
     * Set this property to be 0 if you don't want to export messages until the application terminates.
114
     */
115
    public $exportInterval = 1000;
116
    /**
117
     * @var array the messages that are retrieved from the logger so far by this log target.
118
     * Please refer to [[Logger::messages]] for the details about the message structure.
119
     */
120
    public $messages = [];
121
    /**
122
     * @var bool whether to log time with microseconds.
123
     * Defaults to false.
124
     * @since 2.0.13
125
     */
126
    public $microtime = false;
127
128
    private $_levels = 0;
129
    private $_enabled = true;
130
131
132
    /**
133
     * Exports log [[messages]] to a specific destination.
134
     * Child classes must implement this method.
135
     */
136
    abstract public function export();
137
138
    /**
139
     * Processes the given log messages.
140
     * This method will filter the given messages with [[levels]] and [[categories]].
141
     * And if requested, it will also export the filtering result to specific medium (e.g. email).
142
     * @param array $messages log messages to be processed. See [[Logger::messages]] for the structure
143
     * of each message.
144
     * @param bool $final whether this method is called at the end of the current application
145
     */
146 413
    public function collect($messages, $final)
147
    {
148 413
        $this->messages = array_merge($this->messages, static::filterMessages($messages, $this->getLevels(), $this->categories, $this->except));
149 413
        $count = count($this->messages);
150 413
        if ($count > 0 && ($final || $this->exportInterval > 0 && $count >= $this->exportInterval)) {
151 27
            if (($context = $this->getContextMessage()) !== '') {
152 7
                $this->messages[] = [$context, Logger::LEVEL_INFO, 'application', YII_BEGIN_TIME, [], 0];
153
            }
154
            // set exportInterval to 0 to avoid triggering export again while exporting
155 27
            $oldExportInterval = $this->exportInterval;
156 27
            $this->exportInterval = 0;
157 27
            $this->export();
158 27
            $this->exportInterval = $oldExportInterval;
159
160 27
            $this->messages = [];
161
        }
162
    }
163
164
    /**
165
     * Generates the context information to be logged.
166
     * The default implementation will dump user information, system variables, etc.
167
     * @return string the context information. If an empty string, it means no context information.
168
     */
169 28
    protected function getContextMessage()
170
    {
171 28
        $context = ArrayHelper::filter($GLOBALS, $this->logVars);
172 28
        foreach ($this->maskVars as $var) {
173 28
            if (ArrayHelper::getValue($context, $var) !== null) {
174 1
                ArrayHelper::setValue($context, $var, '***');
175
            }
176
        }
177 28
        $result = [];
178 28
        foreach ($context as $key => $value) {
179 8
            $result[] = "\${$key} = " . VarDumper::dumpAsString($value);
180
        }
181
182 28
        return implode("\n\n", $result);
183
    }
184
185
    /**
186
     * @return int the message levels that this target is interested in. This is a bitmap of
187
     * level values. Defaults to 0, meaning all available levels.
188
     */
189 415
    public function getLevels()
190
    {
191 415
        return $this->_levels;
192
    }
193
194
    /**
195
     * Sets the message levels that this target is interested in.
196
     *
197
     * The parameter can be either an array of interested level names or an integer representing
198
     * the bitmap of the interested level values. Valid level names include: 'error',
199
     * 'warning', 'info', 'trace' and 'profile'; valid level values include:
200
     * [[Logger::LEVEL_ERROR]], [[Logger::LEVEL_WARNING]], [[Logger::LEVEL_INFO]],
201
     * [[Logger::LEVEL_TRACE]] and [[Logger::LEVEL_PROFILE]].
202
     *
203
     * For example,
204
     *
205
     * ```php
206
     * ['error', 'warning']
207
     * // which is equivalent to:
208
     * Logger::LEVEL_ERROR | Logger::LEVEL_WARNING
209
     * ```
210
     *
211
     * @param array|int $levels message levels that this target is interested in.
212
     * @throws InvalidConfigException if $levels value is not correct.
213
     */
214 23
    public function setLevels($levels)
215
    {
216 23
        static $levelMap = [
217 23
            'error' => Logger::LEVEL_ERROR,
218 23
            'warning' => Logger::LEVEL_WARNING,
219 23
            'info' => Logger::LEVEL_INFO,
220 23
            'trace' => Logger::LEVEL_TRACE,
221 23
            'profile' => Logger::LEVEL_PROFILE,
222 23
        ];
223 23
        if (is_array($levels)) {
224 10
            $this->_levels = 0;
225 10
            foreach ($levels as $level) {
226 10
                if (isset($levelMap[$level])) {
227 10
                    $this->_levels |= $levelMap[$level];
228
                } else {
229 1
                    throw new InvalidConfigException("Unrecognized level: $level");
230
                }
231
            }
232
        } else {
233 13
            $bitmapValues = array_reduce($levelMap, function ($carry, $item) {
234 13
                return $carry | $item;
235 13
            });
236 13
            if (!($bitmapValues & $levels) && $levels !== 0) {
237 1
                throw new InvalidConfigException("Incorrect $levels value");
238
            }
239 13
            $this->_levels = $levels;
240
        }
241
    }
242
243
    /**
244
     * Filters the given messages according to their categories and levels.
245
     * @param array $messages messages to be filtered.
246
     * The message structure follows that in [[Logger::messages]].
247
     * @param int $levels the message levels to filter by. This is a bitmap of
248
     * level values. Value 0 means allowing all levels.
249
     * @param array $categories the message categories to filter by. If empty, it means all categories are allowed.
250
     * @param array $except the message categories to exclude. If empty, it means all categories are allowed.
251
     * @return array the filtered messages.
252
     */
253 413
    public static function filterMessages($messages, $levels = 0, $categories = [], $except = [])
254
    {
255 413
        foreach ($messages as $i => $message) {
256 413
            if ($levels && !($levels & $message[1])) {
257 382
                unset($messages[$i]);
258 382
                continue;
259
            }
260
261 326
            $matched = empty($categories);
262 326
            foreach ($categories as $category) {
263 310
                if ($message[2] === $category || !empty($category) && substr_compare($category, '*', -1, 1) === 0 && strpos($message[2], rtrim($category, '*')) === 0) {
264 252
                    $matched = true;
265 252
                    break;
266
                }
267
            }
268
269 326
            if ($matched) {
270 268
                foreach ($except as $category) {
271 3
                    $prefix = rtrim($category, '*');
272 3
                    if (($message[2] === $category || $prefix !== $category) && strpos($message[2], $prefix) === 0) {
273 3
                        $matched = false;
274 3
                        break;
275
                    }
276
                }
277
            }
278
279 326
            if (!$matched) {
280 311
                unset($messages[$i]);
281
            }
282
        }
283
284 413
        return $messages;
285
    }
286
287
    /**
288
     * Formats a log message for display as a string.
289
     * @param array $message the log message to be formatted.
290
     * The message structure follows that in [[Logger::messages]].
291
     * @return string the formatted message
292
     */
293 2
    public function formatMessage($message)
294
    {
295 2
        list($text, $level, $category, $timestamp) = $message;
296 2
        $level = Logger::getLevelName($level);
297 2
        if (!is_string($text)) {
298
            // exceptions may not be serializable if in the call stack somewhere is a Closure
299
            if ($text instanceof \Exception || $text instanceof \Throwable) {
300
                $text = (string) $text;
301
            } else {
302
                $text = VarDumper::export($text);
303
            }
304
        }
305 2
        $traces = [];
306 2
        if (isset($message[4])) {
307 1
            foreach ($message[4] as $trace) {
308
                $traces[] = "in {$trace['file']}:{$trace['line']}";
309
            }
310
        }
311
312 2
        $prefix = $this->getMessagePrefix($message);
313 2
        return $this->getTime($timestamp) . " {$prefix}[$level][$category] $text"
314 2
            . (empty($traces) ? '' : "\n    " . implode("\n    ", $traces));
315
    }
316
317
    /**
318
     * Returns a string to be prefixed to the given message.
319
     * If [[prefix]] is configured it will return the result of the callback.
320
     * The default implementation will return user IP, user ID and session ID as a prefix.
321
     * @param array $message the message being exported.
322
     * The message structure follows that in [[Logger::messages]].
323
     * @return string the prefix string
324
     */
325 8
    public function getMessagePrefix($message)
326
    {
327 8
        if ($this->prefix !== null) {
328
            return call_user_func($this->prefix, $message);
329
        }
330
331 8
        if (Yii::$app === null) {
332 1
            return '';
333
        }
334
335 7
        $request = Yii::$app->getRequest();
336 7
        $ip = $request instanceof Request ? $request->getUserIP() : '-';
337
338
        /* @var $user \yii\web\User */
339 7
        $user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
340 7
        if ($user && ($identity = $user->getIdentity(false))) {
341
            $userID = $identity->getId();
342
        } else {
343 7
            $userID = '-';
344
        }
345
346
        /* @var $session \yii\web\Session */
347 7
        $session = Yii::$app->has('session', true) ? Yii::$app->get('session') : null;
348 7
        $sessionID = $session && $session->getIsActive() ? $session->getId() : '-';
349
350 7
        return "[$ip][$userID][$sessionID]";
351
    }
352
353
    /**
354
     * Sets a value indicating whether this log target is enabled.
355
     * @param bool|callable $value a boolean value or a callable to obtain the value from.
356
     * The callable value is available since version 2.0.13.
357
     *
358
     * A callable may be used to determine whether the log target should be enabled in a dynamic way.
359
     * For example, to only enable a log if the current user is logged in you can configure the target
360
     * as follows:
361
     *
362
     * ```php
363
     * 'enabled' => function() {
364
     *     return !Yii::$app->user->isGuest;
365
     * }
366
     * ```
367
     */
368 2
    public function setEnabled($value)
369
    {
370 2
        $this->_enabled = $value;
371
    }
372
373
    /**
374
     * Check whether the log target is enabled.
375
     * @property bool Indicates whether this log target is enabled. Defaults to true.
376
     * @return bool A value indicating whether this log target is enabled.
377
     */
378 414
    public function getEnabled()
379
    {
380 414
        if (is_callable($this->_enabled)) {
381 1
            return call_user_func($this->_enabled, $this);
0 ignored issues
show
$this->_enabled of type boolean is incompatible with the type callable expected by parameter $callback of call_user_func(). ( Ignorable by Annotation )

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

381
            return call_user_func(/** @scrutinizer ignore-type */ $this->_enabled, $this);
Loading history...
382
        }
383
384 414
        return $this->_enabled;
385
    }
386
387
    /**
388
     * Returns formatted ('Y-m-d H:i:s') timestamp for message.
389
     * If [[microtime]] is configured to true it will return format 'Y-m-d H:i:s.u'.
390
     * @param float $timestamp
391
     * @return string
392
     * @since 2.0.13
393
     */
394 2
    protected function getTime($timestamp)
395
    {
396 2
        $parts = explode('.', sprintf('%F', $timestamp));
397
398 2
        return date('Y-m-d H:i:s', $parts[0]) . ($this->microtime ? ('.' . $parts[1]) : '');
0 ignored issues
show
$parts[0] of type string is incompatible with the type integer|null expected by parameter $timestamp of date(). ( Ignorable by Annotation )

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

398
        return date('Y-m-d H:i:s', /** @scrutinizer ignore-type */ $parts[0]) . ($this->microtime ? ('.' . $parts[1]) : '');
Loading history...
399
    }
400
}
401