Passed
Pull Request — 1.11.x (#5852)
by Angel Fernando Quiroz
17:05 queued 06:57
created

Compilatio::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 15
dl 0
loc 26
rs 9.7666
c 0
b 0
f 0
cc 3
nc 4
nop 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Psr7\Utils;
7
8
/**
9
 * Build the communication with the SOAP server Compilatio.net
10
 * call several methods for the file management in Compilatio.net.
11
 *
12
 * @version: 2.0
13
 */
14
class Compilatio
15
{
16
    /** Identification key for the Compilatio account*/
17
    public $key;
18
    /**
19
     * @var string
20
     */
21
    protected $baseUrl;
22
    /** Webservice connection*/
23
    private $maxFileSize;
24
    private $proxyHost;
25
    private $proxyPort;
26
27
    /**
28
     * @var Client
29
     */
30
    public $client;
31
32
    /**
33
     * Compilatio constructor.
34
     *
35
     * @throws Exception
36
     */
37
    public function __construct()
38
    {
39
        $settings = $this->getSettings();
40
41
        $this->maxFileSize = $settings['max_filesize'];
42
        $this->key = $settings['key'];
43
        $this->baseUrl = $settings['api_url'];
44
45
        if (!empty($settings['proxy_host'])) {
46
            $this->proxyHost = $settings['proxy_host'];
47
            $this->proxyPort = $settings['proxy_port'];
48
        }
49
50
        $clientConfig = [
51
            'base_uri' => api_remove_trailing_slash($this->baseUrl).'/',
52
            'headers' => [
53
                'X-Auth-Token' => $this->key,
54
                'Accept' => 'application/json',
55
            ],
56
        ];
57
58
        if ($this->proxyPort) {
59
            $clientConfig['proxy'] = $this->proxyHost.':'.$this->proxyPort;
60
        }
61
62
        $this->client = new Client($clientConfig);
63
    }
64
65
    /**
66
     * @throws Exception
67
     */
68
    protected function getSettings(): array
69
    {
70
        if (empty(api_get_configuration_value('allow_compilatio_tool')) ||
71
            empty(api_get_configuration_value('compilatio_tool'))
72
        ) {
73
            throw new Exception('Compilatio not available');
74
        }
75
76
        $compilatioTool = api_get_configuration_value('compilatio_tool');
77
78
        if (!isset($compilatioTool['settings'])) {
79
            throw new Exception('Compilatio config available');
80
        }
81
82
        $settings = $compilatioTool['settings'];
83
84
        if (empty($settings['key'])) {
85
            throw new Exception('API key not available');
86
        }
87
88
        if (empty($settings['api_url'])) {
89
            throw new Exception('Api URL not available');
90
        }
91
92
        return $settings;
93
    }
94
95
    /**
96
     * @return string
97
     */
98
    public function getKey()
99
    {
100
        return $this->key;
101
    }
102
103
    /**
104
     * @param mixed $key
105
     *
106
     * @return Compilatio
107
     */
108
    public function setKey($key)
109
    {
110
        $this->key = $key;
111
112
        return $this;
113
    }
114
115
    /**
116
     * @return mixed
117
     */
118
    public function getMaxFileSize()
119
    {
120
        return $this->maxFileSize;
121
    }
122
123
    /**
124
     * @return mixed
125
     */
126
    public function getProxyHost()
127
    {
128
        return $this->proxyHost;
129
    }
130
131
    /**
132
     * @return mixed
133
     */
134
    public function getProxyPort()
135
    {
136
        return $this->proxyPort;
137
    }
138
139
    /**
140
     * Method for the file load.
141
     */
142
    public function sendDoc(
143
        string $title,
144
        string $description,
145
        string $filename,
146
        string $filepath
147
    ) {
148
        $user = api_get_user_entity(api_get_user_id());
149
150
        $postData = [
151
            'folder_id' => '',
152
            'title' => $title,
153
            'filename' => basename($filename),
154
            'indexed' => 'true',
155
            'user_notes' => [
156
                'description' => $description
157
            ],
158
            'authors' => [
159
                [
160
                    'firstname' => $user->getFirstname(),
161
                    'lastname' => $user->getlastname(),
162
                    'email_address' => $user->getEmail(),
163
                ]
164
            ],
165
            'depositor' => [
166
                'firstname' => $user->getFirstname(),
167
                'lastname' => $user->getlastname(),
168
                'email_address' => $user->getEmail(),
169
            ]
170
        ];
171
172
        try {
173
            $responseBody = $this->client
174
                ->post(
175
                    'private/documents',
176
                    [
177
                        'multipart' => [
178
                            [
179
                                'name'     => 'postData',
180
                                'contents' => json_encode($postData)
181
                            ],
182
                            [
183
                                'name'     => 'file',
184
                                'contents' => Utils::tryFopen($filepath, 'r'),
185
                            ]
186
                        ]
187
                    ]
188
                )
189
                ->getBody()
190
            ;
191
        } catch (Exception $e) {
192
            throw new Exception($e->getMessage());
193
        }
194
195
        $body = json_decode((string) $responseBody, true);
196
197
        return $body['data']['document']['id'];
198
    }
199
200
    /**
201
     * Method for recover a document's information.
202
     *
203
     * @throws Exception
204
     */
205
    public function getDoc(string $documentId): array
206
    {
207
        try {
208
            $responseBody = $this->client
209
                ->get(
210
                    "private/documents/$documentId"
211
                )
212
                ->getBody()
213
            ;
214
        } catch (Exception $e) {
215
            throw new Exception($e->getMessage());
216
        }
217
218
        $responseJson = json_decode((string) $responseBody, true);
219
        $dataDocument = $responseJson['data']['document'];
220
221
        $documentInfo = [
222
            'report_url' => $dataDocument['report_url'],
223
        ];
224
225
        if (isset($dataDocument['analyses']['anasim']['state'])) {
226
            $documentInfo['analysis_status'] = $dataDocument['analyses']['anasim']['state'];
227
        }
228
229
        if (isset($dataDocument['light_reports']['anasim']['scores']['global_score_percent'])) {
230
            $documentInfo['report_percent'] = $dataDocument['light_reports']['anasim']['scores']['global_score_percent'];
231
        }
232
233
        return $documentInfo;
234
    }
235
236
    /**
237
     *  Method for deleting a Compialtio's account document.
238
     */
239
    public function deldoc(string $documentId)
240
    {
241
242
    }
243
244
    /**
245
     * Method for start the analysis for a document.
246
     *
247
     * @throws Exception
248
     */
249
    public function startAnalyse(string $compilatioId): string
250
    {
251
        try {
252
            $responseBody = $this->client
253
                ->post(
254
                    'private/analyses',
255
                    [
256
                        'json' => [
257
                            'doc_id' => $compilatioId,
258
                            'recipe_name' => 'anasim'
259
                        ],
260
                    ]
261
                )
262
                ->getBody()
263
            ;
264
        } catch (Exception $e) {
265
            throw new Exception($e->getMessage());
266
        }
267
268
        $body = json_decode((string) $responseBody, true);
269
270
        return $body['data']['analysis']['state'];
271
    }
272
273
    /**
274
     * Method for identify a file extension and the possibility that the document can be managed by Compilatio.
275
     */
276
    public static function verifiFileType(string $filename): bool
277
    {
278
        $types = ['doc', 'docx', 'rtf', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'pdf', 'txt', 'htm', 'html'];
279
        $extension = substr($filename, strrpos($filename, '.') + 1);
280
        $extension = strtolower($extension);
281
282
        return in_array($extension, $types);
283
    }
284
285
    /**
286
     * Method for display the PomprseuilmankBar (% de plagiat).
287
     */
288
    public static function getPomprankBarv31(
289
        int $index,
290
        int $weakThreshold,
291
        int $highThreshold
292
    ): string {
293
        $index = round($index);
294
        $class = 'danger';
295
        if ($index < $weakThreshold) {
296
            $class = 'success';
297
        } elseif ($index < $highThreshold) {
298
            $class = 'warning';
299
        }
300
301
        return Display::bar_progress($index, true, null, $class);
302
    }
303
304
    /**
305
     * Function for delete a document of the compilatio table if plagiarismTool is Compilatio.
306
     */
307
    public static function plagiarismDeleteDoc(int $courseId, int $itemId)
308
    {
309
        if (api_get_configuration_value('allow_compilatio_tool') !== false) {
310
            $table = Database::get_course_table(TABLE_PLAGIARISM);
311
            $params = [$courseId, $itemId];
312
            Database::delete($table, ['c_id = ? AND document_id = ?' => $params]);
313
        }
314
    }
315
316
    public function saveDocument(int $courseId, int $documentId, string $compilatioId)
317
    {
318
        $table = Database::get_course_table(TABLE_PLAGIARISM);
319
        $params = [
320
            'c_id' => $courseId,
321
            'document_id' => $documentId,
322
            'compilatio_id' => $compilatioId,
323
        ];
324
        Database::insert($table, $params);
325
    }
326
327
    public function getCompilatioId(int $documentId, int $courseId): ?string
328
    {
329
        $table = Database::get_course_table(TABLE_PLAGIARISM);
330
        $sql = "SELECT compilatio_id FROM $table
331
                WHERE document_id = $documentId AND c_id= $courseId";
332
        $result = Database::query($sql);
333
        $result = Database::fetch_object($result);
334
335
        return $result ? (string)$result->compilatio_id : null;
336
    }
337
338
    public function giveWorkIdState(int $workId): string
339
    {
340
        $courseId = api_get_course_int_id();
341
        $compilatioId = $this->getCompilatioId($workId, $courseId);
342
343
        // if the compilatio's hash is not a valide hash md5,
344
        // we return à specific status (cf : IsInCompilatio() )
345
        $actionCompilatio = get_lang('CompilatioDocumentTextNotImage').'<br/>'.
346
            get_lang('CompilatioDocumentNotCorrupt');
347
        $status = '';
348
        if (!empty($compilatioId)) {
349
            // if compilatio_id is a hash md5, we call the function of the compilatio's
350
            // webservice who return the document's status
351
            $soapRes = $this->getDoc($compilatioId);
352
            $status = $soapRes['analysis_status'] ?? '';
353
354
            $spinnerIcon = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
355
356
            switch ($status) {
357
                case 'finished':
358
                    $actionCompilatio .= self::getPomprankBarv31($soapRes['report_percent'], 10, 35)
359
                        .PHP_EOL
360
                        .Display::url(
361
                            get_lang('CompilatioAnalysis'),
362
                            $soapRes['report_url'],
363
                            ['class' => 'btn btn-primary btn-xs', 'target' => '_blank']
364
                        );
365
                    break;
366
                case 'running':
367
                    $actionCompilatio .= "<div style='font-weight:bold;text-align:left'>"
368
                        .get_lang('CompilatioAnalysisInProgress')
369
                        ."</div>";
370
                    $actionCompilatio .= "<div style='font-size:80%;font-style:italic;margin-bottom:5px;'>"
371
                        .get_lang('CompilatioAnalysisPercentage')
372
                        ."</div>";
373
                    $actionCompilatio .= $spinnerIcon.PHP_EOL .get_lang('CompilatioAnalysisEnding');
374
                    break;
375
                case 'waiting':
376
                    $actionCompilatio .= $spinnerIcon.PHP_EOL.get_lang('CompilatioWaitingAnalysis');
377
                    break;
378
                case 'canceled':
379
                    $actionCompilatio .= get_lang('Cancelled');
380
                    break;
381
                case 'scheduled':
382
                    $actionCompilatio .= $spinnerIcon.PHP_EOL.get_lang('CompilatioAwaitingAnalysis');
383
                    break;
384
            }
385
        }
386
387
        return $workId.'|'.$actionCompilatio.'|'.$status.'|';
388
    }
389
}
390