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
Pull Request — main (#5565)
by Pedro
17:30 queued 02:37
created

AddCustomRouteContent::customRoutesFileEndLine()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 20
rs 9.9666
c 0
b 0
f 0
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
    /**
12
     * The name and signature of the console command.
13
     *
14
     * @var string
15
     */
16
    protected $signature = 'backpack:add-custom-route
17
                                {code : HTML/PHP code that registers a route. Use either single quotes or double quotes. Never both. }
18
                                {--route-file=routes/backpack/custom.php : The file where the code should be added relative to the root of the project. }';
19
20
    /**
21
     * The console command description.
22
     *
23
     * @var string
24
     */
25
    protected $description = 'Add HTML/PHP code to the routes/backpack/custom.php file';
26
27
    /**
28
     * Create a new command instance.
29
     *
30
     * @return void
31
     */
32
    public function __construct()
33
    {
34
        parent::__construct();
35
    }
36
37
    /**
38
     * Execute the console command.
39
     *
40
     * @return mixed
41
     */
42
    public function handle()
43
    {
44
        $routeFilePath = base_path($this->option('route-file'));
45
        // check if the file exists
46
        if (! file_exists($routeFilePath)) {
47
            $this->line("The route file  <fg=blue>$routeFilePath</> does not exist.");
48
            $createRouteFile = $this->confirm('Should we create the file in  <fg=blue>'.$routeFilePath.'</> ?', '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

48
            $createRouteFile = $this->confirm('Should we create the file in  <fg=blue>'.$routeFilePath.'</> ?', /** @scrutinizer ignore-type */ 'yes');
Loading history...
49
            if ($createRouteFile) {
50
                $this->call('vendor:publish', ['--provider' => \Backpack\CRUD\BackpackServiceProvider::class, '--tag' => 'custom_routes']);
51
            } else {
52
                $this->error('The route file does not exist. Please create it first.');
53
            }
54
        }
55
56
        $code = $this->argument('code');
57
58
        $this->progressBlock("Adding route to <fg=blue>$routeFilePath</>");
59
60
        $originalContent = file($routeFilePath);
61
62
        // clean the content from comments etc
63
        $cleanContent = $this->cleanContentArray($originalContent);
64
65
        // if the content contains code, don't add it again.
66
        if (array_search($code, $cleanContent, true) !== false) {
67
            $this->closeProgressBlock('Already existed', 'yellow');
68
69
            return;
70
        }
71
72
        // get the last element of the array contains '}'
73
        $lastLine = $this->getLastLineNumberThatContains('}', $cleanContent);
74
75
        if ($lastLine === false) {
0 ignored issues
show
introduced by
The condition $lastLine === false is always false.
Loading history...
76
            $this->closeProgressBlock('Could not find the last line, file '.$routeFilePath.' may be corrupted.', 'red');
77
78
            return;
79
        }
80
81
        // add the code to the line before the last line
82
        array_splice($originalContent, $lastLine, 0, '    '.$code.PHP_EOL);
83
84
        // write the new content to the file
85
        if (file_put_contents($routeFilePath, implode('', $originalContent)) === false) {
86
            $this->closeProgressBlock('Failed to add route. Failed writing the modified route file. Maybe check file permissions?', 'red');
87
88
            return;
89
        }
90
91
        $this->closeProgressBlock('done', 'green');
92
    }
93
94
    private function cleanContentArray(array $content)
95
    {
96
        return array_filter(array_map(function ($line) {
97
            $lineText = trim($line);
98
            if ($lineText === '' ||
99
                $lineText === '\n' ||
100
                $lineText === '\r' ||
101
                $lineText === '\r\n' ||
102
                $lineText === PHP_EOL ||
103
                str_starts_with($lineText, '<?php') ||
104
                str_starts_with($lineText, '?>') ||
105
                str_starts_with($lineText, '//') ||
106
                str_starts_with($lineText, '/*') ||
107
                str_starts_with($lineText, '*/') ||
108
                str_ends_with($lineText, '*/') ||
109
                str_starts_with($lineText, '*') ||
110
                str_starts_with($lineText, 'use ') ||
111
                str_starts_with($lineText, 'return ') ||
112
                str_starts_with($lineText, 'namespace ')) {
113
                return null;
114
            }
115
116
            return $lineText;
117
        }, $content));
118
    }
119
120
    /**
121
     * Parse the given file stream and return the line number where a string is found.
122
     *
123
     * @param  string  $needle  The string that's being searched for.
124
     * @param  array  $haystack  The file where the search is being performed.
125
     * @return bool|int The last line number where the string was found. Or false.
126
     */
127
    private function getLastLineNumberThatContains($needle, $haystack)
128
    {
129
        $matchingLines = array_filter($haystack, function ($k) use ($needle) {
130
            return strpos($k, $needle) !== false;
131
        });
132
133
        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...
134
            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...
135
        }
136
137
        return false;
138
    }
139
}
140