ComposerCompatibilityCheckerStep2   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 20
eloc 72
c 1
b 0
f 0
dl 0
loc 136
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getTitle() 0 6 2
A getDescription() 0 3 1
A runActualTask() 0 18 2
A hasCommitAndPush() 0 3 1
B testEachRequirement() 0 28 6
A moveToTmpVar() 0 23 5
A updateComposerJson() 0 20 3
1
<?php
2
3
namespace Sunnysideup\UpgradeToSilverstripe4\Tasks\IndividualTasks;
4
5
use Sunnysideup\UpgradeToSilverstripe4\Tasks\Helpers\ComposerJsonFixes;
6
use Sunnysideup\UpgradeToSilverstripe4\Tasks\Task;
7
8
//use either of the following to create the info.json file required
9
//your project will also require a composer.json.default file
10
//this file is used to reset the project to the default state before attempting to install each library
11
//composer info --format=json > info.json
12
//composer info --direct --format=json > info.json
13
14
class ComposerCompatibilityCheckerStep2 extends Task
15
{
16
    protected $taskStep = 's10';
17
18
    protected $alwaysKeepArray = [
19
        'silverstripe/recipe-cms',
20
    ];
21
22
    protected $appendixToKey = '-tmp';
23
24
    public function getTitle()
25
    {
26
        if ($this->mu()->getIsModuleUpgrade()) {
0 ignored issues
show
Bug introduced by
The method getIsModuleUpgrade() does not exist on Sunnysideup\UpgradeToSilverstripe4\ModuleUpgrader. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

26
        if ($this->mu()->/** @scrutinizer ignore-call */ getIsModuleUpgrade()) {
Loading history...
Bug introduced by
It seems like getIsModuleUpgrade() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

26
        if ($this->mu()->/** @scrutinizer ignore-call */ getIsModuleUpgrade()) {
Loading history...
27
            return 'For module upgrades, this is not being used right now.';
28
        }
29
        return 'Check what composer requirements can be added.';
30
    }
31
32
    public function getDescription()
33
    {
34
        return 'Goes through all the composer requirements and adds them one by one....';
35
    }
36
37
    /**
38
     * @param array $params
39
     */
40
    public function runActualTask($params = []): ?string
41
    {
42
        $this->mu()->setBreakOnAllErrors(true);
0 ignored issues
show
Bug introduced by
It seems like setBreakOnAllErrors() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

42
        $this->mu()->/** @scrutinizer ignore-call */ setBreakOnAllErrors(true);
Loading history...
43
        if ($this->mu()->getIsModuleUpgrade()) {
44
            return null;
45
        }
46
        $this->moveToTmpVar();
47
        $this->testEachRequirement();
48
49
        $this->mu()->execMe(
0 ignored issues
show
Bug introduced by
It seems like execMe() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

49
        $this->mu()->/** @scrutinizer ignore-call */ execMe(
Loading history...
50
            $this->mu()->getGitRootDir(),
0 ignored issues
show
Bug introduced by
It seems like getGitRootDir() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

50
            $this->mu()->/** @scrutinizer ignore-call */ getGitRootDir(),
Loading history...
51
            'composer update -vvv --no-interaction',
52
            'run composer update',
53
            false
54
        );
55
        $this->mu()->setBreakOnAllErrors(false);
56
57
        return null;
58
    }
59
60
    protected function moveToTmpVar()
61
    {
62
        $composerData = ComposerJsonFixes::inst($this->mu())->getJSON(
63
            $this->mu()->getGitRootDir()
64
        );
65
        foreach (['require', 'require-dev'] as $section) {
66
            $tmpSection = $section . $this->appendixToKey;
67
            // move all
68
            if (! empty($composerData[$section])) {
69
                $composerData[$tmpSection] = $composerData[$section];
70
                unset($composerData[$section]);
71
            }
72
            // move the keeps back!
73
            foreach ($this->alwaysKeepArray as $package) {
74
                if (isset($composerData[$tmpSection][$package])) {
75
                    $composerData[$section][$package] = $composerData[$tmpSection][$package];
76
                    unset($composerData[$tmpSection][$package]);
77
                }
78
            }
79
        }
80
        ComposerJsonFixes::inst($this->mu())->setJSON(
81
            $this->mu()->getGitRootDir(),
82
            $composerData
83
        );
84
    }
85
86
    protected function testEachRequirement()
87
    {
88
        $composerData = ComposerJsonFixes::inst($this->mu())->getJSON(
89
            $this->mu()->getGitRootDir()
90
        );
91
        foreach (['require', 'require-dev'] as $section) {
92
            $tmpSection = $section . $this->appendixToKey;
93
            if (! empty($composerData[$tmpSection])) {
94
                foreach ($composerData[$tmpSection] as $package => $version) {
95
                    $this->mu()->colourPrint('trying to add ' . $package . ':' . $version, 'yellow', 1);
0 ignored issues
show
Bug introduced by
It seems like colourPrint() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

95
                    $this->mu()->/** @scrutinizer ignore-call */ colourPrint('trying to add ' . $package . ':' . $version, 'yellow', 1);
Loading history...
96
97
                    // Attempt to require the package
98
                    $output = '';
99
                    exec("composer require $package:$version --no-update", $output, $returnVar);
0 ignored issues
show
Bug introduced by
$output of type string is incompatible with the type array expected by parameter $output of exec(). ( Ignorable by Annotation )

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

99
                    exec("composer require $package:$version --no-update", /** @scrutinizer ignore-type */ $output, $returnVar);
Loading history...
100
                    if ($returnVar !== 0) {
101
                        $this->mu()->colourPrint("$package:$version could not be added. Skipping...", 'red', 1);
102
                        $this->updateComposerJson($section, $package, $version, 'remove');
103
                        // Skip adding to suggest or removing since it's being processed dynamically
104
                    } else {
105
                        // If require was successful, update composer
106
                        $output = '';
107
                        exec('composer update', $output, $updateReturnVar);
108
                        if ($updateReturnVar !== 0) {
109
                            // If update fails, revert the require
110
                            $this->mu()->colourPrint("Update failed after requiring $package. Reverting...", 'red', 1);
111
                            $this->updateComposerJson($section, $package, $version, 'remove');
112
                        } else {
113
                            $this->updateComposerJson($section, $package, $version, 'add');
114
                        }
115
                    }
116
                }
117
            }
118
        }
119
    }
120
121
    /**
122
     * Update composer.json to add, remove, or suggest a package.
123
     */
124
    protected function updateComposerJson(string $section, string $package, string $version, string $action, string $message = ''): void
0 ignored issues
show
Unused Code introduced by
The parameter $message is not used and could be removed. ( Ignorable by Annotation )

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

124
    protected function updateComposerJson(string $section, string $package, string $version, string $action, /** @scrutinizer ignore-unused */ string $message = ''): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
125
    {
126
        $composerData = ComposerJsonFixes::inst($this->mu())->getJSON(
127
            $this->mu()->getGitRootDir()
128
        );
129
        switch ($action) {
130
            case 'remove':
131
                $this->mu()->colourPrint('removing ' . $package . ':' . $version, 'red', 1);
132
                unset($composerData[$section][$package]);
133
                $composerData[$section . '-tmp'][$package] = $version;
134
                break;
135
            case 'add':
136
                $this->mu()->colourPrint('adding ' . $package . ':' . $version, 'green', 1);
137
                $composerData[$section][$package] = $version;
138
                unset($composerData[$section . '-tmp'][$package]);
139
                break;
140
        }
141
        ComposerJsonFixes::inst($this->mu())->setJSON(
142
            $this->mu()->getGitRootDir(),
143
            $composerData
144
        );
145
    }
146
147
    protected function hasCommitAndPush()
148
    {
149
        return false;
150
    }
151
}
152