Passed
Push — master ( e764f6...d90321 )
by Nicolaas
02:09
created

ComposerCompatibilityCheckerStep2::moveToTmpVar()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 14
c 1
b 1
f 0
dl 0
loc 23
rs 9.4888
cc 5
nc 7
nop 0
1
<?php
2
3
namespace Sunnysideup\UpgradeToSilverstripe4\Tasks\IndividualTasks;
4
5
use Sunnysideup\UpgradeToSilverstripe4\Api\FileSystemFixes;
6
use Sunnysideup\UpgradeToSilverstripe4\Tasks\Helpers\ComposerJsonFixes;
7
use Sunnysideup\UpgradeToSilverstripe4\Tasks\Task;
8
9
//use either of the following to create the info.json file required
10
//your project will also require a composer.json.default file
11
//this file is used to reset the project to the default state before attempting to install each library
12
//composer info --format=json > info.json
13
//composer info --direct --format=json > info.json
14
15
class ComposerCompatibilityCheckerStep2 extends Task
16
{
17
    protected $taskStep = 's10';
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
    /**
39
     * @param array $params
40
     * @return string|null
41
     */
42
    public function runActualTask($params = [])
43
    {
44
        if ($this->mu()->getIsModuleUpgrade()) {
45
            return null;
46
        }
47
        $this->moveToTmpVar();
48
        $this->testEachRequirement();
49
50
        $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

50
        $this->mu()->/** @scrutinizer ignore-call */ execMe(
Loading history...
51
            $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

51
            $this->mu()->/** @scrutinizer ignore-call */ getGitRootDir(),
Loading history...
52
            'composer update -vvv --no-interaction',
53
            'run composer update',
54
            false
55
        );
56
        return null;
57
    }
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
87
    protected function testEachRequirement()
88
    {
89
        $composerData = ComposerJsonFixes::inst($this->mu())->getJSON(
90
            $this->mu()->getGitRootDir()
91
        );
92
        foreach (['require', 'require-dev'] as $section) {
93
            $tmpSection = $section.$this->appendixToKey;
94
            if (isset($composerData[$tmpSection]) && is_array($composerData[$tmpSection]) && count($composerData[$tmpSection])) {
95
                foreach ($composerData[$tmpSection] as $package => $version) {
96
97
                    $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

97
                    $this->mu()->/** @scrutinizer ignore-call */ colourPrint('trying to add '.$package.':'.$version, 'yellow', 1);
Loading history...
98
99
                    // Attempt to require the package
100
                    $output = '';
101
                    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

101
                    exec("composer require $package:$version --no-update", /** @scrutinizer ignore-type */ $output, $returnVar);
Loading history...
102
                    if ($returnVar !== 0) {
103
                        $this->mu()->colourPrint("$package:$version could not be added. Skipping...", 'red', 1);
104
                        $this->updateComposerJson($section, $package, $version, 'remove');
105
                        // Skip adding to suggest or removing since it's being processed dynamically
106
                    } else {
107
                        // If require was successful, update composer
108
                        $output = '';
109
                        exec('composer update', $output, $updateReturnVar);
110
                        if ($updateReturnVar !== 0) {
111
                            // If update fails, revert the require
112
                            $this->mu()->colourPrint("Update failed after requiring $package. Reverting...", 'red', 1);
113
                            $this->updateComposerJson($section, $package, $version, 'remove');
114
                        } else {
115
                            $this->updateComposerJson($section, $package, $version, 'add');
116
                        }
117
                    }
118
                }
119
            }
120
        }
121
122
    }
123
124
    /**
125
     * Update composer.json to add, remove, or suggest a package.
126
     */
127
    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

127
    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...
128
    {
129
        $composerData = ComposerJsonFixes::inst($this->mu())->getJSON(
130
            $this->mu()->getGitRootDir()
131
        );
132
        switch ($action) {
133
            case 'remove':
134
                $this->mu()->colourPrint('removing to add '.$package.':'.$version, 'red', 1);
135
                unset($composerJson[$section][$package]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $composerJson seems to be never defined.
Loading history...
136
                $composerJson[$section.'-tmp'][$package] = $version;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$composerJson was never initialized. Although not strictly required by PHP, it is generally a good practice to add $composerJson = array(); before regardless.
Loading history...
137
                break;
138
            case 'add':
139
                $this->mu()->colourPrint('adding '.$package.':'.$version, 'green', 1);
140
                $composerJson[$section][$package] = $version;
141
                unset($composerJson[$section.'-tmp'][$package]);
142
                break;
143
        }
144
        ComposerJsonFixes::inst($this->mu())->setJSON(
145
            $this->mu()->getGitRootDir(),
146
            $composerData
147
        );
148
    }
149
150
151
152
    protected function hasCommitAndPush()
153
    {
154
        return false;
155
    }
156
}
157