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 — master (#3714)
by
unknown
11:17
created

AddCustomRouteContent::handle()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 20
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 32
rs 9.6
1
<?php
2
3
namespace Backpack\CRUD\app\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\Storage;
7
8
class AddCustomRouteContent extends Command
9
{
10
    /**
11
     * The name and signature of the console command.
12
     *
13
     * @var string
14
     */
15
    protected $signature = 'backpack:add-custom-route
16
                                {code : HTML/PHP code that registers a route. Use either single quotes or double quotes. Never both. }';
17
18
    /**
19
     * The console command description.
20
     *
21
     * @var string
22
     */
23
    protected $description = 'Add HTML/PHP code to the routes/backpack/custom.php file';
24
25
    /**
26
     * Create a new command instance.
27
     *
28
     * @return void
29
     */
30
    public function __construct()
31
    {
32
        parent::__construct();
33
    }
34
35
    /**
36
     * Execute the console command.
37
     *
38
     * @return mixed
39
     */
40
    public function handle()
41
    {
42
        $path = 'routes/backpack/custom.php';
43
        $disk_name = config('backpack.base.root_disk_name');
44
        $disk = Storage::disk($disk_name);
45
        $code = $this->argument('code');
46
47
        if ($disk->exists($path)) {
48
            $old_file_path = $disk->path($path);
49
50
            // insert the given code before the file's last line
51
            $file_lines = file($old_file_path, FILE_IGNORE_NEW_LINES);
52
53
            // if the code already exists in the file, abort
54
            if ($this->getLastLineNumberThatContains($code, $file_lines)) {
0 ignored issues
show
Bug introduced by
It seems like $code can also be of type string[]; however, parameter $needle of Backpack\CRUD\app\Consol...ineNumberThatContains() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

54
            if ($this->getLastLineNumberThatContains(/** @scrutinizer ignore-type */ $code, $file_lines)) {
Loading history...
55
                return $this->comment('Route already existed.');
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->comment('Route already existed.') targeting Illuminate\Console\Command::comment() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
56
            }
57
58
            $end_line_number = $this->customRoutesFileEndLine($file_lines);
59
            $file_lines[$end_line_number + 1] = $file_lines[$end_line_number];
60
            $file_lines[$end_line_number] = '    '.$code;
0 ignored issues
show
Bug introduced by
Are you sure $code of type null|string|string[] can be used in concatenation? ( Ignorable by Annotation )

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

60
            $file_lines[$end_line_number] = '    './** @scrutinizer ignore-type */ $code;
Loading history...
61
            $new_file_content = implode(PHP_EOL, $file_lines);
62
63
            if ($disk->put($path, $new_file_content)) {
64
                $this->info('Successfully added code to '.$path);
65
            } else {
66
                $this->error('Could not write to file: '.$path);
67
            }
68
        } else {
69
            Artisan::call('vendor:publish', ['--provider' => 'Backpack\CRUD\BackpackServiceProvider', '--tag' => 'custom_routes']);
0 ignored issues
show
Bug introduced by
The type Backpack\CRUD\app\Console\Commands\Artisan was not found. Did you mean Artisan? If so, make sure to prefix the type with \.
Loading history...
70
71
            $this->handle();
72
        }
73
    }
74
75
    private function customRoutesFileEndLine($file_lines)
76
    {
77
        // in case the last line has not been modified at all
78
        $end_line_number = array_search('}); // this should be the absolute last line of this file', $file_lines);
79
80
        if ($end_line_number) {
81
            return $end_line_number;
82
        }
83
84
        // otherwise, in case the last line HAS been modified
85
        // return the last line that has an ending in it
86
        $possible_end_lines = array_filter($file_lines, function ($k) {
87
            return strpos($k, '});') === 0;
88
        });
89
90
        if ($possible_end_lines) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $possible_end_lines 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...
91
            end($possible_end_lines);
92
            $end_line_number = key($possible_end_lines);
93
94
            return $end_line_number;
95
        }
96
    }
97
98
    /**
99
     * Parse the given file stream and return the line number where a string is found.
100
     *
101
     * @param  string $needle   The string that's being searched for.
102
     * @param  array $haystack  The file where the search is being performed.
103
     * @return bool|int         The last line number where the string was found. Or false.
104
     */
105
    private function getLastLineNumberThatContains($needle, $haystack)
106
    {
107
        $matchingLines = array_filter($haystack, function ($k) use ($needle) {
108
            return strpos($k, $needle) !== false;
109
        });
110
111
        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...
112
            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 null|string which is incompatible with the documented return type boolean|integer.
Loading history...
113
        }
114
115
        return false;
116
    }
117
}
118