Passed
Push — master ( 3b9459...1d6d9a )
by Ron
11:07 queued 34s
created

updateRun::handle()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
nc 3
nop 0
dl 0
loc 20
ccs 0
cts 11
cp 0
crap 12
rs 9.9
c 1
b 0
f 0
1
<?php
2
3
namespace App\Console\Commands;
4
5
use Zip;
6
use Illuminate\Console\Command;
7
use Illuminate\Support\Facades\File;
8
use Illuminate\Support\Facades\Storage;
9
10
class updateRun extends Command
11
{
12
    protected $signature = 'tb-update:run';
13
    protected $description = 'Update the Tech Bench to a newer version';
14
15 2
    public function __construct()
16
    {
17 2
        parent::__construct();
18 2
    }
19
20
    public function handle()
21
    {
22
        $this->line('');
23
        //  Select which update file to use
24
        $updateFile = $this->checkForUpdate();
25
        if ($updateFile) {
26
            //  Open up the file and verify it is at least the same version as the current setup
27
            $valid = $this->openUpdate($updateFile);
28
29
            if ($valid)
30
            {
31
                $this->call('down');
32
                $this->copyFiles($updateFile);
33
34
                $this->info('Update Completed');
35
            }
36
            else
37
            {
38
                $this->error('The selected update is not a newer version');
39
                $this->error('Cannot downgrade Tech Bench in this manner');
40
            }
41
        }
42
    }
43
44
    //  Check to see if any backups are in the backup folder
45
    private function checkForUpdate()
46
    {
47
        $updateList = [];
48
        $updates    = Storage::disk('staging')->files('updates');
49
50
        //  Cycle through each file in the update directory to see if they are update files
51
        foreach ($updates as $update)
52
        {
53
            $baseName = explode('/', $update)[1];
54
55
            //  Verify the file is in the .zip format
56
            $fileParts = pathinfo($baseName);
57
            if ($fileParts['extension'] == 'zip')
58
            {
59
                //  Verify this is actually an update file
60
                $zip = Zip::open(config('filesystems.disks.staging.root') .
61
                    DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . $baseName);
62
                $files = $zip->listFiles();
63
                if (in_array($fileParts['filename'] . '/config/version.yml', $files))
64
                {
65
                    $updateList[] = $baseName;
66
                }
67
            }
68
        }
69
70
        if (empty($updateList))
71
        {
72
            $this->error('No updates have been loaded to the system');
73
            $this->error('Please upload update package to the Storage/Staging/Updates folder');
74
            return false;
75
        }
76
77
        //  Determine if there is more than one update that can be applied
78
        if (count($updateList) > 1)
79
        {
80
            $this->line('');
81
82
            $anticipate = [];
83
            foreach ($updateList as $key => $up) {
84
                $opt = $key + 1;
85
                $anticipate[$opt] = $up;
86
                $this->line('[' . $opt . '] ' . $up);
87
            }
88
            $updateFile = $this->choice('Please select which update you would like to load', $anticipate);
89
        }
90
        else
91
        {
92
            $updateFile = $updateList[0];
93
        }
94
95
        return $updateFile;
96
    }
97
98
    //  Unzip the update and verify it is a newer or the same version
99
    private function openUpdate($file)
100
    {
101
        $fileParts = pathinfo($file);
102
        $folder = $fileParts['filename'];
103
104
        $zip = Zip::open(config('filesystems.disks.staging.root') .
105
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . $file);
106
107
        $zip->extract(config('filesystems.disks.staging.root') .
108
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp');
109
        $zip->close();
110
111
        $verFile = fopen(config('filesystems.disks.staging.root') .
112
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp' .
113
            DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . 'config' .
114
            DIRECTORY_SEPARATOR . 'version.yml', 'r');
115
116
        $verData = [];
117
        $i = 0;
118
        while (!feof(
119
        /** @scrutinizer ignore-type */
120
        $verFile))
121
        {
122
            $line = fgets(
123
            /** @scrutinizer ignore-type */
124
            $verFile);
125
            $data = explode(':', $line);
126
127
            if (($data[0] === '  major' || $data[0] === '  minor' || $data[0] === '  patch') && $i < 3)
128
            {
129
                $verData[trim($data[0])] = trim($data[1]);
130
                $i++;
131
            }
132
        }
133
134
        $curVersion = new \PragmaRX\Version\Package\Version();
135
136
        $valid = false;
137
        if ($verData['major'] > $curVersion->major())
138
        {
139
            $valid = true;
140
        }
141
        else if ($verData['minor'] > $curVersion->minor())
142
        {
143
            $valid = true;
144
        }
145
        else if ($verData['patch'] >= $curVersion->patch())
146
        {
147
            $valid = true;
148
        }
149
150
        return $valid;
151
    }
152
153
    //  copy the update files to the proper folders
154
    private function copyFiles($updateFile)
155
    {
156
        $fileParts = pathinfo($updateFile);
157
        $folder = $fileParts['filename'];
158
159
        $updateFile = config('filesystems.disks.staging.root') .
160
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp' .
161
            DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR;
162
163
        // Copy files
164
        File::copyDirectory($updateFile . 'app',       base_path() . DIRECTORY_SEPARATOR . 'app');
165
        File::copyDirectory($updateFile . 'bootstrap', base_path() . DIRECTORY_SEPARATOR . 'bootstrap');
166
        File::copyDirectory($updateFile . 'config',    base_path() . DIRECTORY_SEPARATOR . 'config');
167
        File::copyDirectory($updateFile . 'database',  base_path() . DIRECTORY_SEPARATOR . 'database');
168
        File::copyDirectory($updateFile . 'resources', base_path() . DIRECTORY_SEPARATOR . 'resources');
169
        File::copyDirectory($updateFile . 'routes',    base_path() . DIRECTORY_SEPARATOR . 'routes');
170
171
        //  Run Composer Updates
172
        exec('cd ' . base_path() . ' && composer install --no-dev --no-interaction --optimize-autoloader --no-ansi > /dev/null 2>&1');
173
        $this->call('ziggy:generate');
174
        //  Run NPM
175
        exec('cd ' . base_path() . ' && npm install --only=production > /dev/null 2>&1');
176
        exec('cd ' . base_path() . ' && npm run production > /dev/null 2>&1');
177
178
        //  Update the database
179
        $this->call('migrate', ['--force' => 'default']);
180
181
        //  Update the cache
182
        $this->call('config:cache');
183
        $this->call('route:cache');
184
185
        //  Put the app back in working order
186
        $this->call('up');
187
188
        return true;
189
    }
190
}
191