InstallerBase   A
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 91
c 0
b 0
f 0
dl 0
loc 181
rs 9.52
wmc 36

8 Methods

Rating   Name   Duplication   Size   Complexity  
A _install() 0 22 3
A _uninstall() 0 7 2
B checkVersionInfo() 0 10 7
A parseVersion() 0 12 4
A __construct() 0 4 1
A transactionDB() 0 35 3
B insertWhenNotExist() 0 39 8
B checkRequirement() 0 22 8
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
            if (isset($this->babelConfig["require"]["tlsv1.3"])) {
104
                $supportTLS=in_array("tlsv1.3", stream_get_transports());
105
                if ($this->babelConfig["require"]["tlsv1.3"] && !$supportTLS) {
106
                    if (!$this->command->option('ignore-platform-reqs')) {
107
                        $this->command->line("Your Current PHP Registered Stream Socket Transports doesn't support the following extension: ");
108
                        $this->command->line("  - <fg=green>{$this->ocode}</> requires PHP Registered Stream Socket Transports supports <fg=yellow>TLS v1.3</>");
109
                        throw new Exception();
110
                    }
111
                }
112
            }
113
        } catch (InvalidVersionException $e) {
114
            throw new Exception('Illegal Compability Info.');
115
        }
116
    }
117
118
    private function transactionDB()
119
    {
120
        DB::beginTransaction();
121
        $ocode=$this->ocode;
122
        try {
123
            // get current installed version info
124
            $info=OJModel::basic(OJModel::oid($ocode));
125
126
            $this->insertWhenNotExist($info);
127
128
            // init worker
129
            $this->worker=new InstallerWorker($this->ocode, $this->babelConfig, $this->oid, $this->command);
130
131
            // retrieve compiler config and then import it
132
            $latest_timestamp=$this->worker->importCompilerInfo($info);
133
134
            // import css
135
            $this->worker->importCSS();
136
137
            // import icon
138
            $this->worker->importICON();
139
140
            $this->oid=OJModel::updateOJ(OJModel::oid($this->babelConfig["code"]), [
141
                "version"=>$this->babelConfig["version"],
142
                "compiler_timestamp"=>$latest_timestamp,
143
            ]);
144
145
            DB::commit();
146
147
        } catch (Throwable $e) {
148
            DB::rollback();
149
            if ($e->getMessage()!=="") {
150
                $this->command->line("\n  <bg=red;fg=white> {$e->getMessage()} </>\n");
151
            }
152
            return;
153
        }
154
    }
155
156
    private function insertWhenNotExist($info)
157
    {
158
        $ocode=$this->ocode;
0 ignored issues
show
Unused Code introduced by
The assignment to $ocode is dead and can be removed.
Loading history...
159
160
        // if there isn't, create one
161
        if (empty($info)) {
162
            $this->oid=OJModel::insertOJ([
163
                "ocode"=>$this->babelConfig["code"],
164
                "name"=>$this->babelConfig["name"],
165
                "home_page"=>$this->babelConfig["website"],
166
                "logo"=>"/static/img/oj/default.png",
167
                "status"=>1,
168
                "version"=>"",
169
                "compiler_timestamp"=>"",
170
            ]);
171
        } else {
172
            // check legal version format
173
            try {
174
                $currentVersion=new Version($this->babelConfig["version"]);
175
            } catch (InvalidVersionException $e) {
176
                throw new Exception('Illegal Version Info, aborting.');
177
            }
178
179
            // check there is a not null version
180
            if (isset($info["version"]) && !is_null($info["version"]) && trim($info["version"])!="") {
181
                try {
182
                    $installedVersion=new Version($info["version"]);
183
                } catch (InvalidVersionException $e) {
184
                    throw new Exception('Illegal Version Info, aborting.');
185
                }
186
187
                if (!($currentVersion->isGreaterThan($installedVersion))) {
188
                    // lower version or even
189
                    $this->command->line("Nothing to install or update.");
190
                    throw new Exception();
191
                }
192
            }
193
194
            $this->oid=$info["oid"];
195
        }
196
    }
197
}
198