Passed
Push — feature/fix-non-seekable-strea... ( e26a6f...fbfc82 )
by Tobias
35:49 queued 32:19
created

Controller::bindActionParams()   D

Complexity

Conditions 17
Paths 228

Size

Total Lines 55
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 17.0538

Importance

Changes 0
Metric Value
cc 17
eloc 38
c 0
b 0
f 0
nc 228
nop 2
dl 0
loc 55
ccs 33
cts 35
cp 0.9429
crap 17.0538
rs 4.0333

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
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\console;
9
10
use Yii;
11
use yii\base\Action;
12
use yii\base\InlineAction;
13
use yii\base\InvalidRouteException;
14
use yii\helpers\Console;
15
use yii\helpers\Inflector;
16
17
/**
18
 * Controller is the base class of console command classes.
19
 *
20
 * A console controller consists of one or several actions known as sub-commands.
21
 * Users call a console command by specifying the corresponding route which identifies a controller action.
22
 * The `yii` program is used when calling a console command, like the following:
23
 *
24
 * ```
25
 * yii <route> [--param1=value1 --param2 ...]
26
 * ```
27
 *
28
 * where `<route>` is a route to a controller action and the params will be populated as properties of a command.
29
 * See [[options()]] for details.
30
 *
31
 * @property string $help This property is read-only.
32
 * @property string $helpSummary This property is read-only.
33
 * @property array $passedOptionValues The properties corresponding to the passed options. This property is
34
 * read-only.
35
 * @property array $passedOptions The names of the options passed during execution. This property is
36
 * read-only.
37
 *
38
 * @author Qiang Xue <[email protected]>
39
 * @since 2.0
40
 */
