Passed
Push — master ( f01d00...2f7647 )
by Nicolaas
03:27
created

Task   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 323
Duplicated Lines 0 %

Importance

Changes 14
Bugs 3 Features 1
Metric Value
wmc 32
eloc 108
c 14
b 3
f 1
dl 0
loc 323
rs 9.84

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getTaskStep() 0 8 2
A starter() 0 7 3
A getJSON() 0 6 1
A ender() 0 4 2
A __construct() 0 5 1
A mu() 0 7 2
A getDescriptionNice() 0 6 1
A run() 0 11 3
A setJSON() 0 6 1
A setCommitMessage() 0 5 1
A commitAndPush() 0 34 3
A getTaskName() 0 3 1
A create() 0 8 2
A getCommitMessage() 0 6 2
A getTaskStepCode() 0 3 1
A updateJSONViaCommandLine() 0 14 1
A runSilverstripeUpgradeTask() 0 25 4
A deleteTask() 0 5 1
1
<?php
2
/**
3
 * mu stands for Module Object
4
 * @var [type]
5
 */
6
7
namespace Sunnysideup\UpgradeToSilverstripe4\Tasks;
8
9
use Sunnysideup\UpgradeToSilverstripe4\ModuleUpgrader;
10
11
abstract class Task
12
{
13
    /**
14
     * Are we running in debug mode?
15
     * @var bool
16
     */
17
    protected $debug = false;
18
19
    /**
20
     * set a specific task name if needed
21
     * @var string
22
     */
23
    protected $taskName = '';
24
25
    protected $taskStep = 's99';
26
27
    /**
28
     * Array of params that define this task, holds information such as its taskName etc.
29
     * @var mixed
30
     */
31
    protected $params = [];
32
33
    /**
34
     * @var ModuleUpgrader|null the 'Manager' of all the modules responsible for holding Meta data and runtime
35
     * specific runtime arguments.
36
     */
37
    protected $mu = null;
38
39
    /**
40
     * What to write in the commit message after the task is run, only useful if hasCommitAndPush() returns true
41
     * @var string message
42
     */
43
    protected $commitMessage = '';
44
45
    /**
46
     * A static array for holding all the different Tasks that are running
47
     * @var Task[]
48
     */
49
    private static $_singletons = [];
50
51
    /**
52
     * On instantiation sets the parameters and a refernece to the parent ModuleUpgrader
53
     * @param ModuleUpgrader $mu Reference to the master ModuleUpgrader
54
     * @param array  $params All parameters that define this task or are required at any stage during its execution
55
     */
56
    public function __construct($mu, $params = [])
57
    {
58
        $this->mu = $mu;
59
        $this->params = $params;
60
        $this->mu = ModuleUpgrader::create();
61
    }
62
63
    public function getTaskName()
64
    {
65
        return $this->taskName;
66
    }
67
68
    public function getTaskStepCode()
69
    {
70
        return $this->taskStep;
71
    }
72
73
    public function getTaskStep($currentStepCode = '')
74
    {
75
        $taskSteps = $this->mu()->getTaskSteps();
0 ignored issues
show
Bug introduced by
The method getTaskSteps() 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

75
        $taskSteps = $this->mu()->/** @scrutinizer ignore-call */ getTaskSteps();
Loading history...
76
        if (! $currentStepCode) {
77
            $currentStepCode = $this->getTaskStepCode();
78
        }
79
80
        return $taskSteps[$currentStepCode];
81
    }
82
83
    /**
84
     * Creates all the singletons and puts them in the array of singletons. Depending on if they exist already or not.
85
     * While creating the new instances it also passes a reference to the ModuleUpgrader or MU for short.
86
     *
87
     * @param  ModuleUpgrader $mu A reference to the ModuleUpgrader; to be passed on to all instantiated singletons
88
     * @param  array  $params Params that should be passed on to the given Task once it is instantiated
89
     * @return Task Returns the newly created task
90
     */
91
    public static function create($mu, $params = [])
92
    {
93
        $className = static::class;
94
        if (empty(self::$_singletons[$params['taskName']])) {
95
            self::$_singletons[$params['taskName']] = new $className($mu, $params);
96
        }
97
98
        return self::$_singletons[$params['taskName']];
99
    }
100
101
    /**
102
     * Deletes reference to given task and removes it from list of tasks
103
     *
104
     * @param array $params array containing the 'taskName' of target task to delete
105
     */
106
    public static function deleteTask($params)
107
    {
108
        unset(self::$_singletons[$params['taskName']]);
109
110
        return null;
111
    }
112
113
    public function mu()
114
    {
115
        if (! $this->mu) {
116
            $this->mu = ModuleUpgrader::create();
117
        }
118
119
        return $this->mu;
120
    }
121
122
    /**
123
     * returns title of the task at hand ...
124
     *
125
     * @return string
126
     */
127
    abstract public function getTitle();
128
129
    /**
130
     * @return string
131
     */
132
    abstract public function getDescription();
133
134
    /**
135
     * remove white space from description and add # at the end
136
     * lines are also wordwrapped
137
     *
138
     * @return string
139
     */
140
    public function getDescriptionNice()
141
    {
142
        $des = $this->getDescription();
143
        $des = trim(preg_replace('/\s+/', ' ', $des));
144
        $des = trim(wordwrap($des));
145
        return str_replace("\n", "\n" . '# ', $des);
146
    }
147
148
    /**
149
     * Executes the seperate stages of this task in chronological ordering
150
     */
151
    public function run()
152
    {
153
        $this->starter($this->params);
154
        $error = $this->runActualTask($this->params);
155
        if (is_string($error) && strlen($error) > 0) {
156
            $this->mu()->colourPrint("\n\n" . '------------------- EXIT WITH ERROR -------------------------', 'red');
157
            $this->mu()->colourPrint($error, 'red');
158
            $this->mu()->colourPrint("\n\n" . '------------------- EXIT WITH ERROR -------------------------', 'red');
159
            die("\n\n\n---");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
160
        }
161
        $this->ender($this->params);
162
    }
163
164
    /**
165
     * runs the actual task and needs to be defined in any class that extends
166
     * this class.
167
     *
168
     * When it returns a string, we regard this to be a description of a fatal error!
169
     *
170
     * @return string|null
171
     */
172
    abstract public function runActualTask($params = []);
173
174
    public function setCommitMessage($s)
175
    {
176
        $this->commitMessage = $s;
177
178
        return $this;
179
    }
180
181
    public function getJSON($dir)
182
    {
183
        $location = $dir . '/composer.json';
184
        $jsonString = file_get_contents($location);
185
186
        return json_decode($jsonString, true);
187
    }
188
189
    public function setJSON($dir, $data)
190
    {
191
        $location = $dir . '/composer.json';
192
        $newJsonString = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
193
        file_put_contents("'.${location}.'", $newJsonString);
194
        return $this;
195
    }
196
197
    public function updateJSONViaCommandLine($dir, $code, $comment)
198
    {
199
        $location = $dir . '/composer.json';
200
        $this->mu()->execMe(
201
            $dir,
202
            'php -r  \''
203
                . '$jsonString = file_get_contents("' . $location . '"); '
204
                . '$data = json_decode($jsonString, true); '
205
                . $code
206
                . '$newJsonString = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); '
207
                . 'file_put_contents("' . $location . '", $newJsonString); '
208
                . '\'',
209
            $comment . ' --- in ' . $location,
210
            false
211
        );
212
    }
213
214
    /**
215
     * Runs everything that should be run and begining of execution, I.e commiting everything to get or creating a
216
     * backup branch before making changes
217
     */
218
    protected function starter($params = [])
219
    {
220
        foreach ($params as $paramKey => $paramValue) {
221
            if (isset($this->{$paramKey})) {
222
                $this->{$paramKey} = $paramValue;
223
            } else {
224
                user_error('You are trying to set ' . $paramKey . ' but it is meaninguless to this class: ' . static::class);
225
            }
226
        }
227
    }
228
229
    /**
230
     * Executed as the last step of a task. Used primarily for finishing off of changes made during execution of task.
231
     * I.e Making a git commit or tagging the new branch etc etc after all changes are made
232
     */
233
    protected function ender($params = [])
0 ignored issues
show
Unused Code introduced by
The parameter $params 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

233
    protected function ender(/** @scrutinizer ignore-unused */ $params = [])

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...
234
    {
235
        if ($this->hasCommitAndPush()) {
236
            $this->commitAndPush();
237
        }
238
    }
239
240
    /**
241
     * Does the task require the module changes to be committed after the task has run.
242
     * @return bool Defaults to true
243
     */
244
    abstract protected function hasCommitAndPush();
245
246
    /**
247
     * The commit message that is used for the final git commit after running this task. IF none are set it will
248
     * return a default message
249
     * @return string commit message
250
     */
251
    protected function getCommitMessage()
252
    {
253
        if (! $this->commitMessage) {
254
            $this->commitMessage = 'MAJOR: upgrade to new version of Silverstripe - step: ' . $this->getTitle();
255
        }
256
        return $this->commitMessage;
257
    }
258
259
    /**
260
     * Adds all files to Git staging and commits them with set commit message after execution and pushes it via git
261
     */
262
    protected function commitAndPush()
263
    {
264
        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

264
        if ($this->mu()->/** @scrutinizer ignore-call */ getIsModuleUpgrade()) {
Loading history...
265
            $moduleDirs = $this->mu()->getExistingModuleDirLocations();
266
        } else {
267
            $moduleDirs = [$this->mu()->getWebRootDirLocation()];
0 ignored issues
show
Bug introduced by
The method getWebRootDirLocation() 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

267
            $moduleDirs = [$this->mu()->/** @scrutinizer ignore-call */ getWebRootDirLocation()];
Loading history...
268
        }
269
        foreach ($moduleDirs as $moduleDir) {
270
            $message = $this->getCommitMessage();
271
            $this->mu()->execMe(
272
                $moduleDir,
273
                'git add . -A',
274
                'git add all',
275
                false
276
            );
277
278
            $this->mu()->execMe(
279
                $moduleDir,
280
                // 'if ! git diff --quiet; then git commit . -m "'.addslashes($message).'"; fi;',
281
                '
282
                if [ -z "$(git status --porcelain)" ]; then
283
                    echo \'OKI DOKI - Nothing to commit\';
284
                else
285
                    git commit . -m "' . addslashes($message) . '"
286
                fi',
287
                'commit changes: ' . $message,
288
                false
289
            );
290
291
            $this->mu()->execMe(
292
                $moduleDir,
293
                'git push origin ' . $this->mu()->getNameOfTempBranch(),
294
                'pushing changes to origin on the ' . $this->mu()->getNameOfTempBranch() . ' branch',
295
                false
296
            );
297
        }
298
    }
299
300
    /**
301
     * Runs the SilverStripe made upgrader
302
     * @param  string $task     [description]
303
     * @param  string $param1   [description]
304
     * @param  string $param2   [description]
305
     * @param  string $rootDirForCommand  modules root directory
306
     * @param  string $settings [description]
307
     * @param  string  $keyNotesLogFileLocation
308
     */
309
    protected function runSilverstripeUpgradeTask(
310
        $task,
311
        $param1 = '',
312
        $param2 = '',
313
        $rootDirForCommand = '',
314
        $settings = '',
315
        $keyNotesLogFileLocation = ''
316
    ) {
317
        if (! $rootDirForCommand) {
318
            $rootDirForCommand = $this->mu()->getWebRootDirLocation();
319
        }
320
        if (! $keyNotesLogFileLocation) {
321
            $fileName = '/upgrade_notes.md';
322
            if (file_exists($param1)) {
323
                $keyNotesLogFileLocation = $param1 . $fileName;
324
            } else {
325
                $keyNotesLogFileLocation = $rootDirForCommand . $fileName;
326
            }
327
        }
328
        $this->mu()->execMe(
329
            $this->mu()->getWebRootDirLocation(),
330
            'php ' . $this->mu()->getLocationOfSSUpgradeModule() . ' ' . $task . ' ' . $param1 . ' ' . $param2 . ' --root-dir=' . $rootDirForCommand . ' --write -vvv ' . $settings,
0 ignored issues
show
Bug introduced by
The method getLocationOfSSUpgradeModule() 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

330
            'php ' . $this->mu()->/** @scrutinizer ignore-call */ getLocationOfSSUpgradeModule() . ' ' . $task . ' ' . $param1 . ' ' . $param2 . ' --root-dir=' . $rootDirForCommand . ' --write -vvv ' . $settings,
Loading history...
331
            'running php upgrade ' . $task . ' see: https://github.com/silverstripe/silverstripe-upgrader',
332
            false,
333
            $keyNotesLogFileLocation
334
        );
335
    }
336
}
337