From 97a6bab4a5a2aa11339ac8ef3a0d27d9fd4f43cc Mon Sep 17 00:00:00 2001
From: Angel Fernando Quiroz Campos <1697880+AngelFQC@users.noreply.github.com>
Date: Sat, 12 Oct 2024 23:59:28 -0500
Subject: [PATCH 1/3] Compilatio: Refactoring to use RESTful api - refs
BT#22064
---
main/inc/lib/Compilatio.php | 597 ++++++------------
main/plagiarism/compilatio/compiladmin.php | 34 +-
.../plagiarism/compilatio/compilatio_ajax.php | 18 +-
main/plagiarism/compilatio/upload.php | 106 +---
main/work/work.lib.php | 33 +-
5 files changed, 273 insertions(+), 515 deletions(-)
diff --git a/main/inc/lib/Compilatio.php b/main/inc/lib/Compilatio.php
index 42bb007fa1f..6e3b780ad1f 100644
--- a/main/inc/lib/Compilatio.php
+++ b/main/inc/lib/Compilatio.php
@@ -2,6 +2,9 @@
/* For licensing terms, see /license.txt */
+use GuzzleHttp\Client;
+use GuzzleHttp\Psr7\Utils;
+
/**
* Build the communication with the SOAP server Compilatio.net
* call several methods for the file management in Compilatio.net.
@@ -12,6 +15,10 @@ class Compilatio
{
/** Identification key for the Compilatio account*/
public $key;
+ /**
+ * @var string
+ */
+ protected $baseUrl;
/** Webservice connection*/
public $soapcli;
private $transportMode;
@@ -22,165 +29,92 @@ class Compilatio
private $proxyHost;
private $proxyPort;
+ /**
+ * @var Client
+ */
+ public $client;
+
/**
* Compilatio constructor.
*/
public function __construct()
{
- if (empty(api_get_configuration_value('allow_compilatio_tool')) ||
- empty(api_get_configuration_value('compilatio_tool'))
- ) {
- throw new Exception('Compilatio not available');
- }
+ $settings = $this->getSettings();
- $settings = api_get_configuration_value('compilatio_tool');
-
- if (isset($settings['settings'])) {
- $settings = $settings['settings'];
- } else {
- throw new Exception('Compilatio config available');
- }
-
- $key = $this->key = $settings['key'];
- $urlsoap = $settings['soap_url'];
- $proxyHost = $this->proxyHost = $settings['proxy_host'];
- $proxyPort = $this->proxyPort = $settings['proxy_port'];
$this->transportMode = $settings['transport_mode'];
$this->maxFileSize = $settings['max_filesize'];
$this->wgetUri = $settings['wget_uri'];
$this->wgetLogin = $settings['wget_login'];
$this->wgetPassword = $settings['wget_password'];
- $soapVersion = 2;
+ $this->key = $settings['key'];
+ $this->baseUrl = $settings['soap_url'];
- try {
- if (!empty($key)) {
- $this->key = $key;
- if (!empty($urlsoap)) {
- if (!empty($proxyHost)) {
- $param = [
- 'trace' => false,
- 'soap_version' => $soapVersion,
- 'exceptions' => true,
- 'proxy_host' => '"'.$proxyHost.'"',
- 'proxy_port' => $proxyPort,
- ];
- } else {
- $param = [
- 'trace' => false,
- 'soap_version' => $soapVersion,
- 'exceptions' => true,
- ];
- }
- $this->soapcli = new SoapClient($urlsoap, $param);
- } else {
- throw new Exception('WS urlsoap not available');
- }
- } else {
- throw new Exception('API key not available');
- }
- } catch (SoapFault $fault) {
- $this->soapcli = "Error constructor compilatio $fault->faultcode $fault->faultstring ";
- } catch (Exception $e) {
- $this->soapcli = "Error constructor compilatio with urlsoap $urlsoap ".$e->getMessage();
+ if (!empty($settings['proxy_host'])) {
+ $this->proxyHost = $settings['proxy_host'];
+ $this->proxyPort = $settings['proxy_port'];
}
- }
-
- /**
- * @return string
- */
- public function getKey()
- {
- return $this->key;
- }
- /**
- * @param mixed $key
- *
- * @return Compilatio
- */
- public function setKey($key)
- {
- $this->key = $key;
+ $clientConfig = [
+ 'base_uri' => api_remove_trailing_slash($this->baseUrl).'/',
+ 'headers' => [
+ 'X-Auth-Token' => $this->key,
+ 'Accept' => 'application/json',
+ ],
+ ];
- return $this;
- }
+ if ($this->proxyPort) {
+ $clientConfig['proxy'] = $this->proxyHost.':'.$this->proxyPort;
+ }
- /**
- * @return mixed
- */
- public function getTransportMode()
- {
- return $this->transportMode;
+ $this->client = new Client($clientConfig);
}
/**
- * @param mixed $transportMode
- *
- * @return Compilatio
+ * @throws Exception
*/
- public function setTransportMode($transportMode)
+ protected function getSettings(): array
{
- $this->transportMode = $transportMode;
-
- return $this;
- }
+ if (empty(api_get_configuration_value('allow_compilatio_tool')) ||
+ empty(api_get_configuration_value('compilatio_tool'))
+ ) {
+ throw new Exception('Compilatio not available');
+ }
- /**
- * @return mixed
- */
- public function getMaxFileSize()
- {
- return $this->maxFileSize;
- }
+ $compilatioTool = api_get_configuration_value('compilatio_tool');
- /**
- * @param mixed $maxFileSize
- *
- * @return Compilatio
- */
- public function setMaxFileSize($maxFileSize)
- {
- $this->maxFileSize = $maxFileSize;
+ if (!isset($compilatioTool['settings'])) {
+ throw new Exception('Compilatio config available');
+ }
- return $this;
- }
+ $settings = $compilatioTool['settings'];
- /**
- * @return mixed
- */
- public function getWgetUri()
- {
- return $this->wgetUri;
- }
+ if (empty($settings['key'])) {
+ throw new Exception('API key not available');
+ }
- /**
- * @param mixed $wgetUri
- *
- * @return Compilatio
- */
- public function setWgetUri($wgetUri)
- {
- $this->wgetUri = $wgetUri;
+ if (empty($settings['soap_url'])) {
+ throw new Exception('WS urlsoap not available');
+ }
- return $this;
+ return $settings;
}
/**
- * @return mixed
+ * @return string
*/
- public function getWgetLogin()
+ public function getKey()
{
- return $this->wgetLogin;
+ return $this->key;
}
/**
- * @param mixed $wgetLogin
+ * @param mixed $key
*
* @return Compilatio
*/
- public function setWgetLogin($wgetLogin)
+ public function setKey($key)
{
- $this->wgetLogin = $wgetLogin;
+ $this->key = $key;
return $this;
}
@@ -188,21 +122,9 @@ public function setWgetLogin($wgetLogin)
/**
* @return mixed
*/
- public function getWgetPassword()
- {
- return $this->wgetPassword;
- }
-
- /**
- * @param mixed $wgetPassword
- *
- * @return Compilatio
- */
- public function setWgetPassword($wgetPassword)
+ public function getMaxFileSize()
{
- $this->wgetPassword = $wgetPassword;
-
- return $this;
+ return $this->maxFileSize;
}
/**
@@ -213,18 +135,6 @@ public function getProxyHost()
return $this->proxyHost;
}
- /**
- * @param mixed $proxyHost
- *
- * @return Compilatio
- */
- public function setProxyHost($proxyHost)
- {
- $this->proxyHost = $proxyHost;
-
- return $this;
- }
-
/**
* @return mixed
*/
@@ -233,161 +143,144 @@ public function getProxyPort()
return $this->proxyPort;
}
- /**
- * @param mixed $proxyPort
- *
- * @return Compilatio
- */
- public function setProxyPort($proxyPort)
- {
- $this->proxyPort = $proxyPort;
-
- return $this;
- }
-
/**
* Method for the file load.
- *
- * @param $title
- * @param $description
- * @param $filename
- * @param $mimeType
- * @param $content
- *
- * @return string
*/
- public function sendDoc($title, $description, $filename, $mimeType, $content)
- {
- try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() $this->soapcli";
- }
-
- return $this->soapcli->__call(
- 'addDocumentBase64',
+ public function sendDoc(
+ string $title,
+ string $description,
+ string $filename,
+ string $filepath
+ ) {
+ $user = api_get_user_entity(api_get_user_id());
+
+ $postData = [
+ 'folder_id' => '',
+ 'title' => $title,
+ 'filename' => basename($filename),
+ 'indexed' => 'true',
+ 'user_notes' => [
+ 'description' => $description
+ ],
+ 'authors' => [
[
- $this->key,
- utf8_encode(urlencode($title)),
- utf8_encode(urlencode($description)),
- utf8_encode(urlencode($filename)),
- utf8_encode($mimeType),
- base64_encode($content),
+ 'firstname' => $user->getFirstname(),
+ 'lastname' => $user->getlastname(),
+ 'email_address' => $user->getEmail(),
]
- );
- } catch (SoapFault $fault) {
- return "Erreur sendDoc()".$fault->faultcode." ".$fault->faultstring;
+ ],
+ 'depositor' => [
+ 'firstname' => $user->getFirstname(),
+ 'lastname' => $user->getlastname(),
+ 'email_address' => $user->getEmail(),
+ ]
+ ];
+
+ try {
+ $responseBody = $this->client
+ ->post(
+ 'private/documents',
+ [
+ 'multipart' => [
+ [
+ 'name' => 'postData',
+ 'contents' => json_encode($postData)
+ ],
+ [
+ 'name' => 'file',
+ 'contents' => Utils::tryFopen($filepath, 'r'),
+ ]
+ ]
+ ]
+ )
+ ->getBody()
+ ;
+ } catch (Exception $e) {
+ throw new Exception($e->getMessage());
}
+
+ $body = json_decode((string) $responseBody, true);
+
+ return $body['data']['document']['id'];
}
/**
* Method for recover a document's information.
*
- * @param $compiHash
- *
- * @return string
+ * @throws Exception
*/
- public function getDoc($compiHash)
+ public function getDoc(string $documentId): array
{
try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() ".$this->soapcli;
- }
- $param = [$this->key, $compiHash];
-
- return $this->soapcli->__call('getDocument', $param);
- } catch (SoapFault $fault) {
- return "Erreur getDoc()".$fault->faultcode." ".$fault->faultstring;
+ $responseBody = $this->client
+ ->get(
+ "private/documents/$documentId"
+ )
+ ->getBody()
+ ;
+ } catch (Exception $e) {
+ throw new Exception($e->getMessage());
}
- }
- /**
- * method for recover an url document's report.
- *
- * @param $compiHash
- *
- * @return string
- */
- public function getReportUrl($compiHash)
- {
- try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() ".$this->soapcli;
- }
- $param = [$this->key, $compiHash];
+ $responseJson = json_decode((string) $responseBody, true);
+ $dataDocument = $responseJson['data']['document'];
- return $this->soapcli->__call('getDocumentReportUrl', $param);
- } catch (SoapFault $fault) {
- return "Erreur getReportUrl()".$fault->faultcode." ".$fault->faultstring;
+ $documentInfo = [
+ 'report_url' => $dataDocument['report_url'],
+ ];
+
+ if (isset($dataDocument['analyses']['anasim']['state'])) {
+ $documentInfo['analysis_status'] = $dataDocument['analyses']['anasim']['state'];
}
+
+ if (isset($dataDocument['light_reports']['anasim']['scores']['global_score_percent'])) {
+ $documentInfo['report_percent'] = $dataDocument['light_reports']['anasim']['scores']['global_score_percent'];
+ }
+
+ return $documentInfo;
}
/**
* Method for deleting a Compialtio's account document.
- *
- * @param $compiHash
- *
- * @return string
*/
- public function deldoc($compiHash)
+ public function deldoc(string $documentId)
{
- try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() ".$this->soapcli;
- }
- $param = [$this->key, $compiHash];
- $this->soapcli->__call('deleteDocument', $param);
- } catch (SoapFault $fault) {
- return "Erreur deldoc()".$fault->faultcode." ".$fault->faultstring;
- }
+
}
/**
* Method for start the analysis for a document.
*
- * @param $compiHash
- *
- * @return string
+ * @throws Exception
*/
- public function startAnalyse($compiHash)
+ public function startAnalyse(string $compilatioId): string
{
try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() ".$this->soapcli;
- }
- $param = [$this->key, $compiHash];
- $this->soapcli->__call('startDocumentAnalyse', $param);
- } catch (SoapFault $fault) {
- return "Erreur startAnalyse()".$fault->faultcode." ".$fault->faultstring;
+ $responseBody = $this->client
+ ->post(
+ 'private/analyses',
+ [
+ 'json' => [
+ 'doc_id' => $compilatioId,
+ 'recipe_name' => 'anasim'
+ ],
+ ]
+ )
+ ->getBody()
+ ;
+ } catch (Exception $e) {
+ throw new Exception($e->getMessage());
}
- }
- /**
- * Method for recover the account's quota.
- *
- * @return string
- */
- public function getQuotas()
- {
- try {
- if (!is_object($this->soapcli)) {
- return "Error in constructor compilatio() ".$this->soapcli;
- }
- $param = [$this->key];
+ $body = json_decode((string) $responseBody, true);
- return $this->soapcli->__call('getAccountQuotas', $param);
- } catch (SoapFault $fault) {
- return "Erreur getQuotas()".$fault->faultcode." ".$fault->faultstring;
- }
+ return $body['data']['analysis']['state'];
}
/**
* Method for identify a file extension and the possibility that the document can be managed by Compilatio.
- *
- * @param $filename
- *
- * @return bool
*/
- public static function verifiFileType($filename)
+ public static function verifiFileType(string $filename): bool
{
$types = ['doc', 'docx', 'rtf', 'xls', 'xlsx', 'ppt', 'pptx', 'odt', 'pdf', 'txt', 'htm', 'html'];
$extension = substr($filename, strrpos($filename, '.') + 1);
@@ -396,105 +289,39 @@ public static function verifiFileType($filename)
return in_array($extension, $types);
}
- /**
- * Fonction affichage de la barre de progression d'analyse version 3.1.
- *
- * @param string $status From the document
- * @param int $pour
- * @param array $text Array includes the extract from the text
- *
- * @return string
- */
- public static function getProgressionAnalyseDocv31($status, $pour = 0, $text = [])
- {
- $loading = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
- $loading .= ' ';
-
- switch ($status) {
- case 'ANALYSE_IN_QUEUE':
- $content = $loading.$text['analysisinqueue'];
- break;
- case 'ANALYSE_PROCESSING':
- $content = $loading.$text['analysisinfinalization'];
- break;
- default:
- $content = Display::bar_progress($pour, true);
- break;
- }
-
- return $content;
- }
-
/**
* Method for display the PomprseuilmankBar (% de plagiat).
- *
- * @param $index
- * @param $weakThreshold
- * @param $highThreshold
- *
- * @return string
*/
public static function getPomprankBarv31(
- $index,
- $weakThreshold,
- $highThreshold
- ) {
+ int $index,
+ int $weakThreshold,
+ int $highThreshold
+ ): string {
$index = round($index);
- $class = 'error';
+ $class = 'danger';
if ($index < $weakThreshold) {
$class = 'success';
- } else {
- if ($index >= $weakThreshold && $index < $highThreshold) {
- $class = 'warning';
- }
+ } elseif ($index < $highThreshold) {
+ $class = 'warning';
}
return Display::bar_progress($index, true, null, $class);
}
/**
- * Method for validation of hash.
- *
- * @param string $hash
- *
- * @return bool
+ * Function for delete a document of the compilatio table if plagiarismTool is Compilatio.
*/
- public static function isMd5($hash)
+ public static function plagiarismDeleteDoc(int $courseId, int $itemId)
{
- return preg_match('`^[a-f0-9]{32}$`', $hash) || preg_match('`^[a-f0-9]{40}$`', $hash);
- }
-
- /**
- * function for delete a document of the compilatio table if plagiarismTool is Compilatio.
- *
- * @param int $courseId
- * @param int $itemId
- *
- * @return bool
- */
- public static function plagiarismDeleteDoc($courseId, $itemId)
- {
- if (api_get_configuration_value('allow_compilatio_tool') === false) {
- return false;
+ if (api_get_configuration_value('allow_compilatio_tool') !== false) {
+ $table = Database::get_course_table(TABLE_PLAGIARISM);
+ $params = [$courseId, $itemId];
+ Database::delete($table, ['c_id = ? AND document_id = ?' => $params]);
}
-
- $table = Database::get_course_table(TABLE_PLAGIARISM);
- $params = [$courseId, $itemId];
- Database::delete($table, ['c_id = ? AND document_id = ?' => $params]);
-
- return true;
}
- /**
- * @param int $courseId
- * @param int $documentId
- * @param int $compilatioId
- */
- public function saveDocument($courseId, $documentId, $compilatioId)
+ public function saveDocument(int $courseId, int $documentId, string $compilatioId)
{
- $documentId = (int) $documentId;
- $courseId = (int) $courseId;
-
$table = Database::get_course_table(TABLE_PLAGIARISM);
$params = [
'c_id' => $courseId,
@@ -504,100 +331,62 @@ public function saveDocument($courseId, $documentId, $compilatioId)
Database::insert($table, $params);
}
- /**
- * @param int $documentId
- * @param int $courseId
- *
- * @return string md5 value
- */
- public function getCompilatioId($documentId, $courseId)
+ public function getCompilatioId(int $documentId, int $courseId): ?string
{
- $documentId = (int) $documentId;
- $courseId = (int) $courseId;
-
$table = Database::get_course_table(TABLE_PLAGIARISM);
$sql = "SELECT compilatio_id FROM $table
WHERE document_id = $documentId AND c_id= $courseId";
$result = Database::query($sql);
$result = Database::fetch_object($result);
- if ($result) {
- return (string) $result->compilatio_id;
- }
-
- return 0;
+ return $result ? (string)$result->compilatio_id : null;
}
- /**
- * @param int $workId
- *
- * @return string
- */
- public function giveWorkIdState($workId)
+ public function giveWorkIdState(int $workId): string
{
$courseId = api_get_course_int_id();
$compilatioId = $this->getCompilatioId($workId, $courseId);
- $actionCompilatio = '';
+ // if the compilatio's hash is not a valide hash md5,
+ // we return à specific status (cf : IsInCompilatio() )
+ $actionCompilatio = get_lang('CompilatioDocumentTextNotImage').'
'.
+ get_lang('CompilatioDocumentNotCorrupt');
$status = '';
if (!empty($compilatioId)) {
- if (self::isMd5($compilatioId)) {
- // if compilatio_id is a hash md5, we call the function of the compilatio's
- // webservice who return the document's status
- $soapRes = $this->getDoc($compilatioId);
- if (isset($soapRes->documentStatus)) {
- $status = $soapRes->documentStatus->status;
- }
- } else {
- // if the compilatio's hash is not a valide hash md5,
- // we return à specific status (cf : IsInCompilatio() )
- $status = 'NOT_IN_COMPILATIO';
- $actionCompilatio = get_lang('CompilatioDocumentTextNotImage').'
'.
- get_lang('CompilatioDocumentNotCorrupt');
- }
+ // if compilatio_id is a hash md5, we call the function of the compilatio's
+ // webservice who return the document's status
+ $soapRes = $this->getDoc($compilatioId);
+ $status = $soapRes['analysis_status'] ?? '';
+
+ $spinnerIcon = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
switch ($status) {
- case 'ANALYSE_COMPLETE':
- $urlRapport = $this->getReportUrl($compilatioId);
- $actionCompilatio .= self::getPomprankBarv31(
- $soapRes->documentStatus->indice,
- 10,
- 35
- )
+ case 'finished':
+ $actionCompilatio .= self::getPomprankBarv31($soapRes['report_percent'], 10, 35)
+ .PHP_EOL
.Display::url(
get_lang('CompilatioAnalysis'),
- $urlRapport,
+ $soapRes['report_url'],
['class' => 'btn btn-primary btn-xs', 'target' => '_blank']
);
break;
- case 'ANALYSE_PROCESSING':
+ case 'running':
$actionCompilatio .= "