41
class Controller extends \yii\base\Controller
42
{
43
    /**
44
     * @deprecated since 2.0.13. Use [[ExitCode::OK]] instead.
45
     */
46
    const EXIT_CODE_NORMAL = 0;
47
    /**
48
     * @deprecated since 2.0.13. Use [[ExitCode::UNSPECIFIED_ERROR]] instead.
49
     */
50
    const EXIT_CODE_ERROR = 1;
51
52
    /**
53
     * @var bool whether to run the command interactively.
54
     */
55
    public $interactive = true;
56
    /**
57
     * @var bool whether to enable ANSI color in the output.
58
     * If not set, ANSI color will only be enabled for terminals that support it.
59
     */
60
    public $color;
61
    /**
62
     * @var bool whether to display help information about current command.
63
     * @since 2.0.10
64
     */
65
    public $help;
66
    /**
67
     * @var bool if true - script finish with `ExitCode::OK` in case of exception.
68
     * false - `ExitCode::UNSPECIFIED_ERROR`.
69
     * Default: `YII_ENV_TEST`
70
     * @since 2.0.36
71
     */
72
    public $silentExitOnException;
73
74
    /**
75
     * @var array the options passed during execution.
76
     */
77
    private $_passedOptions = [];
78
79
80 212
    public function beforeAction($action)
81
    {
82 212
        $silentExit = $this->silentExitOnException !== null ? $this->silentExitOnException : YII_ENV_TEST;
83 212
        Yii::$app->errorHandler->silentExitOnException = $silentExit;
84
85 212
        return parent::beforeAction($action);
86
    }
87
88
    /**
89
     * Returns a value indicating whether ANSI color is enabled.
90
     *
91
     * ANSI color is enabled only if [[color]] is set true or is not set
92
     * and the terminal supports ANSI color.
93
     *
94
     * @param resource $stream the stream to check.
95
     * @return bool Whether to enable ANSI style in output.
96
     */
97 7
    public function isColorEnabled($stream = \STDOUT)
98
    {
99 7
        return $this->color === null ? Console::streamSupportsAnsiColors($stream) : $this->color;
100
    }
101
102
    /**
103
     * Runs an action with the specified action ID and parameters.
104
     * If the action ID is empty, the method will use [[defaultAction]].
105
     * @param string $id the ID of the action to be executed.
106
     * @param array $params the parameters (name-value pairs) to be passed to the action.
107
     * @return int the status of the action execution. 0 means normal, other values mean abnormal.
108
     * @throws InvalidRouteException if the requested action ID cannot be resolved into an action successfully.
109
     * @throws Exception if there are unknown options or missing arguments
110
     * @see createAction
111
     */
112 212
    public function runAction($id, $params = [])
113
    {
114 212
        if (!empty($params)) {
115
            // populate options here so that they are available in beforeAction().
116 200
            $options = $this->options($id === '' ? $this->defaultAction : $id);
117 200
            if (isset($params['_aliases'])) {
118 1
                $optionAliases = $this->optionAliases();
119 1
                foreach ($params['_aliases'] as $name => $value) {
120 1
                    if (array_key_exists($name, $optionAliases)) {
121 1
                        $params[$optionAliases[$name]] = $value;
122
                    } else {
123
                        $message = Yii::t('yii', 'Unknown alias: -{name}', ['name' => $name]);
124
                        if (!empty($optionAliases)) {
125
                            $aliasesAvailable = [];
126
                            foreach ($optionAliases as $alias => $option) {
127
                                $aliasesAvailable[] = '-' . $alias . ' (--' . $option . ')';
128
                            }
129
130
                            $message .= '. ' . Yii::t('yii', 'Aliases available: {aliases}', [
131
                                'aliases' => implode(', ', $aliasesAvailable)
132
                            ]);
133
                        }
134 1
                        throw new Exception($message);
135
                    }
136
                }
137 1
                unset($params['_aliases']);
138
            }
139 200
            foreach ($params as $name => $value) {
140
                // Allow camelCase options to be entered in kebab-case
141 200
                if (!in_array($name, $options, true) && strpos($name, '-') !== false) {
142 1
                    $kebabName = $name;
143 1
                    $altName = lcfirst(Inflector::id2camel($kebabName));
144 1
                    if (in_array($altName, $options, true)) {
145 1
                        $name = $altName;
146
                    }
147
                }
148
149 200
                if (in_array($name, $options, true)) {
150 51
                    $default = $this->$name;
151 51
                    if (is_array($default)) {
152 51
                        $this->$name = preg_split('/\s*,\s*(?![^()]*\))/', $value);
153 11
                    } elseif ($default !== null) {
154 10
                        settype($value, gettype($default));
155 10
                        $this->$name = $value;
156
                    } else {
157 1
                        $this->$name = $value;
158
                    }
159 51
                    $this->_passedOptions[] = $name;
160 51
                    unset($params[$name]);
161 51
                    if (isset($kebabName)) {
162 51
                        unset($params[$kebabName]);
163
                    }
164 194
                } elseif (!is_int($name)) {
165
                    $message = Yii::t('yii', 'Unknown option: --{name}', ['name' => $name]);
166
                    if (!empty($options)) {
167
                        $message .= '. ' . Yii::t('yii', 'Options available: {options}', ['options' => '--' . implode(', --', $options)]);
168
                    }
169
170 200
                    throw new Exception($message);
171
                }
172
            }
173
        }
174 212
        if ($this->help) {
175 2
            $route = $this->getUniqueId() . '/' . $id;
176 2
            return Yii::$app->runAction('help', [$route]);
177
        }
178
179 212
        return parent::runAction($id, $params);
180
    }
181
182
    /**
183
     * Binds the parameters to the action.
184
     * This method is invoked by [[Action]] when it begins to run with the given parameters.
185
     * This method will first bind the parameters with the [[options()|options]]
186
     * available to the action. It then validates the given arguments.
187
     * @param Action $action the action to be bound with parameters
188
     * @param array $params the parameters to be bound to the action
189
     * @return array the valid parameters that the action can run with.
190
     * @throws Exception if there are unknown options or missing arguments
191
     */
192 226
    public function bindActionParams($action, $params)
193
    {
194 226
        if ($action instanceof InlineAction) {
195 226
            $method = new \ReflectionMethod($this, $action->actionMethod);
196
        } else {
197
            $method = new \ReflectionMethod($action, 'run');
198
        }
199
200 226
        $args = [];
201 226
        $missing = [];
202 226
        $actionParams = [];
203 226
        $requestedParams = [];
204 226
        foreach ($method->getParameters() as $i => $param) {
205 220
            $name = $param->getName();
206 220
            $key = null;
207 220
            if (array_key_exists($i, $params)) {
208 194
                $key = $i;
209 57
            } elseif (array_key_exists($name, $params)) {
210 7
                $key = $name;
211
            }
212
213 220
            if ($key !== null) {
214 201
                if (PHP_VERSION_ID >= 80000) {
215
                    $isArray = ($type = $param->getType()) instanceof \ReflectionNamedType && $type->getName() === 'array';
216
                } else {
217 201
                    $isArray = $param->isArray();
218
                }
219 201
                if ($isArray) {
220 1
                    $params[$key] = $params[$key] === '' ? [] : preg_split('/\s*,\s*/', $params[$key]);
221
                }
222 201
                $args[] = $actionParams[$key] = $params[$key];
223 201
                unset($params[$key]);
224 53
            } elseif (PHP_VERSION_ID >= 70100 && ($type = $param->getType()) !== null && !$type->isBuiltin()) {
225
                try {
226 5
                    $this->bindInjectedParams($type, $name, $args, $requestedParams);
227 2
                } catch (\yii\base\Exception $e) {
228 5
                    throw new Exception($e->getMessage());
229
                }
230 48
            } elseif ($param->isDefaultValueAvailable()) {
231 48
                $args[] = $actionParams[$i] = $param->getDefaultValue();
232
            } else {
233 220
                $missing[] = $name;
234
            }
235
        }
236
237 224
        if (!empty($missing)) {
238 1
            throw new Exception(Yii::t('yii', 'Missing required arguments: {params}', ['params' => implode(', ', $missing)]));
239
        }
240
241
        // We use a different array here, specifically one that doesn't contain service instances but descriptions instead.
242 224
        if (\Yii::$app->requestedParams === null) {
243 224
            \Yii::$app->requestedParams = array_merge($actionParams, $requestedParams);
244
        }
245
246 224
        return array_merge($args, $params);
247
    }
248
249
    /**
250
     * Formats a string with ANSI codes.
251
     *
252
     * You may pass additional parameters using the constants defined in [[\yii\helpers\Console]].
253
     *
254
     * Example:
255
     *
256
     * ```
257
     * echo $this->ansiFormat('This will be red and underlined.', Console::FG_RED, Console::UNDERLINE);
258
     * ```
259
     *
260
     * @param string $string the string to be formatted
261
     * @return string
262
     */
263 7
    public function ansiFormat($string)
264
    {
265 7
        if ($this->isColorEnabled()) {
266 1
            $args = func_get_args();
267 1
            array_shift($args);
268 1
            $string = Console::ansiFormat($string, $args);
269
        }
270
271 7
        return $string;
272
    }
273
274
    /**
275
     * Prints a string to STDOUT.
276
     *
277
     * You may optionally format the string with ANSI codes by
278
     * passing additional parameters using the constants defined in [[\yii\helpers\Console]].
279
     *
280
     * Example:
281
     *
282
     * ```
283
     * $this->stdout('This will be red and underlined.', Console::FG_RED, Console::UNDERLINE);
284
     * ```
285
     *
286
     * @param string $string the string to print
287
     * @param int ...$args additional parameters to decorate the output
288
     * @return int|bool Number of bytes printed or false on error
289
     */
290
    public function stdout($string)
291
    {
292
        if ($this->isColorEnabled()) {
293
            $args = func_get_args();
294
            array_shift($args);
295
            $string = Console::ansiFormat($string, $args);
296
        }
297
298
        return Console::stdout($string);
299
    }
300
301
    /**
302
     * Prints a string to STDERR.
303
     *
304
     * You may optionally format the string with ANSI codes by
305
     * passing additional parameters using the constants defined in [[\yii\helpers\Console]].
306
     *
307
     * Example:
308
     *
309
     * ```
310
     * $this->stderr('This will be red and underlined.', Console::FG_RED, Console::UNDERLINE);
311
     * ```
312
     *
313
     * @param string $string the string to print
314
     * @return int|bool Number of bytes printed or false on error
315
     */
316
    public function stderr($string)
317
    {
318
        if ($this->isColorEnabled(\STDERR)) {
319
            $args = func_get_args();
320
            array_shift($args);
321
            $string = Console::ansiFormat($string, $args);
322
        }
323
324
        return fwrite(\STDERR, $string);
325
    }
326
327
    /**
328
     * Prompts the user for input and validates it.
329
     *
330
     * @param string $text prompt string
331
     * @param array $options the options to validate the input:
332
     *
333
     *  - required: whether it is required or not
334
     *  - default: default value if no input is inserted by the user
335
     *  - pattern: regular expression pattern to validate user input
336
     *  - validator: a callable function to validate input. The function must accept two parameters:
337
     *      - $input: the user input to validate
338
     *      - $error: the error value passed by reference if validation failed.
339
     *
340
     * An example of how to use the prompt method with a validator function.
341
     *
342
     * ```php
343
     * $code = $this->prompt('Enter 4-Chars-Pin', ['required' => true, 'validator' => function($input, &$error) {
344
     *     if (strlen($input) !== 4) {
345
     *         $error = 'The Pin must be exactly 4 chars!';
346
     *         return false;
347
     *     }
348
     *     return true;
349
     * }]);
350
     * ```
351
     *
352
     * @return string the user input
353
     */
354
    public function prompt($text, $options = [])
355
    {
356
        if ($this->interactive) {
357
            return Console::prompt($text, $options);
358
        }
359
360
        return isset($options['default']) ? $options['default'] : '';
361
    }
362
363
    /**
364
     * Asks user to confirm by typing y or n.
365
     *
366
     * A typical usage looks like the following:
367
     *
368
     * ```php
369
     * if ($this->confirm("Are you sure?")) {
370
     *     echo "user typed yes\n";
371
     * } else {
372
     *     echo "user typed no\n";
373
     * }
374
     * ```
375
     *
376
     * @param string $message to echo out before waiting for user input
377
     * @param bool $default this value is returned if no selection is made.
378
     * @return bool whether user confirmed.
379
     * Will return true if [[interactive]] is false.
380
     */
381 145
    public function confirm($message, $default = false)
382
    {
383 145
        if ($this->interactive) {
384
            return Console::confirm($message, $default);
385
        }
386
387 145
        return true;
388
    }
389
390
    /**
391
     * Gives the user an option to choose from. Giving '?' as an input will show
392
     * a list of options to choose from and their explanations.
393
     *
394
     * @param string $prompt the prompt message
395
     * @param array $options Key-value array of options to choose from
396
     *
397
     * @return string An option character the user chose
398
     */
399
    public function select($prompt, $options = [])
400
    {
401
        return Console::select($prompt, $options);
402
    }
403
404
    /**
405
     * Returns the names of valid options for the action (id)
406
     * An option requires the existence of a public member variable whose
407
     * name is the option name.
408
     * Child classes may override this method to specify possible options.
409
     *
410
     * Note that the values setting via options are not available
411
     * until [[beforeAction()]] is being called.
412
     *
413
     * @param string $actionID the action id of the current request
414
     * @return string[] the names of the options valid for the action
415
     */
416 203
    public function options($actionID)
0 ignored issues
show
Unused Code introduced by
The parameter $actionID is not used and could be removed. ( Ignorable by Annotation )

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

416
    public function options(/** @scrutinizer ignore-unused */ $actionID)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
417
    {
418
        // $actionId might be used in subclasses to provide options specific to action id
419 203
        return ['color', 'interactive', 'help', 'silentExitOnException'];
420
    }
421
422
    /**
423
     * Returns option alias names.
424
     * Child classes may override this method to specify alias options.
425
     *
426
     * @return array the options alias names valid for the action
427
     * where the keys is alias name for option and value is option name.
428
     *
429
     * @since 2.0.8
430
     * @see options()
431
     */
432 2
    public function optionAliases()
433
    {
434
        return [
435 2
            'h' => 'help',
436
        ];
437
    }
438
439
    /**
440
     * Returns properties corresponding to the options for the action id
441
     * Child classes may override this method to specify possible properties.
442
     *
443
     * @param string $actionID the action id of the current request
444
     * @return array properties corresponding to the options for the action
445
     */
446 65
    public function getOptionValues($actionID)
0 ignored issues
show
Unused Code introduced by
The parameter $actionID is not used and could be removed. ( Ignorable by Annotation )

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

446
    public function getOptionValues(/** @scrutinizer ignore-unused */ $actionID)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
447
    {
448
        // $actionId might be used in subclasses to provide properties specific to action id
449 65
        $properties = [];
450 65
        foreach ($this->options($this->action->id) as $property) {
451 65
            $properties[$property] = $this->$property;
452
        }
453
454 65
        return $properties;
455
    }
456
457
    /**
458
     * Returns the names of valid options passed during execution.
459
     *
460
     * @return array the names of the options passed during execution
461
     */
462
    public function getPassedOptions()
463
    {
464
        return $this->_passedOptions;
465
    }
466
467
    /**
468
     * Returns the properties corresponding to the passed options.
469
     *
470
     * @return array the properties corresponding to the passed options
471
     */
472 59
    public function getPassedOptionValues()
473
    {
474 59
        $properties = [];
475 59
        foreach ($this->_passedOptions as $property) {
476
            $properties[$property] = $this->$property;
477
        }
478
479 59
        return $properties;
480
    }
481
482
    /**
483
     * Returns one-line short summary describing this controller.
484
     *
485
     * You may override this method to return customized summary.
486
     * The default implementation returns first line from the PHPDoc comment.
487
     *
488
     * @return string
489
     */
490 5
    public function getHelpSummary()
491
    {
492 5
        return $this->parseDocCommentSummary(new \ReflectionClass($this));
493
    }
494
495
    /**
496
     * Returns help information for this controller.
497
     *
498
     * You may override this method to return customized help.
499
     * The default implementation returns help information retrieved from the PHPDoc comment.
500
     * @return string
501
     */
502
    public function getHelp()
503
    {
504
        return $this->parseDocCommentDetail(new \ReflectionClass($this));
505
    }
506
507
    /**
508
     * Returns a one-line short summary describing the specified action.
509
     * @param Action $action action to get summary for
510
     * @return string a one-line short summary describing the specified action.
511
     */
512 3
    public function getActionHelpSummary($action)
513
    {
514 3
        if ($action === null) {
515 1
            return $this->ansiFormat(Yii::t('yii', 'Action not found.'), Console::FG_RED);
516
        }
517
518 2
        return $this->parseDocCommentSummary($this->getActionMethodReflection($action));
519
    }
520
521
    /**
522
     * Returns the detailed help information for the specified action.
523
     * @param Action $action action to get help for
524
     * @return string the detailed help information for the specified action.
525
     */
526 3
    public function getActionHelp($action)
527
    {
528 3
        return $this->parseDocCommentDetail($this->getActionMethodReflection($action));
529
    }
530
531
    /**
532
     * Returns the help information for the anonymous arguments for the action.
533
     *
534
     * The returned value should be an array. The keys are the argument names, and the values are
535
     * the corresponding help information. Each value must be an array of the following structure:
536
     *
537
     * - required: boolean, whether this argument is required.
538
     * - type: string, the PHP type of this argument.
539
     * - default: string, the default value of this argument
540
     * - comment: string, the comment of this argument
541
     *
542
     * The default implementation will return the help information extracted from the doc-comment of
543
     * the parameters corresponding to the action method.
544
     *
545
     * @param Action $action
546
     * @return array the help information of the action arguments
547
     */
548 6
    public function getActionArgsHelp($action)
549
    {
550 6
        $method = $this->getActionMethodReflection($action);
551 6
        $tags = $this->parseDocCommentTags($method);
552 6
        $params = isset($tags['param']) ? (array) $tags['param'] : [];
553
554 6
        $args = [];
555
556
        /** @var \ReflectionParameter $reflection */
557 6
        foreach ($method->getParameters() as $i => $reflection) {
558 6
            if ($reflection->getClass() !== null) {
559 1
                continue;
560
            }
561 6
            $name = $reflection->getName();
562 6
            $tag = isset($params[$i]) ? $params[$i] : '';
563 6
            if (preg_match('/^(\S+)\s+(\$\w+\s+)?(.*)/s', $tag, $matches)) {
564 4
                $type = $matches[1];
565 4
                $comment = $matches[3];
566
            } else {
567 2
                $type = null;
568 2
                $comment = $tag;
569
            }
570 6
            if ($reflection->isDefaultValueAvailable()) {
571 3
                $args[$name] = [
572 3
                    'required' => false,
573 3
                    'type' => $type,
574 3
                    'default' => $reflection->getDefaultValue(),
575 3
                    'comment' => $comment,
576
                ];
577
            } else {
578 4
                $args[$name] = [
579 4
                    'required' => true,
580 4
                    'type' => $type,
581
                    'default' => null,
582 6
                    'comment' => $comment,
583
                ];
584
            }
585
        }
586
587 6
        return $args;
588
    }
589
590
    /**
591
     * Returns the help information for the options for the action.
592
     *
593
     * The returned value should be an array. The keys are the option names, and the values are
594
     * the corresponding help information. Each value must be an array of the following structure:
595
     *
596
     * - type: string, the PHP type of this argument.
597
     * - default: string, the default value of this argument
598
     * - comment: string, the comment of this argument
599
     *
600
     * The default implementation will return the help information extracted from the doc-comment of
601
     * the properties corresponding to the action options.
602
     *
603
     * @param Action $action
604
     * @return array the help information of the action options
605
     */
606 4
    public function getActionOptionsHelp($action)
607
    {
608 4
        $optionNames = $this->options($action->id);
609 4
        if (empty($optionNames)) {
610
            return [];
611
        }
612
613 4
        $class = new \ReflectionClass($this);
614 4
        $options = [];
615 4
        foreach ($class->getProperties() as $property) {
616 4
            $name = $property->getName();
617 4
            if (!in_array($name, $optionNames, true)) {
618 4
                continue;
619
            }
620 4
            $defaultValue = $property->getValue($this);
621 4
            $tags = $this->parseDocCommentTags($property);
622
623
            // Display camelCase options in kebab-case
624 4
            $name = Inflector::camel2id($name, '-', true);
625
626 4
            if (isset($tags['var']) || isset($tags['property'])) {
627 4
                $doc = isset($tags['var']) ? $tags['var'] : $tags['property'];
628 4
                if (is_array($doc)) {
629
                    $doc = reset($doc);
630
                }
631 4
                if (preg_match('/^(\S+)(.*)/s', $doc, $matches)) {
632 4
                    $type = $matches[1];
633 4
                    $comment = $matches[2];
634
                } else {
635
                    $type = null;
636
                    $comment = $doc;
637
                }
638 4
                $options[$name] = [
639 4
                    'type' => $type,
640 4
                    'default' => $defaultValue,
641 4
                    'comment' => $comment,
642
                ];
643
            } else {
644 1
                $options[$name] = [
645 1
                    'type' => null,
646 1
                    'default' => $defaultValue,
647 4
                    'comment' => '',
648
                ];
649
            }
650
        }
651
652 4
        return $options;
653
    }
654
655
    private $_reflections = [];
656
657
    /**
658
     * @param Action $action
659
     * @return \ReflectionMethod
660
     */
661 8
    protected function getActionMethodReflection($action)
662
    {
663 8
        if (!isset($this->_reflections[$action->id])) {
664 8
            if ($action instanceof InlineAction) {
665 8
                $this->_reflections[$action->id] = new \ReflectionMethod($this, $action->actionMethod);
666
            } else {
667
                $this->_reflections[$action->id] = new \ReflectionMethod($action, 'run');
668
            }
669
        }
670
671 8
        return $this->_reflections[$action->id];
672
    }
673
674
    /**
675
     * Parses the comment block into tags.
676
     * @param \Reflector $reflection the comment block
677
     * @return array the parsed tags
678
     */
679 6
    protected function parseDocCommentTags($reflection)
680
    {
681 6
        $comment = $reflection->getDocComment();
0 ignored issues
show
Bug introduced by
The method getDocComment() does not exist on Reflector. It seems like you code against a sub-type of Reflector such as ReflectionFunction or ReflectionProperty or ReflectionFunctionAbstract or ReflectionClassConstant or ReflectionObject or ReflectionClass or ReflectionMethod. ( Ignorable by Annotation )

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

681
        /** @scrutinizer ignore-call */ 
682
        $comment = $reflection->getDocComment();
Loading history...
682 6
        $comment = "@description \n" . strtr(trim(preg_replace('/^\s*\**( |\t)?/m', '', trim($comment, '/'))), "\r", '');
683 6
        $parts = preg_split('/^\s*@/m', $comment, -1, PREG_SPLIT_NO_EMPTY);
684 6
        $tags = [];
685 6
        foreach ($parts as $part) {
686 6
            if (preg_match('/^(\w+)(.*)/ms', trim($part), $matches)) {
687 6
                $name = $matches[1];
688 6
                if (!isset($tags[$name])) {
689 6
                    $tags[$name] = trim($matches[2]);
690
                } elseif (is_array($tags[$name])) {
691
                    $tags[$name][] = trim($matches[2]);
692
                } else {
693 6
                    $tags[$name] = [$tags[$name], trim($matches[2])];
694
                }
695
            }
696
        }
697
698 6
        return $tags;
699
    }
700
701
    /**
702
     * Returns the first line of docblock.
703
     *
704
     * @param \Reflector $reflection
705
     * @return string
706
     */
707 5
    protected function parseDocCommentSummary($reflection)
708
    {
709 5
        $docLines = preg_split('~\R~u', $reflection->getDocComment());
710 5
        if (isset($docLines[1])) {
711 5
            return trim($docLines[1], "\t *");
712
        }
713
714 2
        return '';
715
    }
716
717
    /**
718
     * Returns full description from the docblock.
719
     *
720
     * @param \Reflector $reflection
721
     * @return string
722
     */
723 3
    protected function parseDocCommentDetail($reflection)
724
    {
725 3
        $comment = strtr(trim(preg_replace('/^\s*\**( |\t)?/m', '', trim($reflection->getDocComment(), '/'))), "\r", '');
726 3
        if (preg_match('/^\s*@\w+/m', $comment, $matches, PREG_OFFSET_CAPTURE)) {
727 2
            $comment = trim(substr($comment, 0, $matches[0][1]));
728
        }
729 3
        if ($comment !== '') {
730 2
            return rtrim(Console::renderColoredString(Console::markdownToAnsi($comment)));
731
        }
732
733 1
        return '';
734
    }
735
}
736