Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — improve-route-duplicity-detect... ( 2e6948 )
by Pedro
36:42 queued 21:43
created

AddCustomRouteContent::handle()   B

Complexity

Conditions 7
Paths 10

Size

Total Lines 56
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 7
eloc 28
c 3
b 2
f 0
nc 10
nop 0
dl 0
loc 56
rs 8.5386

How to fix   Long Method   

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
namespace Backpack\CRUD\app\Console\Commands;
4
5
use Illuminate\Console\Command;
6
7
class AddCustomRouteContent extends Command
8
{
9
    use \Backpack\CRUD\app\Console\Commands\Traits\PrettyCommandOutput;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Consol...its\PrettyCommandOutput requires some properties which are not provided by Backpack\CRUD\app\Consol...s\AddCustomRouteContent: $progressBar, $statusColor, $status
Loading history...
10
11
    private $backpackCustomRouteFile = 'routes/backpack/custom.php';
12
13
    /**
14
     * The name and signature of the console command.
15
     *
16
     * @var string
17
     */
18
    protected $signature = 'backpack:add-custom-route
19
                                {code : HTML/PHP code that registers a route. Use either single quotes or double quotes. Never both. }
20
                                {--route-file=routes/backpack/custom.php : The file where the code should be added relative to the root of the project. }';
21
22
    /**
23
     * The console command description.
24
     *
25
     * @var string
26
     */
27
    protected $description = 'Add HTML/PHP code to the routes/backpack/custom.php file';
28
29
    /**
30
     * Create a new command instance.
31
     *
32
     * @return void
33
     */
34
    public function __construct()
35
    {
36
        parent::__construct();
37
    }
38
39
    /**
40
     * Execute the console command.
41
     *
42
     * @return mixed
43
     */
44
    public function handle()
45
    {
46
        $routeFilePath = base_path($this->option('route-file'));
47
48
        if (! file_exists($routeFilePath)) {
49
            if ($routeFilePath !== base_path($this->backpackCustomRouteFile)) {
50
                $this->info('The route file <fg=blue>'.$routeFilePath.'</> does not exist. Please create it first.');
51
                return 1;
52
            }
53
54
            $createRouteFile = $this->confirm('The route file <fg=blue>'.$routeFilePath.'</> does not exist. Should we create it?', 'yes');
0 ignored issues
show
Bug introduced by
'yes' of type string is incompatible with the type boolean expected by parameter $default of Illuminate\Console\Command::confirm(). ( Ignorable by Annotation )

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

54
            $createRouteFile = $this->confirm('The route file <fg=blue>'.$routeFilePath.'</> does not exist. Should we create it?', /** @scrutinizer ignore-type */ 'yes');
Loading history...
55
            if ($createRouteFile === 'yes') {
0 ignored issues
show
introduced by
The condition $createRouteFile === 'yes' is always false.
Loading history...
56
                $this->call('vendor:publish', ['--provider' => \Backpack\CRUD\BackpackServiceProvider::class, '--tag' => 'custom_routes']);
57
            } else {
58
                $this->info('The route file <fg=blue>'.$routeFilePath.'</> does not exist. Please create it first.');
59
                return 1;
60
            }
61
        }
62
63
        $code = $this->argument('code');
64
65
        $this->progressBlock("Adding route to <fg=blue>$routeFilePath</>");
66
67
        $originalContent = file($routeFilePath);
68
69
        // clean the content from comments etc
70
        $cleanContent = $this->cleanContentArray($originalContent);
71
        $cleanCode = $this->cleanCodeString($code);
72
73
        // if the content contains code, don't add it again.
74
        if (array_search($cleanCode, $cleanContent, true) !== false) {
75
            $this->closeProgressBlock('Already existed', 'yellow');
76
77
            return;
78
        }
79
80
        // get the last element of the array contains '}'
81
        $lastLine = $this->getLastLineNumberThatContains('}', $cleanContent);
82
83
        if ($lastLine === false) {
0 ignored issues
show
introduced by
The condition $lastLine === false is always false.
Loading history...
84
            $this->closeProgressBlock('Could not find the last line, file '.$routeFilePath.' may be corrupted.', 'red');
85
86
            return;
87
        }
88
89
        // add the code to the line before the last line
90
        array_splice($originalContent, $lastLine, 0, '    '.$code.PHP_EOL);
91
92
        // write the new content to the file
93
        if (file_put_contents($routeFilePath, implode('', $originalContent)) === false) {
94
            $this->closeProgressBlock('Failed to add route. Failed writing the modified route file. Maybe check file permissions?', 'red');
95
96
            return;
97
        }
98
99
        $this->closeProgressBlock('done', 'green');
100
    }
101
102
    private function cleanCodeString($code)
103
    {
104
        $code = trim($code);
105
        $code = str_replace('"', "'", $code);
106
        $code = preg_replace('/function\(.*\)/', '', $code);
107
        $code = preg_replace('/fn\(.*\)/', '', $code);
108
        $code = preg_replace('/\[.*\]/', '', $code);
109
        
110
        return $code;
111
    }
112
113
    private function cleanContentArray(array $content)
114
    {
115
        return array_filter(array_map(function ($line) {
116
            $lineText = trim($line);            
117
            if ($lineText === '' ||
118
                $lineText === '\n' ||
119
                $lineText === '\r' ||
120
                $lineText === '\r\n' ||
121
                $lineText === PHP_EOL ||
122
                str_starts_with($lineText, '<?php') ||
123
                str_starts_with($lineText, '?>') ||
124
                str_starts_with($lineText, '//') ||
125
                str_starts_with($lineText, '/*') ||
126
                str_starts_with($lineText, '*/') ||
127
                str_ends_with($lineText, '*/') ||
128
                str_starts_with($lineText, '*') ||
129
                str_starts_with($lineText, 'use ') ||
130
                str_starts_with($lineText, 'return ') ||
131
                str_starts_with($lineText, 'namespace ')) {
132
                return null;
133
            }
134
135
            // replace all double quotes with single quotes for easier comparison
136
            $lineText = str_replace('"', "'", $lineText);
137
138
            // if line starts with Route:: remove anything as function() { ... } and fn () => ...;
139
            if (str_starts_with($lineText, 'Route::')) {
140
                $lineText = preg_replace('/function\(.*\)/', '', $lineText);
141
                $lineText = preg_replace('/fn\(.*\)/', '', $lineText);
142
            }
143
144
            // remove everything inside [] 
145
            $lineText = preg_replace('/\[.*\]/', '', $lineText);
146
            
147
            return $lineText;
148
        }, $content));
149
    }
150
151
    /**
152
     * Parse the given file stream and return the line number where a string is found.
153
     *
154
     * @param  string  $needle  The string that's being searched for.
155
     * @param  array  $haystack  The file where the search is being performed.
156
     * @return bool|int The last line number where the string was found. Or false.
157
     */
158
    private function getLastLineNumberThatContains($needle, $haystack)
159
    {
160
        $matchingLines = array_filter($haystack, function ($k) use ($needle) {
161
            return strpos($k, $needle) !== false;
162
        });
163
164
        if ($matchingLines) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $matchingLines 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...
165
            return array_key_last($matchingLines);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_key_last($matchingLines) also could return the type string which is incompatible with the documented return type boolean|integer.
Loading history...
166
        }
167
168
        return false;
169
    }
170
}
171