Passed
Push — dev5 ( a3bb6d...a23557 )
by Ron
07:18
created

updateRun::copyFiles()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 20
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 36
ccs 0
cts 21
cp 0
crap 2
rs 9.6
1
<?php
2
3
namespace App\Console\Commands;
4
5
// use Doctrine\Common\Cache\Version;
6
use Zip;
7
use Illuminate\Console\Command;
8
use Illuminate\Support\Facades\Storage;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\Facades\File;
11
12
use PragmaRX\Version\Package\Version;
13
14
15
class updateRun extends Command
16
{
17
    /**
18
     * The name and signature of the console command.
19
     *
20
     * @var string
21
     */
22
    protected $signature = 'tb-update:run';
23
24
    /**
25
     * The console command description.
26
     *
27
     * @var string
28
     */
29
    protected $description = 'Update the Tech Bench to a newer version';
30
31
    /**
32
     * Create a new command instance.
33
     *
34
     * @return void
35
     */
36 2
    public function __construct()
37
    {
38 2
        parent::__construct();
39 2
    }
40
41
    /**
42
     * Execute the console command.
43
     *
44
     * @return mixed
45
     */
46
    public function handle()
47
    {
48
        $this->line('');
49
        //  Select which update file to use
50
        $updateFile = $this->checkForUpdate();
51
        if ($updateFile) {
52
            //  Open up the file and verify it is at least the same version as the current setup
53
            $valid = $this->openUpdate($updateFile);
54
55
            if ($valid) {
56
                $this->call('down');
57
                $this->copyFiles($updateFile);
58
59
                $this->info('Update Completed');
60
            } else {
61
                $this->error('The selected update is not a newer version');
62
                $this->error('Cannot downgrade Tech Bench in this manner');
63
            }
64
        }
65
    }
66
67
    //  Check to see if any backups are in the backup folder
68
    private function checkForUpdate()
69
    {
70
        $updateList = [];
71
        $updates    = Storage::disk('staging')->files('updates');
72
73
        //  Cycle through each file in the update directory to see if they are update files
74
        foreach ($updates as $update) {
75
            $baseName = explode('/', $update)[1];
76
77
            //  Verify the file is in the .zip format
78
            $fileParts = pathinfo($baseName);
79
            if ($fileParts['extension'] == 'zip') {
80
                //  Verify this is actually an update file
81
                $zip = Zip::open(config('filesystems.disks.staging.root') .
82
                    DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . $baseName);
83
                $files = $zip->listFiles();
84
                if (in_array($fileParts['filename'] . '/config/version.yml', $files)) {
85
                    $updateList[] = $baseName;
86
                }
87
            }
88
        }
89
90
        if (empty($updateList)) {
91
            $this->error('No updates have been loaded to the system');
92
            $this->error('Please upload update package to the Storage/Staging/Updates folder');
93
            return false;
94
        }
95
96
        //  Determine if there is more than one update that can be applied
97
        if (count($updateList) > 1) {
98
            $this->line('');
99
100
            $anticipate = [];
101
            foreach ($updateList as $key => $up) {
102
                $opt = $key + 1;
103
                $anticipate[$opt] = $up;
104
                $this->line('[' . $opt . '] ' . $up);
105
            }
106
            $updateFile = $this->choice('Please select which update you would like to load', $anticipate);
107
        } else {
108
            $updateFile = $updateList[0];
109
        }
110
111
        return $updateFile;
112
    }
113
114
    //  Unzip the update and verify it is a newer or the same version
115
    private function openUpdate($file)
116
    {
117
        $fileParts = pathinfo($file);
118
        $folder = $fileParts['filename'];
119
120
        $zip = Zip::open(config('filesystems.disks.staging.root') .
121
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . $file);
122
123
        $zip->extract(config('filesystems.disks.staging.root') .
124
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp');
125
        $zip->close();
126
127
        $verFile = fopen(config('filesystems.disks.staging.root') .
128
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp' .
129
            DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . 'config' .
130
            DIRECTORY_SEPARATOR . 'version.yml', 'r');
131
132
        $verData = [];
133
        $i = 0;
134
        while (!feof($verFile)) {
0 ignored issues
show
Bug introduced by
It seems like $verFile can also be of type false; however, parameter $handle of feof() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

134
        while (!feof(/** @scrutinizer ignore-type */ $verFile)) {
Loading history...
135
            $line = fgets($verFile);
0 ignored issues
show
Bug introduced by
It seems like $verFile can also be of type false; however, parameter $handle of fgets() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

135
            $line = fgets(/** @scrutinizer ignore-type */ $verFile);
Loading history...
136
            $data = explode(':', $line);
137
138
            if (($data[0] === '  major' || $data[0] === '  minor' || $data[0] === '  patch') && $i < 3) {
139
                $verData[trim($data[0])] = trim($data[1]);
140
                $i++;
141
            }
142
        }
143
144
        $curVersion = new \PragmaRX\Version\Package\Version();
145
146
        $valid = false;
147
        if ($verData['major'] > $curVersion->major()) {
148
            $valid = true;
149
        } else if ($verData['minor'] > $curVersion->minor()) {
150
            $valid = true;
151
        } else if ($verData['patch'] >= $curVersion->patch()) {
152
            $valid = true;
153
        }
154
155
        return $valid;
156
    }
157
158
    //  copy the update files to the proper folders
159
    private function copyFiles($updateFile)
160
    {
161
        $fileParts = pathinfo($updateFile);
162
        $folder = $fileParts['filename'];
163
164
        $updateFile = config('filesystems.disks.staging.root') .
165
            DIRECTORY_SEPARATOR . 'updates' . DIRECTORY_SEPARATOR . 'tmp' .
166
            DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR;
167
168
        // Copy files
169
        File::copyDirectory($updateFile . 'app',       base_path() . DIRECTORY_SEPARATOR . 'app');
170
        File::copyDirectory($updateFile . 'bootstrap', base_path() . DIRECTORY_SEPARATOR . 'bootstrap');
171
        File::copyDirectory($updateFile . 'config',    base_path() . DIRECTORY_SEPARATOR . 'config');
172
        File::copyDirectory($updateFile . 'database',  base_path() . DIRECTORY_SEPARATOR . 'database');
173
        File::copyDirectory($updateFile . 'resources', base_path() . DIRECTORY_SEPARATOR . 'resources');
174
        File::copyDirectory($updateFile . 'routes',    base_path() . DIRECTORY_SEPARATOR . 'routes');
175
176
        //  Run Composer Updates
177
        exec('cd ' . base_path() . ' && composer install --no-dev --no-interaction --optimize-autoloader --no-ansi');
178
        // exec('cd'.base_path().  ' && ziggy:generate');
179
        $this->call('ziggy:generate');
180
        //  Run NPM
181
        exec('cd'.base_path().' && npm install --only=production');
182
        exec('cd'.base_path().' && npm run production');
183
184
        //  Update the database
185
        $this->call('migrate', ['--force']);
186
187
        //  Update the cache
188
        $this->call('config:cache');
189
        $this->call('route:cache');
190
191
        //  Put the app back in working order
192
        $this->call('up');
193
194
        return true;
195
    }
196
}
197