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 — add-update-command ( 3eac9b )
by Pedro
15:29
created

EnsureFirstPartyAddonsAreCompatibleStep::fix()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 4
eloc 11
c 1
b 0
f 1
nc 3
nop 1
dl 0
loc 21
rs 9.9
1
<?php
2
3
namespace Backpack\CRUD\app\Console\Commands\Upgrade\v7\Steps;
4
5
use Backpack\CRUD\app\Console\Commands\Upgrade\Step;
6
use Backpack\CRUD\app\Console\Commands\Upgrade\StepResult;
7
use Backpack\CRUD\app\Console\Commands\Upgrade\StepStatus;
8
9
class EnsureFirstPartyAddonsAreCompatibleStep extends Step
10
{
11
    protected array $recommendations = [
12
        'backpack/pro' => '^3.0.0-alpha',
13
        'backpack/filemanager' => 'dev-next',
14
        'backpack/theme-coreuiv2' => 'dev-next',
15
        'backpack/theme-coreuiv4' => 'dev-next',
16
        'backpack/theme-tabler' => 'dev-next',
17
        'backpack/logmanager' => 'dev-next',
18
        'backpack/settings' => 'dev-next',
19
        'backpack/newscrud' => 'dev-next',
20
        'backpack/permissionmanager' => 'dev-next',
21
        'backpack/pagemanager' => 'dev-next',
22
        'backpack/menucrud' => 'dev-next',
23
        'backpack/backupmanager' => 'dev-next',
24
        'backpack/editable-columns' => 'dev-next',
25
        'backpack/revise-operation' => 'dev-next',
26
        'backpack/medialibrary-uploaders' => 'dev-next',
27
        'backpack/devtools' => 'dev-next',
28
        'backpack/generators' => 'dev-next',
29
    ];
30
31
    private array $mismatched = [];
32
33
    public function title(): string
34
    {
35
        return 'Ensure Backpack add-ons target v7 compatible releases';
36
    }
37
38
    public function run(): StepResult
39
    {
40
        $this->mismatched = [];
41
42
        foreach ($this->recommendations as $package => $expectedConstraint) {
43
            $constraint = $this->context()->composerRequirement($package);
44
45
            if ($constraint === null) {
46
                continue;
47
            }
48
49
            if (! $this->matchesExpectedConstraint($constraint, $expectedConstraint)) {
50
                $this->mismatched[] = [
51
                    'package' => $package,
52
                    'current' => $constraint,
53
                    'expected' => $expectedConstraint,
54
                    'section' => $this->context()->composerRequirementSection($package) ?? 'require',
55
                ];
56
            }
57
        }
58
59
        if (empty($this->mismatched)) {
60
            return StepResult::success('Detected Backpack add-ons already targeting v7 compatible releases.');
61
        }
62
63
        return StepResult::warning(
64
            'Update the following Backpack add-ons to their v7 compatible versions.',
65
            array_map(fn ($item) => sprintf('%s (current: %s, expected: %s)', $item['package'], $item['current'], $item['expected']), $this->mismatched)
66
        );
67
    }
68
69
    protected function matchesExpectedConstraint(string $constraint, string $expected): bool
70
    {
71
        if ($expected === 'dev-next') {
72
            return str_contains($constraint, 'dev-next');
73
        }
74
75
        if (str_starts_with($expected, '^')) {
76
            $expectedMajor = $this->extractFirstInteger($expected);
77
            $constraintMajor = $this->extractFirstInteger($constraint);
78
79
            return $constraintMajor !== null && $expectedMajor !== null && $constraintMajor >= $expectedMajor;
80
        }
81
82
        return trim($constraint) === trim($expected);
83
    }
84
85
    protected function extractFirstInteger(string $value): ?int
86
    {
87
        if (preg_match('/(\d+)/', $value, $matches)) {
88
            return (int) $matches[1];
89
        }
90
91
        return null;
92
    }
93
94
    public function canFix(StepResult $result): bool
95
    {
96
        return $result->status === StepStatus::Warning && ! empty($this->mismatched);
97
    }
98
99
    public function fix(StepResult $result): StepResult
100
    {
101
        if (empty($this->mismatched)) {
102
            return StepResult::skipped('No add-on constraints require updates.');
103
        }
104
105
        $mismatched = $this->mismatched;
106
107
        $updated = $this->context()->updateComposerJson(function (array &$composer) use ($mismatched) {
108
            foreach ($mismatched as $item) {
109
                $section = $item['section'] ?? 'require';
110
                $composer[$section] = $composer[$section] ?? [];
111
                $composer[$section][$item['package']] = $item['expected'];
112
            }
113
        });
114
115
        if (! $updated) {
116
            return StepResult::failure('Could not update composer.json automatically.');
117
        }
118
119
        return StepResult::success('Updated composer.json constraints for Backpack add-ons.');
120
    }
121
}
122