Passed
Push — fix-php8 ( 924a16...2b80f5 )
by Alexander
10:56
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 213
    public function beforeAction($action)
81
    {
82 213
        $silentExit = $this->silentExitOnException !== null ? $this->silentExitOnException : YII_ENV_TEST;
83 213
        Yii::$app->errorHandler->silentExitOnException = $silentExit;
84
85 213
        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 213
    public function runAction($id, $params = [])
113
    {
114 213
        if (!empty($params)) {
115
            // populate options here so that they are available in beforeAction().
116 201
            $options = $this->options($id === '' ? $this->defaultAction : $id);
117 201
            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 201
            foreach ($params as $name => $value) {
140
                // Allow camelCase options to be entered in kebab-case
141 201
                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 201
                if (in_array($name, $options, true)) {
150 52
                    $default = $this->$name;
151 52
                    if (is_array($default)) {
152 52
                        $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 52
                    $this->_passedOptions[] = $name;
160 52
                    unset($params[$name]);
161 52
                    if (isset($kebabName)) {
162 52
                        unset($params[$kebabName]);
163
                    }
164 195
                } 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 201
                    throw new Exception($message);
171
                }
172
            }
173
        }
174 213
        if ($this->help) {
175 2
            $route = $this->getUniqueId() . '/' . $id;
176 2
            return Yii::$app->runAction('help', [$route]);
177
        }
178
179 213
        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 227
    public function bindActionParams($action, $params)
193
    {
194 227
        if ($action instanceof InlineAction) {
195 227
            $method = new \ReflectionMethod($this, $action->actionMethod);
196
        } else {
197
            $method = new \ReflectionMethod($action, 'run');
198
        }
199
200 227
        $args = [];
201 227
        $missing = [];
202 227
        $actionParams = [];
203 227
        $requestedParams = [];
204 227
        foreach ($method->getParameters() as $i => $param) {
205 221
            $name = $param->getName();
206 221
            $key = null;
207 221
            if (array_key_exists($i, $params)) {
208 195
                $key = $i;
209 57
            } elseif (array_key_exists($name, $params)) {
210 7
                $key = $name;
211
            }
212
213 221
            if ($key !== null) {
214 202
                if (PHP_VERSION_ID >= 80000) {
215
                    $isArray = ($type = $param->getType()) instanceof \ReflectionNamedType && $type->getName() === 'array';
216
                } else {
217 202
                    $isArray = $param->isArray();
218
                }
219 202
                if ($isArray) {
220 1
                    $params[$key] = $params[$key] === '' ? [] : preg_split('/\s*,\s*/', $params[$key]);
221
                }
222 202
                $args[] = $actionParams[$key] = $params[$key];
223 202
                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 221
                $missing[] = $name;
234
            }
235
        }
236
237 225
        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 225
        if (\Yii::$app->requestedParams === null) {
243 225
            \Yii::$app->requestedParams = array_merge($actionParams, $requestedParams);
244
        }
245
246 225
        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 146
    public function confirm($message, $default = false)
382
    {
383 146
        if ($this->interactive) {
384
            return Console::confirm($message, $default);
385
        }
386
387 146
        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 204
    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 204
        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 (PHP_VERSION_ID >= 80000) {
559
                $class = $reflection->getType();
560
            } else {
561 6
                $class = $reflection->getClass();
562
            }
563
564 6
            if ($class !== null) {
565 1
                continue;
566
            }
567 6
            $name = $reflection->getName();
568 6
            $tag = isset($params[$i]) ? $params[$i] : '';
569 6
            if (preg_match('/^(\S+)\s+(\$\w+\s+)?(.*)/s', $tag, $matches)) {
570 4
                $type = $matches[1];
571 4
                $comment = $matches[3];
572
            } else {
573 2
                $type = null;
574 2
                $comment = $tag;
575
            }
576 6
            if ($reflection->isDefaultValueAvailable()) {
577 3
                $args[$name] = [
578 3
                    'required' => false,
579 3
                    'type' => $type,
580 3
                    'default' => $reflection->getDefaultValue(),
581 3
                    'comment' => $comment,
582
                ];
583
            } else {
584 4
                $args[$name] = [
585 4
                    'required' => true,
586 4
                    'type' => $type,
587
                    'default' => null,
588 6
                    'comment' => $comment,
589
                ];
590
            }
591
        }
592
593 6
        return $args;
594
    }
595
596
    /**
597
     * Returns the help information for the options for the action.
598
     *
599
     * The returned value should be an array. The keys are the option names, and the values are
600
     * the corresponding help information. Each value must be an array of the following structure:
601
     *
602
     * - type: string, the PHP type of this argument.
603
     * - default: string, the default value of this argument
604
     * - comment: string, the comment of this argument
605
     *
606
     * The default implementation will return the help information extracted from the doc-comment of
607
     * the properties corresponding to the action options.
608
     *
609
     * @param Action $action
610
     * @return array the help information of the action options
611
     */
612 4
    public function getActionOptionsHelp($action)
613
    {
614 4
        $optionNames = $this->options($action->id);
615 4
        if (empty($optionNames)) {
616
            return [];
617
        }
618
619 4
        $class = new \ReflectionClass($this);
620 4
        $options = [];
621 4
        foreach ($class->getProperties() as $property) {
622 4
            $name = $property->getName();
623 4
            if (!in_array($name, $optionNames, true)) {
624 4
                continue;
625
            }
626 4
            $defaultValue = $property->getValue($this);
627 4
            $tags = $this->parseDocCommentTags($property);
628
629
            // Display camelCase options in kebab-case
630 4
            $name = Inflector::camel2id($name, '-', true);
631
632 4
            if (isset($tags['var']) || isset($tags['property'])) {
633 4
                $doc = isset($tags['var']) ? $tags['var'] : $tags['property'];
634 4
                if (is_array($doc)) {
635
                    $doc = reset($doc);
636
                }
637 4
                if (preg_match('/^(\S+)(.*)/s', $doc, $matches)) {
638 4
                    $type = $matches[1];
639 4
                    $comment = $matches[2];
640
                } else {
641
                    $type = null;
642
                    $comment = $doc;
643
                }
644 4
                $options[$name] = [
645 4
                    'type' => $type,
646 4
                    'default' => $defaultValue,
647 4
                    'comment' => $comment,
648
                ];
649
            } else {
650 1
                $options[$name] = [
651 1
                    'type' => null,
652 1
                    'default' => $defaultValue,
653 4
                    'comment' => '',
654
                ];
655
            }
656
        }
657
658 4
        return $options;
659
    }
660
661
    private $_reflections = [];
662
663
    /**
664
     * @param Action $action
665
     * @return \ReflectionMethod
666
     */
667 8
    protected function getActionMethodReflection($action)
668
    {
669 8
        if (!isset($this->_reflections[$action->id])) {
670 8
            if ($action instanceof InlineAction) {
671 8
                $this->_reflections[$action->id] = new \ReflectionMethod($this, $action->actionMethod);
672
            } else {
673
                $this->_reflections[$action->id] = new \ReflectionMethod($action, 'run');
674
            }
675
        }
676
677 8
        return $this->_reflections[$action->id];
678
    }
679
680
    /**
681
     * Parses the comment block into tags.
682
     * @param \Reflector $reflection the comment block
683
     * @return array the parsed tags
684
     */
685 6
    protected function parseDocCommentTags($reflection)
686
    {
687 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

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