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 — master ( 42b837...c99185 )
by Cristian
98:50 queued 14s
created

AddCustomRouteContent   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 38
c 2
b 1
f 0
dl 0
loc 108
rs 10
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getLastLineNumberThatContains() 0 11 2
A handle() 0 32 4
A __construct() 0 3 1
A customRoutesFileEndLine() 0 20 3
1
<?php
2
3
namespace Backpack\CRUD\app\Console\Commands;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Facades\Artisan;
7
use Illuminate\Support\Facades\Storage;
8
9
class AddCustomRouteContent extends Command
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
19
    /**
20
     * The console command description.
21
     *
22
     * @var string
23
     */
24
    protected $description = 'Add HTML/PHP code to the routes/backpack/custom.php file';
25
26
    /**
27
     * Create a new command instance.
28
     *
29
     * @return void
30
     */
31
    public function __construct()
32
    {
33
        parent::__construct();
34
    }
35
36
    /**
37
     * Execute the console command.
38
     *
39
     * @return mixed
40
     */
41
    public function handle()
42
    {
43
        $path = 'routes/backpack/custom.php';
44
        $disk_name = config('backpack.base.root_disk_name');
45
        $disk = Storage::disk($disk_name);
46
        $code = $this->argument('code');
47
48
        if ($disk->exists($path)) {
49
            $old_file_path = $disk->path($path);
50
51
            // insert the given code before the file's last line
52
            $file_lines = file($old_file_path, FILE_IGNORE_NEW_LINES);
53
54
            // if the code already exists in the file, abort
55
            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

55
            if ($this->getLastLineNumberThatContains(/** @scrutinizer ignore-type */ $code, $file_lines)) {
Loading history...
56
                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...
57
            }
58
59
            $end_line_number = $this->customRoutesFileEndLine($file_lines);
60
            $file_lines[$end_line_number + 1] = $file_lines[$end_line_number];
61
            $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

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