Passed
Push — master ( 4487e6...d49ffc )
by John
05:45
created

InstallerBase::insertWhenNotExist()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 39
c 0
b 0
f 0
rs 8.4444
cc 8
nc 6
nop 1
1
<?php
2
3
namespace App\Babel\Install;
4
5
use App\Models\OJModel;
6
use App\Models\CompilerModel;
7
use PharIo\Version\Version;
8
use PharIo\Version\VersionConstraintParser;
9
use PharIo\Version\InvalidVersionException;
10
use Illuminate\Support\Facades\DB;
11
use Exception;
12
use Throwable;
13
14
class InstallerBase
15
{
16
    protected $command;
17
    protected $versionParser;
18
    protected $oid=0;
19
    protected $babelConfig=[];
20
    protected $ocode=null;
21
    protected $worker=null;
22
23
    protected function _install($ocode)
24
    {
25
        try {
26
            $this->ocode=$ocode;
27
            $this->command->line("Installing <fg=green>$ocode</>");
28
            $this->babelConfig=json_decode(file_get_contents(babel_path("Extension/$ocode/babel.json")), true);
29
30
            // check version info
31
            $this->checkVersionInfo();
32
33
            // support __cur__ variables
34
            $this->parseVersion();
35
36
            // check requirement
37
            $this->checkRequirement();
38
39
            //writing database
40
            $this->transactionDB();
41
42
        } catch (Throwable $e) {
43
            if ($e->getMessage()!=="") {
44
                $this->command->line("\n  <bg=red;fg=white> {$e->getMessage()} </>\n");
45
            }
46
        }
47
    }
48
49
    protected function _uninstall($ocode)
50
    {
51
        $this->command->line("<fg=red>Warning: Removing an installed and already-used extension may cause severe consequences, including lossing user submission, problem data and contests regaring or involving the usage of this extension. </>");
52
        if ($this->command->confirm("Are you sure you want to uninstall $ocode?")) {
53
            //uninstall
54
            OJModel::removeOJ(["ocode"=>$ocode]);
55
            $this->command->line("Already removed <fg=green>$ocode</>");
56
        }
57
    }
58
59
    public function __construct($class)
60
    {
61
        $this->command=$class;
62
        $this->versionParser=new VersionConstraintParser();
63
    }
64
65
    private function parseVersion()
66
    {
67
        if (empty($this->babelConfig)) {
68
            throw new Exception('Missing babel.json Config file.');
69
        }
70
71
        if ($this->babelConfig["version"]=="__cur__") {
72
            $this->babelConfig["version"]=explode("-", version())[0];
73
        }
74
75
        if ($this->babelConfig["require"]["NOJ"]=="__cur__") {
76
            $this->babelConfig["require"]["NOJ"]=explode("-", version())[0];
77
        }
78
    }
79
80
    private function checkVersionInfo()
81
    {
82
        // check version info
83
        if (!isset($this->babelConfig["version"]) || is_null($this->babelConfig["version"]) || trim($this->babelConfig["version"])=="") {
84
            throw new Exception('Lack version info.');
85
        }
86
87
        // check require info
88
        if (!isset($this->babelConfig["require"]["NOJ"]) || is_null($this->babelConfig["require"]["NOJ"]) || trim($this->babelConfig["require"]["NOJ"])=="") {
89
            throw new Exception('Lack NOJ compability info.');
90
        }
91
    }
92
93
    private function checkRequirement()
94
    {
95
        try {
96
            if (!($this->versionParser->parse($this->babelConfig["require"]["NOJ"])->complies(new Version(explode("-", version())[0])))) {
97
                if (!$this->command->option('ignore-platform-reqs')) {
98
                    $this->command->line("Your Current NOJ Version <fg=yellow>".version()."</> doesn't support the following extension: ");
99
                    $this->command->line("  - <fg=green>{$this->ocode}</> requires NOJ version <fg=yellow>{$this->babelConfig['require']['NOJ']}</>");
100
                    throw new Exception();
101
                }
102
            }
103
            $needTLS=false;
0 ignored issues
show
Unused Code introduced by
The assignment to $needTLS is dead and can be removed.
Loading history...
104
            if (isset($this->babelConfig["require"]["tlsv1.3"])) {
105
                $needTLS=$this->babelConfig["require"]["tlsv1.3"]?true:false;
106
                $supportTLS=in_array("tlsv1.3", stream_get_transports());
107
                if ($needTLS && !$supportTLS) {
108
                    if (!$this->command->option('ignore-platform-reqs')) {
109
                        $this->command->line("Your Current PHP Registered Stream Socket Transports doesn't support the following extension: ");
110
                        $this->command->line("  - <fg=green>{$this->ocode}</> requires PHP Registered Stream Socket Transports supports <fg=yellow>TLS v1.3</>");
111
                        throw new Exception();
112
                    }
113
                }
114
            }
115
        } catch (InvalidVersionException $e) {
116
            throw new Exception('Illegal Compability Info.');
117
        }
118
    }
119
120
    private function transactionDB()
121
    {
122
        DB::beginTransaction();
123
        $ocode=$this->ocode;
124
        try {
125
            // get current installed version info
126
            $info=OJModel::basic(OJModel::oid($ocode));
127
128
            $this->insertWhenNotExist($info);
129
130
            // init worker
131
            $this->worker=new InstallerWorker($this->ocode, $this->babelConfig, $this->oid, $this->command);
132
133
            // retrieve compiler config and then import it
134
            $latest_timestamp=$this->worker->importCompilerInfo($info);
135
136
            // import css
137
            $this->worker->importCSS();
138
139
            // import icon
140
            $this->worker->importICON();
141
142
            $this->oid=OJModel::updateOJ(OJModel::oid($this->babelConfig["code"]), [
143
                "version"=>$this->babelConfig["version"],
144
                "compiler_timestamp"=>$latest_timestamp,
145
            ]);
146
147
            DB::commit();
148
149
        } catch (Throwable $e) {
150
            DB::rollback();
151
            if ($e->getMessage()!=="") {
152
                $this->command->line("\n  <bg=red;fg=white> {$e->getMessage()} </>\n");
153
            }
154
            return;
155
        }
156
    }
157
158
    private function insertWhenNotExist($info)
159
    {
160
        $ocode=$this->ocode;
0 ignored issues
show
Unused Code introduced by
The assignment to $ocode is dead and can be removed.
Loading history...
161
162
        // if there isn't, create one
163
        if (empty($info)) {
164
            $this->oid=OJModel::insertOJ([
165
                "ocode"=>$this->babelConfig["code"],
166
                "name"=>$this->babelConfig["name"],
167
                "home_page"=>$this->babelConfig["website"],
168
                "logo"=>"/static/img/oj/default.png",
169
                "status"=>1,
170
                "version"=>"",
171
                "compiler_timestamp"=>"",
172
            ]);
173
        } else {
174
            // check legal version format
175
            try {
176
                $currentVersion=new Version($this->babelConfig["version"]);
177
            } catch (InvalidVersionException $e) {
178
                throw new Exception('Illegal Version Info, aborting.');
179
            }
180
181
            // check there is a not null version
182
            if (isset($info["version"]) && !is_null($info["version"]) && trim($info["version"])!="") {
183
                try {
184
                    $installedVersion=new Version($info["version"]);
185
                } catch (InvalidVersionException $e) {
186
                    throw new Exception('Illegal Version Info, aborting.');
187
                }
188
189
                if (!($currentVersion->isGreaterThan($installedVersion))) {
190
                    // lower version or even
191
                    $this->command->line("Nothing to install or update.");
192
                    throw new Exception();
193
                }
194
            }
195
196
            $this->oid=$info["oid"];
197
        }
198
    }
199
}
200