diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index e4e68ebdf..0dbcc9727 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -5,6 +5,7 @@ on:
branches:
- GaelO2
- GaelO2-dev
+ - tmtv-inference
tags:
- '*'
@@ -22,6 +23,7 @@ jobs:
with:
images: ghcr.io/pixilib/gaelo
tags: |
+ type=ref,event=branch
type=ref,event=tag
v2-latest
diff --git a/GaelO2/.env.example b/GaelO2/.env.example
index 5fff70efc..a9bfe77ca 100644
--- a/GaelO2/.env.example
+++ b/GaelO2/.env.example
@@ -15,22 +15,22 @@ DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
-TUS_URL = 'http://localhost:1080'
+TUS_URL='http://localhost:1080'
-ORTHANC_TEMPORARY_URL = 'http://localhost:8042'
-ORTHANC_TEMPORARY_LOGIN = 'login'
-ORTHANC_TEMPORARY_PASSWORD = 'password'
+ORTHANC_TEMPORARY_URL='http://localhost:8042'
+ORTHANC_TEMPORARY_LOGIN='login'
+ORTHANC_TEMPORARY_PASSWORD='password'
-ORTHANC_STORAGE_URL = 'http://localhost:8043'
-ORTHANC_STORAGE_LOGIN = 'login'
-ORTHANC_STORAGE_PASSWORD = 'password'
+ORTHANC_STORAGE_URL='http://localhost:8043'
+ORTHANC_STORAGE_LOGIN='login'
+ORTHANC_STORAGE_PASSWORD='password'
-GAELO_PROCESSING_PROTOCOL='http://'
-GAELO_PROCESSING_HOST = 'gaeloprocessing'
-GAELO_PROCESSING_PORT= '8000'
+GAELO_PROCESSING_URL='http://gaeloprocessing:8000'
+GAELO_PROCESSING_LOGIN='login'
+GAELO_PROCESSING_PASSWORD='password'
-AZURE_CLIENT_ID =''
-AZURE_DIRECTORY_ID =''
+AZURE_CLIENT_ID=''
+AZURE_DIRECTORY_ID=''
AZURE_CLIENT_SECRET=''
AZURE_SUBSCRIPTION_ID=''
AZURE_CONTAINER_GROUP=''
diff --git a/GaelO2/app/GaelO/Adapters/FrameworkAdapter.php b/GaelO2/app/GaelO/Adapters/FrameworkAdapter.php
index 671923614..65c235000 100644
--- a/GaelO2/app/GaelO/Adapters/FrameworkAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/FrameworkAdapter.php
@@ -59,7 +59,7 @@ public static function sendRegisteredEventForEmailVerification(int $userId): voi
public static function sendResetPasswordLink(string $email): bool
{
$status = Password::sendResetLink(
- ['email' => $email]
+ ['email' => strtolower($email)]
);
return $status === Password::RESET_LINK_SENT;
diff --git a/GaelO2/app/GaelO/Adapters/HttpClientAdapter.php b/GaelO2/app/GaelO/Adapters/HttpClientAdapter.php
index f3a3913b3..cd35648ec 100644
--- a/GaelO2/app/GaelO/Adapters/HttpClientAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/HttpClientAdapter.php
@@ -46,6 +46,19 @@ public function setBasicAuthentication(string $login, string $password): void
$this->password = $password;
}
+ public function uploadFile(string $method, string $uri, string $filename): Psr7ResponseInterface
+ {
+ $fileHandler = fopen($filename, 'rb');
+ $headers = [
+ 'auth' => [$this->login, $this->password],
+ 'content-type' => 'application/zip',
+ 'body' => $fileHandler
+ ];
+
+ $response = $this->client->request($method, $this->address . $uri, $headers);
+ return new Psr7ResponseAdapter($response);
+ }
+
public function requestUploadArrayDicom(string $method, string $uri, array $files): array
{
@@ -71,7 +84,7 @@ public function requestUploadArrayDicom(string $method, string $uri, array $file
},
'rejected' => function (RequestException $exception, $index) {
$reason = "Error sending dicom to orthanc";
-
+
if ($exception->hasResponse()) {
$reason = $exception->getResponse()->getStatusCode();
Log::error($exception->getResponse()->getBody()->getContents());
@@ -79,7 +92,7 @@ public function requestUploadArrayDicom(string $method, string $uri, array $file
$reason = $exception->getMessage();
}
// this is delivered each failed request
- Log::error('DICOM Import Failed in Orthanc Temporary: '.$reason. ' index: '.$index);
+ Log::error('DICOM Import Failed in Orthanc Temporary: ' . $reason . ' index: ' . $index);
},
]);
@@ -95,7 +108,14 @@ public function requestUploadArrayDicom(string $method, string $uri, array $file
public function requestJson(string $method, string $uri, array $body = []): Psr7ResponseInterface
{
- $authenticationOption = ['auth' => [$this->login, $this->password]];
+ if ($this->login !== '' && $this->password !== '') {
+ $authenticationOption['auth'] = [$this->login, $this->password];
+ }
+
+ if ($this->authorizationToken != null) {
+ $authenticationOption['headers']['Authorization'] = 'Bearer ' . $this->authorizationToken;
+ }
+
$bodyOption = ['json' => $body];
$options = array_merge($authenticationOption, $bodyOption);
$response = $this->client->request($method, $this->address . $uri, $options);
@@ -135,7 +155,7 @@ public function requestStreamResponseToFile(string $method, string $uri, $ressou
return new Psr7ResponseAdapter($response);
}
- public function rowRequest(string $method, string $uri, $body, ?array $headers, $ressourceDestination = null, $httpErrors = true): Psr7ResponseInterface
+ public function rawRequest(string $method, string $uri, $body, ?array $headers, $ressourceDestination = null, $httpErrors = true): Psr7ResponseInterface
{
$options = [];
diff --git a/GaelO2/app/GaelO/Adapters/JobAdapter.php b/GaelO2/app/GaelO/Adapters/JobAdapter.php
index cc57b101a..7cc69ed77 100644
--- a/GaelO2/app/GaelO/Adapters/JobAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/JobAdapter.php
@@ -4,6 +4,7 @@
use App\GaelO\Interfaces\Adapters\JobInterface;
use App\Jobs\JobQcReport;
+use App\Jobs\JobRadiomicsReport;
class JobAdapter implements JobInterface
{
@@ -11,4 +12,9 @@ public function sendQcReportJob(int $visitId): void
{
JobQcReport::dispatch($visitId);
}
+
+ public function sendRadiomicsReport(int $visitId, int $behalfUserId): void
+ {
+ JobRadiomicsReport::dispatch($visitId, $behalfUserId);
+ }
}
diff --git a/GaelO2/app/GaelO/Adapters/MailerAdapter.php b/GaelO2/app/GaelO/Adapters/MailerAdapter.php
index 12e6c4d8f..35662096c 100644
--- a/GaelO2/app/GaelO/Adapters/MailerAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/MailerAdapter.php
@@ -29,7 +29,9 @@
use App\GaelO\Interfaces\Adapters\MailerInterface;
use App\Mail\QcReport;
use App\Mail\ImportPatient;
+use App\Mail\JobFailure;
use App\Mail\MagicLink;
+use App\Mail\RadiomicsReport;
use App\Mail\RequestPatientCreation;
use App\Mail\UserCreated;
use Illuminate\Mail\Mailable;
@@ -158,6 +160,12 @@ private function getModel(int $model): Mailable
case MailConstants::EMAIL_REQUEST_PATIENT_CREATION:
$model = new RequestPatientCreation($this->parameters);
break;
+ case MailConstants::EMAIL_RADIOMICS_REPORT:
+ $model = new RadiomicsReport($this->parameters);
+ break;
+ case MailConstants::EMAIL_JOB_FAILURE:
+ $model = new JobFailure($this->parameters);
+ break;
default:
throw new GaelOException("Unkown Mail Type");
break;
diff --git a/GaelO2/app/GaelO/Adapters/MimeAdapter.php b/GaelO2/app/GaelO/Adapters/MimeAdapter.php
index 4fe0196d1..8e30d5883 100644
--- a/GaelO2/app/GaelO/Adapters/MimeAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/MimeAdapter.php
@@ -3,20 +3,22 @@
namespace App\GaelO\Adapters;
use App\GaelO\Interfaces\Adapters\MimeInterface;
-use Mimey\MimeTypes;
+use Illuminate\Support\Facades\Log;
+use League\MimeTypeDetection\ExtensionMimeTypeDetector;
+use League\MimeTypeDetection\GeneratedExtensionToMimeTypeMap;
class MimeAdapter implements MimeInterface
{
public static function getExtensionsFromMime(string $mime): array
{
- $mimes = new MimeTypes();
- return $mimes->getAllExtensions($mime);
+ $mimes = new ExtensionMimeTypeDetector();
+ return $mimes->lookupAllExtensions($mime);
}
- public static function getMimesFromExtension(string $extension): array
+ public static function getMimeFromExtension(string $extension): string
{
- $mimes = new MimeTypes();
- return $mimes->getAllMimeTypes($extension);
+ $mimes = new GeneratedExtensionToMimeTypeMap();
+ return $mimes->lookupMimeType($extension);
}
}
diff --git a/GaelO2/app/GaelO/Adapters/PdfAdapter.php b/GaelO2/app/GaelO/Adapters/PdfAdapter.php
new file mode 100644
index 000000000..fa5db9726
--- /dev/null
+++ b/GaelO2/app/GaelO/Adapters/PdfAdapter.php
@@ -0,0 +1,16 @@
+setOption('defaultFont', 'sans-serif');
+ $pdf->save($filename);
+ }
+}
diff --git a/GaelO2/app/GaelO/Adapters/Psr7ResponseAdapter.php b/GaelO2/app/GaelO/Adapters/Psr7ResponseAdapter.php
index 095043d02..253767eef 100644
--- a/GaelO2/app/GaelO/Adapters/Psr7ResponseAdapter.php
+++ b/GaelO2/app/GaelO/Adapters/Psr7ResponseAdapter.php
@@ -4,6 +4,7 @@
use App\GaelO\Interfaces\Adapters\Psr7ResponseInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
class Psr7ResponseAdapter implements Psr7ResponseInterface
{
@@ -20,6 +21,11 @@ public function getStatusCode(): int
return $this->response->getStatusCode();
}
+ public function getStream(): StreamInterface
+ {
+ return $this->response->getBody();
+ }
+
public function getBody(): string
{
return $this->response->getBody()->getContents();
diff --git a/GaelO2/app/GaelO/Constants/Constants.php b/GaelO2/app/GaelO/Constants/Constants.php
index d974735f4..0616da62c 100644
--- a/GaelO2/app/GaelO/Constants/Constants.php
+++ b/GaelO2/app/GaelO/Constants/Constants.php
@@ -23,6 +23,7 @@ class Constants
const TRACKER_CREATE_VISIT = "Create Visit";
const TRACKER_UPLOAD_SERIES = "Upload Series";
const TRACKER_UPDATE_VISIT_DATE = "Update Visit Date";
+ const TRACKER_UPDATE_VISIT_FILE = "Update Visit File";
const TRACKER_UPLOAD_VALIDATION_FAILED = "Upload Failed";
const TRACKER_ASK_UNLOCK = "Ask Unlock Form";
const TRACKER_UNLOCK_INVESTIGATOR_FORM = "Unlock Investigator Form";
diff --git a/GaelO2/app/GaelO/Constants/MailConstants.php b/GaelO2/app/GaelO/Constants/MailConstants.php
index c6cbf333a..c23ac65a8 100644
--- a/GaelO2/app/GaelO/Constants/MailConstants.php
+++ b/GaelO2/app/GaelO/Constants/MailConstants.php
@@ -27,4 +27,6 @@ class MailConstants {
const EMAIL_UNLOCK_QC_REQUEST=22;
const EMAIL_QC_REPORT = 23;
const EMAIL_REQUEST_PATIENT_CREATION = 24;
+ const EMAIL_RADIOMICS_REPORT = 25;
+ const EMAIL_JOB_FAILURE = 26;
}
diff --git a/GaelO2/app/GaelO/Constants/SettingsConstants.php b/GaelO2/app/GaelO/Constants/SettingsConstants.php
index 79d8f2ac7..32a42bddb 100644
--- a/GaelO2/app/GaelO/Constants/SettingsConstants.php
+++ b/GaelO2/app/GaelO/Constants/SettingsConstants.php
@@ -20,9 +20,9 @@ class SettingsConstants {
const ORTHANC_STORAGE_LOGIN = 'orthanc_storage_login';
const ORTHANC_STORAGE_PASSWORD = 'orthanc_storage_password';
- const GAELO_PROCESSING_PROTOCOL='gaelo_processing_protocol';
- const GAELO_PROCESSING_HOST = 'gaelo_processing_host';
- const GAELO_PROCESSING_PORT= 'gaelo_processing_port';
+ const GAELO_PROCESSING_URL='gaelo_processing_url';
+ const GAELO_PROCESSING_LOGIN='gaelo_processing_login';
+ const GAELO_PROCESSING_PASSWORD='gaelo_processing_password';
const AZURE_CLIENT_ID ='azure_client_id';
const AZURE_DIRECTORY_ID ='azure_directory_id';
diff --git a/GaelO2/app/GaelO/Entities/ReviewEntity.php b/GaelO2/app/GaelO/Entities/ReviewEntity.php
index 86ec4ef12..9c4fa053c 100644
--- a/GaelO2/app/GaelO/Entities/ReviewEntity.php
+++ b/GaelO2/app/GaelO/Entities/ReviewEntity.php
@@ -21,13 +21,13 @@ public static function fillFromDBReponseArray(array $array): ReviewEntity
$reviewEntity = new ReviewEntity();
$reviewEntity->local = $array['local'];
$reviewEntity->id = $array['id'];
- $reviewEntity->study_name = $array['study_name'];
+ $reviewEntity->studyName = $array['study_name'];
$reviewEntity->userId = $array['user_id'];
$reviewEntity->date = $array['review_date'];
$reviewEntity->visitId = $array['visit_id'];
$reviewEntity->validated = $array['validated'];
$reviewEntity->data = $array['review_data'];
- $reviewEntity->files = $array['sent_files'];
+ $reviewEntity->files = $array['sent_files'] ?? [];
$reviewEntity->adjudication = $array['adjudication'];
return $reviewEntity;
}
diff --git a/GaelO2/app/GaelO/Entities/StudyEntity.php b/GaelO2/app/GaelO/Entities/StudyEntity.php
index bbb68c2b8..bfa3eb20d 100644
--- a/GaelO2/app/GaelO/Entities/StudyEntity.php
+++ b/GaelO2/app/GaelO/Entities/StudyEntity.php
@@ -13,6 +13,7 @@ class StudyEntity
public bool $monitorShowAll;
public bool $documentationMandatory;
public bool $deleted;
+ public bool $creatablePatientsInvestigator;
public ?string $ancillaryOf;
//Array of VisitGroupEntities
@@ -29,6 +30,7 @@ public static function fillFromDBReponseArray(array $array) : StudyEntity
$studyEntity->monitorShowAll = $array['monitor_show_all'];
$studyEntity->ancillaryOf = $array['ancillary_of'];
$studyEntity->documentationMandatory = $array['documentation_mandatory'];
+ $studyEntity->creatablePatientsInvestigator = $array['creatable_patients_investigator'];
$studyEntity->deleted = $array['deleted_at'] !== null;
return $studyEntity;
diff --git a/GaelO2/app/GaelO/Entities/VisitEntity.php b/GaelO2/app/GaelO/Entities/VisitEntity.php
index 28b6b0f65..68f1c477f 100644
--- a/GaelO2/app/GaelO/Entities/VisitEntity.php
+++ b/GaelO2/app/GaelO/Entities/VisitEntity.php
@@ -30,6 +30,7 @@ class VisitEntity
public ?bool $correctiveActionInvestigatorForm;
public ?string $correctiveActionOther;
public ?bool $correctiveActionDecision;
+ public array $files;
public ?string $deletedAt;
public VisitGroupEntity $visitGroup;
@@ -70,6 +71,7 @@ public static function fillFromDBReponseArray(array $array): VisitEntity
$visitEntity->correctiveActionInvestigatorForm = $array['corrective_action_investigator_form'];
$visitEntity->correctiveActionOther = $array['corrective_action_comment'];
$visitEntity->correctiveActionDecision = $array['corrective_action_applied'];
+ $visitEntity->files = $array['sent_files'] ?? [];
$visitEntity->deletedAt = $array['deleted_at'];
return $visitEntity;
}
diff --git a/GaelO2/app/GaelO/Interfaces/Adapters/HttpClientInterface.php b/GaelO2/app/GaelO/Interfaces/Adapters/HttpClientInterface.php
index 7db7ad477..0a6394e9a 100644
--- a/GaelO2/app/GaelO/Interfaces/Adapters/HttpClientInterface.php
+++ b/GaelO2/app/GaelO/Interfaces/Adapters/HttpClientInterface.php
@@ -13,8 +13,9 @@ public function setAuthorizationToken(string $authorizationToken): void;
public function setBasicAuthentication(string $login, string $password): void;
- public function rowRequest(string $method, string $uri, $body, ?array $headers, $ressourceDestination = null, $httpErrors = true): Psr7ResponseInterface;
+ public function rawRequest(string $method, string $uri, $body, ?array $headers, $ressourceDestination = null, $httpErrors = true): Psr7ResponseInterface;
+ public function uploadFile(string $method, string $uri, string $filename) : Psr7ResponseInterface;
/**
* Return array of PSR7 response adapter of multiple request, used to sent multiple files to an endpoint
*/
diff --git a/GaelO2/app/GaelO/Interfaces/Adapters/JobInterface.php b/GaelO2/app/GaelO/Interfaces/Adapters/JobInterface.php
index 5e24d8861..c064361df 100644
--- a/GaelO2/app/GaelO/Interfaces/Adapters/JobInterface.php
+++ b/GaelO2/app/GaelO/Interfaces/Adapters/JobInterface.php
@@ -5,4 +5,5 @@
interface JobInterface
{
public function sendQcReportJob(int $visitId) : void;
+ public function sendRadiomicsReport(int $visitId, int $behalfUserId) :void;
}
\ No newline at end of file
diff --git a/GaelO2/app/GaelO/Interfaces/Adapters/MimeInterface.php b/GaelO2/app/GaelO/Interfaces/Adapters/MimeInterface.php
index 43c09af6f..7fcc343bc 100644
--- a/GaelO2/app/GaelO/Interfaces/Adapters/MimeInterface.php
+++ b/GaelO2/app/GaelO/Interfaces/Adapters/MimeInterface.php
@@ -4,5 +4,5 @@
Interface MimeInterface{
public static function getExtensionsFromMime(string $mime) : array;
- public static function getMimesFromExtension(string $extension) : array;
+ public static function getMimeFromExtension(string $extension) : string;
}
diff --git a/GaelO2/app/GaelO/Interfaces/Adapters/PdfInterface.php b/GaelO2/app/GaelO/Interfaces/Adapters/PdfInterface.php
new file mode 100644
index 000000000..a88af820b
--- /dev/null
+++ b/GaelO2/app/GaelO/Interfaces/Adapters/PdfInterface.php
@@ -0,0 +1,8 @@
+studyModel->findOrFail($name)->delete();
}
- public function addStudy(String $name, string $code, int $patientCodeLength, string $contactEmail, bool $controllerShowAll, bool $monitorShowAll, bool $documentationMandatory, ?string $ancillaryOf): void
+ public function addStudy(String $name, string $code, int $patientCodeLength, string $contactEmail, bool $controllerShowAll, bool $monitorShowAll, bool $documentationMandatory, ?string $ancillaryOf, bool $creatablePatientsInvestigator): void
{
$study = new Study();
$study->name = $name;
@@ -38,6 +38,7 @@ public function addStudy(String $name, string $code, int $patientCodeLength, str
$study->monitor_show_all = $monitorShowAll;
$study->documentation_mandatory = $documentationMandatory;
$study->ancillary_of = $ancillaryOf;
+ $study->creatable_patients_investigator = $creatablePatientsInvestigator;
$study->save();
}
diff --git a/GaelO2/app/GaelO/Repositories/UserRepository.php b/GaelO2/app/GaelO/Repositories/UserRepository.php
index 251f7f146..dc5dfd496 100644
--- a/GaelO2/app/GaelO/Repositories/UserRepository.php
+++ b/GaelO2/app/GaelO/Repositories/UserRepository.php
@@ -65,7 +65,7 @@ public function createUser(
$user = new User();
$user->lastname = $lastname;
$user->firstname = $firstname;
- $user->email = $email;
+ $user->email = strtolower($email);
$user->phone = $phone;
$user->administrator = $administrator;
$user->center_code = $centerCode;
@@ -98,7 +98,7 @@ public function updateUser(
$user = $this->userModel->findOrFail($id);
$user->lastname = $lastname;
$user->firstname = $firstname;
- $user->email = $email;
+ $user->email = strtolower($email);
$user->phone = $phone;
$user->administrator = $administrator;
$user->center_code = $centerCode;
@@ -136,9 +136,9 @@ public function resetAttemptsAndUpdateLastConnexion(int $userId): void
public function getUserByEmail(String $email, bool $withTrashed = false): array
{
if ($withTrashed) {
- $user = $this->userModel->withTrashed()->where('email', $email)->sole();
+ $user = $this->userModel->withTrashed()->where('email', strtolower($email))->sole();
} else {
- $user = $this->userModel->where('email', $email)->sole();
+ $user = $this->userModel->where('email', strtolower($email))->sole();
}
return $user->toArray();
@@ -146,7 +146,7 @@ public function getUserByEmail(String $email, bool $withTrashed = false): array
public function isExistingEmail(String $email): bool
{
- $user = $this->userModel->withTrashed()->where('email', $email);
+ $user = $this->userModel->withTrashed()->where('email', strtolower($email));
return $user->count() > 0 ? true : false;
}
@@ -157,8 +157,8 @@ public function reactivateUser(int $id): void
public function getAdministrators(): array
{
- $emails = $this->userModel->where('administrator', true)->get();
- return empty($emails) ? [] : $emails->toArray();
+ $administrators = $this->userModel->where('administrator', true)->get();
+ return empty($administrators) ? [] : $administrators->toArray();
}
/**
@@ -168,7 +168,7 @@ public function getAdministrators(): array
public function getInvestigatorsOfStudyFromCenter(string $study, int $centerCode, ?string $job): array
{
- $emails = $this->userModel
+ $investigators = $this->userModel
->with('affiliatedCenters')
->whereHas('roles', function ($query) use ($study, $job) {
if ($job !== null) {
@@ -188,7 +188,7 @@ public function getInvestigatorsOfStudyFromCenter(string $study, int $centerCode
})
->get();
- return empty($emails) ? [] : $emails->toArray();
+ return empty($investigators) ? [] : $investigators->toArray();
}
public function getUsersByRolesInStudy(string $study, string $role): array
diff --git a/GaelO2/app/GaelO/Repositories/VisitRepository.php b/GaelO2/app/GaelO/Repositories/VisitRepository.php
index c797bca0b..b69b02e85 100644
--- a/GaelO2/app/GaelO/Repositories/VisitRepository.php
+++ b/GaelO2/app/GaelO/Repositories/VisitRepository.php
@@ -14,7 +14,6 @@
use App\GaelO\Util;
use App\Models\ReviewStatus;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Log;
class VisitRepository implements VisitRepositoryInterface
{
@@ -489,7 +488,10 @@ public function resetQc(int $visitId): void
$visitEntity = $this->visitModel->findOrFail($visitId);
- $visitEntity['state_quality_control'] = QualityControlStateEnum::NOT_DONE->value;
+ //If status Qc Not needed keep the not needed status
+ if ($visitEntity['state_quality_control'] !== QualityControlStateEnum::NOT_NEEDED) {
+ $visitEntity['state_quality_control'] = QualityControlStateEnum::NOT_DONE;
+ }
$visitEntity['controller_user_id'] = null;
$visitEntity['control_date'] = null;
$visitEntity['image_quality_control'] = null;
@@ -558,4 +560,12 @@ public function reactivateVisit(int $visitId): void
{
$this->visitModel->withTrashed()->findOrFail($visitId)->restore();
}
+
+ public function updateVisitFile(int $visitId, array $associatedFile): void
+ {
+
+ $review = $this->visitModel->findOrFail($visitId);
+ $review->sent_files = $associatedFile;
+ $review->save();
+ }
}
diff --git a/GaelO2/app/GaelO/Services/DicomService.php b/GaelO2/app/GaelO/Services/DicomService.php
index 096e2dd3d..8d0775048 100644
--- a/GaelO2/app/GaelO/Services/DicomService.php
+++ b/GaelO2/app/GaelO/Services/DicomService.php
@@ -14,6 +14,7 @@ class DicomService
private DicomSeriesRepositoryInterface $dicomSeriesRepositoryInterface;
private DicomStudyRepositoryInterface $dicomStudyRepositoryInterface;
private VisitService $visitService;
+ private int $currentUserId;
public function __construct(
DicomSeriesRepositoryInterface $dicomSeriesRepositoryInterface,
@@ -26,6 +27,11 @@ public function __construct(
$this->visitService = $visitService;
}
+ public function setCurrentUserId(int $userId)
+ {
+ $this->currentUserId = $userId;
+ }
+
public function deleteSeries(string $seriesInstanceUID, string $role)
{
@@ -40,6 +46,7 @@ public function deleteSeries(string $seriesInstanceUID, string $role)
if (sizeof($remainingSeries) === 0) {
$this->dicomStudyRepositoryInterface->delete($seriesData['dicom_study']['study_uid']);
$this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($this->currentUserId);
$this->visitService->updateUploadStatus(UploadStatusEnum::NOT_DONE->value);
//Reset QC only if suppervisor, we don't change QC status for investigator and controller (as it still ongoing)
if ($role === Constants::ROLE_SUPERVISOR) {
@@ -67,6 +74,7 @@ public function reactivateDicomStudy(string $studyInstanceUID): void
//Update upload status to Done
$this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($this->currentUserId);
$this->visitService->updateUploadStatus(UploadStatusEnum::DONE->value);
}
}
diff --git a/GaelO2/app/GaelO/Services/ExportStudyService.php b/GaelO2/app/GaelO/Services/ExportStudyService.php
index fc2b1fca1..313dbf417 100644
--- a/GaelO2/app/GaelO/Services/ExportStudyService.php
+++ b/GaelO2/app/GaelO/Services/ExportStudyService.php
@@ -146,7 +146,7 @@ public function exportVisitTable(): void
unset($visit['patient']);
//transform target_lesions as json string
$visit['review_status']['target_lesions'] = json_encode($visit['review_status']['target_lesions']);
-
+ $visit['sent_files'] = json_encode($visit['sent_files']);
$resultsData[$sheetName][] = array_merge(['visit_group' => $visitGroupName, 'visit_type' => $visitTypeName], $visit, $visit['review_status']);
}
diff --git a/GaelO2/app/GaelO/Services/FormService/FormService.php b/GaelO2/app/GaelO/Services/FormService/FormService.php
index 26364751d..e7c428d97 100644
--- a/GaelO2/app/GaelO/Services/FormService/FormService.php
+++ b/GaelO2/app/GaelO/Services/FormService/FormService.php
@@ -5,6 +5,7 @@
use App\GaelO\Entities\StudyEntity;
use App\GaelO\Exceptions\GaelOBadRequestException;
use App\GaelO\Exceptions\GaelOException;
+use App\GaelO\Exceptions\GaelOForbiddenException;
use App\GaelO\Interfaces\Adapters\FrameworkInterface;
use App\GaelO\Interfaces\Repositories\ReviewRepositoryInterface;
use App\GaelO\Interfaces\Repositories\StudyRepositoryInterface;
@@ -53,6 +54,7 @@ public function __construct(
public function setCurrentUserId(int $currentUserId): void
{
$this->currentUserId = $currentUserId;
+ $this->visitService->setCurrentUserId($currentUserId);
}
public function setVisitContextAndStudy(array $visitContext, string $studyName): void
@@ -79,13 +81,13 @@ public abstract function updateForm(int $reviewId, array $uploadedFileKeys, arra
public abstract function unlockForm(int $reviewId);
public abstract function deleteForm(int $reviewId);
- public function attachFile(array $reviewEntity, string $key, string $filename, string $mimeType, $binaryData): void
+ public function attachFile(array $reviewEntity, string $key, string $mimeType, string $extension, $binaryData): string
{
$associatedFiles = [];
//Safty check
- if($reviewEntity['local']!== $this->local) throw new GaelOException("Form Service Unconsitancy");
+ if ($reviewEntity['local'] !== $this->local) throw new GaelOException("Form Service Unconsitancy");
if ($reviewEntity['local']) {
$associatedFiles = $this->abstractVisitRules->getAssociatedFilesInvestigator();
@@ -95,24 +97,32 @@ public function attachFile(array $reviewEntity, string $key, string $filename, s
else $associatedFiles = $this->abstractVisitRules->getAssociatedFilesReview();
}
+ if (!array_key_exists($key, $associatedFiles)) {
+ throw new GaelOForbiddenException("Unexpected file key");
+ }
+
$associatiedFile = $associatedFiles[$key];
if (!empty($reviewEntity['sent_files'][$key])) {
throw new GaelOBadRequestException("Already Existing File for this review");
}
- if ( !in_array($mimeType, $associatiedFile->mimes) ) {
+ if (!in_array($mimeType, $associatiedFile->mimes)) {
throw new GaelOBadRequestException("File Key or Mime Not Allowed");
}
$destinationPath = $this->studyName . '/' . 'attached_review_file';
+ $filename = 'review_' . $reviewEntity['id'] . '_' . $key . '.' . $extension;
$destinationFileName = $destinationPath . '/' . $filename;
+
$this->frameworkInterface->storeFile($destinationFileName, $binaryData);
$reviewEntity['sent_files'][$key] = $destinationFileName;
$this->reviewRepositoryInterface->updateReviewFile($reviewEntity['id'], $reviewEntity['sent_files']);
+
+ return $filename;
}
public function removeFile(array $reviewEntity, string $key): void
@@ -133,7 +143,7 @@ public function getVisitRules(): AbstractVisitRules
return $this->abstractVisitRules;
}
- public function getVisitDecisionObject() : AbstractVisitDecisions
+ public function getVisitDecisionObject(): AbstractVisitDecisions
{
return $this->abstractVisitRules->getVisitDecisionObject();
}
diff --git a/GaelO2/app/GaelO/Services/FormService/ReviewFormService.php b/GaelO2/app/GaelO/Services/FormService/ReviewFormService.php
index d56855d2e..a9eb42f09 100644
--- a/GaelO2/app/GaelO/Services/FormService/ReviewFormService.php
+++ b/GaelO2/app/GaelO/Services/FormService/ReviewFormService.php
@@ -11,6 +11,9 @@
use App\GaelO\Interfaces\Repositories\ReviewStatusRepositoryInterface;
use App\GaelO\Interfaces\Repositories\StudyRepositoryInterface;
use App\GaelO\Services\FormService\FormService;
+use App\GaelO\Services\GaelOStudiesService\AbstractGaelOStudy;
+use App\GaelO\Services\GaelOStudiesService\Events\AwaitingAdjudicationEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\VisitConcludedEvent;
use App\GaelO\Services\MailServices;
use App\GaelO\Services\VisitService;
@@ -103,18 +106,16 @@ private function doSpecificReviewDecisions()
//Send Notification emails
if ($reviewStatus === ReviewStatusEnum::WAIT_ADJUDICATION->value) {
- $this->mailServices->sendAwaitingAdjudicationMessage($this->studyName, $this->patientId, $this->patientCode, $this->visitType, $this->visitId);
- } else if ($reviewStatus === ReviewStatusEnum::DONE->value ) {
+ $awaitingAdjudicationEvent = new AwaitingAdjudicationEvent($this->visitContext);
+ $studyObject = AbstractGaelOStudy::getSpecificStudyObject($this->studyName);
+ $studyObject->onEventStudy($awaitingAdjudicationEvent);
+ } else if ($reviewStatus === ReviewStatusEnum::DONE->value) {
//In case of conclusion reached send conclusion (but not to uploader if ancillary study)
- $this->mailServices->sendVisitConcludedMessage(
- $this->visitId,
- $this->studyEntity->isAncillaryStudy() ? null : $this->uploaderId,
- $this->studyName,
- $this->patientId,
- $this->patientCode,
- $this->visitType,
- $conclusion
- );
+ $visitConcludedEvent = new VisitConcludedEvent($this->visitContext);
+ $visitConcludedEvent->setConclusion($conclusion);
+ $visitConcludedEvent->setUploaderUserId($this->studyEntity->isAncillaryStudy() ? null : $this->uploaderId);
+ $studyObject = AbstractGaelOStudy::getSpecificStudyObject($this->studyName);
+ $studyObject->onEventStudy($visitConcludedEvent);
}
}
}
diff --git a/GaelO2/app/GaelO/Services/GaelOClientService.php b/GaelO2/app/GaelO/Services/GaelOClientService.php
new file mode 100644
index 000000000..6f679c8d6
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOClientService.php
@@ -0,0 +1,55 @@
+httpClientInterface = $httpClientInterface;
+ $this->frameworkInterface = $frameworkInterface;
+ }
+
+ public function loadUrl()
+ {
+ //Set address of Orthanc server
+ $url = $this->frameworkInterface::getConfig(SettingsConstants::APP_URL);
+ if ($url) $this->httpClientInterface->setUrl($url);
+ }
+
+ public function setAuthorizationToken(string $token): void
+ {
+ $this->httpClientInterface->setAuthorizationToken($token);
+ }
+
+ public function login(string $email, $password): void
+ {
+ $payload = [
+ 'email' => $email,
+ 'password' => $password
+ ];
+ $answer = $this->httpClientInterface->requestJson("POST", '/api/login', $payload);
+ $this->httpClientInterface->setAuthorizationToken($answer['access_token']);
+ }
+
+ public function createFileToVisit(string $studyName, int $visitId, string $key, ?string $extension, string $filePath)
+ {
+ $payload = [
+ 'extension' => $extension,
+ 'content' => base64_encode(file_get_contents($filePath))
+ ];
+ $this->httpClientInterface->requestJson("POST", '/api/visits/' . $visitId . '/files/' . $key . '?studyName=' . $studyName . '&role=Supervisor', $payload);
+ }
+
+ public function deleteFileToVisit(string $studyName, int $visitId, string $key)
+ {
+ $this->httpClientInterface->rawRequest('DELETE', '/api/visits/' . $visitId . '/files/' . $key . '?studyName=' . $studyName . '&role=Supervisor', null, null);
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOProcessingService/AzureService.php b/GaelO2/app/GaelO/Services/GaelOProcessingService/AzureService.php
index 44ad6d3b8..11e6f6361 100644
--- a/GaelO2/app/GaelO/Services/GaelOProcessingService/AzureService.php
+++ b/GaelO2/app/GaelO/Services/GaelOProcessingService/AzureService.php
@@ -48,7 +48,7 @@ public function startAci(): bool
{
$this->setAccessToken();
$uri = "/start?api-version=2021-09-01";
- $response = $this->httpClientInterface->rowRequest('POST', $uri, null, ['Accept' => 'application/json'])->getStatusCode();
+ $response = $this->httpClientInterface->rawRequest('POST', $uri, null, ['Accept' => 'application/json'])->getStatusCode();
return $response === 202;
}
@@ -57,7 +57,7 @@ public function stopACI(): bool
{
$this->setAccessToken();
$uri = "/stop?api-version=2021-09-01";
- $response = $this->httpClientInterface->rowRequest('POST', $uri, null, ['Accept' => 'application/json'])->getStatusCode();
+ $response = $this->httpClientInterface->rawRequest('POST', $uri, null, ['Accept' => 'application/json'])->getStatusCode();
return $response === 204;
}
@@ -66,7 +66,7 @@ public function getStatusAci(): array
{
$this->setAccessToken();
$uri = "?api-version=2021-09-01";
- $response = $this->httpClientInterface->rowRequest('GET', $uri, null, ['Accept' => 'application/json'])->getJsonBody();
+ $response = $this->httpClientInterface->rawRequest('GET', $uri, null, ['Accept' => 'application/json'])->getJsonBody();
/*3 states disponible
* Pending -> Creation en cours
diff --git a/GaelO2/app/GaelO/Services/GaelOProcessingService/GaelOProcessingService.php b/GaelO2/app/GaelO/Services/GaelOProcessingService/GaelOProcessingService.php
index 30738ac7f..29bc99d21 100644
--- a/GaelO2/app/GaelO/Services/GaelOProcessingService/GaelOProcessingService.php
+++ b/GaelO2/app/GaelO/Services/GaelOProcessingService/GaelOProcessingService.php
@@ -5,61 +5,157 @@
use App\GaelO\Constants\SettingsConstants;
use App\GaelO\Interfaces\Adapters\FrameworkInterface;
use App\GaelO\Interfaces\Adapters\HttpClientInterface;
-use App\GaelO\Interfaces\Adapters\Psr7ResponseInterface;
-use App\GaelO\Services\OrthancService;
+use Illuminate\Support\Facades\Log;
class GaelOProcessingService
{
private HttpClientInterface $httpClientInterface;
- private OrthancService $orthancService;
private FrameworkInterface $frameworkInterface;
- private string $host;
- private int $port;
- private string $protocol;
-
- /**
- * GaelO Processing Interaction
- */
- public function __construct(OrthancService $orthancService, FrameworkInterface $frameworkInterface, HttpClientInterface $httpClientInterface)
+ public function __construct(HttpClientInterface $httpClientInterface, FrameworkInterface $frameworkInterface)
{
-
$this->httpClientInterface = $httpClientInterface;
- $this->orthancService = $orthancService;
$this->frameworkInterface = $frameworkInterface;
- //Set GAELO Processing URL Passed in Env variable (default address)
- $this->port = $this->frameworkInterface::getConfig(SettingsConstants::GAELO_PROCESSING_PORT);
- $this->protocol = $this->frameworkInterface::getConfig(SettingsConstants::GAELO_PROCESSING_PROTOCOL);
- $this->host = $this->frameworkInterface::getConfig(SettingsConstants::GAELO_PROCESSING_HOST);
- $this->setServerAdress();
- //Need to access to Orthanc storage
- $this->orthancService->setOrthancServer(true);
+ $this->setParams();
}
- public function setHost(string $host)
+ public function setParams(): void
{
- $this->host = $host;
+ //Set Time Limit at 1H as operation could be long
+ set_time_limit(3600);
+ //Set address of Processing Server
+ $url = $this->frameworkInterface->getConfig(SettingsConstants::GAELO_PROCESSING_URL);
+ $login = $this->frameworkInterface->getConfig(SettingsConstants::GAELO_PROCESSING_LOGIN);
+ $password = $this->frameworkInterface->getConfig(SettingsConstants::GAELO_PROCESSING_PASSWORD);
+ $this->httpClientInterface->setUrl($url);
+ $this->httpClientInterface->setBasicAuthentication($login, $password);
}
- /**
- * Setter for dynamic IP of gaelo processing
- */
- public function setServerAdress()
+
+ public function createSeriesFromOrthanc(string $orthancSeriesId, bool $pet = false, bool $convertToSuv = false)
{
- $url = $this->protocol . $this->host . ':' . $this->port;
- $this->httpClientInterface->setUrl($url);
+ $request = $this->httpClientInterface->requestJson('POST', "/tools/create-series-from-orthanc", ['seriesId' => $orthancSeriesId, 'PET' => $pet, 'convertToSuv' => $convertToSuv]);
+ return $request->getBody();
+ }
+
+ public function createDicom(string $filename){
+ $request = $this->httpClientInterface->uploadFile('POST', "/dicoms", $filename);
+ return $request->getBody();
+ }
+
+ public function executeInference(string $modelName, array $payload)
+ {
+ $request = $this->httpClientInterface->requestJson('POST', "/models/" . $modelName . "/inference", $payload);
+ return $request->getJsonBody();
+ }
+
+ public function createMIPForSeries(string $seriesId, array $payload = []): string
+ {
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+
+ $this->httpClientInterface->requestStreamResponseToFile('POST', "/series/" . $seriesId . "/mip", $downloadedFilePath, ['content-Type' => 'application/json'], $payload);
+ return $downloadedFilePath;
+ }
+
+ public function getNiftiMask(string $maskId): string
+ {
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+
+ $this->httpClientInterface->requestStreamResponseToFile('GET', "/masks/" . $maskId . "/file", $downloadedFilePath, ['content-Type' => 'application/json'], []);
+ return $downloadedFilePath;
+ }
+
+ public function getNiftiSeries(string $imageId): string
+ {
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+
+ $this->httpClientInterface->requestStreamResponseToFile('GET', "/series/" . $imageId . "/file", $downloadedFilePath, ['content-Type' => 'application/json'], []);
+ return $downloadedFilePath;
+ }
+
+ public function createRtssFromMask(string $orthancSeriesId, string $maskId): string
+ {
+ $payload = [
+ 'maskId' => $maskId,
+ 'orthancSeriesId' => $orthancSeriesId
+ ];
+
+ $request = $this->httpClientInterface->requestJson('POST', "/tools/mask-to-rtss", $payload);
+ return $request->getBody();
}
- /**
- * Fetch zipped dicom and transmit it to GaelO Processing
- */
- public function sendDicom(array $orthancID, ?string $transferSyntaxUID): Psr7ResponseInterface
+ public function getRtss(string $rtssId): string
{
- // Fetch dicom from Orthanc
- $psr7Response = $this->orthancService->getOrthancZipStreamAsString($orthancID, $transferSyntaxUID);
- // Send Dicom to GaelO Processing
- $response = $this->httpClientInterface->rowRequest('POST', "/app/dicom", $psr7Response->getBody(), ['content-type' => 'application/zip', 'Accept' => 'application/json']);
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
- return $response;
+ $this->httpClientInterface->requestStreamResponseToFile('GET', "/rtss/" . $rtssId . "/file", $downloadedFilePath, []);
+ return $downloadedFilePath;
+ }
+
+ public function createSegFromMask(string $orthancSeriesId, string $maskId): string
+ {
+ $payload = [
+ 'maskId' => $maskId,
+ 'orthancSeriesId' => $orthancSeriesId
+ ];
+
+ $request = $this->httpClientInterface->requestJson('POST', "/tools/mask-to-seg", $payload);
+ return $request->getBody();
+ }
+
+ public function getSeg(string $segId): string
+ {
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+
+ $this->httpClientInterface->requestStreamResponseToFile('GET', "/seg/" . $segId . "/file", $downloadedFilePath, []);
+ return $downloadedFilePath;
+ }
+
+ public function thresholdMask(string $maskId, string $seriesId, string|float $threshold)
+ {
+ $payload = [
+ 'maskId' => $maskId,
+ 'seriesId' => $seriesId,
+ 'threshold' => $threshold
+ ];
+ $request = $this->httpClientInterface->requestJson('POST', "/tools/threshold-mask", $payload);
+ return $request->getBody();
+ }
+
+ public function fragmentMask(string $seriesId, string $maskId, bool $output3D): string
+ {
+ $payload = [
+ 'maskId' => $maskId,
+ 'seriesId' => $seriesId,
+ 'ouput3D' => $output3D
+ ];
+
+ $request = $this->httpClientInterface->requestJson('POST', "/tools/mask-fragmentation", $payload);
+ return $request->getBody();
+ }
+
+ public function getMaskDicomOrientation(string $maskId, string $orientation, bool $compress): string
+ {
+ $downloadedFilePath = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+
+ $payload = [
+ 'maskId' => $maskId,
+ 'orientation' => $orientation,
+ 'compress' => $compress
+ ];
+
+ $this->httpClientInterface->requestStreamResponseToFile('POST', "/tools/mask-dicom", $downloadedFilePath, [], $payload);
+ return $downloadedFilePath;
+ }
+
+ public function getStatsMask(string $maskId): array
+ {
+ $request = $this->httpClientInterface->requestJson('GET', "/masks/" . $maskId . "/stats");
+ return $request->getJsonBody();
+ }
+
+ public function deleteRessource(string $type, string $id): void
+ {
+ $request = $this->httpClientInterface->requestJson('DELETE', "/" . $type . "/" . $id);
}
}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractGaelOStudy.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractGaelOStudy.php
index 3037eee68..f901d00c1 100644
--- a/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractGaelOStudy.php
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractGaelOStudy.php
@@ -3,11 +3,35 @@
namespace App\GaelO\Services\GaelOStudiesService;
use App\GaelO\Adapters\FrameworkAdapter;
+use App\GaelO\Constants\Constants;
+use App\GaelO\Interfaces\Adapters\JobInterface;
+use App\GaelO\Interfaces\Repositories\ReviewRepositoryInterface;
+use App\GaelO\Interfaces\Repositories\UserRepositoryInterface;
+use App\GaelO\Services\GaelOStudiesService\Events\AwaitingAdjudicationEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\BaseStudyEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\CorrectiveActionEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\QCModifiedEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\VisitConcludedEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\VisitUploadedEvent;
+use App\GaelO\Services\MailService\MailListBuilder;
+use App\GaelO\Services\MailServices;
abstract class AbstractGaelOStudy
{
+ protected MailServices $mailServices;
+ protected UserRepositoryInterface $userRepositoryInterface;
+ protected ReviewRepositoryInterface $reviewRepositoryInterface;
+ protected JobInterface $jobInterface;
protected string $studyName;
+ public function __construct(MailServices $mailServices, UserRepositoryInterface $userRepositoryInterface, ReviewRepositoryInterface $reviewRepositoryInterface, JobInterface $jobInterface)
+ {
+ $this->mailServices = $mailServices;
+ $this->userRepositoryInterface = $userRepositoryInterface;
+ $this->reviewRepositoryInterface = $reviewRepositoryInterface;
+ $this->jobInterface = $jobInterface;
+ }
+
public abstract function getVisitRulesClass(string $visitGroupName, string $visitTypeName): String;
public function getSpecificVisitRules(string $visitGroup, string $visitName): AbstractVisitRules
@@ -32,11 +56,208 @@ public function getReviewableVisitTypeIds(): null|array
/**
* For ancillaries studies, shall return the patients metadata tags for which a review is expected
*/
- public function getReviewablePatientsTags() : null|array
+ public function getReviewablePatientsTags(): null|array
{
return null;
}
+ /**
+ * If needed to predifine expected patients
+ * return
+ */
+ public function getExpectedPatients(): array
+ {
+ return [];
+ }
+
+ /**
+ * To make specific study action on study event, can be overriden to avoid some automatic mails
+ */
+ public function onEventStudy(BaseStudyEvent $studyEvent): void
+ {
+ if ($studyEvent instanceof VisitUploadedEvent) {
+ $this->onVisitUploaded($studyEvent);
+ } else if ($studyEvent instanceof QCModifiedEvent) {
+ $this->onQcModified($studyEvent);
+ } else if ($studyEvent instanceof CorrectiveActionEvent) {
+ $this->onCorrectiveAction($studyEvent);
+ } else if ($studyEvent instanceof AwaitingAdjudicationEvent) {
+ $this->onAwaitingAdjudication($studyEvent);
+ } else if ($studyEvent instanceof VisitConcludedEvent) {
+ $this->onVisitConcluded($studyEvent);
+ }
+ }
+
+ protected function onVisitUploaded(VisitUploadedEvent $visitUploadedEvent): void
+ {
+ $studyName = $visitUploadedEvent->getStudyName();
+ $patientId = $visitUploadedEvent->getPatientId();
+ $patientCode = $visitUploadedEvent->getPatientCode();
+ $visitId = $visitUploadedEvent->getVisitId();
+ $qcNeeded = $visitUploadedEvent->isQcNeeded();
+ $visitType = $visitUploadedEvent->getVisitTypeName();
+ $creatorUserId = $visitUploadedEvent->getCreatorUserId();
+ $uploaderUserId = $visitUploadedEvent->getUploaderUserId();
+ $reviewNeeded = $visitUploadedEvent->isReviewNeeded();
+
+ //Send to supervisors and monitors of the study
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR)
+ ->withUserEmail($creatorUserId)
+ ->withUserEmail($uploaderUserId);
+
+ //If QC is awaiting add controllers
+ if ($qcNeeded) {
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_CONTROLLER);
+ }
+
+ $this->mailServices->sendUploadedVisitMessage($mailListBuilder->get(), $visitId, $studyName, $patientId, $patientCode, $visitType);
+
+ if ($qcNeeded) {
+ $this->jobInterface->sendQcReportJob($visitId);
+ }
+
+ if (!$qcNeeded && $reviewNeeded) {
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_REVIEWER);
+ $this->mailServices->sendReviewReadyMessage($mailListBuilder->get(), $visitId, $studyName, $patientId, $patientCode, $visitType);
+ }
+ }
+
+ protected function onQcModified(QCModifiedEvent $qcModifiedEvent)
+ {
+ $studyName = $qcModifiedEvent->getStudyName();
+ $creatorId = $qcModifiedEvent->getCreatorUserId();
+ $patientId = $qcModifiedEvent->getPatientId();
+ $patientCode = $qcModifiedEvent->getPatientCode();
+ $patientCenterCode = $qcModifiedEvent->getPatientCenterCode();
+ $visitId = $qcModifiedEvent->getVisitId();
+ $visitType = $qcModifiedEvent->getVisitTypeName();
+ $currentUserId = $qcModifiedEvent->getCurrentUserId();
+ $visitModality = $qcModifiedEvent->getVisitModality();
+ $qcStatus = $qcModifiedEvent->getQcStatus();
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR)
+ ->withUserEmail($creatorId)
+ ->withUserEmail($currentUserId)
+ ->withInvestigatorOfCenterInStudy($studyName, $patientCenterCode);
+
+ $this->mailServices->sendQcDecisionMessage(
+ $mailListBuilder->get(),
+ $visitId,
+ $studyName,
+ $qcStatus,
+ $patientId,
+ $patientCode,
+ $visitModality,
+ $visitType,
+ $qcModifiedEvent->getFormQcStatus(),
+ $qcModifiedEvent->getImageQcStatus(),
+ $qcModifiedEvent->getFormQcComment(),
+ $qcModifiedEvent->getImageQcComment()
+ );
+ }
+
+ protected function onCorrectiveAction(CorrectiveActionEvent $correctiveActionEvent)
+ {
+ $studyName = $correctiveActionEvent->getStudyName();
+ $patientId = $correctiveActionEvent->getPatientId();
+ $patientCode = $correctiveActionEvent->getPatientCode();
+ $visitId = $correctiveActionEvent->getVisitId();
+ $visitType = $correctiveActionEvent->getVisitTypeName();
+ $currentUserId = $correctiveActionEvent->getCurrentUserId();
+ $visitModality = $correctiveActionEvent->getVisitModality();
+ $correctiveActionDone = $correctiveActionEvent->getCorrectiveActionDone();
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_CONTROLLER)
+ ->withUserEmail($currentUserId);
+
+ $this->mailServices->sendCorrectiveActionMessage(
+ $mailListBuilder->get(),
+ $visitId,
+ $studyName,
+ $correctiveActionDone,
+ $patientId,
+ $patientCode,
+ $visitModality,
+ $visitType
+ );
+ }
+
+ protected function onAwaitingAdjudication(AwaitingAdjudicationEvent $event)
+ {
+ $studyName = $event->getStudyName();
+ $patientId = $event->getPatientId();
+ $patientCode = $event->getPatientCode();
+ $visitId = $event->getVisitId();
+ $visitType = $event->getVisitTypeName();
+
+ //Get All Users with Reviwers in this study
+ $reviewersUsers = $this->userRepositoryInterface->getUsersByRolesInStudy($studyName, Constants::ROLE_REVIEWER);
+
+ //Get All Reviews of this visit
+ $reviews = $this->reviewRepositoryInterface->getReviewsForStudyVisit($studyName, $visitId, true);
+ $reviewerDoneUserIdArray = array_map(function ($user) {
+ return $user['user_id'];
+ }, $reviews);
+
+ //Select users who didn't validate review form of this visit
+ $availableReviewers = array_filter($reviewersUsers, function ($user) use ($reviewerDoneUserIdArray) {
+ return !in_array($user['id'], $reviewerDoneUserIdArray);
+ });
+
+ //Build email list
+ $availableReviewersEmails = array_map(function ($user) {
+ return $user['email'];
+ }, $availableReviewers);
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+ $supervisorEmails = $mailListBuilder->get();
+
+ $emails = [
+ ...$availableReviewersEmails,
+ ...$supervisorEmails
+ ];
+
+ $this->mailServices->sendAwaitingAdjudicationMessage($emails, $studyName, $patientId, $patientCode, $visitType, $visitId);
+ }
+
+ protected function onVisitConcluded(VisitConcludedEvent $event)
+ {
+ $studyName = $event->getStudyName();
+ $patientId = $event->getPatientId();
+ $patientCode = $event->getPatientCode();
+ $visitId = $event->getVisitId();
+ $visitType = $event->getVisitTypeName();
+ $conclusion = $event->getConclusion();
+ $uploaderUserId = $event->getUploaderUserId();
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR);
+
+ //If uplaoder need to be included
+ if ($uploaderUserId) {
+ $mailListBuilder->withUserEmail($uploaderUserId);
+ }
+
+ $this->mailServices->sendVisitConcludedMessage(
+ $mailListBuilder->get(),
+ $visitId,
+ $studyName,
+ $patientId,
+ $patientCode,
+ $visitType,
+ $conclusion,
+ );
+ }
+
/**
* Facade to instanciate specific study object, if does not exist, return the DefaultGaelOStudy Object
*/
@@ -46,5 +267,4 @@ public static function getSpecificStudyObject(string $studyName): AbstractGaelOS
if (class_exists($class)) return FrameworkAdapter::make($class);
else return FrameworkAdapter::make(DefaultGaelOStudy::class);
}
-
}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractVisitRules.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractVisitRules.php
index 320114ea4..592d45e25 100644
--- a/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractVisitRules.php
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/AbstractVisitRules.php
@@ -30,6 +30,11 @@ abstract public static function getReviewerValidationRules(): array;
abstract public static function getReviewerAdjudicationValidationRules(): array;
+ /**
+ * @return AssociatedFile[]
+ */
+ abstract public static function getAssociatedFilesVisit() : array;
+
/**
* @return AssociatedFile[]
*/
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/AssociatedFiles/AssociatedFile.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/AssociatedFiles/AssociatedFile.php
index e4bda6bf4..433c10376 100644
--- a/GaelO2/app/GaelO/Services/GaelOStudiesService/AssociatedFiles/AssociatedFile.php
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/AssociatedFiles/AssociatedFile.php
@@ -4,7 +4,7 @@
class AssociatedFile
{
- public String $key;
+ public string $key;
public array $mimes;
public bool $mandatory;
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/DefaultVisitRules.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/DefaultVisitRules.php
index 04468de79..7c3e49ba9 100644
--- a/GaelO2/app/GaelO/Services/GaelOStudiesService/DefaultVisitRules.php
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/DefaultVisitRules.php
@@ -10,7 +10,7 @@ public static function getInvestigatorValidationRules(): array
return [];
}
- public static function getReviewerValidationRules(): array
+ public static function getReviewerValidationRules(): array
{
return [];
}
@@ -20,6 +20,11 @@ public static function getReviewerAdjudicationValidationRules(): array
return [];
}
+ public static function getAssociatedFilesVisit(): array
+ {
+ return [];
+ }
+
public static function getAssociatedFilesInvestigator(): array
{
return [];
@@ -39,6 +44,4 @@ public static function getVisitDecisionClass(): string
{
return DefaultVisitDecisions::class;
}
-
-
}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/AwaitingAdjudicationEvent.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/AwaitingAdjudicationEvent.php
new file mode 100644
index 000000000..d7177d26d
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/AwaitingAdjudicationEvent.php
@@ -0,0 +1,12 @@
+type = $type;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/BaseVisitEvent.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/BaseVisitEvent.php
new file mode 100644
index 000000000..25f06e8d9
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/BaseVisitEvent.php
@@ -0,0 +1,61 @@
+visitEntity = $visitEntity;
+ }
+
+ public function getStudyName(): string
+ {
+ return $this->visitEntity['patient']['study_name'];
+ }
+
+ public function getVisitId(): int
+ {
+ return $this->visitEntity['id'];
+ }
+
+ public function getPatientId(): string
+ {
+ return $this->visitEntity['patient_id'];
+ }
+
+ public function getPatientCode(): string
+ {
+ return $this->visitEntity['patient']['code'];
+ }
+
+ public function getPatientCenterCode(): string
+ {
+ return $this->visitEntity['patient']['center_code'];
+ }
+
+ public function getVisitTypeName(): string
+ {
+ return $this->visitEntity['visit_type']['name'];
+ }
+
+ public function isQcNeeded(): bool
+ {
+ return $this->visitEntity['state_quality_control'] !== QualityControlStateEnum::NOT_NEEDED->value;
+ }
+
+ public function getCreatorUserId(): int
+ {
+ return $this->visitEntity['creator_user_id'];
+ }
+
+ public function getVisitModality(): string
+ {
+ return $this->visitEntity['visit_type']['visit_group']['modality'];
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/CorrectiveActionEvent.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/CorrectiveActionEvent.php
new file mode 100644
index 000000000..93bb2b29c
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/CorrectiveActionEvent.php
@@ -0,0 +1,34 @@
+userId = $userId;
+ }
+
+ public function getCurrentUserId(): int
+ {
+ return $this->userId;
+ }
+
+ public function setCorrrectiveActionDone(bool $done): void
+ {
+ $this->correctiveActionDone = $done;
+ }
+
+ public function getCorrectiveActionDone(): bool
+ {
+ return $this->correctiveActionDone;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/GaelOStudyEventEnum.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/GaelOStudyEventEnum.php
new file mode 100644
index 000000000..8546cc46d
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/GaelOStudyEventEnum.php
@@ -0,0 +1,12 @@
+userId = $userId;
+ }
+
+ public function getCurrentUserId(): int
+ {
+ return $this->userId;
+ }
+
+ public function setQcStatus(string $qcStatus) :void
+ {
+ $this->qcStatus = $qcStatus;
+ }
+
+ public function getQcStatus() :string
+ {
+ return $this->qcStatus;
+ }
+
+ public function setFormQcStatus(string $status): void
+ {
+ $this->formQcStatus = $status;
+ }
+
+ public function getFormQcStatus(): string
+ {
+ return $this->formQcStatus;
+ }
+
+ public function setImageQcStatus(string $status): void
+ {
+ $this->imageQcStatus = $status;
+ }
+
+ public function getImageQcStatus(): string
+ {
+ return $this->imageQcStatus;
+ }
+
+ public function setFormQcComment(string $formQcComment): void
+ {
+ $this->formQcComment = $formQcComment;
+ }
+
+ public function getFormQcComment(): string
+ {
+ return $this->formQcComment;
+ }
+
+ public function setImageQcComment(string $imageQcComment): void
+ {
+ $this->imageQcComment = $imageQcComment;
+ }
+
+ public function getImageQcComment(): string
+ {
+ return $this->imageQcComment;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitConcludedEvent.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitConcludedEvent.php
new file mode 100644
index 000000000..55cc72130
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitConcludedEvent.php
@@ -0,0 +1,34 @@
+uploaderUserId = $userId;
+ }
+
+ public function getUploaderUserId(): ?int
+ {
+ return $this->uploaderUserId;
+ }
+
+ public function setConclusion(?string $conclusion): void
+ {
+ $this->conclusion = $conclusion;
+ }
+
+ public function getConclusion(): ?string
+ {
+ return $this->conclusion;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitUploadedEvent.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitUploadedEvent.php
new file mode 100644
index 000000000..f2b4fd9d2
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitUploadedEvent.php
@@ -0,0 +1,35 @@
+uploaderUserId = $userId;
+ }
+
+ public function setReviewNeeded(bool $reviewNeeded): void
+ {
+ $this->reviewNeeded = $reviewNeeded;
+ }
+
+ public function isReviewNeeded(): bool
+ {
+ return $this->reviewNeeded;
+ }
+
+ public function getUploaderUserId() :int
+ {
+ return $this->uploaderUserId;
+ }
+
+}
diff --git a/GaelO2/app/GaelO/Services/GaelOStudiesService/ExpectedPatient/ExpectedPatient.php b/GaelO2/app/GaelO/Services/GaelOStudiesService/ExpectedPatient/ExpectedPatient.php
new file mode 100644
index 000000000..1f0f5a9c1
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/GaelOStudiesService/ExpectedPatient/ExpectedPatient.php
@@ -0,0 +1,17 @@
+code = $code;
+ $this->centerCode = $centerCode;
+ $this->inclusionStatus = $inclusionStatus;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/MailService/MailListBuilder.php b/GaelO2/app/GaelO/Services/MailService/MailListBuilder.php
new file mode 100644
index 000000000..d5886e558
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/MailService/MailListBuilder.php
@@ -0,0 +1,66 @@
+userRepositoryInterface = $userRepositoryInterface;
+ }
+
+ public function withUserEmail(int $userId): self
+ {
+ $email = $this->userRepositoryInterface->find($userId)['email'];
+ $this->emails[] = $email;
+ return $this;
+ }
+
+ public function withAdminsEmails(): self
+ {
+ $admins = $this->userRepositoryInterface->getAdministrators();
+ $adminsEmails = array_map(function ($user) {
+ return $user['email'];
+ }, $admins);
+ $this->emails = [...$adminsEmails, ...$this->emails];
+ return $this;
+ }
+
+ private function filterNonVerifiedEmailsUsers(array $users)
+ {
+ $emails = [];
+ foreach ($users as $user) {
+ if ($user['email_verified_at'] != null) $emails[] = $user['email'];
+ }
+ return $emails;
+ }
+
+ public function withUsersEmailsByRolesInStudy(string $studyName, string $role): self
+ {
+ $users = $this->userRepositoryInterface->getUsersByRolesInStudy($studyName, $role);
+ //Filter user with a verified email (password have been set)
+ $emails = $this->filterNonVerifiedEmailsUsers($users);
+ $this->emails = [...$emails, ...$this->emails];
+ return $this;
+ }
+
+ public function withInvestigatorOfCenterInStudy(String $studyName, String $center, ?String $job = null): self
+ {
+ $users = $this->userRepositoryInterface->getInvestigatorsOfStudyFromCenter($studyName, $center, $job);
+ $emails = $this->filterNonVerifiedEmailsUsers($users);
+ $this->emails = [...$emails, ...$this->emails];
+ return $this;
+ }
+
+ public function get(): array
+ {
+ return $this->emails;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/MailServices.php b/GaelO2/app/GaelO/Services/MailServices.php
index 21e124e2f..d97a476ce 100644
--- a/GaelO2/app/GaelO/Services/MailServices.php
+++ b/GaelO2/app/GaelO/Services/MailServices.php
@@ -5,77 +5,43 @@
use App\GaelO\Constants\Constants;
use App\GaelO\Constants\MailConstants;
use App\GaelO\Interfaces\Adapters\MailerInterface;
-use App\GaelO\Interfaces\Repositories\ReviewRepositoryInterface;
use App\GaelO\Interfaces\Repositories\StudyRepositoryInterface;
use App\GaelO\Interfaces\Repositories\UserRepositoryInterface;
-use App\GaelO\Repositories\ReviewRepository;
+use App\GaelO\Services\MailService\MailListBuilder;
class MailServices
{
private MailerInterface $mailInterface;
private UserRepositoryInterface $userRepositoryInterface;
- private ReviewRepository $reviewRepositoryInterface;
private StudyRepositoryInterface $studyRepositoryInterface;
public function __construct(
MailerInterface $mailInterface,
UserRepositoryInterface $userRepositoryInterface,
- ReviewRepositoryInterface $reviewRepositoryInterface,
- StudyRepositoryInterface $studyRepositoryInterface,
+ StudyRepositoryInterface $studyRepositoryInterface
) {
$this->mailInterface = $mailInterface;
$this->userRepositoryInterface = $userRepositoryInterface;
- $this->reviewRepositoryInterface = $reviewRepositoryInterface;
$this->studyRepositoryInterface = $studyRepositoryInterface;
}
- private function getUserEmail(int $userId): string
+ public function getStudyContactEmail(string $studyName): string
{
- return $this->userRepositoryInterface->find($userId)['email'];
+ $studyEntity = $this->studyRepositoryInterface->find($studyName);
+ return $studyEntity->contactEmail;
}
- private function getUserName(int $userId)
+
+ public function getUserName(int $userId)
{
$userEntity = $this->userRepositoryInterface->find($userId);
return $userEntity['firstname'] . ' ' . $userEntity['lastname'];
}
- private function getAdminsEmails(): array
- {
- $admins = $this->userRepositoryInterface->getAdministrators();
- $adminsEmails = array_map(function ($user) {
- return $user['email'];
- }, $admins);
- return $adminsEmails;
- }
-
- private function filterNonVerifiedEmailsUsers(array $users)
- {
- $emails = [];
- foreach ($users as $user) {
- if ($user['email_verified_at'] != null) $emails[] = $user['email'];
- }
- return $emails;
- }
-
- private function getUsersEmailsByRolesInStudy(string $studyName, string $role)
- {
- $users = $this->userRepositoryInterface->getUsersByRolesInStudy($studyName, $role);
- //Filter user with a verified email (password have been set)
- return $this->filterNonVerifiedEmailsUsers($users);
- }
-
- private function getInvestigatorOfCenterInStudy(String $studyName, String $center, ?String $job = null): array
- {
- $users = $this->userRepositoryInterface->getInvestigatorsOfStudyFromCenter($studyName, $center, $job);
- return $this->filterNonVerifiedEmailsUsers($users);
- }
-
- private function getStudyContactEmail(string $studyName): string
+ public function getUserEmail(int $userId)
{
- $studyEntity = $this->studyRepositoryInterface->find($studyName);
- return $studyEntity->contactEmail;
+ return $this->userRepositoryInterface->find($userId)['email'];
}
public function sendRequestMessage(string $name, string $email, string $center, string $request): void
@@ -87,7 +53,10 @@ public function sendRequestMessage(string $name, string $email, string $center,
'request' => $request
];
- $destinators = [...$this->getAdminsEmails(), $email];
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+ $destinators = [...$mailListBuilder->get(), $email];
+
$this->mailInterface->setTo($destinators);
$this->mailInterface->setReplyTo();
$this->mailInterface->setParameters($parameters);
@@ -110,7 +79,11 @@ public function sendAccountBlockedMessage(String $email, int $userId): void
'studies' => $studies
];
//Send to user and administrators
- $this->mailInterface->setTo([$email, ...$this->getAdminsEmails()]);
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+ $destinators = [...$mailListBuilder->get(), $email];
+
+ $this->mailInterface->setTo($destinators);
$this->mailInterface->setReplyTo();
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_BLOCKED_ACCOUNT);
@@ -125,7 +98,10 @@ public function sendAdminConnectedMessage(String $email, String $remoteAddress):
'remoteAddress' => $remoteAddress
];
//Send to administrators
- $this->mailInterface->setTo($this->getAdminsEmails());
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo();
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_ADMIN_LOGGED);
@@ -143,7 +119,10 @@ public function sendForbiddenResetPasswordDueToDeactivatedAccount(String $userEm
];
//Send to administrators
- $this->mailInterface->setTo([$userEmail, ...$this->getAdminsEmails()]);
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+
+ $this->mailInterface->setTo([$userEmail, ...$mailListBuilder->get()]);
$this->mailInterface->setReplyTo();
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_CHANGE_PASSWORD_DEACTIVATED);
@@ -161,14 +140,17 @@ public function sendImportPatientMessage(String $studyName, string $contactEmail
];
//Send to supervisors of the study
- $this->mailInterface->setTo($this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR));
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($contactEmail);
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_IMPORT_PATIENT);
$this->mailInterface->send();
}
- public function sendUploadedVisitMessage(int $visitId, int $uploadUserId, string $studyName, string $patientId, string $patientCode, string $visitType, bool $qcNeeded)
+ public function sendUploadedVisitMessage(array $emails, int $visitId, string $studyName, string $patientId, string $patientCode, string $visitType)
{
$parameters = [
@@ -180,28 +162,14 @@ public function sendUploadedVisitMessage(int $visitId, int $uploadUserId, string
'visitId' => $visitId
];
- //Send to supervisors and monitors of the study
- $destinators = [
- $this->getUserEmail($uploadUserId),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR)
- ];
- //If QC is awaiting add controllers
- if ($qcNeeded) {
- $destinators = [
- ...$destinators,
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_CONTROLLER)
- ];
- }
-
- $this->mailInterface->setTo($destinators);
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_UPLOADED_VISIT);
$this->mailInterface->send();
}
- public function sendReviewReadyMessage(int $visitId, string $studyName, string $patientId, string $patientCode, string $visitType)
+ public function sendReviewReadyMessage(array $emails, int $visitId, string $studyName, string $patientId, string $patientCode, string $visitType)
{
$parameters = [
@@ -212,7 +180,7 @@ public function sendReviewReadyMessage(int $visitId, string $studyName, string $
'visitId' => $visitId
];
- $this->mailInterface->setTo($this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_REVIEWER));
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_REVIEW_READY);
@@ -229,6 +197,8 @@ public function sendValidationFailMessage(
string $errorMessage
) {
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+
$parameters = [
'name' => 'User',
'idVisit' => $visitId,
@@ -241,7 +211,7 @@ public function sendValidationFailMessage(
'errorMessage' => $errorMessage
];
- $this->mailInterface->setTo($this->getAdminsEmails());
+ $this->mailInterface->setTo($mailListBuilder->withAdminsEmails()->get());
$this->mailInterface->setReplyTo();
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_UPLOAD_FAILURE);
@@ -249,11 +219,9 @@ public function sendValidationFailMessage(
}
public function sendQcDecisionMessage(
+ array $emails,
int $visitId,
- int $uploaderId,
- int $controllerId,
string $studyName,
- int $centerCode,
string $qcDecision,
string $patientId,
string $patientCode,
@@ -280,27 +248,15 @@ public function sendQcDecisionMessage(
'imageComment' => $imageComment
];
-
- $this->mailInterface->setTo(
- [
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR),
- $this->getUserEmail($uploaderId),
- $this->getUserEmail($controllerId),
- ...$this->getInvestigatorOfCenterInStudy($studyName, $centerCode)
- ]
- );
-
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_QC_DECISION);
$this->mailInterface->send();
}
- public function sendCorrectiveActionMessage(int $visitId, int $currentUserId, string $studyName, bool $correctionApplied, string $patientId, string $patientCode, string $visitModality, string $visitType)
+ public function sendCorrectiveActionMessage(array $emails, int $visitId, string $studyName, bool $correctionApplied, string $patientId, string $patientCode, string $visitModality, string $visitType)
{
-
-
$parameters = [
'name' => 'User',
'correctionApplied' => $correctionApplied,
@@ -312,14 +268,7 @@ public function sendCorrectiveActionMessage(int $visitId, int $currentUserId, st
'visitId' => $visitId
];
- $this->mailInterface->setTo(
- [
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_CONTROLLER),
- $this->getUserEmail($currentUserId),
- ]
- );
-
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_CORRECTIVE_ACTION);
@@ -340,11 +289,11 @@ public function sendUnlockMessage(int $visitId, int $currentUserId, string $role
'visitId' => $visitId
];
- $this->mailInterface->setTo([
- $this->getUserEmail($currentUserId),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
- ]);
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUserEmail($currentUserId)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_UNLOCK_REQUEST);
@@ -364,17 +313,18 @@ public function sendUnlockQCMessage(int $visitId, int $currentUserId, string $st
'visitId' => $visitId
];
- $this->mailInterface->setTo([
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
- ]);
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ ->withUserEmail($currentUserId);
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_UNLOCK_QC_REQUEST);
$this->mailInterface->send();
}
- public function sendAwaitingAdjudicationMessage(string $studyName, string $patientId, string $patientCode, string $visitType, int $visitId)
+ public function sendAwaitingAdjudicationMessage(array $emails, string $studyName, string $patientId, string $patientCode, string $visitType, int $visitId)
{
$parameters = [
@@ -386,39 +336,14 @@ public function sendAwaitingAdjudicationMessage(string $studyName, string $patie
'visitId' => $visitId
];
- //Get All Users with Reviwers in this study
- $reviewersUsers = $this->userRepositoryInterface->getUsersByRolesInStudy($studyName, Constants::ROLE_REVIEWER);
-
- //Get All Reviews of this visit
- $reviews = $this->reviewRepositoryInterface->getReviewsForStudyVisit($studyName, $visitId, true);
- $reviewerDoneUserIdArray = array_map(function ($user) {
- return $user['user_id'];
- }, $reviews);
-
- //Select users who didn't validate review form of this visit
- $availableReviewers = array_filter($reviewersUsers, function ($user) use ($reviewerDoneUserIdArray) {
- return !in_array($user['id'], $reviewerDoneUserIdArray);
- });
-
- //Build email list
- $availableReviewersEmails = array_map(function ($user) {
- return $user['email'];
- }, $availableReviewers);
-
- $this->mailInterface->setTo(
- [
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR),
- ...$availableReviewersEmails,
- ]
- );
-
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_ADJUDICATION);
$this->mailInterface->send();
}
- public function sendVisitConcludedMessage(int $visitId, ?int $uploaderId, string $studyName, string $patientId, string $patientCode, string $visitType, string $conclusionValue)
+ public function sendVisitConcludedMessage(array $emails, int $visitId, string $studyName, string $patientId, string $patientCode, string $visitType, string $conclusionValue)
{
$parameters = [
@@ -431,18 +356,7 @@ public function sendVisitConcludedMessage(int $visitId, ?int $uploaderId, string
'conclusionValue' => $conclusionValue
];
- $destinators = [
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR),
- ...$this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_MONITOR),
-
- ];
- //If uplaoder need to be included
- if ($uploaderId) {
- $destinators[] = $this->getUserEmail($uploaderId);
- }
-
- $this->mailInterface->setTo($destinators);
-
+ $this->mailInterface->setTo($emails);
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_CONCLUSION);
@@ -452,6 +366,8 @@ public function sendVisitConcludedMessage(int $visitId, ?int $uploaderId, string
public function sendDeleteFormMessage(int $visitId, bool $investigatorForm, int $formOwnerId, string $studyName, string $patientId, string $patientCode, string $visitType)
{
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+
$parameters = [
'name' => $this->getUserName($formOwnerId),
'study' => $studyName,
@@ -462,12 +378,7 @@ public function sendDeleteFormMessage(int $visitId, bool $investigatorForm, int
'formType' => $investigatorForm ? 'Investigator' : 'Review'
];
- $this->mailInterface->setTo(
- [
- $this->getUserEmail($formOwnerId)
- ]
- );
-
+ $this->mailInterface->setTo($mailListBuilder->withUserEmail($formOwnerId)->get());
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_DELETED_FORM);
@@ -476,6 +387,7 @@ public function sendDeleteFormMessage(int $visitId, bool $investigatorForm, int
public function sendUnlockedFormMessage(int $visitId, bool $investigatorForm, int $requestingUserId, string $studyName, string $patientId, string $patientCode, string $visitType)
{
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
$parameters = [
'name' => $this->getUserName($requestingUserId),
@@ -487,8 +399,9 @@ public function sendUnlockedFormMessage(int $visitId, bool $investigatorForm, in
'formType' => $investigatorForm ? 'Investigator' : 'Review'
];
- $this->mailInterface->setTo($this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR));
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_UNLOCK_FORM);
@@ -498,6 +411,7 @@ public function sendUnlockedFormMessage(int $visitId, bool $investigatorForm, in
public function sendVisitNotDoneMessage(int $visitId, string $studyName, string $patientId, string $patientCode, string $visitType, string $reasonNotDone, int $userId)
{
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
$parameters = [
'patientId' => $patientId,
@@ -510,9 +424,8 @@ public function sendVisitNotDoneMessage(int $visitId, string $studyName, string
];
$this->mailInterface->setTo(
- $this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)->get()
);
-
$this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_VISIT_NOT_DONE);
@@ -528,13 +441,14 @@ public function sendReminder(string $senderId, array $userIds, string $studyName
'content' => $content
];
- $destinatorsEmails = array_map(function ($userId) {
- return $this->getUserEmail($userId);
- }, $userIds);
- $senderEmail = $this->getUserEmail($senderId);
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ foreach ($userIds as $userId) {
+ return $mailListBuilder->withUserEmail($userId);
+ };
+ $mailListBuilder->withUserEmail($senderId);
- $this->mailInterface->setTo([...$destinatorsEmails, $senderEmail]);
- $this->mailInterface->setReplyTo($senderEmail);
+ $this->mailInterface->setTo($mailListBuilder->get());
+ $this->mailInterface->setReplyTo($this->getUserEmail($senderId));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_REMINDER);
$this->mailInterface->send();
@@ -548,9 +462,10 @@ public function sendPatientCreationRequest(int $senderId, string $studyName, str
'patients' => $patients
];
- $this->mailInterface->setTo(
- $this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
- );
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getUserEmail($senderId));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_REQUEST_PATIENT_CREATION);
@@ -571,9 +486,10 @@ public function sendMailToSupervisors(int $senderId, string $studyName, string $
'canReply' => true
];
- $this->mailInterface->setTo(
- $this->getUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR)
- );
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getUserEmail($senderId));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_USER);
@@ -589,14 +505,12 @@ public function sendMailToUser(int $senderId, array $userIds, ?string $studyName
'canReply' => true
];
- $this->mailInterface->setTo(
- array_map(function ($userId) {
- return $this->getUserEmail($userId);
- }, $userIds)
- );
-
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ foreach ($userIds as $userId) {
+ $mailListBuilder->withUserEmail($userId);
+ }
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getUserEmail($senderId));
-
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_USER);
$this->mailInterface->send();
@@ -612,9 +526,9 @@ public function sendMailToAdministrators(int $senderId, string $studyName, strin
'canReply' => true
];
- $this->mailInterface->setTo(
- $this->getAdminsEmails()
- );
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+ $this->mailInterface->setTo($mailListBuilder->get());
$this->mailInterface->setReplyTo($this->getUserEmail($senderId));
$this->mailInterface->setParameters($parameters);
$this->mailInterface->setBody(MailConstants::EMAIL_USER);
@@ -680,4 +594,43 @@ public function sendQcReport(string $studyName, string $visitType, string $patie
$this->mailInterface->setBody(MailConstants::EMAIL_QC_REPORT);
$this->mailInterface->send();
}
+
+ public function sendRadiomicsReport(string $studyName, string $patientCode, string $visitType, string $visitDate, string $imagePath, array $stats, int $uploaderId)
+ {
+ $parameters = [
+ 'patientCode' => $patientCode,
+ 'visitType' => $visitType,
+ 'studyName' => $studyName,
+ 'visitDate' => $visitDate,
+ 'image_path' => [$imagePath],
+ 'stats' => $stats
+ ];
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface, $this->studyRepositoryInterface);
+ $mailListBuilder->withUserEmail($uploaderId)
+ ->withUsersEmailsByRolesInStudy($studyName, Constants::ROLE_SUPERVISOR);
+
+ $this->mailInterface->setTo($mailListBuilder->get());
+ $this->mailInterface->setReplyTo($this->getStudyContactEmail($studyName));
+ $this->mailInterface->setParameters($parameters);
+ $this->mailInterface->setBody(MailConstants::EMAIL_RADIOMICS_REPORT);
+ $this->mailInterface->send();
+ }
+
+
+ public function sendJobFailure(string $jobType, array $details, string $errorMessage)
+ {
+ $parameters = [
+ 'jobType' => $jobType,
+ 'details' => $details,
+ 'errorMessage' => $errorMessage
+ ];
+
+ $mailListBuilder = new MailListBuilder($this->userRepositoryInterface, $this->studyRepositoryInterface);
+ $mailListBuilder->withAdminsEmails();
+ $this->mailInterface->setTo($mailListBuilder->get());
+ $this->mailInterface->setParameters($parameters);
+ $this->mailInterface->setBody(MailConstants::EMAIL_JOB_FAILURE);
+ $this->mailInterface->send();
+ }
}
diff --git a/GaelO2/app/GaelO/Services/OrthancService.php b/GaelO2/app/GaelO/Services/OrthancService.php
index 7ae785608..904b4ebaa 100644
--- a/GaelO2/app/GaelO/Services/OrthancService.php
+++ b/GaelO2/app/GaelO/Services/OrthancService.php
@@ -86,7 +86,7 @@ public function addPeer(string $name, string $url, string $username, string $pas
*/
public function deletePeer(string $name)
{
- $this->httpClientInterface->rowRequest('DELETE', '/peers/' . $name, null, null);
+ $this->httpClientInterface->rawRequest('DELETE', '/peers/' . $name, null, null);
}
/**
@@ -132,13 +132,13 @@ public function searchInOrthanc(
public function deleteFromOrthanc(string $level, string $uid)
{
- $this->httpClientInterface->rowRequest('DELETE', '/' . $level . '/' . $uid, null, null);
+ $this->httpClientInterface->rawRequest('DELETE', '/' . $level . '/' . $uid, null, null);
}
public function isPeerAccelerated(string $peer): bool
{
- $peers = $this->httpClientInterface->rowRequest('GET', '/transfers/peers', null, null)->getJsonBody();
+ $peers = $this->httpClientInterface->rawRequest('GET', '/transfers/peers', null, null)->getJsonBody();
if ($peers[$peer] == "installed") {
return true;
@@ -376,7 +376,7 @@ public function getOrthancZipStream(array $seriesOrthancIDs, ?string $transfertS
$this->httpClientInterface->streamResponse('POST', '/tools/create-archive', $payload);
}
- public function getOrthancZipStreamAsString(array $seriesOrthancIDs, ?string $transfertSyntaxUID = null): Psr7ResponseAdapter
+ public function getOrthancZipAsStream(array $seriesOrthancIDs, ?string $transfertSyntaxUID = null): Psr7ResponseAdapter
{
$payload = [
'Resources' => $seriesOrthancIDs
diff --git a/GaelO2/app/GaelO/Services/PdfServices.php b/GaelO2/app/GaelO/Services/PdfServices.php
new file mode 100644
index 000000000..4b0384fa6
--- /dev/null
+++ b/GaelO2/app/GaelO/Services/PdfServices.php
@@ -0,0 +1,32 @@
+pdfInterface = $pdfInterface;
+ }
+
+ public function saveRadiomicsPdf(string $studyName, string $patientCode, string $visitType, string $visitDate, array $stats): string
+ {
+ $parameters = [
+ 'patientCode' => $patientCode,
+ 'visitType' => $visitType,
+ 'studyName' => $studyName,
+ 'visitDate' => $visitDate,
+ 'stats' => $stats
+ ];
+
+ $pdfReportTempFile = tempnam(ini_get('upload_tmp_dir'), 'TMP_pdf_');
+ $this->pdfInterface->saveViewToPdf('mails.mail_radiomics_report', $parameters, $pdfReportTempFile);
+
+ return $pdfReportTempFile;
+ }
+}
diff --git a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST.php b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST.php
index a8b419573..aa7453f3f 100644
--- a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST.php
+++ b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST.php
@@ -4,6 +4,8 @@
use App\GaelO\Services\GaelOStudiesService\AbstractGaelOStudy;
use App\GaelO\Services\GaelOStudiesService\DefaultVisitRules;
+use App\GaelO\Services\GaelOStudiesService\Events\BaseStudyEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\VisitUploadedEvent;
class TEST extends AbstractGaelOStudy {
diff --git a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_FDG_PET0.php b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_FDG_PET0.php
index 366fe8f13..dd27f0395 100644
--- a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_FDG_PET0.php
+++ b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_FDG_PET0.php
@@ -80,11 +80,19 @@ public static function getReviewerAdjudicationValidationRules(): array
return [];
}
+ public static function getAssociatedFilesVisit(): array
+ {
+ return [
+ 'prediction' => new AssociatedFile('prediction', [MimeAdapter::getMimeFromExtension('csv')], false),
+ 'tmtv41' => new AssociatedFile('tmtv41', [MimeAdapter::getMimeFromExtension('gz')], false)
+ ];
+ }
+
public static function getAssociatedFilesInvestigator(): array
{
return [
- '41' => new AssociatedFile('41', MimeAdapter::getMimesFromExtension('csv'), true),
- '25' => new AssociatedFile('25', MimeAdapter::getMimesFromExtension('zip'), false)
+ '41' => new AssociatedFile('41', [MimeAdapter::getMimeFromExtension('csv')], true),
+ '25' => new AssociatedFile('25', [MimeAdapter::getMimeFromExtension('zip')], false)
];
}
diff --git a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_WB_CT0.php b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_WB_CT0.php
index 5cb3260ea..f1a7feb79 100644
--- a/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_WB_CT0.php
+++ b/GaelO2/app/GaelO/Services/SpecificStudiesRules/TEST/TEST_WB_CT0.php
@@ -29,6 +29,11 @@ public static function getReviewerValidationRules(): array
];
}
+ public static function getAssociatedFilesVisit(): array
+ {
+ return [];
+ }
+
public static function getAssociatedFilesInvestigator(): array
{
return [];
diff --git a/GaelO2/app/GaelO/Services/TusService.php b/GaelO2/app/GaelO/Services/TusService.php
index c0d76571d..674521251 100644
--- a/GaelO2/app/GaelO/Services/TusService.php
+++ b/GaelO2/app/GaelO/Services/TusService.php
@@ -32,7 +32,7 @@ public function getFile(string $tusFileId) : string {
}
public function deleteFile(string $tusFileId) : void {
- $this->httpClientInterface->rowRequest('DELETE', '/api/tus/'.$tusFileId, null, ['Tus-Resumable' => '1.0.0'] );
+ $this->httpClientInterface->rawRequest('DELETE', '/api/tus/'.$tusFileId, null, ['Tus-Resumable' => '1.0.0'] );
}
}
diff --git a/GaelO2/app/GaelO/Services/VisitService.php b/GaelO2/app/GaelO/Services/VisitService.php
index 9bea498db..adca68ec8 100644
--- a/GaelO2/app/GaelO/Services/VisitService.php
+++ b/GaelO2/app/GaelO/Services/VisitService.php
@@ -2,38 +2,41 @@
namespace App\GaelO\Services;
-use App\GaelO\Constants\Constants;
use App\GaelO\Constants\Enums\InvestigatorFormStateEnum;
use App\GaelO\Constants\Enums\QualityControlStateEnum;
use App\GaelO\Constants\Enums\ReviewStatusEnum;
use App\GaelO\Constants\Enums\UploadStatusEnum;
-use App\GaelO\Interfaces\Adapters\JobInterface;
+use App\GaelO\Exceptions\GaelOBadRequestException;
+use App\GaelO\Exceptions\GaelOForbiddenException;
+use App\GaelO\Exceptions\GaelONotFoundException;
+use App\GaelO\Interfaces\Adapters\FrameworkInterface;
use App\GaelO\Repositories\ReviewRepository;
use App\GaelO\Repositories\ReviewStatusRepository;
use App\GaelO\Repositories\VisitRepository;
+use App\GaelO\Services\GaelOStudiesService\AbstractGaelOStudy;
+use App\GaelO\Services\GaelOStudiesService\Events\QCModifiedEvent;
+use App\GaelO\Services\GaelOStudiesService\Events\VisitUploadedEvent;
class VisitService
{
private VisitRepository $visitRepository;
private ReviewRepository $reviewRepository;
- private MailServices $mailServices;
private ReviewStatusRepository $reviewStatusRepository;
- private JobInterface $jobInterface;
+ private FrameworkInterface $frameworkInterface;
private int $visitId;
+ private int $currentUserId;
public function __construct(
+ FrameworkInterface $frameworkInterface,
VisitRepository $visitRepository,
ReviewRepository $reviewRepository,
- ReviewStatusRepository $reviewStatusRepository,
- MailServices $mailServices,
- JobInterface $jobInterface
+ ReviewStatusRepository $reviewStatusRepository
) {
+ $this->frameworkInterface = $frameworkInterface;
$this->visitRepository = $visitRepository;
- $this->mailServices = $mailServices;
$this->reviewStatusRepository = $reviewStatusRepository;
$this->reviewRepository = $reviewRepository;
- $this->jobInterface = $jobInterface;
}
public function setVisitId(int $visitId)
@@ -41,6 +44,11 @@ public function setVisitId(int $visitId)
$this->visitId = $visitId;
}
+ public function setCurrentUserId(int $currentUserId)
+ {
+ $this->currentUserId = $currentUserId;
+ }
+
public function getVisitContext(): array
{
return $this->visitRepository->getVisitContext($this->visitId);
@@ -49,13 +57,12 @@ public function getVisitContext(): array
public function updateUploadStatus(string $uploadStatus)
{
- if($uploadStatus === UploadStatusEnum::NOT_DONE->value){
- $visitContext = $this->visitRepository->getVisitContext($this->visitId);
- if($visitContext['state_investigator_form'] === InvestigatorFormStateEnum::DONE->value) {
+ if ($uploadStatus === UploadStatusEnum::NOT_DONE->value) {
+ $visitContext = $this->getVisitContext($this->visitId);
+ if ($visitContext['state_investigator_form'] === InvestigatorFormStateEnum::DONE->value) {
$this->reviewRepository->unlockInvestigatorForm($this->visitId);
$this->updateInvestigatorFormStatus(InvestigatorFormStateEnum::DRAFT->value);
}
-
}
$updatedEntity = $this->visitRepository->updateUploadStatus($this->visitId, $uploadStatus);
@@ -64,7 +71,7 @@ public function updateUploadStatus(string $uploadStatus)
$updatedEntity['upload_status'] === UploadStatusEnum::DONE->value
&& ($updatedEntity['state_investigator_form'] === InvestigatorFormStateEnum::NOT_NEEDED->value || $updatedEntity['state_investigator_form'] === InvestigatorFormStateEnum::DONE->value)
) {
- $this->sendUploadEmailAndSkipQcIfNeeded($this->visitId);
+ $this->visitUploaded($this->visitId);
}
}
@@ -75,41 +82,39 @@ public function updateInvestigatorFormStatus(string $stateInvestigatorForm)
$updatedEntity['upload_status'] === UploadStatusEnum::DONE->value
&& ($updatedEntity['state_investigator_form'] === InvestigatorFormStateEnum::DONE->value)
) {
- $this->sendUploadEmailAndSkipQcIfNeeded($this->visitId);
+ $this->visitUploaded($this->visitId);
}
}
- private function sendUploadEmailAndSkipQcIfNeeded()
+ /**
+ * Skip QC if needed and send email notification of uploaded visit
+ */
+ private function visitUploaded()
{
- //If uploaded done and investigator done (Done or Not Needed) send notification message
- $visitEntity = $this->visitRepository->getVisitContext($this->visitId);
-
- $patientId = $visitEntity['patient_id'];
- $visitType = $visitEntity['visit_type']['name'];
+ $visitEntity = $this->getVisitContext($this->visitId);
$studyName = $visitEntity['patient']['study_name'];
- $patientCode = $visitEntity['patient']['code'];
-
$reviewStatus = $this->getReviewStatus($studyName);
$qcNeeded = $visitEntity['state_quality_control'] !== QualityControlStateEnum::NOT_NEEDED->value;
$reviewNeeded = $reviewStatus['review_status'] !== ReviewStatusEnum::NOT_NEEDED->value;
- $this->mailServices->sendUploadedVisitMessage($this->visitId, $visitEntity['creator_user_id'], $studyName, $patientId, $patientCode, $visitType, $qcNeeded);
- // Send auto qc job
- if($qcNeeded){
- $this->jobInterface->sendQcReportJob($this->visitId);
- }
//If Qc NotNeeded mark visit as available for review
- if (!$qcNeeded && $reviewNeeded ) {
+ if (!$qcNeeded && $reviewNeeded) {
$this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName, true);
- $this->mailServices->sendReviewReadyMessage($this->visitId, $studyName, $patientId, $patientCode, $visitType);
}
+
+ //Notify of the upload done
+ $visitUploadedEvent = new VisitUploadedEvent($visitEntity);
+ $visitUploadedEvent->setReviewNeeded($reviewNeeded);
+ $visitUploadedEvent->setUploaderUserId($this->currentUserId);
+ $studyObject = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $studyObject->onEventStudy($visitUploadedEvent);
}
public function editQc(string $stateQc, int $controllerId, ?bool $imageQc, ?bool $formQc, ?string $imageQcComment, ?string $formQcComment)
{
- $visitEntity = $this->visitRepository->getVisitContext($this->visitId);
+ $visitEntity = $this->getVisitContext($this->visitId);
$studyName = $visitEntity['patient']['study_name'];
$reviewStatus = $this->getReviewStatus($studyName);
@@ -127,16 +132,27 @@ public function editQc(string $stateQc, int $controllerId, ?bool $imageQc, ?bool
if ($stateQc === QualityControlStateEnum::ACCEPTED->value && $reviewNeeded) {
//Invalidate invistagator form and set it status as draft in the visit
- $this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName , true);
+ $this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName, true);
}
+
+ $qcModifiedEvent = new QCModifiedEvent($visitEntity);
+ $qcModifiedEvent->setCurrentUserId($controllerId);
+ $qcModifiedEvent->setQcStatus($stateQc);
+ $qcModifiedEvent->setFormQcStatus($formQc ? 'Accepted ' : 'Refused');
+ $qcModifiedEvent->setImageQcStatus($imageQc ? 'Accepted ' : 'Refused');
+ $qcModifiedEvent->setFormQcComment($formQcComment ?? 'None');
+ $qcModifiedEvent->setImageQcComment($imageQcComment ?? 'None');
+
+ $studyObject = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $studyObject->onEventStudy($qcModifiedEvent);
}
public function resetQc(): void
{
- $visitEntity = $this->visitRepository->getVisitContext($this->visitId);
+ $visitEntity = $this->getVisitContext($this->visitId);
$studyName = $visitEntity['patient']['study_name'];
$this->visitRepository->resetQc($this->visitId);
- $this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName , false);
+ $this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName, false);
}
public function getReviewStatus(string $studyName)
@@ -144,4 +160,55 @@ public function getReviewStatus(string $studyName)
return $this->reviewStatusRepository->getReviewStatus($this->visitId, $studyName);
}
+ public function attachFile(string $key, string $mimeType, string $extension, $binaryData): string
+ {
+ $visitEntity = $this->getVisitContext($this->visitId);
+ $studyName = $visitEntity['patient']['study_name'];
+ $visitGroupName = $visitEntity['visit_type']['visit_group']['name'];
+ $visitTypeName = $visitEntity['visit_type']['name'];
+
+ $studyRule = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $abstractVisitRules = $studyRule->getSpecificVisitRules($visitGroupName, $visitTypeName);
+ $associatedFilesVisit = $abstractVisitRules->getAssociatedFilesVisit();
+
+ if (!empty($visitEntity['sent_files'][$key])) {
+ throw new GaelOBadRequestException("Already Existing File for this visit");
+ }
+
+ if (!array_key_exists($key, $associatedFilesVisit)) {
+ throw new GaelOForbiddenException("Unexpected file key");
+ }
+
+ $associatiedFile = $associatedFilesVisit[$key];
+
+ if (!in_array($mimeType, $associatiedFile->mimes)) {
+ throw new GaelOBadRequestException("Mime Not Allowed");
+ }
+
+ $destinationPath = $studyName . '/' . 'attached_visit_file';
+
+ $filename = 'visit_' . $this->visitId . '_' . $key . '.' . $extension;
+ $destinationFileName = $destinationPath . '/' . $filename;
+
+ $this->frameworkInterface->storeFile($destinationFileName, $binaryData);
+
+ $visitEntity['sent_files'][$key] = $destinationFileName;
+ $this->visitRepository->updateVisitFile($visitEntity['id'], $visitEntity['sent_files']);
+ return $filename;
+ }
+
+ public function removeFile(string $key): void
+ {
+ $visitEntity = $this->getVisitContext($this->visitId);
+
+ if (empty($visitEntity['sent_files'][$key])) {
+ throw new GaelONotFoundException('Non exisiting key file in review');
+ }
+
+ $targetedFile = $visitEntity['sent_files'][$key];
+ $this->frameworkInterface->deleteFile($targetedFile);
+
+ unset($visitEntity['sent_files'][$key]);
+ $this->visitRepository->updateVisitFile($visitEntity['id'], $visitEntity['sent_files']);
+ }
}
diff --git a/GaelO2/app/GaelO/UseCases/CreateFileToForm/CreateFileToForm.php b/GaelO2/app/GaelO/UseCases/CreateFileToForm/CreateFileToForm.php
index cc282a43a..fd7849c93 100644
--- a/GaelO2/app/GaelO/UseCases/CreateFileToForm/CreateFileToForm.php
+++ b/GaelO2/app/GaelO/UseCases/CreateFileToForm/CreateFileToForm.php
@@ -70,8 +70,6 @@ public function execute(CreateFileToFormRequest $createFileToReviewRequest, Crea
$extension = $this->mimeInterface::getExtensionsFromMime($createFileToReviewRequest->contentType)[0];
- $fileName = 'review_' . $reviewId . '_' . $key . '.' . $extension;
-
$visitContext = $this->visitRepositoryInterface->getVisitWithContextAndReviewStatus($visitId, $studyName);
$formService = null;
@@ -83,11 +81,12 @@ public function execute(CreateFileToFormRequest $createFileToReviewRequest, Crea
}
$formService->setVisitContextAndStudy($visitContext, $studyName);
- $formService->attachFile($reviewEntity, $key, $fileName, $createFileToReviewRequest->contentType, base64_decode($binaryData));
+
+ $filename = $formService->attachFile($reviewEntity, $key, $createFileToReviewRequest->contentType, $extension, base64_decode($binaryData));
$actionDetails = [
'uploaded_file' => $key,
- 'filename' => $fileName,
+ 'filename' => $filename,
'review_id' => $reviewId
];
diff --git a/GaelO2/app/GaelO/UseCases/CreateFileToFormFromTus/CreateFileToFormFromTus.php b/GaelO2/app/GaelO/UseCases/CreateFileToFormFromTus/CreateFileToFormFromTus.php
index cee1f0b28..19dca615f 100644
--- a/GaelO2/app/GaelO/UseCases/CreateFileToFormFromTus/CreateFileToFormFromTus.php
+++ b/GaelO2/app/GaelO/UseCases/CreateFileToFormFromTus/CreateFileToFormFromTus.php
@@ -14,6 +14,7 @@
use App\GaelO\Interfaces\Repositories\VisitRepositoryInterface;
use App\GaelO\Services\AuthorizationService\AuthorizationReviewService;
use App\GaelO\Services\AuthorizationService\AuthorizationVisitService;
+use App\GaelO\Services\FormService\FormService;
use App\GaelO\Services\FormService\InvestigatorFormService;
use App\GaelO\Services\FormService\ReviewFormService;
use App\GaelO\Services\OrthancService;
@@ -141,8 +142,6 @@ public function execute(CreateFileToFormFromTusRequest $createFileToFormFromTusR
$extension = $this->mimeInterface::getExtensionsFromMime($mime)[0];
}
- $fileName = 'review_' . $reviewId . '_' . $key . '.' . $extension;
-
$visitContext = $this->visitRepositoryInterface->getVisitWithContextAndReviewStatus($visitId, $studyName);
$formService = null;
@@ -154,12 +153,13 @@ public function execute(CreateFileToFormFromTusRequest $createFileToFormFromTusR
}
$formService->setVisitContextAndStudy($visitContext, $studyName);
- $formService->attachFile($reviewEntity, $key, $fileName, $mime, fopen($file, 'r'));
+ $filename = $formService->attachFile($reviewEntity, $key, $mime, $extension, fopen($file, 'r'));
+
//Remove temporary file
unlink($file);
$actionDetails = [
'uploaded_file' => $key,
- 'filename' => $fileName,
+ 'filename' => $filename,
'review_id' => $reviewId
];
diff --git a/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisit.php b/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisit.php
new file mode 100644
index 000000000..def410fb8
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisit.php
@@ -0,0 +1,111 @@
+authorizationVisitService = $authorizationVisitService;
+ $this->visitService = $visitService;
+ $this->trackerRepositoryInterface = $trackerRepositoryInterface;
+ $this->mimeInterface = $mimeInterface;
+ }
+
+ public function execute(CreateFileToVisitRequest $createFileToVisitRequest, CreateFileToVisitResponse $createFileToVisitResponse)
+ {
+
+ try {
+
+ $visitId = $createFileToVisitRequest->visitId;
+ $key = $createFileToVisitRequest->key;
+ $content = $createFileToVisitRequest->content;
+ $currentUserId = $createFileToVisitRequest->currentUserId;
+ $contentType = $createFileToVisitRequest->contentType;
+
+ $this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($currentUserId);
+ $visitContext = $this->visitService->getVisitContext();
+ $studyName = $visitContext['patient']['study_name'];
+
+ if ($createFileToVisitRequest->studyName !== $studyName) {
+ throw new GaelOForbiddenException('Should be called from original study');
+ }
+
+ if (!Util::isBase64Encoded($content)) {
+ throw new GaelOBadRequestException("Payload should be base64 encoded");
+ }
+
+ $this->checkAuthorization($visitId, $currentUserId, $studyName);
+
+ if ($createFileToVisitRequest->extension == null) {
+ $extension = $this->mimeInterface::getExtensionsFromMime($createFileToVisitRequest->contentType)[0];
+ } else {
+ $extension = $createFileToVisitRequest->extension;
+ if(strchr($extension, '.')) {
+ $finalExtension = strrchr($extension, '.');
+ //remove first dot
+ $finalExtension = substr($finalExtension, 1);
+ $contentType = $this->mimeInterface::getMimeFromExtension($finalExtension);
+ }else{
+ $contentType = $this->mimeInterface::getMimeFromExtension($extension);
+ }
+
+ }
+
+ $filename = $this->visitService->attachFile($key, $contentType, $extension, base64_decode($content));
+
+ $actionDetails = [
+ 'uploaded_file' => $key,
+ 'filename' => $filename
+ ];
+
+ $this->trackerRepositoryInterface->writeAction(
+ $currentUserId,
+ Constants::ROLE_SUPERVISOR,
+ $studyName,
+ $visitId,
+ Constants::TRACKER_UPDATE_VISIT_FILE,
+ $actionDetails
+ );
+
+ $createFileToVisitResponse->status = 201;
+ $createFileToVisitResponse->statusText = 'Created';
+ } catch (AbstractGaelOException $e) {
+ $createFileToVisitResponse->body = $e->getErrorBody();
+ $createFileToVisitResponse->status = $e->statusCode;
+ $createFileToVisitResponse->statusText = $e->statusText;
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function checkAuthorization(int $visitId, int $currentUserId, string $studyName): void
+ {
+ $this->authorizationVisitService->setVisitId($visitId);
+ $this->authorizationVisitService->setUserId($currentUserId);
+ $this->authorizationVisitService->setStudyName($studyName);
+ if (!$this->authorizationVisitService->isVisitAllowed(Constants::ROLE_SUPERVISOR)) throw new GaelOForbiddenException();
+ }
+}
diff --git a/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisitRequest.php b/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisitRequest.php
new file mode 100644
index 000000000..825a3d3cd
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/CreateFileToVisit/CreateFileToVisitRequest.php
@@ -0,0 +1,14 @@
+documentationMandatory;
$contactEmail = $createStudyRequest->contactEmail;
$ancillaryOf = $createStudyRequest->ancillaryOf;
+ $creatablePatientsInvestigator = $createStudyRequest->creatablePatientsInvestigator;
if (preg_match('/[^A-Z0-9]/', $studyName)) {
throw new GaelOBadRequestException('Only uppercase alphanumerical name allowed, no space or special characters');
@@ -70,7 +71,11 @@ public function execute(CreateStudyRequest $createStudyRequest, CreateStudyRespo
throw new GaelOBadRequestException('Missing Monitor Show All');
}
- $this->studyRepositoryInterface->addStudy($studyName, $studyCode, $patientCodeLength, $contactEmail, $controllerShowAll, $monitorShowAll, $documentationMandatory, $ancillaryOf);
+ if (!isset($creatablePatientsInvestigator)) {
+ throw new GaelOBadRequestException('Missing Creatable Patient Investigator');
+ }
+
+ $this->studyRepositoryInterface->addStudy($studyName, $studyCode, $patientCodeLength, $contactEmail, $controllerShowAll, $monitorShowAll, $documentationMandatory, $ancillaryOf, $creatablePatientsInvestigator);
$currentUserId = $createStudyRequest->currentUserId;
$actionDetails = [
diff --git a/GaelO2/app/GaelO/UseCases/CreateStudy/CreateStudyRequest.php b/GaelO2/app/GaelO/UseCases/CreateStudy/CreateStudyRequest.php
index f536dc7d0..d4b55c670 100644
--- a/GaelO2/app/GaelO/UseCases/CreateStudy/CreateStudyRequest.php
+++ b/GaelO2/app/GaelO/UseCases/CreateStudy/CreateStudyRequest.php
@@ -13,4 +13,5 @@ class CreateStudyRequest
public bool $controllerShowAll;
public bool $documentationMandatory;
public ?string $ancillaryOf = null;
+ public bool $creatablePatientsInvestigator;
}
diff --git a/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisit.php b/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisit.php
new file mode 100644
index 000000000..0582c978f
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisit.php
@@ -0,0 +1,89 @@
+authorizationVisitService = $authorizationVisitService;
+ $this->trackerRepositoryInterface = $trackerRepositoryInterface;
+ $this->visitService = $visitService;
+ }
+
+ public function execute(DeleteFileOfVisitRequest $deleteFileOfVisitRequest, DeleteFileOfVisitResponse $deleteFileOfVisitResponse)
+ {
+ try {
+
+ $studyName = $deleteFileOfVisitRequest->studyName;
+ $visitId = $deleteFileOfVisitRequest->visitId;
+ $role = $deleteFileOfVisitRequest->role;
+ $currentUserId = $deleteFileOfVisitRequest->currentUserId;
+ $fileKey = $deleteFileOfVisitRequest->key;
+
+ if ($role !== Constants::ROLE_SUPERVISOR) {
+ throw new GaelOForbiddenException("Supervisor role only");
+ }
+
+ $this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($currentUserId);
+ $visitContext = $this->visitService->getVisitContext();
+
+ if ($deleteFileOfVisitRequest->studyName !== $visitContext['patient']['study_name']) {
+ throw new GaelOForbiddenException('Should be called from original study');
+ }
+
+ $this->checkAuthorization($visitContext, $currentUserId);
+
+ $this->visitService->removeFile($fileKey);
+
+ $actionDetails = [
+ 'removed_file' => $fileKey
+ ];
+
+ $this->trackerRepositoryInterface->writeAction(
+ $currentUserId,
+ Constants::ROLE_SUPERVISOR,
+ $studyName,
+ $visitId,
+ Constants::TRACKER_UPDATE_VISIT_FILE,
+ $actionDetails
+ );
+
+ $deleteFileOfVisitResponse->status = 200;
+ $deleteFileOfVisitResponse->statusText = 'OK';
+ } catch (AbstractGaelOException $e) {
+ $deleteFileOfVisitResponse->body = $e->getErrorBody();
+ $deleteFileOfVisitResponse->status = $e->statusCode;
+ $deleteFileOfVisitResponse->statusText = $e->statusText;
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function checkAuthorization(array $visitContext, int $currentUserId): void
+ {
+ $this->authorizationVisitService->setUserId($currentUserId);
+ $this->authorizationVisitService->setVisitContext($visitContext);
+ $this->authorizationVisitService->setStudyName($visitContext['patient']['study_name']);
+ if (!$this->authorizationVisitService->isVisitAllowed(Constants::ROLE_SUPERVISOR)) {
+ throw new GaelOForbiddenException();
+ };
+ }
+}
diff --git a/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisitRequest.php b/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisitRequest.php
new file mode 100644
index 000000000..0159030db
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/DeleteFileOfVisit/DeleteFileOfVisitRequest.php
@@ -0,0 +1,12 @@
+checkAuthorization($currentUserId, $visitId, $role, $studyName, $visitContext);
+ $this->dicomService->setCurrentUserId($currentUserId);
$this->dicomService->deleteSeries($seriesInstanceUID, $role);
$actionDetails = [
diff --git a/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatients.php b/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatients.php
new file mode 100644
index 000000000..61c801911
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatients.php
@@ -0,0 +1,72 @@
+authorizationStudyService = $authorizationStudyService;
+ $this->patientRepositoryInterface = $patientRepositoryInterface;
+ }
+
+ public function execute(GetCreatablePatientsRequest $getCreatablePatientsRequest, GetCreatablePatientsResponse $getCreatablePatientsResponse)
+ {
+ try {
+
+ $studyName = $getCreatablePatientsRequest->studyName;
+ $role = $getCreatablePatientsRequest->role;
+ $currentUserId = $getCreatablePatientsRequest->currentUserId;
+
+ $this->checkAuthorization($currentUserId, $studyName, $role);
+
+ $studyRule = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $expectedPatients = $studyRule->getExpectedPatients();
+
+ if (sizeof($expectedPatients) > 0) {
+ $createdPatients = $this->patientRepositoryInterface->getPatientsInStudy($studyName, false);
+ $createdPatientsCode = array_column($createdPatients, 'code');
+ $creatablePatients = array_values(array_filter($expectedPatients, function (ExpectedPatient $expectedPatient) use ($createdPatientsCode) {
+ return !in_array($expectedPatient->code, $createdPatientsCode);
+ }));
+ $getCreatablePatientsResponse->body = $creatablePatients;
+ } else {
+ $getCreatablePatientsResponse->body = [];
+ }
+
+ $getCreatablePatientsResponse->status = 200;
+ $getCreatablePatientsResponse->statusText = 'OK';
+ } catch (AbstractGaelOException $e) {
+ $getCreatablePatientsResponse->body = $e->getErrorBody();
+ $getCreatablePatientsResponse->status = $e->statusCode;
+ $getCreatablePatientsResponse->statusText = $e->statusText;
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function checkAuthorization(int $userId, string $studyName, string $role)
+ {
+ if (!in_array($role, [Constants::ROLE_INVESTIGATOR, Constants::ROLE_SUPERVISOR])) {
+ throw new GaelOForbiddenException();
+ };
+ $this->authorizationStudyService->setUserId($userId);
+ $this->authorizationStudyService->setStudyName($studyName);
+ if (!$this->authorizationStudyService->isAllowedStudy($role)) {
+ throw new GaelOForbiddenException();
+ }
+ }
+}
diff --git a/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatientsRequest.php b/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatientsRequest.php
new file mode 100644
index 000000000..f67785019
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/GetCreatablePatients/GetCreatablePatientsRequest.php
@@ -0,0 +1,10 @@
+authorizationVisitService = $authorizationVisitService;
+ $this->visitRepositoryInterface = $visitRepositoryInterface;
+ }
+
+ public function execute(GetFileOfVisitRequest $getFileOfVisitRequest, GetFileOfVisitResponse $getFileOfVisitResponse)
+ {
+
+ try {
+ $visitId = $getFileOfVisitRequest->visitId;
+ $fileKey = $getFileOfVisitRequest->key;
+ $role = $getFileOfVisitRequest->role;
+ $studyName = $getFileOfVisitRequest->studyName;
+ $currentUserId = $getFileOfVisitRequest->currentUserId;
+
+ $visitEntity = $this->visitRepositoryInterface->getVisitContext($visitId);
+
+ $this->checkAuthorization($visitId, $currentUserId, $role, $studyName);
+ if(!array_key_exists($fileKey, $visitEntity['sent_files'])){
+ throw new GaelONotFoundException("File key not found");
+ }
+
+ $getFileOfVisitResponse->status = 200;
+ $getFileOfVisitResponse->statusText = 'OK';
+ $getFileOfVisitResponse->filePath = $visitEntity['sent_files'][$fileKey];
+ $getFileOfVisitResponse->filename = basename($visitEntity['sent_files'][$fileKey]);
+ } catch (AbstractGaelOException $e) {
+ $getFileOfVisitResponse->status = $e->statusCode;
+ $getFileOfVisitResponse->statusText = $e->statusText;
+ $getFileOfVisitResponse->body = $e->getErrorBody();
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function checkAuthorization(int $visitId, int $currentUserId, string $role, string $studyName): void
+ {
+ //Check if visit is allowed
+ $this->authorizationVisitService->setVisitId($visitId);
+ $this->authorizationVisitService->setUserId($currentUserId);
+ $this->authorizationVisitService->setStudyName($studyName);
+ if (!$this->authorizationVisitService->isVisitAllowed($role)) throw new GaelOForbiddenException();
+ }
+}
diff --git a/GaelO2/app/GaelO/UseCases/GetFileOfVisit/GetFileOfVisitRequest.php b/GaelO2/app/GaelO/UseCases/GetFileOfVisit/GetFileOfVisitRequest.php
new file mode 100644
index 000000000..17c890486
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/GetFileOfVisit/GetFileOfVisitRequest.php
@@ -0,0 +1,12 @@
+authorizationStudyService = $authorizationStudyService;
+ $this->visitTypeRepository = $visitTypeRepository;
+ }
+
+ public function execute(GetFilesMetadataFromVisitTypeRequest $getFilesMetadataFromVisitTypeRequest, GetFilesMetadataFromVisitTypeResponse $getFilesMetadataFromVisitTypeResponse)
+ {
+ try {
+
+ $studyName = $getFilesMetadataFromVisitTypeRequest->studyName;
+
+ $this->checkAuthorization($getFilesMetadataFromVisitTypeRequest->currentUserId, $studyName);
+
+ $visitTypeEntity = $this->visitTypeRepository->find($getFilesMetadataFromVisitTypeRequest->visitTypeId, true);
+ $originalStudyName = $visitTypeEntity['visit_group']['study_name'];
+ $visitGroupEntity = $visitTypeEntity['visit_group'];
+
+ //Check that the requested study name is an original or ancillary study of this visit type
+ if (!AuthorizationStudyService::isOriginalOrAncillaryStudyOf($studyName, $originalStudyName)) {
+ throw new GaelOForbiddenException('Forbidden acces to this Visit Type');
+ }
+
+ $visitFiles = [];
+
+ try {
+ $studyRule = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $visitRules = $studyRule->getSpecificVisitRules($visitGroupEntity['name'], $visitTypeEntity['name']);
+ $visitFiles = $visitRules->getAssociatedFilesVisit();
+ } catch (GaelOException $e) {}
+
+ $getFilesMetadataFromVisitTypeResponse->body = $visitFiles;
+ $getFilesMetadataFromVisitTypeResponse->status = 200;
+ $getFilesMetadataFromVisitTypeResponse->statusText = 'OK';
+ } catch (AbstractGaelOException $e) {
+ $getFilesMetadataFromVisitTypeResponse->body = $e->getErrorBody();
+ $getFilesMetadataFromVisitTypeResponse->status = $e->statusCode;
+ $getFilesMetadataFromVisitTypeResponse->statusText = $e->statusText;
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ private function checkAuthorization(int $userId, string $studyName)
+ {
+ $this->authorizationStudyService->setUserId($userId);
+ $this->authorizationStudyService->setStudyName($studyName);
+ if (!$this->authorizationStudyService->isAllowedStudy(Constants::ROLE_SUPERVISOR)) {
+ throw new GaelOForbiddenException();
+ }
+ }
+}
diff --git a/GaelO2/app/GaelO/UseCases/GetFilesMetadataFromVisitType/GetFilesMetadataFromVisitTypeRequest.php b/GaelO2/app/GaelO/UseCases/GetFilesMetadataFromVisitType/GetFilesMetadataFromVisitTypeRequest.php
new file mode 100644
index 000000000..117ad748f
--- /dev/null
+++ b/GaelO2/app/GaelO/UseCases/GetFilesMetadataFromVisitType/GetFilesMetadataFromVisitTypeRequest.php
@@ -0,0 +1,11 @@
+setMainCenter(CenterEntity::fillFromDBReponseArray($data['main_center']));
}
$userEntity->addRoles($data['roles']);
$responseArray[] = $userEntity;
diff --git a/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatients.php b/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatients.php
index 44aa568aa..ad19b95e7 100644
--- a/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatients.php
+++ b/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatients.php
@@ -44,8 +44,10 @@ public function execute(ImportPatientsRequest $importPatientsRequest, ImportPati
$studyName = $importPatientsRequest->studyName;
$currentUserId = $importPatientsRequest->currentUserId;
$patients = $importPatientsRequest->patients;
+ $role = $importPatientsRequest->role;
+
+ $this->checkAuthorization($currentUserId, $studyName, $role);
- $this->checkAuthorization($currentUserId, $studyName);
$arrayPatients = [];
foreach ($patients as $patient) {
@@ -83,14 +85,20 @@ public function execute(ImportPatientsRequest $importPatientsRequest, ImportPati
}
}
- private function checkAuthorization(int $userId, string $studyName)
+ private function checkAuthorization(int $userId, string $studyName, string $role)
{
$this->authorizationStudyService->setUserId($userId);
$this->authorizationStudyService->setStudyName($studyName);
if ($this->authorizationStudyService->getStudyEntity()->isAncillaryStudy()) {
throw new GaelOForbiddenException("Forbidden for ancillary studies");
}
- if (!$this->authorizationStudyService->isAllowedStudy(Constants::ROLE_SUPERVISOR)) {
+ if (!in_array($role, [Constants::ROLE_INVESTIGATOR, Constants::ROLE_SUPERVISOR])) {
+ throw new GaelOForbiddenException("Role forbidden");
+ }
+ if ($role === Constants::ROLE_INVESTIGATOR && !$this->authorizationStudyService->getStudyEntity()->creatablePatientsInvestigator) {
+ throw new GaelOForbiddenException("Patient creation disallowed for investigator");
+ }
+ if (!$this->authorizationStudyService->isAllowedStudy($role)) {
throw new GaelOForbiddenException();
}
}
diff --git a/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatientsRequest.php b/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatientsRequest.php
index 97e41237e..0dbbf42b9 100644
--- a/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatientsRequest.php
+++ b/GaelO2/app/GaelO/UseCases/ImportPatients/ImportPatientsRequest.php
@@ -7,4 +7,5 @@ class ImportPatientsRequest
public int $currentUserId;
public array $patients;
public string $studyName;
+ public string $role;
}
diff --git a/GaelO2/app/GaelO/UseCases/ModifyCorrectiveAction/ModifyCorrectiveAction.php b/GaelO2/app/GaelO/UseCases/ModifyCorrectiveAction/ModifyCorrectiveAction.php
index 58181ca3b..4dbdcf917 100644
--- a/GaelO2/app/GaelO/UseCases/ModifyCorrectiveAction/ModifyCorrectiveAction.php
+++ b/GaelO2/app/GaelO/UseCases/ModifyCorrectiveAction/ModifyCorrectiveAction.php
@@ -11,6 +11,8 @@
use App\GaelO\Interfaces\Repositories\TrackerRepositoryInterface;
use App\GaelO\Interfaces\Repositories\VisitRepositoryInterface;
use App\GaelO\Services\AuthorizationService\AuthorizationVisitService;
+use App\GaelO\Services\GaelOStudiesService\AbstractGaelOStudy;
+use App\GaelO\Services\GaelOStudiesService\Events\CorrectiveActionEvent;
use App\GaelO\Services\MailServices;
use Exception;
@@ -38,7 +40,6 @@ public function execute(ModifyCorrectiveActionRequest $modifyCorrectiveActionReq
$studyName = $visitContext['patient']['study_name'];
$patientId = $visitContext['patient']['id'];
- $patientCode = $visitContext['patient']['code'];
$visitType = $visitContext['visit_type']['name'];
$visitGroupName = $visitContext['visit_type']['visit_group']['name'];
$visitModality = $visitContext['visit_type']['visit_group']['modality'];
@@ -92,17 +93,12 @@ public function execute(ModifyCorrectiveActionRequest $modifyCorrectiveActionReq
$actionDetails
);
- //Send Email
- $this->mailServices->sendCorrectiveActionMessage(
- $modifyCorrectiveActionRequest->visitId,
- $modifyCorrectiveActionRequest->currentUserId,
- $studyName,
- $modifyCorrectiveActionRequest->correctiveActionDone,
- $patientId,
- $patientCode,
- $visitModality,
- $visitType
- );
+ $qcModifiedEvent = new CorrectiveActionEvent($visitContext);
+ $qcModifiedEvent->setCurrentUserId($modifyCorrectiveActionRequest->currentUserId);
+ $qcModifiedEvent->setCorrrectiveActionDone($modifyCorrectiveActionRequest->correctiveActionDone);
+
+ $studyObject = AbstractGaelOStudy::getSpecificStudyObject($studyName);
+ $studyObject->onEventStudy($qcModifiedEvent);
$modifyCorrectiveActionResponse->status = 200;
$modifyCorrectiveActionResponse->statusText = 'OK';
diff --git a/GaelO2/app/GaelO/UseCases/ModifyQualityControl/ModifyQualityControl.php b/GaelO2/app/GaelO/UseCases/ModifyQualityControl/ModifyQualityControl.php
index 1a837a60a..f2926c872 100644
--- a/GaelO2/app/GaelO/UseCases/ModifyQualityControl/ModifyQualityControl.php
+++ b/GaelO2/app/GaelO/UseCases/ModifyQualityControl/ModifyQualityControl.php
@@ -10,7 +10,6 @@
use App\GaelO\Exceptions\GaelOForbiddenException;
use App\GaelO\Interfaces\Repositories\TrackerRepositoryInterface;
use App\GaelO\Services\AuthorizationService\AuthorizationVisitService;
-use App\GaelO\Services\MailServices;
use App\GaelO\Services\VisitService;
use Exception;
@@ -20,14 +19,12 @@ class ModifyQualityControl
private AuthorizationVisitService $authorizationVisitService;
private VisitService $visitService;
private TrackerRepositoryInterface $trackerRepositoryInterface;
- private MailServices $mailServices;
- public function __construct(AuthorizationVisitService $authorizationVisitService, VisitService $visitService, TrackerRepositoryInterface $trackerRepositoryInterface, MailServices $mailServices)
+ public function __construct(AuthorizationVisitService $authorizationVisitService, VisitService $visitService, TrackerRepositoryInterface $trackerRepositoryInterface)
{
$this->authorizationVisitService = $authorizationVisitService;
$this->visitService = $visitService;
$this->trackerRepositoryInterface = $trackerRepositoryInterface;
- $this->mailServices = $mailServices;
}
public function execute(ModifyQualityControlRequest $modifyQualityControlRequest, ModifyQualityControlResponse $modifyQualityControlResponse)
@@ -39,19 +36,17 @@ public function execute(ModifyQualityControlRequest $modifyQualityControlRequest
$currentUserId = $modifyQualityControlRequest->currentUserId;
$this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($currentUserId);
$visitContext = $this->visitService->getVisitContext();
$studyName = $visitContext['patient']['study_name'];
$patientId = $visitContext['patient']['id'];
- $patientCode = $visitContext['patient']['code'];
$visitType = $visitContext['visit_type']['name'];
$visitGroupName = $visitContext['visit_type']['visit_group']['name'];
$visitModality = $visitContext['visit_type']['visit_group']['modality'];
- $centerCode = $visitContext['patient']['center_code'];
- $creatorId = $visitContext['creator_user_id'];
$localFormNeeded = $visitContext['state_investigator_form'] !== InvestigatorFormStateEnum::NOT_NEEDED->value;
- if($modifyQualityControlRequest->studyName !== $studyName){
+ if ($modifyQualityControlRequest->studyName !== $studyName) {
throw new GaelOForbiddenException("Should be called from original study");
}
@@ -105,23 +100,6 @@ public function execute(ModifyQualityControlRequest $modifyQualityControlRequest
$actionDetails
);
- $this->mailServices->sendQcDecisionMessage(
- $visitId,
- $creatorId,
- $currentUserId,
- $studyName,
- $centerCode,
- $modifyQualityControlRequest->stateQc,
- $patientId,
- $patientCode,
- $visitModality,
- $visitType,
- $modifyQualityControlRequest->formQc ? 'Accepted ' : 'Refused',
- $modifyQualityControlRequest->imageQc ? 'Accepted ' : 'Refused',
- $modifyQualityControlRequest->formQcComment ?? 'None',
- $modifyQualityControlRequest->imageQcComment ?? 'None'
- );
-
$modifyQualityControlResponse->status = 200;
$modifyQualityControlResponse->statusText = 'OK';
} catch (AbstractGaelOException $e) {
diff --git a/GaelO2/app/GaelO/UseCases/ModifyQualityControlReset/ModifyQualityControlReset.php b/GaelO2/app/GaelO/UseCases/ModifyQualityControlReset/ModifyQualityControlReset.php
index df6397625..3ec19c604 100644
--- a/GaelO2/app/GaelO/UseCases/ModifyQualityControlReset/ModifyQualityControlReset.php
+++ b/GaelO2/app/GaelO/UseCases/ModifyQualityControlReset/ModifyQualityControlReset.php
@@ -36,6 +36,7 @@ public function execute(ModifyQualityControlResetRequest $modifyQualityControlRe
$currentUserId = $modifyQualityControlResetRequest->currentUserId;
$this->visitService->setVisitId($visitId);
+ $this->visitService->setCurrentUserId($currentUserId);
$visitContext = $this->visitService->getVisitContext();
$studyName = $visitContext['patient']['study_name'];
diff --git a/GaelO2/app/GaelO/UseCases/ReactivateDicomSeries/ReactivateDicomSeriesRequest.php b/GaelO2/app/GaelO/UseCases/ReactivateDicomSeries/ReactivateDicomSeriesRequest.php
index 37cc1c66e..53fe559ca 100644
--- a/GaelO2/app/GaelO/UseCases/ReactivateDicomSeries/ReactivateDicomSeriesRequest.php
+++ b/GaelO2/app/GaelO/UseCases/ReactivateDicomSeries/ReactivateDicomSeriesRequest.php
@@ -8,4 +8,5 @@ class ReactivateDicomSeriesRequest
public string $seriesInstanceUID;
public string $reason;
public string $role;
+ public string $studyName;
}
diff --git a/GaelO2/app/GaelO/UseCases/ReactivateDicomStudy/ReactivateDicomStudy.php b/GaelO2/app/GaelO/UseCases/ReactivateDicomStudy/ReactivateDicomStudy.php
index 6f987440a..490b502ea 100644
--- a/GaelO2/app/GaelO/UseCases/ReactivateDicomStudy/ReactivateDicomStudy.php
+++ b/GaelO2/app/GaelO/UseCases/ReactivateDicomStudy/ReactivateDicomStudy.php
@@ -56,6 +56,7 @@ public function execute(ReactivateDicomStudyRequest $reactivateDicomStudyRequest
$this->checkAuthorization($currentUserId, $visitId, $studyName, $visitContext);
//Change dicom study Activation
+ $this->dicomService->setCurrentUserId($currentUserId);
$this->dicomService->reactivateDicomStudy($studyData['study_uid']);
//Tracker
diff --git a/GaelO2/app/GaelO/UseCases/ReverseProxyDicomWeb/ReverseProxyDicomWeb.php b/GaelO2/app/GaelO/UseCases/ReverseProxyDicomWeb/ReverseProxyDicomWeb.php
index bda479cdd..00cf746f9 100644
--- a/GaelO2/app/GaelO/UseCases/ReverseProxyDicomWeb/ReverseProxyDicomWeb.php
+++ b/GaelO2/app/GaelO/UseCases/ReverseProxyDicomWeb/ReverseProxyDicomWeb.php
@@ -60,7 +60,7 @@ public function execute(ReverseProxyDicomWebRequest $reverseProxyDicomWebRequest
$headers['Forwarded'] = [$forwardedRule];
- $response = $this->httpClientInterface->rowRequest('GET', $calledUrl, null, $headers);
+ $response = $this->httpClientInterface->rawRequest('GET', $calledUrl, null, $headers);
$responseHeaders = $response->getHeaders();
$responseHeaders['Cross-Origin-Embedder-Policy'] = ['require-corp'];
diff --git a/GaelO2/app/GaelO/UseCases/ReverseProxyTus/ReverseProxyTus.php b/GaelO2/app/GaelO/UseCases/ReverseProxyTus/ReverseProxyTus.php
index c54b60d95..a56db4b01 100644
--- a/GaelO2/app/GaelO/UseCases/ReverseProxyTus/ReverseProxyTus.php
+++ b/GaelO2/app/GaelO/UseCases/ReverseProxyTus/ReverseProxyTus.php
@@ -35,7 +35,7 @@ public function execute(ReverseProxyTusRequest $reverseProxyTusRequest, ReverseP
//Make query of TUS
$this->httpClientInterface->setUrl($this->frameworkInterface::getConfig(SettingsConstants::TUS_URL));
- $response = $this->httpClientInterface->rowRequest($reverseProxyTusRequest->method, $reverseProxyTusRequest->url, $reverseProxyTusRequest->body, $headers, null, false);
+ $response = $this->httpClientInterface->rawRequest($reverseProxyTusRequest->method, $reverseProxyTusRequest->url, $reverseProxyTusRequest->body, $headers, null, false);
//Output response
$reverseProxyTusResponse->status = $response->getStatusCode();
diff --git a/GaelO2/app/GaelO/UseCases/ValidateDicomUpload/ValidateDicomUpload.php b/GaelO2/app/GaelO/UseCases/ValidateDicomUpload/ValidateDicomUpload.php
index ce945f88f..9cd32bccc 100644
--- a/GaelO2/app/GaelO/UseCases/ValidateDicomUpload/ValidateDicomUpload.php
+++ b/GaelO2/app/GaelO/UseCases/ValidateDicomUpload/ValidateDicomUpload.php
@@ -31,6 +31,7 @@ class ValidateDicomUpload
private PatientRepositoryInterface $patientRepositoryInterface;
private TrackerRepositoryInterface $trackerRepositoryInterface;
private MailServices $mailServices;
+ private bool $markedProcessing = false;
public function __construct(
AuthorizationVisitService $authorizationService,
@@ -75,15 +76,16 @@ public function execute(ValidateDicomUploadRequest $validateDicomUploadRequest,
$originalOrthancId = $validateDicomUploadRequest->originalOrthancId;
$this->checkAuthorization($currentUserId, $visitId, $studyName, $visitContext);
-
+ $this->visitService->setCurrentUserId($currentUserId);
+
//Make Visit as being upload processing
$this->visitService->updateUploadStatus(UploadStatusEnum::PROCESSING->value);
+ $this->markedProcessing = true;
//Set Time Limit at 30min as operation could be really long
set_time_limit(1800);
//Create Temporary folder to work
$unzipedPath = Util::getUploadTemporaryFolder();
-
//Get uploaded Zips from TUS and upzip it in a temporary folder
foreach ($validateDicomUploadRequest->uploadedFileTusId as $tusFileId) {
$tusTempZip = $this->tusService->getFile($tusFileId);
@@ -111,7 +113,7 @@ public function execute(ValidateDicomUploadRequest $validateDicomUploadRequest,
if ($expectedNumberOfInstances !== $importedNumberOfInstances) {
$this->orthancService->deleteFromOrthanc("studies", $importedOrthancStudyID);
- throw new GaelOValidateDicomException("Imported DICOM (".$importedNumberOfInstances.") not matching announced number of Instances (".$expectedNumberOfInstances.")");
+ throw new GaelOValidateDicomException("Imported DICOM (" . $importedNumberOfInstances . ") not matching announced number of Instances (" . $expectedNumberOfInstances . ")");
}
//Anonymize and store new anonymized study Orthanc ID
@@ -154,6 +156,7 @@ public function execute(ValidateDicomUploadRequest $validateDicomUploadRequest,
//Change Visit status
$this->visitService->updateUploadStatus(UploadStatusEnum::DONE->value);
+ $this->markedProcessing = false;
//Write success in Tracker
$actionDetails = [
@@ -223,7 +226,10 @@ private function checkAuthorization(int $currentUserId, int $visitId, string $st
private function handleImportException(string $errorMessage, int $visitId, string $patientId, string $visitType, ?string $unzipedPath, string $studyName, int $userId)
{
- $this->visitService->updateUploadStatus(UploadStatusEnum::NOT_DONE->value);
+ //Restore upload not done status if it has been updated to processing status
+ if ($this->markedProcessing) {
+ $this->visitService->updateUploadStatus(UploadStatusEnum::NOT_DONE->value);
+ }
$actionDetails = [
'reason' => $errorMessage
diff --git a/GaelO2/app/GaelO/Util.php b/GaelO2/app/GaelO/Util.php
index e918c4eeb..f33d287ae 100644
--- a/GaelO2/app/GaelO/Util.php
+++ b/GaelO2/app/GaelO/Util.php
@@ -13,7 +13,7 @@
class Util
{
- public static function fillObject(array $dataToExtract, object $dataToFill)
+ public static function fillObject(array $dataToExtract, object $dataToFill) :void
{
//Get Expected properties awaited in DTO Request
$reflect = new ReflectionClass($dataToFill);
@@ -24,7 +24,6 @@ public static function fillObject(array $dataToExtract, object $dataToFill)
$propertyName = $property->getName();
if (array_key_exists($propertyName, $dataToExtract)) $dataToFill->$propertyName = $dataToExtract[$propertyName];
}
- return $dataToFill;
}
public static function endsWith(string $haystack, string $needle): bool
diff --git a/GaelO2/app/GaelO/views/mails/mail_job_failure.blade.php b/GaelO2/app/GaelO/views/mails/mail_job_failure.blade.php
new file mode 100644
index 000000000..2389c4577
--- /dev/null
+++ b/GaelO2/app/GaelO/views/mails/mail_job_failure.blade.php
@@ -0,0 +1,9 @@
+@extends('mails.mail_template')
+
+@section('content')
+ A Job Failure occured in the job {{$jobType}}
+ Error Message : {{$errorMessage}}
+ @foreach($details as $key => $value)
+ {{ $key }} : {{ $value }}
+ @endforeach
+@endsection
diff --git a/GaelO2/app/GaelO/views/mails/mail_radiomics_report.blade.php b/GaelO2/app/GaelO/views/mails/mail_radiomics_report.blade.php
new file mode 100644
index 000000000..09326dcbf
--- /dev/null
+++ b/GaelO2/app/GaelO/views/mails/mail_radiomics_report.blade.php
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lymphoma Radiomics Report
+
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Visit {{$visitType}} of the patient {{$patientCode}} from the {{$studyName}}.
+ |
+
+
+
+ Visit Date: {{$visitDate}}
+ |
+
+
+
+
+
+ |
+
+
+
+
+ @if(!empty($message))
+
+
+
+
+
+
+ @foreach($image_path as $path)
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+ @endforeach
+
+ |
+
+
+
+
+ @endif
+
+
+
+
+
+
+
+
+
+
+
+
+ @foreach($stats as $key => $value)
+ {{ $key }} |
+ {{ $value }} |
+ @endforeach
+ |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GaelO2/app/GaelO/views/mails/mjml/radiomics_report.mjml b/GaelO2/app/GaelO/views/mails/mjml/radiomics_report.mjml
new file mode 100644
index 000000000..f8f6a0230
--- /dev/null
+++ b/GaelO2/app/GaelO/views/mails/mjml/radiomics_report.mjml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Lymphoma Radiomics Report
+
+
+
+
+
+
+ Visit {{$visitType}} of the patient {{$patientCode}} from the {{$studyName}}.
+
+ Visit Date: {{$visitDate}}
+
+
+
+
+ @if(!empty($message))
+
+
+
+ @foreach($image_path as $path)
+
+
+
+
+
+ @endforeach
+
+
+
+ @endif
+
+
+
+
+ @foreach($stats as $key => $value)
+
+ {{ $key }} |
+ {{ $value }} |
+
+ @endforeach
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GaelO2/app/Http/Controllers/AskUnlockController.php b/GaelO2/app/Http/Controllers/AskUnlockController.php
index 1a2dd57ee..f00068f8d 100644
--- a/GaelO2/app/Http/Controllers/AskUnlockController.php
+++ b/GaelO2/app/Http/Controllers/AskUnlockController.php
@@ -17,7 +17,7 @@ public function askUnlock(Request $request, RequestUnlock $requestUnlock, Reques
$queryParam = $request->query();
$requestData = $request->all();
- $requestUnlockRequest = Util::fillObject($requestData, $requestUnlockRequest);
+ Util::fillObject($requestData, $requestUnlockRequest);
$requestUnlockRequest->studyName = $queryParam['studyName'];
$requestUnlockRequest->currentUserId = $currentUser['id'];
diff --git a/GaelO2/app/Http/Controllers/AuthController.php b/GaelO2/app/Http/Controllers/AuthController.php
index 2f4e06b85..91a771f00 100644
--- a/GaelO2/app/Http/Controllers/AuthController.php
+++ b/GaelO2/app/Http/Controllers/AuthController.php
@@ -23,14 +23,14 @@ public function login(Request $request, Login $login, LoginRequest $loginRequest
{
$requestData = $request->all();
- $loginRequest = Util::fillObject($requestData, $loginRequest);
+ Util::fillObject($requestData, $loginRequest);
$loginRequest->ip = $request->ip();
$login->execute($loginRequest, $loginResponse);
if ($loginResponse->status === 200) {
- $user = User::where('email', $request->email)->sole();
+ $user = User::where('email', strtolower($request->email))->sole();
$tokenResult = $user->createToken('GaelO');
return response()->json([
@@ -73,11 +73,10 @@ public function createMagicLink(Request $request, CreateMagicLink $createMagicLi
$currentUser = $request->user();
$requestData = $request->all();
+ Util::fillObject($requestData, $createMagicLinkRequest);
$createMagicLinkRequest->targetUser = $userId;
$createMagicLinkRequest->currentUserId = $currentUser['id'];
- $createMagicLinkRequest = Util::fillObject($requestData, $createMagicLinkRequest);
-
$createMagicLink->execute($createMagicLinkRequest, $createMagicLinkResponse);
return $this->getJsonResponse($createMagicLinkResponse->body, $createMagicLinkResponse->status, $createMagicLinkResponse->statusText);
diff --git a/GaelO2/app/Http/Controllers/CenterController.php b/GaelO2/app/Http/Controllers/CenterController.php
index 5762a5931..c74d8a984 100644
--- a/GaelO2/app/Http/Controllers/CenterController.php
+++ b/GaelO2/app/Http/Controllers/CenterController.php
@@ -27,10 +27,10 @@ class CenterController extends Controller
public function getCenter(Request $request, GetCenterRequest $getCenterRequest, GetCenterResponse $getCenterResponse, GetCenter $getCenter, ?int $code = null)
{
$currentUser = Auth::user();
+ $requestData = $request->all();
+ Util::fillObject($requestData, $getCenterRequest);
$getCenterRequest->currentUserId = $currentUser['id'];
$getCenterRequest->code = $code;
- $requestData = $request->all();
- $getCenterRequest = Util::fillObject($requestData, $getCenterRequest);
$getCenter->execute($getCenterRequest, $getCenterResponse);
return $this->getJsonResponse($getCenterResponse->body, $getCenterResponse->status, $getCenterResponse->statusText);
}
@@ -38,11 +38,12 @@ public function getCenter(Request $request, GetCenterRequest $getCenterRequest,
public function modifyCenter(Request $request, ModifyCenterRequest $modifyCenterRequest, ModifyCenterResponse $modifyCenterResponse, ModifyCenter $modifyCenter, int $code)
{
$currentUser = Auth::user();
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $modifyCenterRequest);
$modifyCenterRequest->currentUserId = $currentUser['id'];
$modifyCenterRequest->code = $code;
- $requestData = $request->all();
- $modifyCenterRequest = Util::fillObject($requestData, $modifyCenterRequest);
$modifyCenter->execute($modifyCenterRequest, $modifyCenterResponse);
return $this->getJsonResponse($modifyCenterResponse->body, $modifyCenterResponse->status, $modifyCenterResponse->statusText);
}
@@ -54,7 +55,7 @@ public function createCenter(Request $request, CreateCenter $createCenter, Creat
$createCenterRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
- $createCenterRequest = Util::fillObject($requestData, $createCenterRequest);
+ Util::fillObject($requestData, $createCenterRequest);
$createCenter->execute($createCenterRequest, $createCenterResponse);
return $this->getJsonResponse($createCenterResponse->body, $createCenterResponse->status, $createCenterResponse->statusText);
diff --git a/GaelO2/app/Http/Controllers/DicomController.php b/GaelO2/app/Http/Controllers/DicomController.php
index 105893185..e5263151e 100644
--- a/GaelO2/app/Http/Controllers/DicomController.php
+++ b/GaelO2/app/Http/Controllers/DicomController.php
@@ -70,11 +70,11 @@ public function deleteSeries(Request $request, DeleteSeries $deleteSeries, Delet
$queryParam = $request->query();
$requestData = $request->all();
+ Util::fillObject($requestData, $deleteSeriesRequest);
$deleteSeriesRequest->seriesInstanceUID = $seriesInstanceUID;
$deleteSeriesRequest->role = $queryParam['role'];
$deleteSeriesRequest->studyName = $queryParam['studyName'];
$deleteSeriesRequest->currentUserId = $currentUser['id'];
- $deleteSeriesRequest = Util::fillObject($requestData, $deleteSeriesRequest);
$deleteSeries->execute($deleteSeriesRequest, $deleteSeriesResponse);
@@ -87,11 +87,11 @@ public function reactivateSeries(Request $request, ReactivateDicomSeries $reacti
$requestData = $request->all();
$queryParam = $request->query();
+ Util::fillObject($requestData, $reactivateDicomSeriesRequest);
$reactivateDicomSeriesRequest->studyName = $queryParam['studyName'];
$reactivateDicomSeriesRequest->seriesInstanceUID = $seriesInstanceUID;
$reactivateDicomSeriesRequest->currentUserId = $currentUser['id'];
$reactivateDicomSeriesRequest->role = $queryParam['role'];
- $reactivateDicomSeriesRequest = Util::fillObject($requestData, $reactivateDicomSeriesRequest);
$reactivateDicomSeries->execute($reactivateDicomSeriesRequest, $reactivateDicomSeriesResponse);
@@ -105,10 +105,10 @@ public function reactivateStudy(Request $request, ReactivateDicomStudy $reactiva
$requestData = $request->all();
$queryParam = $request->query();
+ Util::fillObject($requestData, $reactivateDicomStudyRequest);
$reactivateDicomStudyRequest->studyName = $queryParam['studyName'];
$reactivateDicomStudyRequest->studyInstanceUID = $studyInstanceUID;
$reactivateDicomStudyRequest->currentUserId = $currentUser['id'];
- $reactivateDicomStudyRequest = Util::fillObject($requestData, $reactivateDicomStudyRequest);
$reactivateDicomStudy->execute($reactivateDicomStudyRequest, $reactivateDicomStudyResponse);
@@ -120,9 +120,9 @@ public function getSupervisorDicomsFile(Request $request, GetDicomsFileSuperviso
$currentUser = Auth::user();
$requestData = $request->all();
+ Util::fillObject($requestData, $getDicomsFileSupervisorRequest);
$getDicomsFileSupervisorRequest->currentUserId = $currentUser['id'];
$getDicomsFileSupervisorRequest->studyName = $studyName;
- $getDicomsFileSupervisorRequest = Util::fillObject($requestData, $getDicomsFileSupervisorRequest);
$getDicomsFileSupervisor->execute($getDicomsFileSupervisorRequest, $getDicomsFileSupervisorResponse);
diff --git a/GaelO2/app/Http/Controllers/DocumentationController.php b/GaelO2/app/Http/Controllers/DocumentationController.php
index 2ef5bc831..1865ab4db 100644
--- a/GaelO2/app/Http/Controllers/DocumentationController.php
+++ b/GaelO2/app/Http/Controllers/DocumentationController.php
@@ -36,10 +36,12 @@ public function createDocumentation(Request $request, CreateDocumentation $creat
{
$currentUser = Auth::user();
$requestData = $request->all();
- $createDocumentationRequest = Util::fillObject($requestData, $createDocumentationRequest);
+
+ Util::fillObject($requestData, $createDocumentationRequest);
$createDocumentationRequest->currentUserId = $currentUser['id'];
$createDocumentationRequest->studyName = $studyName;
$createDocumentation->execute($createDocumentationRequest, $createDocumentationResponse);
+
return $this->getJsonResponse($createDocumentationResponse->body, $createDocumentationResponse->status, $createDocumentationResponse->statusText);
}
@@ -95,10 +97,12 @@ public function modifyDocumentation(Request $request, ModifyDocumentation $modif
{
$currentUser = Auth::user();
$requestData = $request->all();
- $modifyDocumentationRequest = Util::fillObject($requestData, $modifyDocumentationRequest);
+
+ Util::fillObject($requestData, $modifyDocumentationRequest);
$modifyDocumentationRequest->id = $documentationId;
$modifyDocumentationRequest->currentUserId = $currentUser['id'];
$modifyDocumentation->execute($modifyDocumentationRequest, $modifyDocumentationResponse);
+
return $this->getJsonResponse($modifyDocumentationResponse->body, $modifyDocumentationResponse->status, $modifyDocumentationResponse->statusText);
}
diff --git a/GaelO2/app/Http/Controllers/ExportDBController.php b/GaelO2/app/Http/Controllers/ExportDBController.php
index c6eb34cbf..c58cae518 100644
--- a/GaelO2/app/Http/Controllers/ExportDBController.php
+++ b/GaelO2/app/Http/Controllers/ExportDBController.php
@@ -13,9 +13,11 @@ class ExportDBController extends Controller
{
public function exportDB(Request $request, ExportDatabase $exportDatabase, ExportDatabaseRequest $exportDatabaseRequest, ExportDatabaseResponse $exportDatabaseResponse) {
$currentUser = Auth::user();
- $exportDatabaseRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
- $exportDatabaseRequest = Util::fillObject($requestData, $exportDatabaseRequest);
+
+ Util::fillObject($requestData, $exportDatabaseRequest);
+ $exportDatabaseRequest->currentUserId = $currentUser['id'];
+
$exportDatabase->execute($exportDatabaseRequest, $exportDatabaseResponse);
if($exportDatabaseResponse->status === 200){
return response()->download($exportDatabaseResponse->zipFile, $exportDatabaseResponse->fileName,
diff --git a/GaelO2/app/Http/Controllers/PatientController.php b/GaelO2/app/Http/Controllers/PatientController.php
index daaf180d6..2d472db39 100644
--- a/GaelO2/app/Http/Controllers/PatientController.php
+++ b/GaelO2/app/Http/Controllers/PatientController.php
@@ -61,10 +61,11 @@ public function modifyPatient(Request $request, ModifyPatient $modifyPatient, Mo
$requestData = $request->all();
$queryParam = $request->query();
- $modifyPatientRequest = Util::fillObject($requestData, $modifyPatientRequest);
+ Util::fillObject($requestData, $modifyPatientRequest);
$modifyPatientRequest->studyName = $queryParam['studyName'];
$modifyPatientRequest->patientId = $patientId;
$modifyPatientRequest->currentUserId = $currentUser['id'];
+
$modifyPatient->execute($modifyPatientRequest, $modifyPatientResponse);
return $this->getJsonResponse($modifyPatientResponse->body, $modifyPatientResponse->status, $modifyPatientResponse->statusText);
@@ -89,7 +90,8 @@ public function addPatientTags(Request $request, CreatePatientTags $createPatien
$currentUser = Auth::user();
$requestData = $request->all();
$queryParam = $request->query();
- $createPatientTagsRequest = Util::fillObject($requestData, $createPatientTagsRequest);
+
+ Util::fillObject($requestData, $createPatientTagsRequest);
$createPatientTagsRequest->studyName = $queryParam['studyName'];
$createPatientTagsRequest->patientId = $patientId;
$createPatientTagsRequest->currentUserId = $currentUser['id'];
diff --git a/GaelO2/app/Http/Controllers/RequestController.php b/GaelO2/app/Http/Controllers/RequestController.php
index 93917953f..f8cf6dea2 100644
--- a/GaelO2/app/Http/Controllers/RequestController.php
+++ b/GaelO2/app/Http/Controllers/RequestController.php
@@ -14,7 +14,7 @@ class RequestController extends Controller
public function sendRequest(Request $request, RequestRequest $requestRequest, RequestResponse $requestResponse, SendRequest $sendRequest)
{
$requestData = $request->all();
- $requestRequest = Util::fillObject($requestData, $requestRequest);
+ Util::fillObject($requestData, $requestRequest);
$sendRequest->execute($requestRequest, $requestResponse);
return $this->getJsonResponse($requestResponse->body, $requestResponse->status, $requestResponse->statusText);
}
diff --git a/GaelO2/app/Http/Controllers/ReviewController.php b/GaelO2/app/Http/Controllers/ReviewController.php
index 63fccc940..e3594384a 100644
--- a/GaelO2/app/Http/Controllers/ReviewController.php
+++ b/GaelO2/app/Http/Controllers/ReviewController.php
@@ -5,6 +5,9 @@
use App\GaelO\UseCases\CreateFileToForm\CreateFileToForm;
use App\GaelO\UseCases\CreateFileToForm\CreateFileToFormRequest;
use App\GaelO\UseCases\CreateFileToForm\CreateFileToFormResponse;
+use App\GaelO\UseCases\CreateFileToFormFromTus\CreateFileToFormFromTus;
+use App\GaelO\UseCases\CreateFileToFormFromTus\CreateFileToFormFromTusRequest;
+use App\GaelO\UseCases\CreateFileToFormFromTus\CreateFileToFormFromTusResponse;
use App\GaelO\UseCases\CreateInvestigatorForm\CreateInvestigatorForm;
use App\GaelO\UseCases\CreateInvestigatorForm\CreateInvestigatorFormRequest;
use App\GaelO\UseCases\CreateInvestigatorForm\CreateInvestigatorFormResponse;
@@ -78,14 +81,13 @@ public function deleteInvestigatorForm(Request $request, DeleteInvestigatorForm
{
$currentUser = Auth::user();
$queryParam = $request->query();
+ $requestData = $request->all();
+ Util::fillObject($requestData, $deleteInvestigatorFormRequest);
$deleteInvestigatorFormRequest->currentUserId = $currentUser['id'];
$deleteInvestigatorFormRequest->studyName = $queryParam['studyName'];
$deleteInvestigatorFormRequest->visitId = $visitId;
- $requestData = $request->all();
- $deleteInvestigatorFormRequest = Util::fillObject($requestData, $deleteInvestigatorFormRequest);
-
$deleteInvestigatorForm->execute($deleteInvestigatorFormRequest, $deleteInvestigatorFormResponse);
return $this->getJsonResponse($deleteInvestigatorFormResponse->body, $deleteInvestigatorFormResponse->status, $deleteInvestigatorFormResponse->statusText);
@@ -95,14 +97,13 @@ public function unlockInvestigatorForm(Request $request, UnlockInvestigatorForm
{
$currentUser = Auth::user();
$queryParam = $request->query();
+ $requestData = $request->all();
+ Util::fillObject($requestData, $unlockInvestigatorFormRequest);
$unlockInvestigatorFormRequest->currentUserId = $currentUser['id'];
$unlockInvestigatorFormRequest->studyName = $queryParam['studyName'];
$unlockInvestigatorFormRequest->visitId = $visitId;
- $requestData = $request->all();
- $unlockInvestigatorFormRequest = Util::fillObject($requestData, $unlockInvestigatorFormRequest);
-
$unlockInvestigatorForm->execute($unlockInvestigatorFormRequest, $unlockInvestigatorFormResponse);
return $this->getJsonResponse($unlockInvestigatorFormResponse->body, $unlockInvestigatorFormResponse->status, $unlockInvestigatorFormResponse->statusText);
@@ -112,13 +113,12 @@ public function createInvestigatorForm(Request $request, CreateInvestigatorForm
{
$currentUser = Auth::user();
-
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $createInvestigatorFormRequest);
$createInvestigatorFormRequest->currentUserId = $currentUser['id'];
$createInvestigatorFormRequest->visitId = $visitId;
- $requestData = $request->all();
- $createInvestigatorFormRequest = Util::fillObject($requestData, $createInvestigatorFormRequest);
-
$createInvestigatorForm->execute($createInvestigatorFormRequest, $createInvestigatorFormResponse);
return $this->getJsonResponse($createInvestigatorFormResponse->body, $createInvestigatorFormResponse->status, $createInvestigatorFormResponse->statusText);
@@ -128,14 +128,13 @@ public function modifyInvestigatorForm(Request $request, ModifyInvestigatorForm
{
$currentUser = Auth::user();
+ $requestData = $request->all();
+ Util::fillObject($requestData, $modifyInvestigatorFormRequest);
$modifyInvestigatorFormRequest->currentUserId = $currentUser['id'];
$modifyInvestigatorFormRequest->visitId = $visitId;
- $requestData = $request->all();
- $deleteInvestigatorFormRequest = Util::fillObject($requestData, $modifyInvestigatorFormRequest);
-
- $modifyInvestigatorForm->execute($deleteInvestigatorFormRequest, $modifyInvestigatorFormResponse);
+ $modifyInvestigatorForm->execute($modifyInvestigatorFormRequest, $modifyInvestigatorFormResponse);
return $this->getJsonResponse($modifyInvestigatorFormResponse->body, $modifyInvestigatorFormResponse->status, $modifyInvestigatorFormResponse->statusText);
}
@@ -147,11 +146,10 @@ public function createReviewForm(Request $request, CreateReviewForm $createRevie
$queryParam = $request->query();
$createReviewFormRequest->studyName = $queryParam['studyName'];
+ Util::fillObject($requestData, $createReviewFormRequest);
$createReviewFormRequest->visitId = $visitId;
$createReviewFormRequest->currentUserId = $currentUser['id'];
- $createReviewFormRequest = Util::fillObject($requestData, $createReviewFormRequest);
-
$createReviewForm->execute($createReviewFormRequest, $createReviewFormResponse);
return $this->getJsonResponse($createReviewFormResponse->body, $createReviewFormResponse->status, $createReviewFormResponse->statusText);
@@ -163,9 +161,9 @@ public function modifyReviewForm(Request $request, ModifyReviewForm $modifyRevie
$currentUser = Auth::user();
$requestData = $request->all();
+ Util::fillObject($requestData, $modifyReviewFormRequest);
$modifyReviewFormRequest->reviewId = $reviewId;
$modifyReviewFormRequest->currentUserId = $currentUser['id'];
- $modifyReviewFormRequest = Util::fillObject($requestData, $modifyReviewFormRequest);
$modifyReviewForm->execute($modifyReviewFormRequest, $modifyReviewFormResponse);
@@ -205,11 +203,10 @@ public function deleteReviewForm(Request $request, DeleteReviewForm $deleteRevie
$currentUser = Auth::user();
$requestData = $request->all();
+ Util::fillObject($requestData, $deleteReviewFormRequest);
$deleteReviewFormRequest->currentUserId = $currentUser['id'];
$deleteReviewFormRequest->reviewId = $reviewId;
- $deleteReviewFormRequest = Util::fillObject($requestData, $deleteReviewFormRequest);
-
$deleteReviewForm->execute($deleteReviewFormRequest, $deleteReviewFormResponse);
return $this->getJsonResponse($deleteReviewFormResponse->body, $deleteReviewFormResponse->status, $deleteReviewFormResponse->statusText);
@@ -220,12 +217,11 @@ public function unlockReviewForm(Request $request, UnlockReviewForm $unlockRevie
$currentUser = Auth::user();
$requestData = $request->all();
+ Util::fillObject($requestData, $unlockReviewFormRequest);
$unlockReviewFormRequest->currentUserId = $currentUser['id'];
$unlockReviewFormRequest->reviewId = $reviewId;
- $deleteReviewFormRequest = Util::fillObject($requestData, $unlockReviewFormRequest);
-
- $unlockReviewForm->execute($deleteReviewFormRequest, $unlockReviewFormResponse);
+ $unlockReviewForm->execute($unlockReviewFormRequest, $unlockReviewFormResponse);
return $this->getJsonResponse($unlockReviewFormResponse->body, $unlockReviewFormResponse->status, $unlockReviewFormResponse->statusText);
}
@@ -247,6 +243,19 @@ public function createReviewFile(Request $request, CreateFileToForm $createFileT
return $this->getJsonResponse($createFileToFormResponse->body, $createFileToFormResponse->status, $createFileToFormResponse->statusText);
}
+ public function createReviewFileFromTus(Request $request, CreateFileToFormFromTus $createFileToFormFromTus, CreateFileToFormFromTusRequest $createFileToFormFromTusRequest, CreateFileToFormFromTusResponse $createFileToFormFromTusResponse)
+ {
+ $currentUser = Auth::user();
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $createFileToFormFromTusRequest);
+ $createFileToFormFromTusRequest->currentUserId = $currentUser['id'];
+
+ $createFileToFormFromTus->execute($createFileToFormFromTusRequest, $createFileToFormFromTusResponse);
+
+ return $this->getJsonResponse($createFileToFormFromTusResponse->body, $createFileToFormFromTusResponse->status, $createFileToFormFromTusResponse->statusText);
+ }
+
public function deleteReviewFile(DeleteFileOfForm $deleteFileOfForm, DeleteFileOfFormRequest $deleteFileOfFormRequest, DeleteFileOfFormResponse $deleteFileOfFormResponse, int $reviewId, string $key)
{
diff --git a/GaelO2/app/Http/Controllers/StudyController.php b/GaelO2/app/Http/Controllers/StudyController.php
index 9a66a5770..5429f96e6 100644
--- a/GaelO2/app/Http/Controllers/StudyController.php
+++ b/GaelO2/app/Http/Controllers/StudyController.php
@@ -11,6 +11,9 @@
use App\GaelO\UseCases\ExportStudyData\ExportStudyData;
use App\GaelO\UseCases\ExportStudyData\ExportStudyDataRequest;
use App\GaelO\UseCases\ExportStudyData\ExportStudyDataResponse;
+use App\GaelO\UseCases\GetCreatablePatients\GetCreatablePatients;
+use App\GaelO\UseCases\GetCreatablePatients\GetCreatablePatientsRequest;
+use App\GaelO\UseCases\GetCreatablePatients\GetCreatablePatientsResponse;
use App\GaelO\UseCases\GetDicomsStudiesFromStudy\GetDicomsStudiesFromStudy;
use App\GaelO\UseCases\GetDicomsStudiesFromStudy\GetDicomsStudiesFromStudyRequest;
use App\GaelO\UseCases\GetDicomsStudiesFromStudy\GetDicomsStudiesFromStudyResponse;
@@ -74,17 +77,16 @@
use App\GaelO\Util;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Log;
-
class StudyController extends Controller
{
public function createStudy(Request $request, CreateStudy $createStudy, CreateStudyRequest $createStudyRequest, CreateStudyResponse $createStudyResponse)
{
$currentUser = Auth::user();
- $createStudyRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
- $createStudyRequest = Util::fillObject($requestData, $createStudyRequest);
+
+ Util::fillObject($requestData, $createStudyRequest);
+ $createStudyRequest->currentUserId = $currentUser['id'];
$createStudy->execute($createStudyRequest, $createStudyResponse);
@@ -119,12 +121,11 @@ public function getStudyVisitTypes(GetStudyVisitTypes $getStudyVisitTypes, GetSt
public function deleteStudy(Request $request, DeleteStudy $deleteStudy, DeleteStudyRequest $deleteStudyRequest, DeleteStudyResponse $deleteStudyResponse, String $studyName)
{
$currentUser = Auth::user();
-
$requestData = $request->all();
+ Util::fillObject($requestData, $deleteStudyRequest);
$deleteStudyRequest->currentUserId = $currentUser['id'];
$deleteStudyRequest->studyName = $studyName;
- $deleteStudyRequest = Util::fillObject($requestData, $deleteStudyRequest);
$deleteStudy->execute($deleteStudyRequest, $deleteStudyResponse);
@@ -136,10 +137,10 @@ public function reactivateStudy(Request $request, ReactivateStudy $reactivateStu
$currentUser = Auth::user();
$requestData = $request->all();
-
+ Util::fillObject($requestData, $reactivateStudyRequest);
$reactivateStudyRequest->currentUserId = $currentUser['id'];
$reactivateStudyRequest->studyName = $studyName;
- $reactivateStudyRequest = Util::fillObject($requestData, $reactivateStudyRequest);
+
$reactivateStudy->execute($reactivateStudyRequest, $reactivateStudyResponse);
return $this->getJsonResponse($reactivateStudyResponse->body, $reactivateStudyResponse->status, $reactivateStudyResponse->statusText);
}
@@ -148,8 +149,11 @@ public function importPatients(Request $request, ImportPatients $importPatients,
{
$currentUser = Auth::user();
- $importPatientsRequest->patients = $request->all();
+
+ $queryParam = $request->query();
+ $importPatientsRequest->patients = $request->post();
$importPatientsRequest->studyName = $studyName;
+ $importPatientsRequest->role = $queryParam['role'];
$importPatientsRequest->currentUserId = $currentUser['id'];
$importPatients->execute($importPatientsRequest, $importPatientsResponse);
return $this->getJsonResponse($importPatientsResponse->body, $importPatientsResponse->status, $importPatientsResponse->statusText);
@@ -307,10 +311,12 @@ public function sendReminder(Request $request, SendReminder $sendReminder, SendR
{
$currentUser = Auth::user();
$requestData = $request->all();
+
+ Util::fillObject($requestData, $sendReminderRequest);
$sendReminderRequest->currentUserId = $currentUser['id'];
$sendReminderRequest->studyName = $studyName;
- $reminderRequest = Util::fillObject($requestData, $sendReminderRequest);
- $sendReminder->execute($reminderRequest, $sendReminderResponse);
+
+ $sendReminder->execute($sendReminderRequest, $sendReminderResponse);
return $this->getJsonResponse($sendReminderResponse->body, $sendReminderResponse->status, $sendReminderResponse->statusText);
}
@@ -320,11 +326,11 @@ public function requestPatientCreation(Request $request, RequestPatientCreation
$requestData = $request->all();
$queryParam = $request->query();
+ Util::fillObject($requestData, $requestPatientCreationRequest);
$requestPatientCreationRequest->studyName = $studyName;
$requestPatientCreationRequest->role = $queryParam['role'];
$requestPatientCreationRequest->currentUserId = $currentUser['id'];
- $requestPatientCreationRequest = Util::fillObject($requestData, $requestPatientCreationRequest);
$requestPatientCreation->execute($requestPatientCreationRequest, $requestPatientCreationResponse);
return $this->getJsonResponse($requestPatientCreationResponse->body, $requestPatientCreationResponse->status, $requestPatientCreationResponse->statusText);
@@ -336,9 +342,10 @@ public function sendMail(Request $request, SendMail $sendMail, SendMailRequest $
$requestData = $request->all();
$queryParam = $request->query();
+ Util::fillObject($requestData, $sendMailRequest);
$sendMailRequest->currentUserId = $currentUser['id'];
$sendMailRequest->studyName = key_exists('studyName', $queryParam) ? $queryParam['studyName'] : null;
- $sendMailRequest = Util::fillObject($requestData, $sendMailRequest);
+
$sendMail->execute($sendMailRequest, $sendMailResponse);
return $this->getJsonResponse($sendMailResponse->body, $sendMailResponse->status, $sendMailResponse->statusText);
}
@@ -363,4 +370,16 @@ public function getStudy(GetStudy $getStudy, GetStudyRequest $getStudyRequest, G
$getStudy->execute($getStudyRequest, $getStudyResponse);
return $this->getJsonResponse($getStudyResponse->body, $getStudyResponse->status, $getStudyResponse->statusText);
}
+
+ public function getCreatablePatients(Request $request, GetCreatablePatients $getCreatablePatients, GetCreatablePatientsRequest $getCreatablePatientsRequest, GetCreatablePatientsResponse $getCreatablePatientsResponse, string $studyName)
+ {
+ $currentUser = Auth::user();
+ $queryParam = $request->query();
+
+ $getCreatablePatientsRequest->currentUserId = $currentUser['id'];
+ $getCreatablePatientsRequest->studyName = $studyName;
+ $getCreatablePatientsRequest->role = $queryParam['role'];
+ $getCreatablePatients->execute($getCreatablePatientsRequest, $getCreatablePatientsResponse);
+ return $this->getJsonResponse($getCreatablePatientsResponse->body, $getCreatablePatientsResponse->status, $getCreatablePatientsResponse->statusText);
+ }
}
diff --git a/GaelO2/app/Http/Controllers/ToolsController.php b/GaelO2/app/Http/Controllers/ToolsController.php
index d261ebb55..bfb2d68d1 100644
--- a/GaelO2/app/Http/Controllers/ToolsController.php
+++ b/GaelO2/app/Http/Controllers/ToolsController.php
@@ -30,9 +30,10 @@ public function getPatientsInStudyFromCenters(Request $request,
GetPatientsInStudyFromCentersResponse $getPatientsInStudyFromCentersResponse) {
$currentUser = Auth::user();
- $getPatientsInStudyFromCentersRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
- $getPatientsInStudyFromCentersRequest = Util::fillObject($requestData, $getPatientsInStudyFromCentersRequest);
+
+ Util::fillObject($requestData, $getPatientsInStudyFromCentersRequest);
+ $getPatientsInStudyFromCentersRequest->currentUserId = $currentUser['id'];
$getPatientsInStudyFromCenters->execute($getPatientsInStudyFromCentersRequest, $getPatientsInStudyFromCentersResponse);
return $this->getJsonResponse($getPatientsInStudyFromCentersResponse->body, $getPatientsInStudyFromCentersResponse->status, $getPatientsInStudyFromCentersResponse->statusText);
@@ -43,13 +44,14 @@ public function getPatientsVisitsInStudy(Request $request,
GetPatientsVisitsInStudyRequest $getPatientsVisitsInStudyRequest,
GetPatientsVisitsInStudyResponse $getPatientsVisitsInStudyResponse) {
- $currentUser = Auth::user();
-
- $getPatientsVisitsInStudyRequest->currentUserId = $currentUser['id'];
+ $currentUser = Auth::user();
$requestData = $request->all();
- $getPatientsVisitsInStudyRequest = Util::fillObject($requestData, $getPatientsVisitsInStudyRequest);
$queryParam = $request->query();
+
+ Util::fillObject($requestData, $getPatientsVisitsInStudyRequest);
+ $getPatientsVisitsInStudyRequest->currentUserId = $currentUser['id'];
$getPatientsVisitsInStudyRequest->studyName = $queryParam['studyName'];
+
$getPatientsVisitsInStudy->execute($getPatientsVisitsInStudyRequest, $getPatientsVisitsInStudyResponse);
return $this->getJsonResponse($getPatientsVisitsInStudyResponse->body, $getPatientsVisitsInStudyResponse->status, $getPatientsVisitsInStudyResponse->statusText);
}
@@ -60,12 +62,13 @@ public function findUser(Request $request,
FindUserResponse $findUserResponse) {
$currentUser = Auth::user();
-
- $findUserRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
- $findUserRequest = Util::fillObject($requestData, $findUserRequest);
$queryParam = $request->query();
+
+ Util::fillObject($requestData, $findUserRequest);
+ $findUserRequest->currentUserId = $currentUser['id'];
$findUserRequest->studyName = $queryParam['studyName'];
+
$findUser->execute($findUserRequest, $findUserResponse);
return $this->getJsonResponse($findUserResponse->body, $findUserResponse->status, $findUserResponse->statusText);
@@ -82,7 +85,7 @@ public function createFormFileFromTus(Request $request, CreateFileToFormFromTus
$currentUser = Auth::user();
$requestData = $request->all();
- $createFileToFormFromTusRequest = Util::fillObject($requestData, $createFileToFormFromTusRequest);
+ Util::fillObject($requestData, $createFileToFormFromTusRequest);
$createFileToFormFromTusRequest->currentUserId = $currentUser['id'];
$createFileToFormFromTus->execute($createFileToFormFromTusRequest, $createFileToFormFromTusResponse);
diff --git a/GaelO2/app/Http/Controllers/UserController.php b/GaelO2/app/Http/Controllers/UserController.php
index a50ebfa8b..163a9b66c 100644
--- a/GaelO2/app/Http/Controllers/UserController.php
+++ b/GaelO2/app/Http/Controllers/UserController.php
@@ -85,8 +85,8 @@ class UserController extends Controller
public function forgotPassword(Request $request, ForgotPasswordRequest $forgotPasswordRequest, ForgotPasswordResponse $forgotPasswordResponse, ForgotPassword $forgotPassword)
{
$requestData = $request->all();
- $requestRequest = Util::fillObject($requestData, $forgotPasswordRequest);
- $forgotPassword->execute($requestRequest, $forgotPasswordResponse);
+ Util::fillObject($requestData, $forgotPasswordRequest);
+ $forgotPassword->execute($forgotPasswordRequest, $forgotPasswordResponse);
return $this->getJsonResponse($forgotPasswordResponse->body, $forgotPasswordResponse->status, $forgotPasswordResponse->statusText);
}
@@ -108,7 +108,12 @@ public function updatePassword(Request $request)
]);
$status = FacadePassword::reset(
- $request->only('email', 'password', 'password_confirmation', 'token'),
+ [
+ 'email' => strtolower($request->input('email')),
+ 'password' => $request->input('password'),
+ 'password_confirmation' => $request->input('password_confirmation'),
+ 'token' => $request->input('token')
+ ],
function ($user, $password) {
$user->forceFill([
'password' => Hash::make($password)
@@ -147,13 +152,12 @@ public function createUser(Request $request, CreateUserRequest $createUserReques
{
//Get current user requesting the API
$currentUser = Auth::user();
- //Add current user ID in Request DTO
- $createUserRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
$queryParam = $request->query();
- //Fill DTO with all other request data
+ //Fill DTO
+ Util::fillObject($requestData, $createUserRequest);
$createUserRequest->studyName = $queryParam['studyName'] ?? null;
- $createUserRequest = Util::fillObject($requestData, $createUserRequest);
+ $createUserRequest->currentUserId = $currentUser['id'];
//Execute use case
$createUser->execute($createUserRequest, $createUserResponse);
//Output result comming from usecase, here no content has to be shown (only http status code and text)
@@ -163,10 +167,10 @@ public function createUser(Request $request, CreateUserRequest $createUserReques
public function modifyUser(Request $request, ModifyUserRequest $modifyUserRequest, ModifyUserResponse $modifyUserResponse, ModifyUser $modifyUser, int $id)
{
$currentUser = Auth::user();
- $modifyUserRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
$requestData['userId'] = $id;
- $modifyUserRequest = Util::fillObject($requestData, $modifyUserRequest);
+ Util::fillObject($requestData, $modifyUserRequest);
+ $modifyUserRequest->currentUserId = $currentUser['id'];
$modifyUser->execute($modifyUserRequest, $modifyUserResponse);
return $this->getJsonResponse($modifyUserResponse->body, $modifyUserResponse->status, $modifyUserResponse->statusText);
}
@@ -174,10 +178,12 @@ public function modifyUser(Request $request, ModifyUserRequest $modifyUserReques
public function modifyUserIdentification(Request $request, ModifyUserIdentificationRequest $modifyUserRequest, ModifyUserIdentificationResponse $modifyUserResponse, ModifyUserIdentification $modifyUser, int $id)
{
$currentUser = Auth::user();
- $modifyUserRequest->currentUserId = $currentUser['id'];
$requestData = $request->all();
$requestData['userId'] = $id;
- $modifyUserRequest = Util::fillObject($requestData, $modifyUserRequest);
+
+ Util::fillObject($requestData, $modifyUserRequest);
+ $modifyUserRequest->currentUserId = $currentUser['id'];
+
$modifyUser->execute($modifyUserRequest, $modifyUserResponse);
return $this->getJsonResponse($modifyUserResponse->body, $modifyUserResponse->status, $modifyUserResponse->statusText);
}
@@ -187,9 +193,11 @@ public function deleteUser(Request $request, DeleteUserRequest $deleteUserReques
$user = Auth::user();
$requestData = get_object_vars($request);
+
+ Util::fillObject($requestData, $deleteUserRequest);
$deleteUserRequest->id = $id;
$deleteUserRequest->currentUserId = $user['id'];
- $deleteUserRequest = Util::fillObject($requestData, $deleteUserRequest);
+
$deleteUser->execute($deleteUserRequest, $deleteUserResponse);
return $this->getJsonResponse($deleteUserResponse->body, $deleteUserResponse->status, $deleteUserResponse->statusText);
}
@@ -221,10 +229,12 @@ public function createRole(Request $request, CreateUserRoles $createUserRole, Cr
$currentUser = Auth::user();
$requestData = $request->all();
$queryParam = $request->query();
+
+ Util::fillObject($requestData, $createUserRoleRequest);
$createUserRoleRequest->studyName = $queryParam['studyName'];
$createUserRoleRequest->userId = $id;
$createUserRoleRequest->currentUserId = $currentUser['id'];
- $createUserRoleRequest = Util::fillObject($requestData, $createUserRoleRequest);
+
$createUserRole->execute($createUserRoleRequest, $createUserRoleResponse);
return $this->getJsonResponse($createUserRoleResponse->body, $createUserRoleResponse->status, $createUserRoleResponse->statusText);
}
@@ -257,11 +267,13 @@ public function modifyValidatedDocumentationForRole(Request $request, ModifyVali
{
$currentUser = Auth::user();
$requestData = $request->all();
- $modifyValidatedDocumentationForRoleRequest = Util::fillObject($requestData, $modifyValidatedDocumentationForRoleRequest);
+
+ Util::fillObject($requestData, $modifyValidatedDocumentationForRoleRequest);
$modifyValidatedDocumentationForRoleRequest->currentUserId = $currentUser['id'];
$modifyValidatedDocumentationForRoleRequest->userId = $userId;
$modifyValidatedDocumentationForRoleRequest->studyName = $studyName;
$modifyValidatedDocumentationForRoleRequest->role = $roleName;
+
$modifyValidatedDocumentationForRole->execute($modifyValidatedDocumentationForRoleRequest, $modifyValidatedDocumentationForRoleResponse);
return $this->getJsonResponse($modifyValidatedDocumentationForRoleResponse->body, $modifyValidatedDocumentationForRoleResponse->status, $modifyValidatedDocumentationForRoleResponse->statusText);
}
@@ -269,8 +281,9 @@ public function modifyValidatedDocumentationForRole(Request $request, ModifyVali
public function addAffiliatedCenter(Request $request, AddAffiliatedCenter $addAffiliatedCenter, AddAffiliatedCenterRequest $addAffiliatedCenterRequest, AddAffiliatedCenterResponse $addAffiliatedCenterResponse, int $userId)
{
$requestData = $request->all();
- $addAffiliatedCenterRequest = Util::fillObject($requestData, $addAffiliatedCenterRequest);
$currentUser = Auth::user();
+
+ Util::fillObject($requestData, $addAffiliatedCenterRequest);
$addAffiliatedCenterRequest->currentUserId = $currentUser['id'];
$addAffiliatedCenterRequest->userId = $userId;
@@ -333,9 +346,11 @@ public function modifyUserOnboarding(Request $request, ModifyUserOnboarding $mod
{
$currentUser = Auth::user();
$requestData = $request->all();
- $modifyUserOnboardingRequest = Util::fillObject($requestData, $modifyUserOnboardingRequest);
+
+ Util::fillObject($requestData, $modifyUserOnboardingRequest);
$modifyUserOnboardingRequest->currentUserId = $currentUser['id'];
$modifyUserOnboardingRequest->userId = $id;
+
$modifyUserOnboarding->execute($modifyUserOnboardingRequest, $modifyUserOnboardingResponse);
return $this->getJsonResponse($modifyUserOnboardingResponse->body, $modifyUserOnboardingResponse->status, $modifyUserOnboardingResponse->statusText);
}
@@ -346,7 +361,7 @@ public function getUserNotifications(Request $request, GetUserNotifications $get
$queryParam = $request->query();
$getUserNotificationsRequest->currentUserId = $currentUser['id'];
$getUserNotificationsRequest->userId = $userId;
- if (key_exists('unread', $queryParam) ) {
+ if (key_exists('unread', $queryParam)) {
$getUserNotificationsRequest->onlyUnread = true;
} else {
$getUserNotificationsRequest->onlyUnread = false;
@@ -359,9 +374,11 @@ public function modifyUserNotifications(Request $request, ModifyUserNotification
{
$currentUser = Auth::user();
$requestData = $request->all();
- $modifyUserNotificationsRequest = Util::fillObject($requestData, $modifyUserNotificationsRequest);
+
+ Util::fillObject($requestData, $modifyUserNotificationsRequest);
$modifyUserNotificationsRequest->currentUserId = $currentUser['id'];
$modifyUserNotificationsRequest->userId = $userId;
+
$modifyUserNotifications->execute($modifyUserNotificationsRequest, $modifyUserNotificationsResponse);
return $this->getJsonResponse($modifyUserNotificationsResponse->body, $modifyUserNotificationsResponse->status, $modifyUserNotificationsResponse->statusText);
}
@@ -370,9 +387,11 @@ public function deleteUserNotifications(Request $request, DeleteUserNotification
{
$currentUser = Auth::user();
$requestData = $request->all();
- $deleteUserNotificationsRequest = Util::fillObject($requestData, $deleteUserNotificationsRequest);
+
+ Util::fillObject($requestData, $deleteUserNotificationsRequest);
$deleteUserNotificationsRequest->currentUserId = $currentUser['id'];
$deleteUserNotificationsRequest->userId = $userId;
+
$deleteUserNotifications->execute($deleteUserNotificationsRequest, $deleteUserNotificationsResponse);
return $this->getJsonResponse($deleteUserNotificationsResponse->body, $deleteUserNotificationsResponse->status, $deleteUserNotificationsResponse->statusText);
}
diff --git a/GaelO2/app/Http/Controllers/VisitController.php b/GaelO2/app/Http/Controllers/VisitController.php
index 880310a1e..0378d882a 100644
--- a/GaelO2/app/Http/Controllers/VisitController.php
+++ b/GaelO2/app/Http/Controllers/VisitController.php
@@ -2,12 +2,21 @@
namespace App\Http\Controllers;
+use App\GaelO\UseCases\CreateFileToVisit\CreateFileToVisit;
+use App\GaelO\UseCases\CreateFileToVisit\CreateFileToVisitRequest;
+use App\GaelO\UseCases\CreateFileToVisit\CreateFileToVisitResponse;
use App\GaelO\UseCases\CreateVisit\CreateVisit;
use App\GaelO\UseCases\CreateVisit\CreateVisitRequest;
use App\GaelO\UseCases\CreateVisit\CreateVisitResponse;
+use App\GaelO\UseCases\DeleteFileOfVisit\DeleteFileOfVisit;
+use App\GaelO\UseCases\DeleteFileOfVisit\DeleteFileOfVisitRequest;
+use App\GaelO\UseCases\DeleteFileOfVisit\DeleteFileOfVisitResponse;
use App\GaelO\UseCases\DeleteVisit\DeleteVisit;
use App\GaelO\UseCases\DeleteVisit\DeleteVisitRequest;
use App\GaelO\UseCases\DeleteVisit\DeleteVisitResponse;
+use App\GaelO\UseCases\GetFileOfVisit\GetFileOfVisit;
+use App\GaelO\UseCases\GetFileOfVisit\GetFileOfVisitRequest;
+use App\GaelO\UseCases\GetFileOfVisit\GetFileOfVisitResponse;
use App\GaelO\UseCases\GetVisit\GetVisit;
use App\GaelO\UseCases\GetVisit\GetVisitRequest;
use App\GaelO\UseCases\GetVisit\GetVisitResponse;
@@ -38,21 +47,23 @@
use App\GaelO\Util;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
class VisitController extends Controller
{
public function createVisit(Request $request, CreateVisit $createVisit, CreateVisitRequest $createVisitRequest, CreateVisitResponse $createVisitResponse, String $visitTypeId)
{
$currentUser = Auth::user();
+ $queryParam = $request->query();
+ $requestData = $request->all();
+ Util::fillObject($requestData, $createVisitRequest);
$createVisitRequest->currentUserId = $currentUser['id'];
$createVisitRequest->visitTypeId = $visitTypeId;
- $queryParam = $request->query();
$createVisitRequest->role = $queryParam['role'];
$createVisitRequest->studyName = $queryParam['studyName'];
- $requestData = $request->all();
- $createVisitRequest = Util::fillObject($requestData, $createVisitRequest);
$createVisit->execute($createVisitRequest, $createVisitResponse);
return $this->getJsonResponse($createVisitResponse->body, $createVisitResponse->status, $createVisitResponse->statusText);
}
@@ -80,7 +91,7 @@ public function getVisitsFromStudy(Request $request, GetVisitsFromStudy $getVisi
$queryParam = $request->query();
$getVisitsFromStudyRequest->currentUserId = $currentUser['id'];
$getVisitsFromStudyRequest->studyName = $studyName;
- if(isset($queryParam['visitType'])) $getVisitsFromStudyRequest->visitTypeId = $queryParam['visitType'];
+ if (isset($queryParam['visitType'])) $getVisitsFromStudyRequest->visitTypeId = $queryParam['visitType'];
$getVisitsFromStudy->execute($getVisitsFromStudyRequest, $getVisitsFromStudyResponse);
return $this->getJsonResponse($getVisitsFromStudyResponse->body, $getVisitsFromStudyResponse->status, $getVisitsFromStudyResponse->statusText);
@@ -90,10 +101,12 @@ public function validateDicom(Request $request, ValidateDicomUpload $validateDic
{
$currentUser = Auth::user();
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $validateDicomUploadRequest);
$validateDicomUploadRequest->currentUserId = $currentUser['id'];
$validateDicomUploadRequest->visitId = $visitId;
- $requestData = $request->all();
- $validateDicomUploadRequest = Util::fillObject($requestData, $validateDicomUploadRequest);
+
$validateDicomUpload->execute($validateDicomUploadRequest, $validateDicomUploadResponse);
return $this->getJsonResponse($validateDicomUploadResponse->body, $validateDicomUploadResponse->status, $validateDicomUploadResponse->statusText);
@@ -104,7 +117,8 @@ public function deleteVisit(Request $request, DeleteVisit $deleteVisit, DeleteVi
$currentUser = Auth::user();
$requestData = $request->all();
$queryParam = $request->query();
- $deleteVisitRequest = Util::fillObject($requestData, $deleteVisitRequest);
+
+ Util::fillObject($requestData, $deleteVisitRequest);
$deleteVisitRequest->currentUserId = $currentUser['id'];
$deleteVisitRequest->visitId = $visitId;
$deleteVisitRequest->role = $queryParam['role'];
@@ -121,7 +135,7 @@ public function modifyQualityControl(Request $request, ModifyQualityControl $mod
$requestData = $request->all();
$queryParam = $request->query();
- $modifyQualityControlRequest = Util::fillObject($requestData, $modifyQualityControlRequest);
+ Util::fillObject($requestData, $modifyQualityControlRequest);
$modifyQualityControlRequest->currentUserId = $currentUser['id'];
$modifyQualityControlRequest->visitId = $visitId;
$modifyQualityControlRequest->studyName = $queryParam['studyName'];
@@ -137,10 +151,10 @@ public function modifyQualityControlReset(Request $request, ModifyQualityControl
$requestData = $request->all();
$queryParam = $request->query();
+ Util::fillObject($requestData, $modifyQualityControlResetRequest);
$modifyQualityControlResetRequest->currentUserId = $currentUser['id'];
$modifyQualityControlResetRequest->visitId = $visitId;
$modifyQualityControlResetRequest->studyName = $queryParam['studyName'];
- $modifyQualityControlResetRequest = Util::fillObject($requestData, $modifyQualityControlResetRequest);
$modifyQualityControlReset->execute($modifyQualityControlResetRequest, $modifyQualityControlResetResponse);
@@ -153,7 +167,7 @@ public function modifyCorrectiveAction(Request $request, ModifyCorrectiveAction
$requestData = $request->all();
$queryParam = $request->query();
- $modifyCorrectiveActionRequest = Util::fillObject($requestData, $modifyCorrectiveActionRequest);
+ Util::fillObject($requestData, $modifyCorrectiveActionRequest);
$modifyCorrectiveActionRequest->currentUserId = $currentUser['id'];
$modifyCorrectiveActionRequest->studyName = $queryParam['studyName'];
$modifyCorrectiveActionRequest->visitId = $visitId;
@@ -163,15 +177,16 @@ public function modifyCorrectiveAction(Request $request, ModifyCorrectiveAction
return $this->getJsonResponse($modifyCorrectiveActionResponse->body, $modifyCorrectiveActionResponse->status, $modifyCorrectiveActionResponse->statusText);
}
- public function modifyVisitDate(Request $request, ModifyVisitDate $modifyVisitDate, ModifyVisitDateRequest $modifyVisitDateRequest, ModifyVisitDateResponse $modifyVisitDateResponse, int $visitId){
+ public function modifyVisitDate(Request $request, ModifyVisitDate $modifyVisitDate, ModifyVisitDateRequest $modifyVisitDateRequest, ModifyVisitDateResponse $modifyVisitDateResponse, int $visitId)
+ {
$currentUser = Auth::user();
$requestData = $request->all();
$queryParam = $request->query();
- $modifyCorrectiveActionRequest = Util::fillObject($requestData, $modifyVisitDateRequest);
- $modifyCorrectiveActionRequest->currentUserId = $currentUser['id'];
- $modifyCorrectiveActionRequest->visitId = $visitId;
- $modifyCorrectiveActionRequest->studyName = $queryParam['studyName'];
+ Util::fillObject($requestData, $modifyVisitDateRequest);
+ $modifyVisitDateRequest->currentUserId = $currentUser['id'];
+ $modifyVisitDateRequest->visitId = $visitId;
+ $modifyVisitDateRequest->studyName = $queryParam['studyName'];
$modifyVisitDate->execute($modifyVisitDateRequest, $modifyVisitDateResponse);
@@ -190,18 +205,78 @@ public function reactivateVisit(ReactivateVisit $reactivateVisit, ReactivateVisi
return $this->getJsonResponse($reactivateVisitResponse->body, $reactivateVisitResponse->status, $reactivateVisitResponse->statusText);
}
- public function unlockQc(Request $request, RequestUnlockQC $requestUnlockQC, RequestUnlockQCRequest $requestUnlockQCRequest, RequestUnlockQCResponse $requestUnlockQCResponse, int $visitId){
+ public function unlockQc(Request $request, RequestUnlockQC $requestUnlockQC, RequestUnlockQCRequest $requestUnlockQCRequest, RequestUnlockQCResponse $requestUnlockQCResponse, int $visitId)
+ {
$currentUser = Auth::user();
$requestData = $request->all();
- $requestUnlockRequest = Util::fillObject($requestData, $requestUnlockQCRequest);
- $requestUnlockRequest->currentUserId = $currentUser['id'];
- $requestUnlockRequest->visitId = $visitId;
+ Util::fillObject($requestData, $requestUnlockQCRequest);
+ $requestUnlockQCRequest->currentUserId = $currentUser['id'];
+ $requestUnlockQCRequest->visitId = $visitId;
- $requestUnlockQC->execute($requestUnlockRequest, $requestUnlockQCResponse);
+ $requestUnlockQC->execute($requestUnlockQCRequest, $requestUnlockQCResponse);
return $this->getJsonResponse($requestUnlockQCResponse->body, $requestUnlockQCResponse->status, $requestUnlockQCResponse->statusText);
+ }
+
+ public function createFileOfVisit(Request $request, CreateFileToVisit $createFileToVisit, CreateFileToVisitRequest $createFileToVisitRequest, CreateFileToVisitResponse $createFileToVisitResponse, int $visitId, string $key)
+ {
+ $currentUser = Auth::user();
+ $requestData = $request->all();
+ $queryParam = $request->query();
+
+ Util::fillObject($requestData, $createFileToVisitRequest);
+ $createFileToVisitRequest->currentUserId = $currentUser['id'];
+ $createFileToVisitRequest->studyName = $queryParam['studyName'];
+ $createFileToVisitRequest->visitId = $visitId;
+ $createFileToVisitRequest->key = $key;
+
+ $createFileToVisit->execute($createFileToVisitRequest, $createFileToVisitResponse);
+
+ return response()->json($createFileToVisitResponse->body)
+ ->setStatusCode($createFileToVisitResponse->status, $createFileToVisitResponse->statusText);
+ }
+
+ public function getFileOfVisit(Request $request, GetFileOfVisitRequest $getFileOfVisitRequest, GetFileOfVisitResponse $getFileOfVisitResponse, GetFileOfVisit $getFileOfVisit, int $visitId, string $key)
+ {
+ $currentUser = Auth::user();
+ $requestData = $request->all();
+ $queryParam = $request->query();
+
+ Util::fillObject($requestData, $getFileOfVisitRequest);
+ $getFileOfVisitRequest->visitId = $visitId;
+ $getFileOfVisitRequest->key = $key;
+ $getFileOfVisitRequest->currentUserId = $currentUser['id'];
+ $getFileOfVisitRequest->role = $queryParam['role'];
+ $getFileOfVisitRequest->studyName = $queryParam['studyName'];
+
+ $getFileOfVisit->execute($getFileOfVisitRequest, $getFileOfVisitResponse);
+
+ if ($getFileOfVisitResponse->status === 200) {
+ return Storage::download($getFileOfVisitResponse->filePath, $getFileOfVisitResponse->filename);
+ } else {
+ return response()->json($getFileOfVisitResponse->body)
+ ->setStatusCode($getFileOfVisitResponse->status, $getFileOfVisitResponse->statusText);
+ }
+ }
+
+ public function deleteFileOfVisit(Request $request, DeleteFileOfVisitRequest $deleteFileOfVisitRequest, DeleteFileOfVisitResponse $deleteFileOfVisitResponse, DeleteFileOfVisit $deleteFileOfVisit, int $visitId, string $key)
+ {
+ $currentUser = Auth::user();
+ $requestData = $request->all();
+ $queryParam = $request->query();
+
+ Util::fillObject($requestData, $deleteFileOfVisitRequest);
+ $deleteFileOfVisitRequest->currentUserId = $currentUser['id'];
+ $deleteFileOfVisitRequest->key = $key;
+ $deleteFileOfVisitRequest->visitId = $visitId;
+ $deleteFileOfVisitRequest->role = $queryParam['role'];
+ $deleteFileOfVisitRequest->studyName = $queryParam['studyName'];
+
+ $deleteFileOfVisit->execute($deleteFileOfVisitRequest, $deleteFileOfVisitResponse);
+ return $this->getJsonResponse($deleteFileOfVisitResponse->body, $deleteFileOfVisitResponse->status, $deleteFileOfVisitResponse->statusText);
}
+
}
diff --git a/GaelO2/app/Http/Controllers/VisitGroupController.php b/GaelO2/app/Http/Controllers/VisitGroupController.php
index e57df7809..c6f82f8f3 100644
--- a/GaelO2/app/Http/Controllers/VisitGroupController.php
+++ b/GaelO2/app/Http/Controllers/VisitGroupController.php
@@ -19,10 +19,12 @@ class VisitGroupController extends Controller
{
public function createVisitGroup(Request $request, CreateVisitGroup $createVisitGroup, CreateVisitGroupRequest $createVisitGroupRequest, CreateVisitGroupResponse $createVisitGroupResponse, String $studyName) {
$currentUser = Auth::user();
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $createVisitGroupRequest);
$createVisitGroupRequest->currentUserId = $currentUser['id'];
$createVisitGroupRequest->studyName = $studyName;
- $requestData = $request->all();
- $createVisitGroupRequest = Util::fillObject($requestData, $createVisitGroupRequest);
+
$createVisitGroup->execute($createVisitGroupRequest, $createVisitGroupResponse);
return $this->getJsonResponse($createVisitGroupResponse->body, $createVisitGroupResponse->status, $createVisitGroupResponse->statusText);
diff --git a/GaelO2/app/Http/Controllers/VisitTypeController.php b/GaelO2/app/Http/Controllers/VisitTypeController.php
index 424404bb2..fa28fd20b 100644
--- a/GaelO2/app/Http/Controllers/VisitTypeController.php
+++ b/GaelO2/app/Http/Controllers/VisitTypeController.php
@@ -8,6 +8,9 @@
use App\GaelO\UseCases\DeleteVisitType\DeleteVisitType;
use App\GaelO\UseCases\DeleteVisitType\DeleteVisitTypeRequest;
use App\GaelO\UseCases\DeleteVisitType\DeleteVisitTypeResponse;
+use App\GaelO\UseCases\GetFilesMetadataFromVisitType\GetFilesMetadataFromVisitTypeRequest;
+use App\GaelO\UseCases\GetFilesMetadataFromVisitType\GetFilesMetadataFromVisitTypeResponse;
+use App\GaelO\UseCases\GetFilesMetadataFromVisitType\GetFilesMetadataFromVisitType;
use App\GaelO\UseCases\GetVisitType\GetVisitType;
use App\GaelO\UseCases\GetVisitType\GetVisitTypeRequest;
use App\GaelO\UseCases\GetVisitType\GetVisitTypeResponse;
@@ -17,21 +20,27 @@
class VisitTypeController extends Controller
{
- public function createVisitType(Request $request, CreateVisitType $createVisitType,
- CreateVisitTypeRequest $createVisitTypeRequest, CreateVisitTypeResponse $createVisitTypeResponse, int $visitGroupId){
+ public function createVisitType(
+ Request $request,
+ CreateVisitType $createVisitType,
+ CreateVisitTypeRequest $createVisitTypeRequest,
+ CreateVisitTypeResponse $createVisitTypeResponse,
+ int $visitGroupId
+ ) {
$currentUser = Auth::user();
+ $requestData = $request->all();
+
+ Util::fillObject($requestData, $createVisitTypeRequest);
$createVisitTypeRequest->currentUserId = $currentUser['id'];
$createVisitTypeRequest->visitGroupId = $visitGroupId;
- $requestData = $request->all();
- $createVisitTypeRequest = Util::fillObject($requestData, $createVisitTypeRequest);
-
$createVisitType->execute($createVisitTypeRequest, $createVisitTypeResponse);
return $this->getJsonResponse($createVisitTypeResponse->body, $createVisitTypeResponse->status, $createVisitTypeResponse->statusText);
}
- public function getVisitType(GetVisitType $getVisitType, GetVisitTypeRequest $getVisitTypeRequest, GetVisitTypeResponse $getVisitTypeResponse, int $visitTypeId){
+ public function getVisitType(GetVisitType $getVisitType, GetVisitTypeRequest $getVisitTypeRequest, GetVisitTypeResponse $getVisitTypeResponse, int $visitTypeId)
+ {
$currentUser = Auth::user();
$getVisitTypeRequest->currentUserId = $currentUser['id'];
$getVisitTypeRequest->visitTypeId = $visitTypeId;
@@ -39,11 +48,25 @@ public function getVisitType(GetVisitType $getVisitType, GetVisitTypeRequest $ge
return $this->getJsonResponse($getVisitTypeResponse->body, $getVisitTypeResponse->status, $getVisitTypeResponse->statusText);
}
- public function deleteVisitType(DeleteVisitType $deleteVisitType, DeleteVisitTypeRequest $deleteVisitTypeRequest, DeleteVisitTypeResponse $deleteVisitTypeResponse, int $visitTypeId){
+ public function deleteVisitType(DeleteVisitType $deleteVisitType, DeleteVisitTypeRequest $deleteVisitTypeRequest, DeleteVisitTypeResponse $deleteVisitTypeResponse, int $visitTypeId)
+ {
$currentUser = Auth::user();
$deleteVisitTypeRequest->currentUserId = $currentUser['id'];
$deleteVisitTypeRequest->visitTypeId = $visitTypeId;
$deleteVisitType->execute($deleteVisitTypeRequest, $deleteVisitTypeResponse);
return $this->getJsonResponse($deleteVisitTypeResponse->body, $deleteVisitTypeResponse->status, $deleteVisitTypeResponse->statusText);
}
+
+ public function getFileMetadataFromVisitType(Request $request, GetFilesMetadataFromVisitType $getFilesMetadataFromVisitType, GetFilesMetadataFromVisitTypeRequest $getFilesMetadataFromVisitTypeRequest, GetFilesMetadataFromVisitTypeResponse $getFilesMetadataFromVisitTypeResponse, int $visitTypeId)
+ {
+ $currentUser = Auth::user();
+
+ $queryParam = $request->query();
+ $getFilesMetadataFromVisitTypeRequest->studyName = $queryParam['studyName'];
+ $getFilesMetadataFromVisitTypeRequest->role = $queryParam['role'];
+ $getFilesMetadataFromVisitTypeRequest->currentUserId = $currentUser['id'];
+ $getFilesMetadataFromVisitTypeRequest->visitTypeId = $visitTypeId;
+ $getFilesMetadataFromVisitType->execute($getFilesMetadataFromVisitTypeRequest, $getFilesMetadataFromVisitTypeResponse);
+ return $this->getJsonResponse($getFilesMetadataFromVisitTypeResponse->body, $getFilesMetadataFromVisitTypeResponse->status, $getFilesMetadataFromVisitTypeResponse->statusText);
+ }
}
diff --git a/GaelO2/app/Jobs/JobGaelOProcessing.php b/GaelO2/app/Jobs/JobGaelOProcessing.php
deleted file mode 100644
index 4493596a6..000000000
--- a/GaelO2/app/Jobs/JobGaelOProcessing.php
+++ /dev/null
@@ -1,46 +0,0 @@
-onQueue('processing');
- $this->orthancSeriesID = $orthancSeriesID;
- $this->processingName = $processingName;
- $this->host = $host;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle(GaelOProcessingService $gaelOProcessingService)
- {
- $gaelOProcessingService->setHost($this->host);
- $gaelOProcessingService->sendDicom($this->orthancSeriesID);
- }
-}
diff --git a/GaelO2/app/Jobs/JobQcReport.php b/GaelO2/app/Jobs/JobQcReport.php
index 4dca64f8b..46dbed014 100644
--- a/GaelO2/app/Jobs/JobQcReport.php
+++ b/GaelO2/app/Jobs/JobQcReport.php
@@ -15,14 +15,16 @@
use App\Jobs\QcReport\SeriesReport;
use App\Jobs\QcReport\VisitReport;
use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Throwable;
-class JobQcReport implements ShouldQueue
+class JobQcReport implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private int $visitId;
@@ -151,6 +153,7 @@ public function handle(
}
}
+
private function convertDate(string $visitDate): \DateTime
{
return new \DateTime($visitDate);
@@ -158,6 +161,7 @@ private function convertDate(string $visitDate): \DateTime
public function failed(Throwable $exception)
{
- Log::error($exception);
+ $mailServices = App::make(MailServices::class);
+ $mailServices->sendJobFailure('QcReport', ['visitId' => $this->visitId], $exception->getMessage());
}
}
diff --git a/GaelO2/app/Jobs/JobRadiomicsReport.php b/GaelO2/app/Jobs/JobRadiomicsReport.php
new file mode 100644
index 000000000..5c2bc0d63
--- /dev/null
+++ b/GaelO2/app/Jobs/JobRadiomicsReport.php
@@ -0,0 +1,212 @@
+onQueue('processing');
+ $this->visitId = $visitId;
+ $this->behalfUserId = $behalfUserId;
+ }
+
+ public function handle(
+ VisitRepositoryInterface $visitRepositoryInterface,
+ DicomStudyRepositoryInterface $dicomStudyRepositoryInterface,
+ OrthancService $orthancService,
+ GaelOProcessingService $gaelOProcessingService,
+ MailServices $mailServices,
+ PdfServices $pdfServices,
+ GaelOClientService $gaeloClientService
+ ): void {
+
+ $this->gaelOProcessingService = $gaelOProcessingService;
+ $this->orthancService = $orthancService;
+ $this->orthancService->setOrthancServer(true);
+
+ $visitEntity = $visitRepositoryInterface->getVisitContext($this->visitId);
+ $studyName = $visitEntity['patient']['study_name'];
+ $visitType = $visitEntity['visit_type']['name'];
+ $patientCode = $visitEntity['patient']['code'];
+ $creatorUserId = $visitEntity['creator_user_id'];
+ $existingFiles = $visitEntity['sent_files'];
+ $visitDate = new DateTime($visitEntity['visit_date']);
+ $formattedVisitDate = $visitDate->format('m/d/Y');
+ $dicomStudyEntity = $dicomStudyRepositoryInterface->getDicomsDataFromVisit($this->visitId, false, false);
+
+ $orthancIds = $this->getSeriesOrthancIds($dicomStudyEntity);
+ $orthancSeriesIdPt = $orthancIds['orthancSeriesIdPt'];
+ $orthancSeriesIdCt = $orthancIds['orthancSeriesIdCt'];
+
+ $this->sendDicomToProcessing($orthancSeriesIdPt);
+ $this->sendDicomToProcessing($orthancSeriesIdCt);
+
+ $idPT = $this->gaelOProcessingService->createSeriesFromOrthanc($orthancSeriesIdPt, true, true);
+ $this->addCreatedRessource('series', $idPT);
+ $idCT = $this->gaelOProcessingService->createSeriesFromOrthanc($orthancSeriesIdCt);
+ $this->addCreatedRessource('series', $idCT);
+
+ $inferencePayload = [
+ 'idPT' => $idPT,
+ 'idCT' => $idCT
+ ];
+ $inferenceResponse = $this->gaelOProcessingService->executeInference('unet_model', $inferencePayload);
+ $maskId = $inferenceResponse['id_mask'];
+ $this->addCreatedRessource('masks', $maskId);
+
+ #Do Mask Fragmentation and threshold
+ $fragmentedMaskId = $this->gaelOProcessingService->fragmentMask($idPT, $maskId, true);
+ $this->addCreatedRessource('masks', $fragmentedMaskId);
+ $threshold41MaskId = $this->gaelOProcessingService->thresholdMask($fragmentedMaskId, $idPT, "41%");
+ $this->addCreatedRessource('masks', $threshold41MaskId);
+
+ #Fragmented Mip
+ $mipFragmentedPayload = ['maskId' => $threshold41MaskId, 'delay' => 0.3, 'min' => 0, 'max' => 5, 'inverted' => true, 'orientation' => 'LPI'];
+ $mipMask = $this->gaelOProcessingService->createMIPForSeries($idPT, $mipFragmentedPayload);
+
+ #Download Rtss
+ #$rtssId = $this->gaelOProcessingService->createRtssFromMask($orthancSeriesIdPt, $threshold41MaskId);
+ #$this->addCreatedRessource('rtss', $rtssId);
+ #$rtssFile = $this->gaelOProcessingService->getRtss($rtssId);
+
+ #Download Seg
+ #$segId = $this->gaelOProcessingService->createSegFromMask($orthancSeriesIdPt, $threshold41MaskId);
+ #$this->addCreatedRessource('seg', $segId);
+ #$segFile = $this->gaelOProcessingService->getSeg($segId);
+
+ #Download .nii.gz Mask Dicom (not thrsholded)
+ $maskdicom = $this->gaelOProcessingService->getMaskDicomOrientation($fragmentedMaskId, 'LPI', true);
+
+ #get Stats
+ $stats = $this->gaelOProcessingService->getStatsMask($threshold41MaskId);
+ $statValue = ['tmtv 41%' => $stats['volume'], 'DmaxVox' => $stats['dMax']];
+
+ $mailServices->sendRadiomicsReport(
+ $studyName,
+ $patientCode,
+ $visitType,
+ $formattedVisitDate,
+ $mipMask,
+ $statValue,
+ $creatorUserId
+ );
+
+ $pdfReport = $pdfServices->saveRadiomicsPdf(
+ $studyName,
+ $patientCode,
+ $visitType,
+ $formattedVisitDate,
+ $statValue
+ );
+
+ //Send file to store using API as job worker may not access to the storage backend
+ $user = User::find($this->behalfUserId);
+ $tokenResult = $user->createToken('GaelO')->plainTextToken;
+ $gaeloClientService->loadUrl();
+ $gaeloClientService->setAuthorizationToken($tokenResult);
+ //In case of changed upload remove the last mask
+ if (array_key_exists('tmtv41', $existingFiles)) {
+ $gaeloClientService->deleteFileToVisit($studyName, $this->visitId, 'tmtv41');
+ }
+ if (array_key_exists('tmtvReport', $existingFiles)) {
+ $gaeloClientService->deleteFileToVisit($studyName, $this->visitId, 'tmtvReport');
+ }
+ if (array_key_exists('mipSegmentation', $existingFiles)) {
+ $gaeloClientService->deleteFileToVisit($studyName, $this->visitId, 'mipSegmentation');
+ }
+ //Store the file for review availability
+ $gaeloClientService->createFileToVisit($studyName, $this->visitId, 'tmtv41', 'nii.gz', $maskdicom);
+ $gaeloClientService->createFileToVisit($studyName, $this->visitId, 'tmtvReport', 'pdf', $pdfReport);
+ $gaeloClientService->createFileToVisit($studyName, $this->visitId, 'mipSegmentation', 'gif', $mipMask);
+
+ $this->deleteCreatedRessources();
+ }
+
+ private function sendDicomToProcessing(string $orthancSeriesIdPt)
+ {
+ $temporaryZipDicom = tempnam(ini_get('upload_tmp_dir'), 'TMP_Inference_');
+ $temporaryZipDicomHandle = fopen($temporaryZipDicom, 'r+');
+
+ $this->orthancService->getZipStreamToFile([$orthancSeriesIdPt], $temporaryZipDicomHandle);
+ $this->gaelOProcessingService->createDicom($temporaryZipDicom);
+ $this->addCreatedRessource('dicoms', $orthancSeriesIdPt);
+
+ unlink($temporaryZipDicom);
+ }
+
+ private function getSeriesOrthancIds(array $dicomStudyEntity)
+ {
+ $idPT = null;
+ $idCT = null;
+ foreach ($dicomStudyEntity[0]['dicom_series'] as $series) {
+ if ($series['modality'] == 'PT') {
+ if ($idPT) throw new GaelOException('Multiple PET Series, unable to perform segmentation');
+ $idPT = $series['orthanc_id'];
+ }
+ if ($series['modality'] == 'CT') {
+ if ($idCT) throw new GaelOException('Multiple CT Series, unable to perform segmentation');
+ $idCT = $series['orthanc_id'];
+ }
+ }
+
+ return [
+ 'orthancSeriesIdPt' => $idPT,
+ 'orthancSeriesIdCt' => $idCT
+ ];
+ }
+
+ private function addCreatedRessource(string $type, string $id)
+ {
+ $this->createdFiles[] = new GaelOProcessingFile($type, $id);
+ }
+
+ private function deleteCreatedRessources()
+ {
+ foreach ($this->createdFiles as $gaeloProcessingFile) {
+ try {
+ $this->gaelOProcessingService->deleteRessource($gaeloProcessingFile->getType(), $gaeloProcessingFile->getId());
+ } catch (Exception) {
+ }
+ }
+ }
+
+ public function failed(Throwable $exception)
+ {
+ $mailServices = App::make(MailServices::class);
+ $mailServices->sendJobFailure('RadiomicsReport', ['visitId' => $this->visitId, 'behalfUserId' => $this->behalfUserId], $exception->getMessage());
+ }
+}
diff --git a/GaelO2/app/Jobs/LoadGaelOProcessing.php b/GaelO2/app/Jobs/LoadGaelOProcessing.php
index f0f49d464..056b4ca81 100644
--- a/GaelO2/app/Jobs/LoadGaelOProcessing.php
+++ b/GaelO2/app/Jobs/LoadGaelOProcessing.php
@@ -47,7 +47,7 @@ public function handle(AzureService $azureService)
//Get IP of the ACI
$ip = $azureService->getIP();
-
+ /*
Bus::batch(
[
new JobGaelOProcessing(
@@ -68,6 +68,7 @@ public function handle(AzureService $azureService)
})
->allowFailures()
->dispatch();
+ */
}
/**
diff --git a/GaelO2/app/Jobs/QcReport/SeriesReport.php b/GaelO2/app/Jobs/QcReport/SeriesReport.php
index 26c3af20c..05a835524 100644
--- a/GaelO2/app/Jobs/QcReport/SeriesReport.php
+++ b/GaelO2/app/Jobs/QcReport/SeriesReport.php
@@ -3,6 +3,7 @@
namespace App\Jobs\QcReport;
use App\GaelO\DicomUtils;
+use App\GaelO\Exceptions\GaelOException;
use App\GaelO\Services\OrthancService;
use App\GaelO\Services\StoreObjects\OrthancMetaData;
use Throwable;
@@ -108,21 +109,31 @@ public function getStudyDetails(): array
private function getPreviewType(): ImageType
{
+ if (!$this->instanceReport) {
+ throw new GaelOException("Instance Report need to be set first");
+ }
+
$mosaicIDs = ['1.2.840.10008.5.1.4.1.1.4', '1.2.840.10008.5.1.4.1.1.4.1'];
$gifIDs = [
'1.2.840.10008.5.1.4.1.1.2', '1.2.840.10008.5.1.4.1.1.2.1', '1.2.840.10008.5.1.4.1.1.20',
'1.2.840.10008.5.1.4.1.1.128', '1.2.840.10008.5.1.4.1.1.130', '1.2.840.10008.5.1.4.1.1.128.1'
];
- if ($this->instanceReport != null && $this->instanceReport->numberOfFrames > 1) {
+ if ($this->instanceReport->numberOfFrames > 1) {
+ //Multi frame image series
return ImageType::MULTIFRAME;
- } else if (in_array($this->SOPClassUID, $mosaicIDs)) {
- return ImageType::MOSAIC;
- } else if (in_array($this->SOPClassUID, $gifIDs)) {
- return ImageType::MIP;
- } else {
- return ImageType::DEFAULT;
}
+
+ if (sizeof($this->orthancInstanceIds) > 1) {
+ if (in_array($this->SOPClassUID, $mosaicIDs)) {
+ return ImageType::MOSAIC;
+ } else if (in_array($this->SOPClassUID, $gifIDs)) {
+ return ImageType::MIP;
+ }
+ }
+
+ #All others case use default rendering of the first instance
+ return ImageType::DEFAULT;
}
public function loadSeriesPreview(OrthancService $orthancService): void
@@ -134,7 +145,7 @@ public function loadSeriesPreview(OrthancService $orthancService): void
try {
switch ($imageType) {
case ImageType::MIP:
- //Mosaic for now
+ //Mosaic for now as mip need significant computation and memory backend
$imagePath[] = $orthancService->getMosaic('series', $this->seriesOrthancId);
break;
case ImageType::MOSAIC:
@@ -149,7 +160,8 @@ public function loadSeriesPreview(OrthancService $orthancService): void
$imagePath[] = $orthancService->getInstancePreview($this->orthancInstanceIds[0]);
break;
}
- } catch (Throwable $t) { }
+ } catch (Throwable $t) {
+ }
$this->previewImagePath = $imagePath;
}
diff --git a/GaelO2/app/Jobs/RadiomicsReport/GaelOProcessingFile.php b/GaelO2/app/Jobs/RadiomicsReport/GaelOProcessingFile.php
new file mode 100644
index 000000000..36c371c4f
--- /dev/null
+++ b/GaelO2/app/Jobs/RadiomicsReport/GaelOProcessingFile.php
@@ -0,0 +1,24 @@
+type = $type;
+ $this->id = $id;
+ }
+
+ public function getType() :string{
+ return $this->type;
+ }
+
+ public function getId() :string {
+ return $this->id;
+ }
+}
diff --git a/GaelO2/app/Mail/JobFailure.php b/GaelO2/app/Mail/JobFailure.php
new file mode 100644
index 000000000..93708d045
--- /dev/null
+++ b/GaelO2/app/Mail/JobFailure.php
@@ -0,0 +1,48 @@
+parameters = $parameters;
+ /*
+ array('jobType' =>'',
+ 'details' => '',
+ 'errorMessage'=>'');
+ */
+ }
+
+ public function envelope(): Envelope
+ {
+ return new Envelope(
+ subject: "Failed Job - ".$this->parameters['jobType']
+ );
+ }
+
+ public function content(): Content
+ {
+ return new Content(
+ view: 'mails.mail_job_failure',
+ with: $this->parameters
+ );
+ }
+
+}
diff --git a/GaelO2/app/Mail/RadiomicsReport.php b/GaelO2/app/Mail/RadiomicsReport.php
new file mode 100644
index 000000000..083d89ff4
--- /dev/null
+++ b/GaelO2/app/Mail/RadiomicsReport.php
@@ -0,0 +1,41 @@
+parameters = $parameters;
+ }
+
+ public function envelope(): Envelope
+ {
+ return new Envelope(
+ subject: $this->parameters['studyName'] . " - Radiomics Report Patient - " . $this->parameters['patientCode'] . " - Visit - " . $this->parameters['visitType']
+ );
+ }
+
+ public function content(): Content
+ {
+ return new Content(
+ view: 'mails.mail_radiomics_report',
+ with: $this->parameters
+ );
+ }
+}
diff --git a/GaelO2/app/Models/Visit.php b/GaelO2/app/Models/Visit.php
index dc60397ab..3298e0813 100644
--- a/GaelO2/app/Models/Visit.php
+++ b/GaelO2/app/Models/Visit.php
@@ -39,7 +39,13 @@ class Visit extends Model
'corrective_action_new_upload' => 'boolean',
'corrective_action_investigator_form' => 'boolean',
'corrective_action_comment' => 'string',
- 'corrective_action_applied' => 'boolean'
+ 'corrective_action_applied' => 'boolean',
+ 'sent_files' => 'array'
+ ];
+
+ //Default value because db does not accept default value json
+ protected $attributes = [
+ 'sent_files' => '{}'
];
public function reviews()
diff --git a/GaelO2/app/Providers/AdapterProvider.php b/GaelO2/app/Providers/AdapterProvider.php
index 830bda56e..72c6c919f 100644
--- a/GaelO2/app/Providers/AdapterProvider.php
+++ b/GaelO2/app/Providers/AdapterProvider.php
@@ -7,13 +7,14 @@
use App\GaelO\Adapters\HttpClientAdapter;
use App\GaelO\Adapters\JobAdapter;
use App\GaelO\Adapters\MimeAdapter;
+use App\GaelO\Adapters\PdfAdapter;
use App\GaelO\Adapters\PhoneNumberAdapter;
use App\GaelO\Interfaces\Adapters\DatabaseDumperInterface;
use App\GaelO\Interfaces\Adapters\FrameworkInterface;
-use App\GaelO\Interfaces\Adapters\HashInterface;
use App\GaelO\Interfaces\Adapters\HttpClientInterface;
use App\GaelO\Interfaces\Adapters\JobInterface;
use App\GaelO\Interfaces\Adapters\MimeInterface;
+use App\GaelO\Interfaces\Adapters\PdfInterface;
use App\GaelO\Interfaces\Adapters\PhoneNumberInterface;
use Illuminate\Support\ServiceProvider;
@@ -32,6 +33,7 @@ public function register()
$this->app->bind(MimeInterface::class, MimeAdapter::class);
$this->app->bind(PhoneNumberInterface::class, PhoneNumberAdapter::class);
$this->app->bind(JobInterface::class, JobAdapter::class);
+ $this->app->bind(PdfInterface::class, PdfAdapter::class);
}
/**
diff --git a/GaelO2/composer.json b/GaelO2/composer.json
index 772e4145d..8843ca984 100644
--- a/GaelO2/composer.json
+++ b/GaelO2/composer.json
@@ -10,6 +10,7 @@
"license": "AGPL-3.0-only",
"require": {
"php": "^8.1",
+ "barryvdh/laravel-dompdf": "^2.0",
"doctrine/dbal": "^3.6",
"giggsey/libphonenumber-for-php": "^8.13",
"guzzlehttp/guzzle": "^7.5",
@@ -18,8 +19,8 @@
"laravel/tinker": "^2.8",
"league/flysystem-ftp": "^3.0",
"league/flysystem-sftp-v3": "^3.0",
+ "league/mime-type-detection": "^1.13",
"phpoffice/phpspreadsheet": "^1.27",
- "ralouphie/mimey": "^1.0",
"sentry/sentry-laravel": "^3.2",
"spatie/db-dumper": "^3.3",
"staudenmeir/eloquent-has-many-deep": "^1.18"
diff --git a/GaelO2/composer.lock b/GaelO2/composer.lock
index 10722cffe..b10c702ed 100644
--- a/GaelO2/composer.lock
+++ b/GaelO2/composer.lock
@@ -4,8 +4,85 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e8d12132f320ba395d950d91a79a3b8f",
+ "content-hash": "a457335d0a3f6e7f0872e83627087293",
"packages": [
+ {
+ "name": "barryvdh/laravel-dompdf",
+ "version": "v2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/barryvdh/laravel-dompdf.git",
+ "reference": "9843d2be423670fb434f4c978b3c0f4dd92c87a6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/9843d2be423670fb434f4c978b3c0f4dd92c87a6",
+ "reference": "9843d2be423670fb434f4c978b3c0f4dd92c87a6",
+ "shasum": ""
+ },
+ "require": {
+ "dompdf/dompdf": "^2.0.1",
+ "illuminate/support": "^6|^7|^8|^9|^10",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "nunomaduro/larastan": "^1|^2",
+ "orchestra/testbench": "^4|^5|^6|^7|^8",
+ "phpro/grumphp": "^1",
+ "squizlabs/php_codesniffer": "^3.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ },
+ "laravel": {
+ "providers": [
+ "Barryvdh\\DomPDF\\ServiceProvider"
+ ],
+ "aliases": {
+ "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf",
+ "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf"
+ }
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Barryvdh\\DomPDF\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Barry vd. Heuvel",
+ "email": "barryvdh@gmail.com"
+ }
+ ],
+ "description": "A DOMPDF Wrapper for Laravel",
+ "keywords": [
+ "dompdf",
+ "laravel",
+ "pdf"
+ ],
+ "support": {
+ "issues": "https://github.com/barryvdh/laravel-dompdf/issues",
+ "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://fruitcake.nl",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/barryvdh",
+ "type": "github"
+ }
+ ],
+ "time": "2023-01-12T15:12:49+00:00"
+ },
{
"name": "brick/math",
"version": "0.11.0",
@@ -297,16 +374,16 @@
},
{
"name": "doctrine/dbal",
- "version": "3.6.4",
+ "version": "3.7.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
- "reference": "19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f"
+ "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/dbal/zipball/19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f",
- "reference": "19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/5b7bd66c9ff58c04c5474ab85edce442f8081cb2",
+ "reference": "5b7bd66c9ff58c04c5474ab85edce442f8081cb2",
"shasum": ""
},
"require": {
@@ -321,11 +398,12 @@
"require-dev": {
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
- "jetbrains/phpstorm-stubs": "2022.3",
- "phpstan/phpstan": "1.10.14",
+ "jetbrains/phpstorm-stubs": "2023.1",
+ "phpstan/phpstan": "1.10.35",
"phpstan/phpstan-strict-rules": "^1.5",
- "phpunit/phpunit": "9.6.7",
+ "phpunit/phpunit": "9.6.13",
"psalm/plugin-phpunit": "0.18.4",
+ "slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.7.2",
"symfony/cache": "^5.4|^6.0",
"symfony/console": "^4.4|^5.4|^6.0",
@@ -389,7 +467,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
- "source": "https://github.com/doctrine/dbal/tree/3.6.4"
+ "source": "https://github.com/doctrine/dbal/tree/3.7.1"
},
"funding": [
{
@@ -405,20 +483,20 @@
"type": "tidelift"
}
],
- "time": "2023-06-15T07:40:12+00:00"
+ "time": "2023-10-06T05:06:20+00:00"
},
{
"name": "doctrine/deprecations",
- "version": "v1.1.1",
+ "version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/deprecations.git",
- "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3"
+ "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3",
- "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
+ "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931",
"shasum": ""
},
"require": {
@@ -450,9 +528,9 @@
"homepage": "https://www.doctrine-project.org/",
"support": {
"issues": "https://github.com/doctrine/deprecations/issues",
- "source": "https://github.com/doctrine/deprecations/tree/v1.1.1"
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.2"
},
- "time": "2023-06-03T09:27:29+00:00"
+ "time": "2023-09-27T20:04:15+00:00"
},
{
"name": "doctrine/event-manager",
@@ -713,18 +791,80 @@
],
"time": "2022-12-15T16:57:16+00:00"
},
+ {
+ "name": "dompdf/dompdf",
+ "version": "v2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dompdf/dompdf.git",
+ "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dompdf/dompdf/zipball/e8d2d5e37e8b0b30f0732a011295ab80680d7e85",
+ "reference": "e8d2d5e37e8b0b30f0732a011295ab80680d7e85",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "masterminds/html5": "^2.0",
+ "phenx/php-font-lib": ">=0.5.4 <1.0.0",
+ "phenx/php-svg-lib": ">=0.3.3 <1.0.0",
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "ext-json": "*",
+ "ext-zip": "*",
+ "mockery/mockery": "^1.3",
+ "phpunit/phpunit": "^7.5 || ^8 || ^9",
+ "squizlabs/php_codesniffer": "^3.5"
+ },
+ "suggest": {
+ "ext-gd": "Needed to process images",
+ "ext-gmagick": "Improves image processing performance",
+ "ext-imagick": "Improves image processing performance",
+ "ext-zlib": "Needed for pdf stream compression"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Dompdf\\": "src/"
+ },
+ "classmap": [
+ "lib/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1"
+ ],
+ "authors": [
+ {
+ "name": "The Dompdf Community",
+ "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
+ }
+ ],
+ "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
+ "homepage": "https://github.com/dompdf/dompdf",
+ "support": {
+ "issues": "https://github.com/dompdf/dompdf/issues",
+ "source": "https://github.com/dompdf/dompdf/tree/v2.0.3"
+ },
+ "time": "2023-02-07T12:51:48+00:00"
+ },
{
"name": "dragonmantank/cron-expression",
- "version": "v3.3.2",
+ "version": "v3.3.3",
"source": {
"type": "git",
"url": "https://github.com/dragonmantank/cron-expression.git",
- "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8"
+ "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8",
- "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8",
+ "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
+ "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a",
"shasum": ""
},
"require": {
@@ -764,7 +904,7 @@
],
"support": {
"issues": "https://github.com/dragonmantank/cron-expression/issues",
- "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2"
+ "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3"
},
"funding": [
{
@@ -772,20 +912,20 @@
"type": "github"
}
],
- "time": "2022-09-10T18:51:20+00:00"
+ "time": "2023-08-10T19:36:49+00:00"
},
{
"name": "egulias/email-validator",
- "version": "4.0.1",
+ "version": "4.0.2",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
- "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff"
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff",
- "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff",
+ "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e",
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e",
"shasum": ""
},
"require": {
@@ -794,8 +934,8 @@
"symfony/polyfill-intl-idn": "^1.26"
},
"require-dev": {
- "phpunit/phpunit": "^9.5.27",
- "vimeo/psalm": "^4.30"
+ "phpunit/phpunit": "^10.2",
+ "vimeo/psalm": "^5.12"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
@@ -831,7 +971,7 @@
],
"support": {
"issues": "https://github.com/egulias/EmailValidator/issues",
- "source": "https://github.com/egulias/EmailValidator/tree/4.0.1"
+ "source": "https://github.com/egulias/EmailValidator/tree/4.0.2"
},
"funding": [
{
@@ -839,7 +979,7 @@
"type": "github"
}
],
- "time": "2023-01-14T14:17:03+00:00"
+ "time": "2023-10-06T06:47:41+00:00"
},
{
"name": "ezyang/htmlpurifier",
@@ -904,21 +1044,21 @@
},
{
"name": "fruitcake/php-cors",
- "version": "v1.2.0",
+ "version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/fruitcake/php-cors.git",
- "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e"
+ "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e",
- "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e",
+ "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b",
+ "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
- "symfony/http-foundation": "^4.4|^5.4|^6"
+ "symfony/http-foundation": "^4.4|^5.4|^6|^7"
},
"require-dev": {
"phpstan/phpstan": "^1.4",
@@ -928,7 +1068,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.1-dev"
+ "dev-master": "1.2-dev"
}
},
"autoload": {
@@ -959,7 +1099,7 @@
],
"support": {
"issues": "https://github.com/fruitcake/php-cors/issues",
- "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0"
+ "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0"
},
"funding": [
{
@@ -971,20 +1111,20 @@
"type": "github"
}
],
- "time": "2022-02-20T15:07:15+00:00"
+ "time": "2023-10-12T05:21:21+00:00"
},
{
"name": "giggsey/libphonenumber-for-php",
- "version": "8.13.15",
+ "version": "8.13.24",
"source": {
"type": "git",
"url": "https://github.com/giggsey/libphonenumber-for-php.git",
- "reference": "b294846e26ea985e6b1fbdfaf15387daca60c2de"
+ "reference": "746ca6a565b9d4167c94c80824f43fa6fb463fd1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/b294846e26ea985e6b1fbdfaf15387daca60c2de",
- "reference": "b294846e26ea985e6b1fbdfaf15387daca60c2de",
+ "url": "https://api.github.com/repos/giggsey/libphonenumber-for-php/zipball/746ca6a565b9d4167c94c80824f43fa6fb463fd1",
+ "reference": "746ca6a565b9d4167c94c80824f43fa6fb463fd1",
"shasum": ""
},
"require": {
@@ -1043,7 +1183,7 @@
"issues": "https://github.com/giggsey/libphonenumber-for-php/issues",
"source": "https://github.com/giggsey/libphonenumber-for-php"
},
- "time": "2023-06-23T07:47:45+00:00"
+ "time": "2023-10-31T08:12:54+00:00"
},
{
"name": "giggsey/locale",
@@ -1163,22 +1303,22 @@
},
{
"name": "guzzlehttp/guzzle",
- "version": "7.7.0",
+ "version": "7.8.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
- "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
+ "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
- "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9",
+ "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9",
"shasum": ""
},
"require": {
"ext-json": "*",
- "guzzlehttp/promises": "^1.5.3 || ^2.0",
- "guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
+ "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
@@ -1269,7 +1409,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
- "source": "https://github.com/guzzle/guzzle/tree/7.7.0"
+ "source": "https://github.com/guzzle/guzzle/tree/7.8.0"
},
"funding": [
{
@@ -1285,20 +1425,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-21T14:04:53+00:00"
+ "time": "2023-08-27T10:20:53+00:00"
},
{
"name": "guzzlehttp/promises",
- "version": "2.0.0",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
- "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
+ "reference": "111166291a0f8130081195ac4556a5587d7f1b5d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
- "reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d",
+ "reference": "111166291a0f8130081195ac4556a5587d7f1b5d",
"shasum": ""
},
"require": {
@@ -1352,7 +1492,7 @@
],
"support": {
"issues": "https://github.com/guzzle/promises/issues",
- "source": "https://github.com/guzzle/promises/tree/2.0.0"
+ "source": "https://github.com/guzzle/promises/tree/2.0.1"
},
"funding": [
{
@@ -1368,20 +1508,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-21T13:50:22+00:00"
+ "time": "2023-08-03T15:11:55+00:00"
},
{
"name": "guzzlehttp/psr7",
- "version": "2.5.0",
+ "version": "2.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
- "reference": "b635f279edd83fc275f822a1188157ffea568ff6"
+ "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
- "reference": "b635f279edd83fc275f822a1188157ffea568ff6",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
+ "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727",
"shasum": ""
},
"require": {
@@ -1468,7 +1608,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
- "source": "https://github.com/guzzle/psr7/tree/2.5.0"
+ "source": "https://github.com/guzzle/psr7/tree/2.6.1"
},
"funding": [
{
@@ -1484,20 +1624,20 @@
"type": "tidelift"
}
],
- "time": "2023-04-17T16:11:26+00:00"
+ "time": "2023-08-27T10:13:57+00:00"
},
{
"name": "guzzlehttp/uri-template",
- "version": "v1.0.1",
+ "version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/uri-template.git",
- "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2"
+ "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2",
- "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2",
+ "url": "https://api.github.com/repos/guzzle/uri-template/zipball/61bf437fc2197f587f6857d3ff903a24f1731b5d",
+ "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d",
"shasum": ""
},
"require": {
@@ -1505,15 +1645,11 @@
"symfony/polyfill-php80": "^1.17"
},
"require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.1",
"phpunit/phpunit": "^8.5.19 || ^9.5.8",
"uri-template/tests": "1.0.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
"autoload": {
"psr-4": {
"GuzzleHttp\\UriTemplate\\": "src"
@@ -1552,7 +1688,7 @@
],
"support": {
"issues": "https://github.com/guzzle/uri-template/issues",
- "source": "https://github.com/guzzle/uri-template/tree/v1.0.1"
+ "source": "https://github.com/guzzle/uri-template/tree/v1.0.2"
},
"funding": [
{
@@ -1568,7 +1704,7 @@
"type": "tidelift"
}
],
- "time": "2021-10-07T12:57:01+00:00"
+ "time": "2023-08-27T10:19:19+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
@@ -1689,16 +1825,16 @@
},
{
"name": "laravel/framework",
- "version": "v10.13.5",
+ "version": "v10.30.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "03106ae9ba2ec4b36dc973b7bdca6fad81e032b4"
+ "reference": "3dd85d9dbea82b937f8eaf344b50d613c5d1127a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/03106ae9ba2ec4b36dc973b7bdca6fad81e032b4",
- "reference": "03106ae9ba2ec4b36dc973b7bdca6fad81e032b4",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/3dd85d9dbea82b937f8eaf344b50d613c5d1127a",
+ "reference": "3dd85d9dbea82b937f8eaf344b50d613c5d1127a",
"shasum": ""
},
"require": {
@@ -1716,11 +1852,12 @@
"ext-tokenizer": "*",
"fruitcake/php-cors": "^1.2",
"guzzlehttp/uri-template": "^1.0",
+ "laravel/prompts": "^0.1.9",
"laravel/serializable-closure": "^1.3",
"league/commonmark": "^2.2.1",
"league/flysystem": "^3.8.0",
"monolog/monolog": "^3.0",
- "nesbot/carbon": "^2.62.1",
+ "nesbot/carbon": "^2.67",
"nunomaduro/termwind": "^1.13",
"php": "^8.1",
"psr/container": "^1.1.1|^2.0.1",
@@ -1730,7 +1867,7 @@
"symfony/console": "^6.2",
"symfony/error-handler": "^6.2",
"symfony/finder": "^6.2",
- "symfony/http-foundation": "^6.2",
+ "symfony/http-foundation": "^6.3",
"symfony/http-kernel": "^6.2",
"symfony/mailer": "^6.2",
"symfony/mime": "^6.2",
@@ -1797,14 +1934,15 @@
"league/flysystem-read-only": "^3.3",
"league/flysystem-sftp-v3": "^3.0",
"mockery/mockery": "^1.5.1",
- "orchestra/testbench-core": "^8.4",
+ "nyholm/psr7": "^1.2",
+ "orchestra/testbench-core": "^8.12",
"pda/pheanstalk": "^4.0",
- "phpstan/phpdoc-parser": "^1.15",
"phpstan/phpstan": "^1.4.7",
"phpunit/phpunit": "^10.0.7",
"predis/predis": "^2.0.2",
"symfony/cache": "^6.2",
- "symfony/http-client": "^6.2.4"
+ "symfony/http-client": "^6.2.4",
+ "symfony/psr-http-message-bridge": "^2.0"
},
"suggest": {
"ably/ably-php": "Required to use the Ably broadcast driver (^1.0).",
@@ -1885,20 +2023,77 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
- "time": "2023-06-08T20:25:36+00:00"
+ "time": "2023-10-31T13:19:45+00:00"
+ },
+ {
+ "name": "laravel/prompts",
+ "version": "v0.1.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/laravel/prompts.git",
+ "reference": "e1379d8ead15edd6cc4369c22274345982edc95a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/laravel/prompts/zipball/e1379d8ead15edd6cc4369c22274345982edc95a",
+ "reference": "e1379d8ead15edd6cc4369c22274345982edc95a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "illuminate/collections": "^10.0|^11.0",
+ "php": "^8.1",
+ "symfony/console": "^6.2|^7.0"
+ },
+ "conflict": {
+ "illuminate/console": ">=10.17.0 <10.25.0",
+ "laravel/framework": ">=10.17.0 <10.25.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.5",
+ "pestphp/pest": "^2.3",
+ "phpstan/phpstan": "^1.10",
+ "phpstan/phpstan-mockery": "^1.1"
+ },
+ "suggest": {
+ "ext-pcntl": "Required for the spinner to be animated."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.1.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Laravel\\Prompts\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "support": {
+ "issues": "https://github.com/laravel/prompts/issues",
+ "source": "https://github.com/laravel/prompts/tree/v0.1.13"
+ },
+ "time": "2023-10-27T13:53:59+00:00"
},
{
"name": "laravel/sanctum",
- "version": "v3.2.5",
+ "version": "v3.3.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
- "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876"
+ "reference": "338f633e6487e76b255470d3373fbc29228aa971"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/sanctum/zipball/8ebda85d59d3c414863a7f4d816ef8302faad876",
- "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876",
+ "url": "https://api.github.com/repos/laravel/sanctum/zipball/338f633e6487e76b255470d3373fbc29228aa971",
+ "reference": "338f633e6487e76b255470d3373fbc29228aa971",
"shasum": ""
},
"require": {
@@ -1911,9 +2106,9 @@
},
"require-dev": {
"mockery/mockery": "^1.0",
- "orchestra/testbench": "^7.0|^8.0",
+ "orchestra/testbench": "^7.28.2|^8.8.3",
"phpstan/phpstan": "^1.10",
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^9.6"
},
"type": "library",
"extra": {
@@ -1951,20 +2146,20 @@
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
- "time": "2023-05-01T19:39:51+00:00"
+ "time": "2023-09-07T15:46:33+00:00"
},
{
"name": "laravel/serializable-closure",
- "version": "v1.3.0",
+ "version": "v1.3.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
- "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37"
+ "reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f23fe9d4e95255dacee1bf3525e0810d1a1b0f37",
- "reference": "f23fe9d4e95255dacee1bf3525e0810d1a1b0f37",
+ "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/076fe2cf128bd54b4341cdc6d49b95b34e101e4c",
+ "reference": "076fe2cf128bd54b4341cdc6d49b95b34e101e4c",
"shasum": ""
},
"require": {
@@ -2011,20 +2206,20 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
- "time": "2023-01-30T18:31:20+00:00"
+ "time": "2023-10-17T13:38:16+00:00"
},
{
"name": "laravel/tinker",
- "version": "v2.8.1",
+ "version": "v2.8.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/tinker.git",
- "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10"
+ "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/tinker/zipball/04a2d3bd0d650c0764f70bf49d1ee39393e4eb10",
- "reference": "04a2d3bd0d650c0764f70bf49d1ee39393e4eb10",
+ "url": "https://api.github.com/repos/laravel/tinker/zipball/b936d415b252b499e8c3b1f795cd4fc20f57e1f3",
+ "reference": "b936d415b252b499e8c3b1f795cd4fc20f57e1f3",
"shasum": ""
},
"require": {
@@ -2037,6 +2232,7 @@
},
"require-dev": {
"mockery/mockery": "~1.3.3|^1.4.2",
+ "phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.5.8|^9.3.3"
},
"suggest": {
@@ -2077,22 +2273,22 @@
],
"support": {
"issues": "https://github.com/laravel/tinker/issues",
- "source": "https://github.com/laravel/tinker/tree/v2.8.1"
+ "source": "https://github.com/laravel/tinker/tree/v2.8.2"
},
- "time": "2023-02-15T16:40:09+00:00"
+ "time": "2023-08-15T14:27:00+00:00"
},
{
"name": "league/commonmark",
- "version": "2.4.0",
+ "version": "2.4.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
- "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048"
+ "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048",
- "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048",
+ "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/3669d6d5f7a47a93c08ddff335e6d945481a1dd5",
+ "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5",
"shasum": ""
},
"require": {
@@ -2185,7 +2381,7 @@
"type": "tidelift"
}
],
- "time": "2023-03-24T15:16:10+00:00"
+ "time": "2023-08-30T16:55:00+00:00"
},
{
"name": "league/config",
@@ -2271,16 +2467,16 @@
},
{
"name": "league/flysystem",
- "version": "3.15.1",
+ "version": "3.18.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
- "reference": "a141d430414fcb8bf797a18716b09f759a385bed"
+ "reference": "015633a05aee22490495159237a5944091d8281e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a141d430414fcb8bf797a18716b09f759a385bed",
- "reference": "a141d430414fcb8bf797a18716b09f759a385bed",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/015633a05aee22490495159237a5944091d8281e",
+ "reference": "015633a05aee22490495159237a5944091d8281e",
"shasum": ""
},
"require": {
@@ -2289,6 +2485,8 @@
"php": "^8.0.2"
},
"conflict": {
+ "async-aws/core": "<1.19.0",
+ "async-aws/s3": "<1.14.0",
"aws/aws-sdk-php": "3.209.31 || 3.210.0",
"guzzlehttp/guzzle": "<7.0",
"guzzlehttp/ringphp": "<1.1.1",
@@ -2296,8 +2494,8 @@
"symfony/http-client": "<5.2"
},
"require-dev": {
- "async-aws/s3": "^1.5",
- "async-aws/simple-s3": "^1.1",
+ "async-aws/s3": "^1.5 || ^2.0",
+ "async-aws/simple-s3": "^1.1 || ^2.0",
"aws/aws-sdk-php": "^3.220.0",
"composer/semver": "^3.0",
"ext-fileinfo": "*",
@@ -2307,8 +2505,8 @@
"google/cloud-storage": "^1.23",
"microsoft/azure-storage-blob": "^1.1",
"phpseclib/phpseclib": "^3.0.14",
- "phpstan/phpstan": "^0.12.26",
- "phpunit/phpunit": "^9.5.11",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.5.11|^10.0",
"sabre/dav": "^4.3.1"
},
"type": "library",
@@ -2343,7 +2541,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
- "source": "https://github.com/thephpleague/flysystem/tree/3.15.1"
+ "source": "https://github.com/thephpleague/flysystem/tree/3.18.0"
},
"funding": [
{
@@ -2355,20 +2553,20 @@
"type": "github"
}
],
- "time": "2023-05-04T09:04:26+00:00"
+ "time": "2023-10-20T17:59:40+00:00"
},
{
"name": "league/flysystem-ftp",
- "version": "3.15.0",
+ "version": "3.16.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-ftp.git",
- "reference": "8b288ff74e85b6d7a247aa7898490e4bd4215795"
+ "reference": "60b6c44194ee94d53eb81971637ef017e123fb20"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/8b288ff74e85b6d7a247aa7898490e4bd4215795",
- "reference": "8b288ff74e85b6d7a247aa7898490e4bd4215795",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-ftp/zipball/60b6c44194ee94d53eb81971637ef017e123fb20",
+ "reference": "60b6c44194ee94d53eb81971637ef017e123fb20",
"shasum": ""
},
"require": {
@@ -2403,7 +2601,7 @@
"ftpd"
],
"support": {
- "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.15.0"
+ "source": "https://github.com/thephpleague/flysystem-ftp/tree/3.16.0"
},
"funding": [
{
@@ -2415,20 +2613,20 @@
"type": "github"
}
],
- "time": "2023-05-02T20:02:14+00:00"
+ "time": "2023-08-30T10:17:23+00:00"
},
{
"name": "league/flysystem-local",
- "version": "3.15.0",
+ "version": "3.18.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-local.git",
- "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3"
+ "reference": "e7381ef7643f658b87efb7dbe98fe538fb1bbf32"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/543f64c397fefdf9cfeac443ffb6beff602796b3",
- "reference": "543f64c397fefdf9cfeac443ffb6beff602796b3",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e7381ef7643f658b87efb7dbe98fe538fb1bbf32",
+ "reference": "e7381ef7643f658b87efb7dbe98fe538fb1bbf32",
"shasum": ""
},
"require": {
@@ -2463,7 +2661,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem-local/issues",
- "source": "https://github.com/thephpleague/flysystem-local/tree/3.15.0"
+ "source": "https://github.com/thephpleague/flysystem-local/tree/3.18.0"
},
"funding": [
{
@@ -2475,20 +2673,20 @@
"type": "github"
}
],
- "time": "2023-05-02T20:02:14+00:00"
+ "time": "2023-10-19T20:07:13+00:00"
},
{
"name": "league/flysystem-sftp-v3",
- "version": "3.15.0",
+ "version": "3.16.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-sftp-v3.git",
- "reference": "659d85c63489ef11130b648f2740277a17337c8b"
+ "reference": "1ba682def8e87fd7fa00883629553c0200d2e974"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem-sftp-v3/zipball/659d85c63489ef11130b648f2740277a17337c8b",
- "reference": "659d85c63489ef11130b648f2740277a17337c8b",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-sftp-v3/zipball/1ba682def8e87fd7fa00883629553c0200d2e974",
+ "reference": "1ba682def8e87fd7fa00883629553c0200d2e974",
"shasum": ""
},
"require": {
@@ -2523,7 +2721,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem-sftp-v3/issues",
- "source": "https://github.com/thephpleague/flysystem-sftp-v3/tree/3.15.0"
+ "source": "https://github.com/thephpleague/flysystem-sftp-v3/tree/3.16.0"
},
"funding": [
{
@@ -2535,30 +2733,30 @@
"type": "github"
}
],
- "time": "2023-05-02T20:02:14+00:00"
+ "time": "2023-08-30T10:25:05+00:00"
},
{
"name": "league/mime-type-detection",
- "version": "1.11.0",
+ "version": "1.14.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/mime-type-detection.git",
- "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
+ "reference": "b6a5854368533df0295c5761a0253656a2e52d9e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
- "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
+ "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/b6a5854368533df0295c5761a0253656a2e52d9e",
+ "reference": "b6a5854368533df0295c5761a0253656a2e52d9e",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
- "php": "^7.2 || ^8.0"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"phpstan/phpstan": "^0.12.68",
- "phpunit/phpunit": "^8.5.8 || ^9.3"
+ "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
},
"type": "library",
"autoload": {
@@ -2579,7 +2777,7 @@
"description": "Mime-type detection for Flysystem",
"support": {
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
- "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
+ "source": "https://github.com/thephpleague/mime-type-detection/tree/1.14.0"
},
"funding": [
{
@@ -2591,7 +2789,7 @@
"type": "tidelift"
}
],
- "time": "2022-04-17T13:12:02+00:00"
+ "time": "2023-10-17T14:13:20+00:00"
},
{
"name": "maennchen/zipstream-php",
@@ -2781,18 +2979,85 @@
},
"time": "2022-12-02T22:17:43+00:00"
},
+ {
+ "name": "masterminds/html5",
+ "version": "2.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Masterminds/html5-php.git",
+ "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf",
+ "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Masterminds\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matt Butcher",
+ "email": "technosophos@gmail.com"
+ },
+ {
+ "name": "Matt Farina",
+ "email": "matt@mattfarina.com"
+ },
+ {
+ "name": "Asmir Mustafic",
+ "email": "goetas@gmail.com"
+ }
+ ],
+ "description": "An HTML5 parser and serializer.",
+ "homepage": "http://masterminds.github.io/html5-php",
+ "keywords": [
+ "HTML5",
+ "dom",
+ "html",
+ "parser",
+ "querypath",
+ "serializer",
+ "xml"
+ ],
+ "support": {
+ "issues": "https://github.com/Masterminds/html5-php/issues",
+ "source": "https://github.com/Masterminds/html5-php/tree/2.8.1"
+ },
+ "time": "2023-05-10T11:58:31+00:00"
+ },
{
"name": "monolog/monolog",
- "version": "3.4.0",
+ "version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "e2392369686d420ca32df3803de28b5d6f76867d"
+ "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/e2392369686d420ca32df3803de28b5d6f76867d",
- "reference": "e2392369686d420ca32df3803de28b5d6f76867d",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448",
+ "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448",
"shasum": ""
},
"require": {
@@ -2868,7 +3133,7 @@
],
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
- "source": "https://github.com/Seldaek/monolog/tree/3.4.0"
+ "source": "https://github.com/Seldaek/monolog/tree/3.5.0"
},
"funding": [
{
@@ -2880,29 +3145,33 @@
"type": "tidelift"
}
],
- "time": "2023-06-21T08:46:11+00:00"
+ "time": "2023-10-27T15:32:31+00:00"
},
{
"name": "nesbot/carbon",
- "version": "2.67.0",
+ "version": "2.71.0",
"source": {
"type": "git",
"url": "https://github.com/briannesbitt/Carbon.git",
- "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8"
+ "reference": "98276233188583f2ff845a0f992a235472d9466a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/c1001b3bc75039b07f38a79db5237c4c529e04c8",
- "reference": "c1001b3bc75039b07f38a79db5237c4c529e04c8",
+ "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/98276233188583f2ff845a0f992a235472d9466a",
+ "reference": "98276233188583f2ff845a0f992a235472d9466a",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.1.8 || ^8.0",
+ "psr/clock": "^1.0",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php80": "^1.16",
"symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
"require-dev": {
"doctrine/dbal": "^2.0 || ^3.1.4",
"doctrine/orm": "^2.7",
@@ -2982,25 +3251,25 @@
"type": "tidelift"
}
],
- "time": "2023-05-25T22:09:47+00:00"
+ "time": "2023-09-25T11:31:05+00:00"
},
{
"name": "nette/schema",
- "version": "v1.2.3",
+ "version": "v1.2.5",
"source": {
"type": "git",
"url": "https://github.com/nette/schema.git",
- "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f"
+ "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
- "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f",
+ "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a",
+ "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a",
"shasum": ""
},
"require": {
"nette/utils": "^2.5.7 || ^3.1.5 || ^4.0",
- "php": ">=7.1 <8.3"
+ "php": "7.1 - 8.3"
},
"require-dev": {
"nette/tester": "^2.3 || ^2.4",
@@ -3042,26 +3311,26 @@
],
"support": {
"issues": "https://github.com/nette/schema/issues",
- "source": "https://github.com/nette/schema/tree/v1.2.3"
+ "source": "https://github.com/nette/schema/tree/v1.2.5"
},
- "time": "2022-10-13T01:24:26+00:00"
+ "time": "2023-10-05T20:37:59+00:00"
},
{
"name": "nette/utils",
- "version": "v4.0.0",
+ "version": "v4.0.3",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
- "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e"
+ "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nette/utils/zipball/cacdbf5a91a657ede665c541eda28941d4b09c1e",
- "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e",
+ "url": "https://api.github.com/repos/nette/utils/zipball/a9d127dd6a203ce6d255b2e2db49759f7506e015",
+ "reference": "a9d127dd6a203ce6d255b2e2db49759f7506e015",
"shasum": ""
},
"require": {
- "php": ">=8.0 <8.3"
+ "php": ">=8.0 <8.4"
},
"conflict": {
"nette/finder": "<3",
@@ -3069,7 +3338,7 @@
},
"require-dev": {
"jetbrains/phpstorm-attributes": "dev-master",
- "nette/tester": "^2.4",
+ "nette/tester": "^2.5",
"phpstan/phpstan": "^1.0",
"tracy/tracy": "^2.9"
},
@@ -3079,8 +3348,7 @@
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
"ext-json": "to use Nette\\Utils\\Json",
"ext-mbstring": "to use Strings::lower() etc...",
- "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
- "ext-xml": "to use Strings::length() etc. when mbstring is not available"
+ "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()"
},
"type": "library",
"extra": {
@@ -3129,22 +3397,22 @@
],
"support": {
"issues": "https://github.com/nette/utils/issues",
- "source": "https://github.com/nette/utils/tree/v4.0.0"
+ "source": "https://github.com/nette/utils/tree/v4.0.3"
},
- "time": "2023-02-02T10:41:53+00:00"
+ "time": "2023-10-29T21:02:13+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.16.0",
+ "version": "v4.17.1",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "19526a33fb561ef417e822e85f08a00db4059c17"
+ "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
- "reference": "19526a33fb561ef417e822e85f08a00db4059c17",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
+ "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
"shasum": ""
},
"require": {
@@ -3185,9 +3453,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
},
- "time": "2023-06-25T14:52:30+00:00"
+ "time": "2023-08-13T19:53:39+00:00"
},
{
"name": "nunomaduro/termwind",
@@ -3470,6 +3738,96 @@
},
"time": "2020-10-15T08:29:30+00:00"
},
+ {
+ "name": "phenx/php-font-lib",
+ "version": "0.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dompdf/php-font-lib.git",
+ "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4",
+ "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3 || ^4 || ^5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "FontLib\\": "src/FontLib"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Ménager",
+ "email": "fabien.menager@gmail.com"
+ }
+ ],
+ "description": "A library to read, parse, export and make subsets of different types of font files.",
+ "homepage": "https://github.com/PhenX/php-font-lib",
+ "support": {
+ "issues": "https://github.com/dompdf/php-font-lib/issues",
+ "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4"
+ },
+ "time": "2021-12-17T19:44:54+00:00"
+ },
+ {
+ "name": "phenx/php-svg-lib",
+ "version": "0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/dompdf/php-svg-lib.git",
+ "reference": "76876c6cf3080bcb6f249d7d59705108166a6685"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/76876c6cf3080bcb6f249d7d59705108166a6685",
+ "reference": "76876c6cf3080bcb6f249d7d59705108166a6685",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": "^7.1 || ^8.0",
+ "sabberworm/php-css-parser": "^8.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Svg\\": "src/Svg"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Ménager",
+ "email": "fabien.menager@gmail.com"
+ }
+ ],
+ "description": "A library to read, parse and export to PDF SVG files.",
+ "homepage": "https://github.com/PhenX/php-svg-lib",
+ "support": {
+ "issues": "https://github.com/dompdf/php-svg-lib/issues",
+ "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.0"
+ },
+ "time": "2022-09-06T12:16:56+00:00"
+ },
{
"name": "php-http/client-common",
"version": "2.7.0",
@@ -3541,16 +3899,16 @@
},
{
"name": "php-http/discovery",
- "version": "1.19.0",
+ "version": "1.19.1",
"source": {
"type": "git",
"url": "https://github.com/php-http/discovery.git",
- "reference": "1856a119a0b0ba8da8b5c33c080aa7af8fac25b4"
+ "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-http/discovery/zipball/1856a119a0b0ba8da8b5c33c080aa7af8fac25b4",
- "reference": "1856a119a0b0ba8da8b5c33c080aa7af8fac25b4",
+ "url": "https://api.github.com/repos/php-http/discovery/zipball/57f3de01d32085fea20865f9b16fb0e69347c39e",
+ "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e",
"shasum": ""
},
"require": {
@@ -3613,9 +3971,9 @@
],
"support": {
"issues": "https://github.com/php-http/discovery/issues",
- "source": "https://github.com/php-http/discovery/tree/1.19.0"
+ "source": "https://github.com/php-http/discovery/tree/1.19.1"
},
- "time": "2023-06-19T08:45:36+00:00"
+ "time": "2023-07-11T07:02:26+00:00"
},
{
"name": "php-http/httplug",
@@ -3800,31 +4158,26 @@
},
{
"name": "php-http/promise",
- "version": "1.1.0",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/promise.git",
- "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88"
+ "reference": "ef4905bfb492ff389eb7f12e26925a0f20073050"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
- "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88",
+ "url": "https://api.github.com/repos/php-http/promise/zipball/ef4905bfb492ff389eb7f12e26925a0f20073050",
+ "reference": "ef4905bfb492ff389eb7f12e26925a0f20073050",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
- "friends-of-phpspec/phpspec-code-coverage": "^4.3.2",
- "phpspec/phpspec": "^5.1.2 || ^6.2"
+ "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3",
+ "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1-dev"
- }
- },
"autoload": {
"psr-4": {
"Http\\Promise\\": "src/"
@@ -3851,9 +4204,9 @@
],
"support": {
"issues": "https://github.com/php-http/promise/issues",
- "source": "https://github.com/php-http/promise/tree/1.1.0"
+ "source": "https://github.com/php-http/promise/tree/1.2.0"
},
- "time": "2020-07-07T09:29:14+00:00"
+ "time": "2023-10-24T09:20:26+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
@@ -4037,16 +4390,16 @@
},
{
"name": "phpseclib/phpseclib",
- "version": "3.0.20",
+ "version": "3.0.33",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
- "reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67"
+ "reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67",
- "reference": "543a1da81111a0bfd6ae7bbc2865c5e89ed3fc67",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/33fa69b2514a61138dd48e7a49f99445711e0ad0",
+ "reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0",
"shasum": ""
},
"require": {
@@ -4127,7 +4480,7 @@
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
- "source": "https://github.com/phpseclib/phpseclib/tree/3.0.20"
+ "source": "https://github.com/phpseclib/phpseclib/tree/3.0.33"
},
"funding": [
{
@@ -4143,7 +4496,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-13T06:30:34+00:00"
+ "time": "2023-10-21T14:00:39+00:00"
},
{
"name": "psr/cache",
@@ -4194,6 +4547,54 @@
},
"time": "2021-02-03T23:26:27+00:00"
},
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
+ },
{
"name": "psr/container",
"version": "2.0.2",
@@ -4299,16 +4700,16 @@
},
{
"name": "psr/http-client",
- "version": "1.0.2",
+ "version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
- "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
- "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
@@ -4345,9 +4746,9 @@
"psr-18"
],
"support": {
- "source": "https://github.com/php-fig/http-client/tree/1.0.2"
+ "source": "https://github.com/php-fig/http-client"
},
- "time": "2023-04-10T20:12:12+00:00"
+ "time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
@@ -4560,16 +4961,16 @@
},
{
"name": "psy/psysh",
- "version": "v0.11.18",
+ "version": "v0.11.22",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
- "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec"
+ "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
- "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
+ "url": "https://api.github.com/repos/bobthecow/psysh/zipball/128fa1b608be651999ed9789c95e6e2a31b5802b",
+ "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b",
"shasum": ""
},
"require": {
@@ -4598,7 +4999,11 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "0.11.x-dev"
+ "dev-0.11": "0.11.x-dev"
+ },
+ "bamarni-bin": {
+ "bin-links": false,
+ "forward-command": false
}
},
"autoload": {
@@ -4630,9 +5035,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
- "source": "https://github.com/bobthecow/psysh/tree/v0.11.18"
+ "source": "https://github.com/bobthecow/psysh/tree/v0.11.22"
},
- "time": "2023-05-23T02:31:11+00:00"
+ "time": "2023-10-14T21:56:36+00:00"
},
{
"name": "ralouphie/getallheaders",
@@ -4678,50 +5083,6 @@
},
"time": "2019-03-08T08:55:37+00:00"
},
- {
- "name": "ralouphie/mimey",
- "version": "1.0.2",
- "source": {
- "type": "git",
- "url": "https://github.com/ralouphie/mimey.git",
- "reference": "2a0e997c733b7c2f9f8b61cafb006fd5fb9fa15a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ralouphie/mimey/zipball/2a0e997c733b7c2f9f8b61cafb006fd5fb9fa15a",
- "reference": "2a0e997c733b7c2f9f8b61cafb006fd5fb9fa15a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3"
- },
- "require-dev": {
- "phpunit/phpunit": "~3.7.0",
- "satooshi/php-coveralls": ">=1.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Mimey\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Ralph Khattar",
- "email": "ralph.khattar@gmail.com"
- }
- ],
- "description": "PHP package for converting file extensions to MIME types and vice versa.",
- "support": {
- "issues": "https://github.com/ralouphie/mimey/issues",
- "source": "https://github.com/ralouphie/mimey/tree/master"
- },
- "time": "2016-09-28T03:36:23+00:00"
- },
{
"name": "ramsey/collection",
"version": "2.0.0",
@@ -4903,6 +5264,59 @@
],
"time": "2023-04-15T23:01:58+00:00"
},
+ {
+ "name": "sabberworm/php-css-parser",
+ "version": "8.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sabberworm/PHP-CSS-Parser.git",
+ "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30",
+ "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "php": ">=5.6.20"
+ },
+ "require-dev": {
+ "codacy/coverage": "^1.4",
+ "phpunit/phpunit": "^4.8.36"
+ },
+ "suggest": {
+ "ext-mbstring": "for parsing UTF-8 CSS"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Sabberworm\\CSS\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Raphael Schweikert"
+ }
+ ],
+ "description": "Parser for CSS Files written in PHP",
+ "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
+ "keywords": [
+ "css",
+ "parser",
+ "stylesheet"
+ ],
+ "support": {
+ "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues",
+ "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0"
+ },
+ "time": "2021-12-11T13:40:54+00:00"
+ },
{
"name": "sentry/sdk",
"version": "3.5.0",
@@ -4962,16 +5376,16 @@
},
{
"name": "sentry/sentry",
- "version": "3.20.1",
+ "version": "3.22.0",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
- "reference": "644ad9768c18139a80ac510090fad000d9ffd8a4"
+ "reference": "c0e3df5a5c1d133cd9461e7672568ff07042c19d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/644ad9768c18139a80ac510090fad000d9ffd8a4",
- "reference": "644ad9768c18139a80ac510090fad000d9ffd8a4",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/c0e3df5a5c1d133cd9461e7672568ff07042c19d",
+ "reference": "c0e3df5a5c1d133cd9461e7672568ff07042c19d",
"shasum": ""
},
"require": {
@@ -4989,7 +5403,7 @@
"psr/http-factory": "^1.0",
"psr/http-factory-implementation": "^1.0",
"psr/log": "^1.0|^2.0|^3.0",
- "symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0",
+ "symfony/options-resolver": "^3.4.43|^4.4.30|^5.0.11|^6.0|^7.0",
"symfony/polyfill-php80": "^1.17"
},
"conflict": {
@@ -5015,11 +5429,6 @@
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.13.x-dev"
- }
- },
"autoload": {
"files": [
"src/functions.php"
@@ -5051,7 +5460,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-php/issues",
- "source": "https://github.com/getsentry/sentry-php/tree/3.20.1"
+ "source": "https://github.com/getsentry/sentry-php/tree/3.22.0"
},
"funding": [
{
@@ -5063,20 +5472,20 @@
"type": "custom"
}
],
- "time": "2023-06-26T11:01:40+00:00"
+ "time": "2023-10-23T20:34:53+00:00"
},
{
"name": "sentry/sentry-laravel",
- "version": "3.5.1",
+ "version": "3.8.2",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-laravel.git",
- "reference": "85c2168e469ca73ee90de5e71cef53153e949e64"
+ "reference": "1293e5732f8405e12f000cdf5dee78c927a18de0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/85c2168e469ca73ee90de5e71cef53153e949e64",
- "reference": "85c2168e469ca73ee90de5e71cef53153e949e64",
+ "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/1293e5732f8405e12f000cdf5dee78c927a18de0",
+ "reference": "1293e5732f8405e12f000cdf5dee78c927a18de0",
"shasum": ""
},
"require": {
@@ -5084,14 +5493,16 @@
"nyholm/psr7": "^1.0",
"php": "^7.2 | ^8.0",
"sentry/sdk": "^3.4",
- "sentry/sentry": "^3.19",
+ "sentry/sentry": "^3.20.1",
"symfony/psr-http-message-bridge": "^1.0 | ^2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.11",
+ "laravel/folio": "^1.0",
"laravel/framework": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0",
"mockery/mockery": "^1.3",
"orchestra/testbench": "^4.7 | ^5.1 | ^6.0 | ^7.0 | ^8.0",
+ "phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8.4 | ^9.3"
},
"type": "library",
@@ -5141,7 +5552,7 @@
],
"support": {
"issues": "https://github.com/getsentry/sentry-laravel/issues",
- "source": "https://github.com/getsentry/sentry-laravel/tree/3.5.1"
+ "source": "https://github.com/getsentry/sentry-laravel/tree/3.8.2"
},
"funding": [
{
@@ -5153,20 +5564,20 @@
"type": "custom"
}
],
- "time": "2023-06-20T13:19:32+00:00"
+ "time": "2023-10-12T14:38:46+00:00"
},
{
"name": "spatie/db-dumper",
- "version": "3.3.1",
+ "version": "3.4.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/db-dumper.git",
- "reference": "3b9fd47899bf6a59d3452392121c9ce675d55d34"
+ "reference": "bbd5ae0f331d47e6534eb307e256c11a65c8e24a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/db-dumper/zipball/3b9fd47899bf6a59d3452392121c9ce675d55d34",
- "reference": "3b9fd47899bf6a59d3452392121c9ce675d55d34",
+ "url": "https://api.github.com/repos/spatie/db-dumper/zipball/bbd5ae0f331d47e6534eb307e256c11a65c8e24a",
+ "reference": "bbd5ae0f331d47e6534eb307e256c11a65c8e24a",
"shasum": ""
},
"require": {
@@ -5204,7 +5615,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/db-dumper/tree/3.3.1"
+ "source": "https://github.com/spatie/db-dumper/tree/3.4.0"
},
"funding": [
{
@@ -5216,20 +5627,20 @@
"type": "github"
}
],
- "time": "2023-05-02T11:05:31+00:00"
+ "time": "2023-06-27T08:34:52+00:00"
},
{
"name": "staudenmeir/eloquent-has-many-deep",
- "version": "v1.18.1",
+ "version": "v1.18.3",
"source": {
"type": "git",
"url": "https://github.com/staudenmeir/eloquent-has-many-deep.git",
- "reference": "b3421d637de05d2cc62166c5decb9727a029185c"
+ "reference": "04cdf25eac68bd02c3aa382ddbf437585bd76708"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep/zipball/b3421d637de05d2cc62166c5decb9727a029185c",
- "reference": "b3421d637de05d2cc62166c5decb9727a029185c",
+ "url": "https://api.github.com/repos/staudenmeir/eloquent-has-many-deep/zipball/04cdf25eac68bd02c3aa382ddbf437585bd76708",
+ "reference": "04cdf25eac68bd02c3aa382ddbf437585bd76708",
"shasum": ""
},
"require": {
@@ -5239,12 +5650,15 @@
},
"require-dev": {
"awobaz/compoships": "^2.2",
+ "barryvdh/laravel-ide-helper": "^2.13",
"illuminate/pagination": "^10.0",
"korridor/laravel-has-many-merged": "^1.0",
+ "mockery/mockery": "^1.6",
+ "phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.1",
"staudenmeir/eloquent-eager-limit": "^1.8",
- "staudenmeir/eloquent-json-relations": "^1.8",
- "staudenmeir/laravel-adjacency-list": "^1.13"
+ "staudenmeir/eloquent-json-relations": "^1.8.2",
+ "staudenmeir/laravel-adjacency-list": "^1.13.7"
},
"type": "library",
"autoload": {
@@ -5265,7 +5679,7 @@
"description": "Laravel Eloquent HasManyThrough relationships with unlimited levels",
"support": {
"issues": "https://github.com/staudenmeir/eloquent-has-many-deep/issues",
- "source": "https://github.com/staudenmeir/eloquent-has-many-deep/tree/v1.18.1"
+ "source": "https://github.com/staudenmeir/eloquent-has-many-deep/tree/v1.18.3"
},
"funding": [
{
@@ -5273,7 +5687,7 @@
"type": "custom"
}
],
- "time": "2023-06-20T18:09:39+00:00"
+ "time": "2023-08-20T17:00:39+00:00"
},
{
"name": "staudenmeir/eloquent-has-many-deep-contracts",
@@ -5318,16 +5732,16 @@
},
{
"name": "symfony/console",
- "version": "v6.3.0",
+ "version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7"
+ "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
- "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7",
+ "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6",
+ "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6",
"shasum": ""
},
"require": {
@@ -5388,7 +5802,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.3.0"
+ "source": "https://github.com/symfony/console/tree/v6.3.4"
},
"funding": [
{
@@ -5404,20 +5818,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-29T12:49:39+00:00"
+ "time": "2023-08-16T10:10:12+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v6.3.0",
+ "version": "v6.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf"
+ "reference": "883d961421ab1709877c10ac99451632a3d6fa57"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf",
- "reference": "88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/883d961421ab1709877c10ac99451632a3d6fa57",
+ "reference": "883d961421ab1709877c10ac99451632a3d6fa57",
"shasum": ""
},
"require": {
@@ -5453,7 +5867,7 @@
"description": "Converts CSS selectors to XPath expressions",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v6.3.0"
+ "source": "https://github.com/symfony/css-selector/tree/v6.3.2"
},
"funding": [
{
@@ -5469,7 +5883,7 @@
"type": "tidelift"
}
],
- "time": "2023-03-20T16:43:42+00:00"
+ "time": "2023-07-12T16:00:22+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -5540,16 +5954,16 @@
},
{
"name": "symfony/error-handler",
- "version": "v6.3.0",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
- "reference": "99d2d814a6351461af350ead4d963bd67451236f"
+ "reference": "1f69476b64fb47105c06beef757766c376b548c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/error-handler/zipball/99d2d814a6351461af350ead4d963bd67451236f",
- "reference": "99d2d814a6351461af350ead4d963bd67451236f",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/1f69476b64fb47105c06beef757766c376b548c4",
+ "reference": "1f69476b64fb47105c06beef757766c376b548c4",
"shasum": ""
},
"require": {
@@ -5594,7 +6008,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/error-handler/tree/v6.3.0"
+ "source": "https://github.com/symfony/error-handler/tree/v6.3.5"
},
"funding": [
{
@@ -5610,20 +6024,20 @@
"type": "tidelift"
}
],
- "time": "2023-05-10T12:03:13+00:00"
+ "time": "2023-09-12T06:57:20+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v6.3.0",
+ "version": "v6.3.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa"
+ "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
- "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
+ "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e",
"shasum": ""
},
"require": {
@@ -5674,7 +6088,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0"
+ "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2"
},
"funding": [
{
@@ -5690,7 +6104,7 @@
"type": "tidelift"
}
],
- "time": "2023-04-21T14:41:17+00:00"
+ "time": "2023-07-06T06:56:43+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -5770,16 +6184,16 @@
},
{
"name": "symfony/finder",
- "version": "v6.3.0",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2"
+ "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2",
- "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/a1b31d88c0e998168ca7792f222cbecee47428c4",
+ "reference": "a1b31d88c0e998168ca7792f222cbecee47428c4",
"shasum": ""
},
"require": {
@@ -5814,7 +6228,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v6.3.0"
+ "source": "https://github.com/symfony/finder/tree/v6.3.5"
},
"funding": [
{
@@ -5830,20 +6244,20 @@
"type": "tidelift"
}
],
- "time": "2023-04-02T01:25:41+00:00"
+ "time": "2023-09-26T12:56:25+00:00"
},
{
"name": "symfony/http-client",
- "version": "v6.3.1",
+ "version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
- "reference": "1c828a06aef2f5eeba42026dfc532d4fc5406123"
+ "reference": "cd67fcaf4524ec6ae5d9b2d9497682d7ad3ce57d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client/zipball/1c828a06aef2f5eeba42026dfc532d4fc5406123",
- "reference": "1c828a06aef2f5eeba42026dfc532d4fc5406123",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/cd67fcaf4524ec6ae5d9b2d9497682d7ad3ce57d",
+ "reference": "cd67fcaf4524ec6ae5d9b2d9497682d7ad3ce57d",
"shasum": ""
},
"require": {
@@ -5906,7 +6320,7 @@
"http"
],
"support": {
- "source": "https://github.com/symfony/http-client/tree/v6.3.1"
+ "source": "https://github.com/symfony/http-client/tree/v6.3.7"
},
"funding": [
{
@@ -5922,7 +6336,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-24T11:51:27+00:00"
+ "time": "2023-10-29T12:41:36+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -6004,16 +6418,16 @@
},
{
"name": "symfony/http-foundation",
- "version": "v6.3.1",
+ "version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66"
+ "reference": "59d1837d5d992d16c2628cd0d6b76acf8d69b33e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e0ad0d153e1c20069250986cd9e9dd1ccebb0d66",
- "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/59d1837d5d992d16c2628cd0d6b76acf8d69b33e",
+ "reference": "59d1837d5d992d16c2628cd0d6b76acf8d69b33e",
"shasum": ""
},
"require": {
@@ -6023,12 +6437,12 @@
"symfony/polyfill-php83": "^1.27"
},
"conflict": {
- "symfony/cache": "<6.2"
+ "symfony/cache": "<6.3"
},
"require-dev": {
- "doctrine/dbal": "^2.13.1|^3.0",
+ "doctrine/dbal": "^2.13.1|^3|^4",
"predis/predis": "^1.1|^2.0",
- "symfony/cache": "^5.4|^6.0",
+ "symfony/cache": "^6.3",
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/expression-language": "^5.4|^6.0",
"symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4",
@@ -6061,7 +6475,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-foundation/tree/v6.3.1"
+ "source": "https://github.com/symfony/http-foundation/tree/v6.3.7"
},
"funding": [
{
@@ -6077,20 +6491,20 @@
"type": "tidelift"
}
],
- "time": "2023-06-24T11:51:27+00:00"
+ "time": "2023-10-28T23:55:27+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v6.3.1",
+ "version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374"
+ "reference": "6d4098095f93279d9536a0e9124439560cc764d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/161e16fd2e35fb4881a43bc8b383dfd5be4ac374",
- "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6d4098095f93279d9536a0e9124439560cc764d0",
+ "reference": "6d4098095f93279d9536a0e9124439560cc764d0",
"shasum": ""
},
"require": {
@@ -6099,7 +6513,7 @@
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/error-handler": "^6.3",
"symfony/event-dispatcher": "^5.4|^6.0",
- "symfony/http-foundation": "^6.2.7",
+ "symfony/http-foundation": "^6.3.4",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
@@ -6107,7 +6521,7 @@
"symfony/cache": "<5.4",
"symfony/config": "<6.1",
"symfony/console": "<5.4",
- "symfony/dependency-injection": "<6.3",
+ "symfony/dependency-injection": "<6.3.4",
"symfony/doctrine-bridge": "<5.4",
"symfony/form": "<5.4",
"symfony/http-client": "<5.4",
@@ -6131,7 +6545,7 @@
"symfony/config": "^6.1",
"symfony/console": "^5.4|^6.0",
"symfony/css-selector": "^5.4|^6.0",
- "symfony/dependency-injection": "^6.3",
+ "symfony/dependency-injection": "^6.3.4",
"symfony/dom-crawler": "^5.4|^6.0",
"symfony/expression-language": "^5.4|^6.0",
"symfony/finder": "^5.4|^6.0",
@@ -6174,7 +6588,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/http-kernel/tree/v6.3.1"
+ "source": "https://github.com/symfony/http-kernel/tree/v6.3.7"
},
"funding": [
{
@@ -6190,20 +6604,20 @@
"type": "tidelift"
}
],
- "time": "2023-06-26T06:07:32+00:00"
+ "time": "2023-10-29T14:31:45+00:00"
},
{
"name": "symfony/mailer",
- "version": "v6.3.0",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435"
+ "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/7b03d9be1dea29bfec0a6c7b603f5072a4c97435",
- "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/d89611a7830d51b5e118bca38e390dea92f9ea06",
+ "reference": "d89611a7830d51b5e118bca38e390dea92f9ea06",
"shasum": ""
},
"require": {
@@ -6254,7 +6668,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v6.3.0"
+ "source": "https://github.com/symfony/mailer/tree/v6.3.5"
},
"funding": [
{
@@ -6270,24 +6684,25 @@
"type": "tidelift"
}
],
- "time": "2023-05-29T12:49:39+00:00"
+ "time": "2023-09-06T09:47:15+00:00"
},
{
"name": "symfony/mime",
- "version": "v6.3.0",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad"
+ "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/7b5d2121858cd6efbed778abce9cfdd7ab1f62ad",
- "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/d5179eedf1cb2946dbd760475ebf05c251ef6a6e",
+ "reference": "d5179eedf1cb2946dbd760475ebf05c251ef6a6e",
"shasum": ""
},
"require": {
"php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
@@ -6296,7 +6711,7 @@
"phpdocumentor/reflection-docblock": "<3.2.2",
"phpdocumentor/type-resolver": "<1.4.0",
"symfony/mailer": "<5.4",
- "symfony/serializer": "<6.2"
+ "symfony/serializer": "<6.2.13|>=6.3,<6.3.2"
},
"require-dev": {
"egulias/email-validator": "^2.1.10|^3.1|^4",
@@ -6305,7 +6720,7 @@
"symfony/dependency-injection": "^5.4|^6.0",
"symfony/property-access": "^5.4|^6.0",
"symfony/property-info": "^5.4|^6.0",
- "symfony/serializer": "^6.2"
+ "symfony/serializer": "~6.2.13|^6.3.2"
},
"type": "library",
"autoload": {
@@ -6337,7 +6752,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v6.3.0"
+ "source": "https://github.com/symfony/mime/tree/v6.3.5"
},
"funding": [
{
@@ -6353,7 +6768,7 @@
"type": "tidelift"
}
],
- "time": "2023-04-28T15:57:00+00:00"
+ "time": "2023-09-29T06:59:36+00:00"
},
{
"name": "symfony/options-resolver",
@@ -6424,16 +6839,16 @@
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
- "reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
"shasum": ""
},
"require": {
@@ -6448,7 +6863,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6486,7 +6901,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
},
"funding": [
{
@@ -6502,20 +6917,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "511a08c03c1960e08a883f4cffcacd219b758354"
+ "reference": "875e90aeea2777b6f135677f618529449334a612"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
- "reference": "511a08c03c1960e08a883f4cffcacd219b758354",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
+ "reference": "875e90aeea2777b6f135677f618529449334a612",
"shasum": ""
},
"require": {
@@ -6527,7 +6942,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6567,7 +6982,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
},
"funding": [
{
@@ -6583,20 +6998,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
- "reference": "639084e360537a19f9ee352433b84ce831f3d2da"
+ "reference": "ecaafce9f77234a6a449d29e49267ba10499116d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da",
- "reference": "639084e360537a19f9ee352433b84ce831f3d2da",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d",
+ "reference": "ecaafce9f77234a6a449d29e49267ba10499116d",
"shasum": ""
},
"require": {
@@ -6610,7 +7025,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6654,7 +7069,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0"
},
"funding": [
{
@@ -6670,20 +7085,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:30:37+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
- "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
"shasum": ""
},
"require": {
@@ -6695,7 +7110,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6738,7 +7153,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
},
"funding": [
{
@@ -6754,20 +7169,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
+ "reference": "42292d99c55abe617799667f454222c54c60e229"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
- "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
+ "reference": "42292d99c55abe617799667f454222c54c60e229",
"shasum": ""
},
"require": {
@@ -6782,7 +7197,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6821,7 +7236,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0"
},
"funding": [
{
@@ -6837,20 +7252,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-07-28T09:04:16+00:00"
},
{
"name": "symfony/polyfill-php72",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
- "reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
+ "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
- "reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179",
+ "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179",
"shasum": ""
},
"require": {
@@ -6859,7 +7274,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6897,7 +7312,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0"
},
"funding": [
{
@@ -6913,20 +7328,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
- "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
"shasum": ""
},
"require": {
@@ -6935,7 +7350,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -6980,7 +7395,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
},
"funding": [
{
@@ -6996,20 +7411,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/polyfill-php83",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "508c652ba3ccf69f8c97f251534f229791b52a57"
+ "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57",
- "reference": "508c652ba3ccf69f8c97f251534f229791b52a57",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
+ "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11",
"shasum": ""
},
"require": {
@@ -7019,7 +7434,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -7032,7 +7447,10 @@
],
"psr-4": {
"Symfony\\Polyfill\\Php83\\": ""
- }
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -7057,7 +7475,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0"
},
"funding": [
{
@@ -7073,20 +7491,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-08-16T06:22:46+00:00"
},
{
"name": "symfony/polyfill-uuid",
- "version": "v1.27.0",
+ "version": "v1.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-uuid.git",
- "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166"
+ "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166",
- "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166",
+ "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e",
+ "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e",
"shasum": ""
},
"require": {
@@ -7101,7 +7519,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.27-dev"
+ "dev-main": "1.28-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -7139,7 +7557,7 @@
"uuid"
],
"support": {
- "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0"
+ "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0"
},
"funding": [
{
@@ -7155,20 +7573,20 @@
"type": "tidelift"
}
],
- "time": "2022-11-03T14:55:06+00:00"
+ "time": "2023-01-26T09:26:14+00:00"
},
{
"name": "symfony/process",
- "version": "v6.3.0",
+ "version": "v6.3.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628"
+ "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628",
- "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628",
+ "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54",
+ "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54",
"shasum": ""
},
"require": {
@@ -7200,7 +7618,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v6.3.0"
+ "source": "https://github.com/symfony/process/tree/v6.3.4"
},
"funding": [
{
@@ -7216,25 +7634,26 @@
"type": "tidelift"
}
],
- "time": "2023-05-19T08:06:44+00:00"
+ "time": "2023-08-07T10:39:22+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
- "version": "v2.2.0",
+ "version": "v2.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git",
- "reference": "28a732c05bbad801304ad5a5c674cf2970508993"
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/28a732c05bbad801304ad5a5c674cf2970508993",
- "reference": "28a732c05bbad801304ad5a5c674cf2970508993",
+ "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/581ca6067eb62640de5ff08ee1ba6850a0ee472e",
+ "reference": "581ca6067eb62640de5ff08ee1ba6850a0ee472e",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/http-message": "^1.0 || ^2.0",
+ "symfony/deprecation-contracts": "^2.5 || ^3.0",
"symfony/http-foundation": "^5.4 || ^6.0"
},
"require-dev": {
@@ -7253,7 +7672,7 @@
"type": "symfony-bridge",
"extra": {
"branch-alias": {
- "dev-main": "2.2-dev"
+ "dev-main": "2.3-dev"
}
},
"autoload": {
@@ -7288,7 +7707,7 @@
],
"support": {
"issues": "https://github.com/symfony/psr-http-message-bridge/issues",
- "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.2.0"
+ "source": "https://github.com/symfony/psr-http-message-bridge/tree/v2.3.1"
},
"funding": [
{
@@ -7304,24 +7723,25 @@
"type": "tidelift"
}
],
- "time": "2023-04-21T08:40:19+00:00"
+ "time": "2023-07-26T11:53:26+00:00"
},
{
"name": "symfony/routing",
- "version": "v6.3.1",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5"
+ "reference": "82616e59acd3e3d9c916bba798326cb7796d7d31"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/d37ad1779c38b8eb71996d17dc13030dcb7f9cf5",
- "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/82616e59acd3e3d9c916bba798326cb7796d7d31",
+ "reference": "82616e59acd3e3d9c916bba798326cb7796d7d31",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
"doctrine/annotations": "<1.12",
@@ -7370,7 +7790,7 @@
"url"
],
"support": {
- "source": "https://github.com/symfony/routing/tree/v6.3.1"
+ "source": "https://github.com/symfony/routing/tree/v6.3.5"
},
"funding": [
{
@@ -7386,7 +7806,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-05T15:30:22+00:00"
+ "time": "2023-09-20T16:05:51+00:00"
},
{
"name": "symfony/service-contracts",
@@ -7472,16 +7892,16 @@
},
{
"name": "symfony/string",
- "version": "v6.3.0",
+ "version": "v6.3.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
+ "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
- "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
+ "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339",
+ "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339",
"shasum": ""
},
"require": {
@@ -7538,7 +7958,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.3.0"
+ "source": "https://github.com/symfony/string/tree/v6.3.5"
},
"funding": [
{
@@ -7554,24 +7974,25 @@
"type": "tidelift"
}
],
- "time": "2023-03-21T21:06:29+00:00"
+ "time": "2023-09-18T10:38:32+00:00"
},
{
"name": "symfony/translation",
- "version": "v6.3.0",
+ "version": "v6.3.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f"
+ "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/f72b2cba8f79dd9d536f534f76874b58ad37876f",
- "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/30212e7c87dcb79c83f6362b00bde0e0b1213499",
+ "reference": "30212e7c87dcb79c83f6362b00bde0e0b1213499",
"shasum": ""
},
"require": {
"php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/translation-contracts": "^2.5|^3.0"
},
@@ -7632,7 +8053,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/translation/tree/v6.3.0"
+ "source": "https://github.com/symfony/translation/tree/v6.3.7"
},
"funding": [
{
@@ -7648,7 +8069,7 @@
"type": "tidelift"
}
],
- "time": "2023-05-19T12:46:45+00:00"
+ "time": "2023-10-28T23:11:45+00:00"
},
{
"name": "symfony/translation-contracts",
@@ -7804,20 +8225,21 @@
},
{
"name": "symfony/var-dumper",
- "version": "v6.3.1",
+ "version": "v6.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "c81268d6960ddb47af17391a27d222bd58cf0515"
+ "reference": "999ede244507c32b8e43aebaa10e9fce20de7c97"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c81268d6960ddb47af17391a27d222bd58cf0515",
- "reference": "c81268d6960ddb47af17391a27d222bd58cf0515",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/999ede244507c32b8e43aebaa10e9fce20de7c97",
+ "reference": "999ede244507c32b8e43aebaa10e9fce20de7c97",
"shasum": ""
},
"require": {
"php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@@ -7826,6 +8248,7 @@
"require-dev": {
"ext-iconv": "*",
"symfony/console": "^5.4|^6.0",
+ "symfony/http-kernel": "^5.4|^6.0",
"symfony/process": "^5.4|^6.0",
"symfony/uid": "^5.4|^6.0",
"twig/twig": "^2.13|^3.0.4"
@@ -7866,7 +8289,7 @@
"dump"
],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v6.3.1"
+ "source": "https://github.com/symfony/var-dumper/tree/v6.3.6"
},
"funding": [
{
@@ -7882,7 +8305,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-21T12:08:28+00:00"
+ "time": "2023-10-12T18:45:56+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -8225,16 +8648,16 @@
},
{
"name": "filp/whoops",
- "version": "2.15.2",
+ "version": "2.15.3",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
- "reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73"
+ "reference": "c83e88a30524f9360b11f585f71e6b17313b7187"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/filp/whoops/zipball/aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
- "reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
+ "url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187",
+ "reference": "c83e88a30524f9360b11f585f71e6b17313b7187",
"shasum": ""
},
"require": {
@@ -8284,7 +8707,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
- "source": "https://github.com/filp/whoops/tree/2.15.2"
+ "source": "https://github.com/filp/whoops/tree/2.15.3"
},
"funding": [
{
@@ -8292,7 +8715,7 @@
"type": "github"
}
],
- "time": "2023-04-12T12:00:00+00:00"
+ "time": "2023-07-13T12:00:00+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -8347,16 +8770,16 @@
},
{
"name": "laravel/telescope",
- "version": "v4.15.0",
+ "version": "v4.17.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/telescope.git",
- "reference": "572a19b4c9b09295848de9a2352737a756a0fb05"
+ "reference": "7afb0f6f82399c488fe6d3bf8e9489f92004504a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/telescope/zipball/572a19b4c9b09295848de9a2352737a756a0fb05",
- "reference": "572a19b4c9b09295848de9a2352737a756a0fb05",
+ "url": "https://api.github.com/repos/laravel/telescope/zipball/7afb0f6f82399c488fe6d3bf8e9489f92004504a",
+ "reference": "7afb0f6f82399c488fe6d3bf8e9489f92004504a",
"shasum": ""
},
"require": {
@@ -8412,43 +8835,39 @@
],
"support": {
"issues": "https://github.com/laravel/telescope/issues",
- "source": "https://github.com/laravel/telescope/tree/v4.15.0"
+ "source": "https://github.com/laravel/telescope/tree/v4.17.0"
},
- "time": "2023-06-08T13:57:22+00:00"
+ "time": "2023-10-31T15:36:43+00:00"
},
{
"name": "mockery/mockery",
- "version": "1.6.2",
+ "version": "1.6.6",
"source": {
"type": "git",
"url": "https://github.com/mockery/mockery.git",
- "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191"
+ "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/mockery/mockery/zipball/13a7fa2642c76c58fa2806ef7f565344c817a191",
- "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191",
+ "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e",
+ "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e",
"shasum": ""
},
"require": {
"hamcrest/hamcrest-php": "^2.0.1",
"lib-pcre": ">=7.0",
- "php": "^7.4 || ^8.0"
+ "php": ">=7.3"
},
"conflict": {
"phpunit/phpunit": "<8.0"
},
"require-dev": {
- "phpunit/phpunit": "^8.5 || ^9.3",
- "psalm/plugin-phpunit": "^0.18",
- "vimeo/psalm": "^5.9"
+ "phpunit/phpunit": "^8.5 || ^9.6.10",
+ "psalm/plugin-phpunit": "^0.18.4",
+ "symplify/easy-coding-standard": "^11.5.0",
+ "vimeo/psalm": "^4.30"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "1.6.x-dev"
- }
- },
"autoload": {
"files": [
"library/helpers.php",
@@ -8466,12 +8885,20 @@
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
- "homepage": "http://blog.astrumfutura.com"
+ "homepage": "https://github.com/padraic",
+ "role": "Author"
},
{
"name": "Dave Marshall",
"email": "dave.marshall@atstsolutions.co.uk",
- "homepage": "http://davedevelopment.co.uk"
+ "homepage": "https://davedevelopment.co.uk",
+ "role": "Developer"
+ },
+ {
+ "name": "Nathanael Esayeas",
+ "email": "nathanael.esayeas@protonmail.com",
+ "homepage": "https://github.com/ghostwriter",
+ "role": "Lead Developer"
}
],
"description": "Mockery is a simple yet flexible PHP mock object framework",
@@ -8489,10 +8916,13 @@
"testing"
],
"support": {
+ "docs": "https://docs.mockery.io/",
"issues": "https://github.com/mockery/mockery/issues",
- "source": "https://github.com/mockery/mockery/tree/1.6.2"
+ "rss": "https://github.com/mockery/mockery/releases.atom",
+ "security": "https://github.com/mockery/mockery/security/advisories",
+ "source": "https://github.com/mockery/mockery"
},
- "time": "2023-06-07T09:07:52+00:00"
+ "time": "2023-08-09T00:03:52+00:00"
},
{
"name": "myclabs/deep-copy",
@@ -8555,40 +8985,40 @@
},
{
"name": "nunomaduro/collision",
- "version": "v7.6.0",
+ "version": "v7.10.0",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
- "reference": "87faf7bc1c42d7fef7c60ec5c143050ce2a6189a"
+ "reference": "49ec67fa7b002712da8526678abd651c09f375b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nunomaduro/collision/zipball/87faf7bc1c42d7fef7c60ec5c143050ce2a6189a",
- "reference": "87faf7bc1c42d7fef7c60ec5c143050ce2a6189a",
+ "url": "https://api.github.com/repos/nunomaduro/collision/zipball/49ec67fa7b002712da8526678abd651c09f375b2",
+ "reference": "49ec67fa7b002712da8526678abd651c09f375b2",
"shasum": ""
},
"require": {
- "filp/whoops": "^2.15.2",
+ "filp/whoops": "^2.15.3",
"nunomaduro/termwind": "^1.15.1",
"php": "^8.1.0",
- "symfony/console": "^6.3.0"
+ "symfony/console": "^6.3.4"
},
"conflict": {
- "phpunit/phpunit": "<10.1.2"
+ "laravel/framework": ">=11.0.0"
},
"require-dev": {
- "brianium/paratest": "^7.2.0",
- "laravel/framework": "^10.13.5",
- "laravel/pint": "^1.10.2",
- "laravel/sail": "^1.22.0",
- "laravel/sanctum": "^3.2.5",
- "laravel/tinker": "^2.8.1",
- "nunomaduro/larastan": "^2.6.3",
- "orchestra/testbench-core": "^8.5.7",
- "pestphp/pest": "^2",
- "phpunit/phpunit": "^10.2.2",
+ "brianium/paratest": "^7.3.0",
+ "laravel/framework": "^10.28.0",
+ "laravel/pint": "^1.13.3",
+ "laravel/sail": "^1.25.0",
+ "laravel/sanctum": "^3.3.1",
+ "laravel/tinker": "^2.8.2",
+ "nunomaduro/larastan": "^2.6.4",
+ "orchestra/testbench-core": "^8.13.0",
+ "pestphp/pest": "^2.23.2",
+ "phpunit/phpunit": "^10.4.1",
"sebastian/environment": "^6.0.1",
- "spatie/laravel-ignition": "^2.1.3"
+ "spatie/laravel-ignition": "^2.3.1"
},
"type": "library",
"extra": {
@@ -8647,7 +9077,7 @@
"type": "patreon"
}
],
- "time": "2023-06-15T10:51:08+00:00"
+ "time": "2023-10-11T15:45:01+00:00"
},
{
"name": "phar-io/manifest",
@@ -8762,16 +9192,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.10.26",
+ "version": "1.10.40",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "5d660cbb7e1b89253a47147ae44044f49832351f"
+ "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f",
- "reference": "5d660cbb7e1b89253a47147ae44044f49832351f",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d",
+ "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d",
"shasum": ""
},
"require": {
@@ -8820,20 +9250,20 @@
"type": "tidelift"
}
],
- "time": "2023-07-19T12:44:37+00:00"
+ "time": "2023-10-30T14:48:31+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "10.1.2",
+ "version": "10.1.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e"
+ "reference": "355324ca4980b8916c18b9db29f3ef484078f26e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db1497ec8dd382e82c962f7abbe0320e4882ee4e",
- "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/355324ca4980b8916c18b9db29f3ef484078f26e",
+ "reference": "355324ca4980b8916c18b9db29f3ef484078f26e",
"shasum": ""
},
"require": {
@@ -8890,7 +9320,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.2"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.7"
},
"funding": [
{
@@ -8898,20 +9328,20 @@
"type": "github"
}
],
- "time": "2023-05-22T09:04:27+00:00"
+ "time": "2023-10-04T15:34:17+00:00"
},
{
"name": "phpunit/php-file-iterator",
- "version": "4.0.2",
+ "version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "5647d65443818959172645e7ed999217360654b6"
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6",
- "reference": "5647d65443818959172645e7ed999217360654b6",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
"shasum": ""
},
"require": {
@@ -8951,7 +9381,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2"
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
},
"funding": [
{
@@ -8959,7 +9389,7 @@
"type": "github"
}
],
- "time": "2023-05-07T09:13:23+00:00"
+ "time": "2023-08-31T06:24:48+00:00"
},
{
"name": "phpunit/php-invoker",
@@ -9026,16 +9456,16 @@
},
{
"name": "phpunit/php-text-template",
- "version": "3.0.0",
+ "version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d"
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
- "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
"shasum": ""
},
"require": {
@@ -9073,7 +9503,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0"
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
},
"funding": [
{
@@ -9081,7 +9512,7 @@
"type": "github"
}
],
- "time": "2023-02-03T06:56:46+00:00"
+ "time": "2023-08-31T14:07:24+00:00"
},
{
"name": "phpunit/php-timer",
@@ -9144,16 +9575,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "10.2.2",
+ "version": "10.4.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "1ab521b24b88b88310c40c26c0cc4a94ba40ff95"
+ "reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1ab521b24b88b88310c40c26c0cc4a94ba40ff95",
- "reference": "1ab521b24b88b88310c40c26c0cc4a94ba40ff95",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/cacd8b9dd224efa8eb28beb69004126c7ca1a1a1",
+ "reference": "cacd8b9dd224efa8eb28beb69004126c7ca1a1a1",
"shasum": ""
},
"require": {
@@ -9167,7 +9598,7 @@
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"php": ">=8.1",
- "phpunit/php-code-coverage": "^10.1.1",
+ "phpunit/php-code-coverage": "^10.1.5",
"phpunit/php-file-iterator": "^4.0",
"phpunit/php-invoker": "^4.0",
"phpunit/php-text-template": "^3.0",
@@ -9177,8 +9608,8 @@
"sebastian/comparator": "^5.0",
"sebastian/diff": "^5.0",
"sebastian/environment": "^6.0",
- "sebastian/exporter": "^5.0",
- "sebastian/global-state": "^6.0",
+ "sebastian/exporter": "^5.1",
+ "sebastian/global-state": "^6.0.1",
"sebastian/object-enumerator": "^5.0",
"sebastian/recursion-context": "^5.0",
"sebastian/type": "^4.0",
@@ -9193,7 +9624,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "10.2-dev"
+ "dev-main": "10.4-dev"
}
},
"autoload": {
@@ -9225,7 +9656,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.2"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.4.2"
},
"funding": [
{
@@ -9241,7 +9672,7 @@
"type": "tidelift"
}
],
- "time": "2023-06-11T06:15:20+00:00"
+ "time": "2023-10-26T07:21:45+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -9412,16 +9843,16 @@
},
{
"name": "sebastian/comparator",
- "version": "5.0.0",
+ "version": "5.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c"
+ "reference": "2db5010a484d53ebf536087a70b4a5423c102372"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c",
- "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372",
+ "reference": "2db5010a484d53ebf536087a70b4a5423c102372",
"shasum": ""
},
"require": {
@@ -9432,7 +9863,7 @@
"sebastian/exporter": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.0"
+ "phpunit/phpunit": "^10.3"
},
"type": "library",
"extra": {
@@ -9476,7 +9907,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0"
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1"
},
"funding": [
{
@@ -9484,20 +9916,20 @@
"type": "github"
}
],
- "time": "2023-02-03T07:07:16+00:00"
+ "time": "2023-08-14T13:18:12+00:00"
},
{
"name": "sebastian/complexity",
- "version": "3.0.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6"
+ "reference": "68cfb347a44871f01e33ab0ef8215966432f6957"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
- "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68cfb347a44871f01e33ab0ef8215966432f6957",
+ "reference": "68cfb347a44871f01e33ab0ef8215966432f6957",
"shasum": ""
},
"require": {
@@ -9510,7 +9942,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.0-dev"
+ "dev-main": "3.1-dev"
}
},
"autoload": {
@@ -9533,7 +9965,8 @@
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
- "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0"
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/3.1.0"
},
"funding": [
{
@@ -9541,7 +9974,7 @@
"type": "github"
}
],
- "time": "2023-02-03T06:59:47+00:00"
+ "time": "2023-09-28T11:50:59+00:00"
},
{
"name": "sebastian/diff",
@@ -9676,16 +10109,16 @@
},
{
"name": "sebastian/exporter",
- "version": "5.0.0",
+ "version": "5.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0"
+ "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
- "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc",
+ "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc",
"shasum": ""
},
"require": {
@@ -9699,7 +10132,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -9741,7 +10174,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0"
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1"
},
"funding": [
{
@@ -9749,20 +10183,20 @@
"type": "github"
}
],
- "time": "2023-02-03T07:06:49+00:00"
+ "time": "2023-09-24T13:22:09+00:00"
},
{
"name": "sebastian/global-state",
- "version": "6.0.0",
+ "version": "6.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "aab257c712de87b90194febd52e4d184551c2d44"
+ "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44",
- "reference": "aab257c712de87b90194febd52e4d184551c2d44",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4",
+ "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4",
"shasum": ""
},
"require": {
@@ -9802,7 +10236,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0"
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1"
},
"funding": [
{
@@ -9810,20 +10245,20 @@
"type": "github"
}
],
- "time": "2023-02-03T07:07:38+00:00"
+ "time": "2023-07-19T07:19:23+00:00"
},
{
"name": "sebastian/lines-of-code",
- "version": "2.0.0",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130"
+ "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130",
- "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d",
+ "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d",
"shasum": ""
},
"require": {
@@ -9859,7 +10294,8 @@
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0"
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1"
},
"funding": [
{
@@ -9867,7 +10303,7 @@
"type": "github"
}
],
- "time": "2023-02-03T07:08:02+00:00"
+ "time": "2023-08-31T09:25:50+00:00"
},
{
"name": "sebastian/object-enumerator",
@@ -10155,16 +10591,16 @@
},
{
"name": "spatie/backtrace",
- "version": "1.4.1",
+ "version": "1.5.3",
"source": {
"type": "git",
"url": "https://github.com/spatie/backtrace.git",
- "reference": "47794d19e3215ace9e005a8f200cd7cc7be52572"
+ "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/backtrace/zipball/47794d19e3215ace9e005a8f200cd7cc7be52572",
- "reference": "47794d19e3215ace9e005a8f200cd7cc7be52572",
+ "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab",
+ "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab",
"shasum": ""
},
"require": {
@@ -10201,7 +10637,7 @@
"spatie"
],
"support": {
- "source": "https://github.com/spatie/backtrace/tree/1.4.1"
+ "source": "https://github.com/spatie/backtrace/tree/1.5.3"
},
"funding": [
{
@@ -10213,43 +10649,44 @@
"type": "other"
}
],
- "time": "2023-06-13T14:35:04+00:00"
+ "time": "2023-06-28T12:59:17+00:00"
},
{
"name": "spatie/flare-client-php",
- "version": "1.3.6",
+ "version": "1.4.3",
"source": {
"type": "git",
"url": "https://github.com/spatie/flare-client-php.git",
- "reference": "530ac81255af79f114344286e4275f8869c671e2"
+ "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/530ac81255af79f114344286e4275f8869c671e2",
- "reference": "530ac81255af79f114344286e4275f8869c671e2",
+ "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec",
+ "reference": "5db2fdd743c3ede33f2a5367d89ec1a7c9c1d1ec",
"shasum": ""
},
"require": {
- "illuminate/pipeline": "^8.0|^9.0|^10.0",
+ "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0",
+ "nesbot/carbon": "^2.62.1",
"php": "^8.0",
- "spatie/backtrace": "^1.2",
- "symfony/http-foundation": "^5.0|^6.0",
- "symfony/mime": "^5.2|^6.0",
- "symfony/process": "^5.2|^6.0",
- "symfony/var-dumper": "^5.2|^6.0"
+ "spatie/backtrace": "^1.5.2",
+ "symfony/http-foundation": "^5.2|^6.0|^7.0",
+ "symfony/mime": "^5.2|^6.0|^7.0",
+ "symfony/process": "^5.2|^6.0|^7.0",
+ "symfony/var-dumper": "^5.2|^6.0|^7.0"
},
"require-dev": {
- "dms/phpunit-arraysubset-asserts": "^0.3.0",
- "pestphp/pest": "^1.20",
+ "dms/phpunit-arraysubset-asserts": "^0.5.0",
+ "pestphp/pest": "^1.20|^2.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
- "spatie/phpunit-snapshot-assertions": "^4.0"
+ "spatie/phpunit-snapshot-assertions": "^4.0|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.1.x-dev"
+ "dev-main": "1.3.x-dev"
}
},
"autoload": {
@@ -10274,7 +10711,7 @@
],
"support": {
"issues": "https://github.com/spatie/flare-client-php/issues",
- "source": "https://github.com/spatie/flare-client-php/tree/1.3.6"
+ "source": "https://github.com/spatie/flare-client-php/tree/1.4.3"
},
"funding": [
{
@@ -10282,41 +10719,41 @@
"type": "github"
}
],
- "time": "2023-04-12T07:57:12+00:00"
+ "time": "2023-10-17T15:54:07+00:00"
},
{
"name": "spatie/ignition",
- "version": "1.8.1",
+ "version": "1.11.3",
"source": {
"type": "git",
"url": "https://github.com/spatie/ignition.git",
- "reference": "d8eb8ea1ed27f48a694405cff363746ffd37f13e"
+ "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/ignition/zipball/d8eb8ea1ed27f48a694405cff363746ffd37f13e",
- "reference": "d8eb8ea1ed27f48a694405cff363746ffd37f13e",
+ "url": "https://api.github.com/repos/spatie/ignition/zipball/3d886de644ff7a5b42e4d27c1e1f67c8b5f00044",
+ "reference": "3d886de644ff7a5b42e4d27c1e1f67c8b5f00044",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"php": "^8.0",
- "spatie/backtrace": "^1.4",
- "spatie/flare-client-php": "^1.1",
- "symfony/console": "^5.4|^6.0",
- "symfony/var-dumper": "^5.4|^6.0"
+ "spatie/backtrace": "^1.5.3",
+ "spatie/flare-client-php": "^1.4.0",
+ "symfony/console": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
},
"require-dev": {
- "illuminate/cache": "^9.52",
+ "illuminate/cache": "^9.52|^10.0|^11.0",
"mockery/mockery": "^1.4",
- "pestphp/pest": "^1.20",
+ "pestphp/pest": "^1.20|^2.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"psr/simple-cache-implementation": "*",
- "symfony/cache": "^6.2",
- "symfony/process": "^5.4|^6.0",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
"vlucas/phpdotenv": "^5.5"
},
"suggest": {
@@ -10365,20 +10802,20 @@
"type": "github"
}
],
- "time": "2023-06-06T14:14:58+00:00"
+ "time": "2023-10-18T14:09:40+00:00"
},
{
"name": "spatie/laravel-ignition",
- "version": "2.1.3",
+ "version": "2.3.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-ignition.git",
- "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25"
+ "reference": "bf21cd15aa47fa4ec5d73bbc932005c70261efc8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/35711943d4725aa80f8033e4f1cb3a6775530b25",
- "reference": "35711943d4725aa80f8033e4f1cb3a6775530b25",
+ "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/bf21cd15aa47fa4ec5d73bbc932005c70261efc8",
+ "reference": "bf21cd15aa47fa4ec5d73bbc932005c70261efc8",
"shasum": ""
},
"require": {
@@ -10388,7 +10825,7 @@
"illuminate/support": "^10.0",
"php": "^8.1",
"spatie/flare-client-php": "^1.3.5",
- "spatie/ignition": "^1.5.0",
+ "spatie/ignition": "^1.9",
"symfony/console": "^6.2.3",
"symfony/var-dumper": "^6.2.3"
},
@@ -10457,7 +10894,7 @@
"type": "github"
}
],
- "time": "2023-05-25T11:30:27+00:00"
+ "time": "2023-10-09T12:55:26+00:00"
},
{
"name": "theseer/tokenizer",
@@ -10519,5 +10956,5 @@
"php": "^8.1"
},
"platform-dev": [],
- "plugin-api-version": "2.3.0"
+ "plugin-api-version": "2.2.0"
}
diff --git a/GaelO2/config/app.php b/GaelO2/config/app.php
index 909a9baca..68c239dd5 100644
--- a/GaelO2/config/app.php
+++ b/GaelO2/config/app.php
@@ -165,9 +165,9 @@
'orthanc_storage_login' => env('ORTHANC_STORAGE_LOGIN'),
'orthanc_storage_password' => env('ORTHANC_STORAGE_PASSWORD'),
'tus_url' => env('TUS_URL'),
- 'gaelo_processing_protocol' => env('GAELO_PROCESSING_PROTOCOL'),
- 'gaelo_processing_host' => env('GAELO_PROCESSING_HOST'),
- 'gaelo_processing_port' => env('GAELO_PROCESSING_PORT'),
+ 'gaelo_processing_url' => env('GAELO_PROCESSING_URL'),
+ 'gaelo_processing_login' => env('GAELO_PROCESSING_LOGIN'),
+ 'gaelo_processing_password' => env('GAELO_PROCESSING_PASSWORD'),
'azure_directory_id' => env('AZURE_DIRECTORY_ID'),
'azure_client_id' => env('AZURE_CLIENT_ID'),
'azure_client_secret' => env('AZURE_CLIENT_SECRET'),
diff --git a/GaelO2/config/dompdf.php b/GaelO2/config/dompdf.php
new file mode 100644
index 000000000..8ad202243
--- /dev/null
+++ b/GaelO2/config/dompdf.php
@@ -0,0 +1,284 @@
+ false, // Throw an Exception on warnings from dompdf
+
+ 'public_path' => null, // Override the public path if needed
+
+ /*
+ * Dejavu Sans font is missing glyphs for converted entities, turn it off if you need to show € and £.
+ */
+ 'convert_entities' => true,
+
+ 'options' => array(
+ /**
+ * The location of the DOMPDF font directory
+ *
+ * The location of the directory where DOMPDF will store fonts and font metrics
+ * Note: This directory must exist and be writable by the webserver process.
+ * *Please note the trailing slash.*
+ *
+ * Notes regarding fonts:
+ * Additional .afm font metrics can be added by executing load_font.php from command line.
+ *
+ * Only the original "Base 14 fonts" are present on all pdf viewers. Additional fonts must
+ * be embedded in the pdf file or the PDF may not display correctly. This can significantly
+ * increase file size unless font subsetting is enabled. Before embedding a font please
+ * review your rights under the font license.
+ *
+ * Any font specification in the source HTML is translated to the closest font available
+ * in the font directory.
+ *
+ * The pdf standard "Base 14 fonts" are:
+ * Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique,
+ * Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique,
+ * Times-Roman, Times-Bold, Times-BoldItalic, Times-Italic,
+ * Symbol, ZapfDingbats.
+ */
+ "font_dir" => storage_path('fonts'), // advised by dompdf (https://github.com/dompdf/dompdf/pull/782)
+
+ /**
+ * The location of the DOMPDF font cache directory
+ *
+ * This directory contains the cached font metrics for the fonts used by DOMPDF.
+ * This directory can be the same as DOMPDF_FONT_DIR
+ *
+ * Note: This directory must exist and be writable by the webserver process.
+ */
+ "font_cache" => storage_path('fonts'),
+
+ /**
+ * The location of a temporary directory.
+ *
+ * The directory specified must be writeable by the webserver process.
+ * The temporary directory is required to download remote images and when
+ * using the PFDLib back end.
+ */
+ "temp_dir" => sys_get_temp_dir(),
+
+ /**
+ * ==== IMPORTANT ====
+ *
+ * dompdf's "chroot": Prevents dompdf from accessing system files or other
+ * files on the webserver. All local files opened by dompdf must be in a
+ * subdirectory of this directory. DO NOT set it to '/' since this could
+ * allow an attacker to use dompdf to read any files on the server. This
+ * should be an absolute path.
+ * This is only checked on command line call by dompdf.php, but not by
+ * direct class use like:
+ * $dompdf = new DOMPDF(); $dompdf->load_html($htmldata); $dompdf->render(); $pdfdata = $dompdf->output();
+ */
+ "chroot" => realpath(base_path()),
+
+ /**
+ * Protocol whitelist
+ *
+ * Protocols and PHP wrappers allowed in URIs, and the validation rules
+ * that determine if a resouce may be loaded. Full support is not guaranteed
+ * for the protocols/wrappers specified
+ * by this array.
+ *
+ * @var array
+ */
+ 'allowed_protocols' => [
+ "file://" => ["rules" => []],
+ "http://" => ["rules" => []],
+ "https://" => ["rules" => []]
+ ],
+
+ /**
+ * @var string
+ */
+ 'log_output_file' => null,
+
+ /**
+ * Whether to enable font subsetting or not.
+ */
+ "enable_font_subsetting" => false,
+
+ /**
+ * The PDF rendering backend to use
+ *
+ * Valid settings are 'PDFLib', 'CPDF' (the bundled R&OS PDF class), 'GD' and
+ * 'auto'. 'auto' will look for PDFLib and use it if found, or if not it will
+ * fall back on CPDF. 'GD' renders PDFs to graphic files. {@link
+ * Canvas_Factory} ultimately determines which rendering class to instantiate
+ * based on this setting.
+ *
+ * Both PDFLib & CPDF rendering backends provide sufficient rendering
+ * capabilities for dompdf, however additional features (e.g. object,
+ * image and font support, etc.) differ between backends. Please see
+ * {@link PDFLib_Adapter} for more information on the PDFLib backend
+ * and {@link CPDF_Adapter} and lib/class.pdf.php for more information
+ * on CPDF. Also see the documentation for each backend at the links
+ * below.
+ *
+ * The GD rendering backend is a little different than PDFLib and
+ * CPDF. Several features of CPDF and PDFLib are not supported or do
+ * not make any sense when creating image files. For example,
+ * multiple pages are not supported, nor are PDF 'objects'. Have a
+ * look at {@link GD_Adapter} for more information. GD support is
+ * experimental, so use it at your own risk.
+ *
+ * @link http://www.pdflib.com
+ * @link http://www.ros.co.nz/pdf
+ * @link http://www.php.net/image
+ */
+ "pdf_backend" => "CPDF",
+
+ /**
+ * PDFlib license key
+ *
+ * If you are using a licensed, commercial version of PDFlib, specify
+ * your license key here. If you are using PDFlib-Lite or are evaluating
+ * the commercial version of PDFlib, comment out this setting.
+ *
+ * @link http://www.pdflib.com
+ *
+ * If pdflib present in web server and auto or selected explicitely above,
+ * a real license code must exist!
+ */
+ //"DOMPDF_PDFLIB_LICENSE" => "your license key here",
+
+ /**
+ * html target media view which should be rendered into pdf.
+ * List of types and parsing rules for future extensions:
+ * http://www.w3.org/TR/REC-html40/types.html
+ * screen, tty, tv, projection, handheld, print, braille, aural, all
+ * Note: aural is deprecated in CSS 2.1 because it is replaced by speech in CSS 3.
+ * Note, even though the generated pdf file is intended for print output,
+ * the desired content might be different (e.g. screen or projection view of html file).
+ * Therefore allow specification of content here.
+ */
+ "default_media_type" => "screen",
+
+ /**
+ * The default paper size.
+ *
+ * North America standard is "letter"; other countries generally "a4"
+ *
+ * @see CPDF_Adapter::PAPER_SIZES for valid sizes ('letter', 'legal', 'A4', etc.)
+ */
+ "default_paper_size" => "a4",
+
+ /**
+ * The default paper orientation.
+ *
+ * The orientation of the page (portrait or landscape).
+ *
+ * @var string
+ */
+ 'default_paper_orientation' => "portrait",
+
+ /**
+ * The default font family
+ *
+ * Used if no suitable fonts can be found. This must exist in the font folder.
+ * @var string
+ */
+ "default_font" => "serif",
+
+ /**
+ * Image DPI setting
+ *
+ * This setting determines the default DPI setting for images and fonts. The
+ * DPI may be overridden for inline images by explictly setting the
+ * image's width & height style attributes (i.e. if the image's native
+ * width is 600 pixels and you specify the image's width as 72 points,
+ * the image will have a DPI of 600 in the rendered PDF. The DPI of
+ * background images can not be overridden and is controlled entirely
+ * via this parameter.
+ *
+ * For the purposes of DOMPDF, pixels per inch (PPI) = dots per inch (DPI).
+ * If a size in html is given as px (or without unit as image size),
+ * this tells the corresponding size in pt.
+ * This adjusts the relative sizes to be similar to the rendering of the
+ * html page in a reference browser.
+ *
+ * In pdf, always 1 pt = 1/72 inch
+ *
+ * Rendering resolution of various browsers in px per inch:
+ * Windows Firefox and Internet Explorer:
+ * SystemControl->Display properties->FontResolution: Default:96, largefonts:120, custom:?
+ * Linux Firefox:
+ * about:config *resolution: Default:96
+ * (xorg screen dimension in mm and Desktop font dpi settings are ignored)
+ *
+ * Take care about extra font/image zoom factor of browser.
+ *
+ * In images, size in pixel attribute, img css style, are overriding
+ * the real image dimension in px for rendering.
+ *
+ * @var int
+ */
+ "dpi" => 96,
+
+ /**
+ * Enable inline PHP
+ *
+ * If this setting is set to true then DOMPDF will automatically evaluate
+ * inline PHP contained within tags.
+ *
+ * Enabling this for documents you do not trust (e.g. arbitrary remote html
+ * pages) is a security risk. Set this option to false if you wish to process
+ * untrusted documents.
+ *
+ * @var bool
+ */
+ "enable_php" => false,
+
+ /**
+ * Enable inline Javascript
+ *
+ * If this setting is set to true then DOMPDF will automatically insert
+ * JavaScript code contained within tags.
+ *
+ * @var bool
+ */
+ "enable_javascript" => true,
+
+ /**
+ * Enable remote file access
+ *
+ * If this setting is set to true, DOMPDF will access remote sites for
+ * images and CSS files as required.
+ * This is required for part of test case www/test/image_variants.html through www/examples.php
+ *
+ * Attention!
+ * This can be a security risk, in particular in combination with DOMPDF_ENABLE_PHP and
+ * allowing remote access to dompdf.php or on allowing remote html code to be passed to
+ * $dompdf = new DOMPDF(, $dompdf->load_html(...,
+ * This allows anonymous users to download legally doubtful internet content which on
+ * tracing back appears to being downloaded by your server, or allows malicious php code
+ * in remote html pages to be executed by your server with your account privileges.
+ *
+ * @var bool
+ */
+ "enable_remote" => true,
+
+ /**
+ * A ratio applied to the fonts height to be more like browsers' line height
+ */
+ "font_height_ratio" => 1.1,
+
+ /**
+ * Use the HTML5 Lib parser
+ *
+ * @deprecated This feature is now always on in dompdf 2.x
+ * @var bool
+ */
+ "enable_html5_parser" => true,
+ ),
+
+
+);
diff --git a/GaelO2/config/queue.php b/GaelO2/config/queue.php
index 178d302bd..2315c9775 100644
--- a/GaelO2/config/queue.php
+++ b/GaelO2/config/queue.php
@@ -38,14 +38,14 @@
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
- 'retry_after' => 90,
+ 'retry_after' => 1800,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => 'localhost',
'queue' => 'default',
- 'retry_after' => 90,
+ 'retry_after' => 1800,
'block_for' => 0,
],
@@ -63,7 +63,7 @@
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
- 'retry_after' => 600,
+ 'retry_after' => 1800,
'block_for' => null,
],
diff --git a/GaelO2/database/factories/StudyFactory.php b/GaelO2/database/factories/StudyFactory.php
index 20d85149c..4933881a7 100644
--- a/GaelO2/database/factories/StudyFactory.php
+++ b/GaelO2/database/factories/StudyFactory.php
@@ -17,7 +17,8 @@ public function definition()
'controller_show_all' => false,
'monitor_show_all' => false,
'documentation_mandatory' => false,
- 'ancillary_of' => null
+ 'ancillary_of' => null,
+ 'creatable_patients_investigator' => false,
];
}
@@ -75,14 +76,21 @@ public function ancillaryOf(string $studyName)
});
}
- public function documentationMandatory()
+ public function documentationMandatory()
{
return $this->state(function (array $attributes) {
return [
'documentation_mandatory' => true,
];
});
+ }
-
+ public function creatablePatientsInvestigator()
+ {
+ return $this->state(function (array $attributes) {
+ return [
+ 'creatable_patients_investigator' => true,
+ ];
+ });
}
}
diff --git a/GaelO2/database/factories/VisitFactory.php b/GaelO2/database/factories/VisitFactory.php
index 5b0d39598..3bfb136ea 100644
--- a/GaelO2/database/factories/VisitFactory.php
+++ b/GaelO2/database/factories/VisitFactory.php
@@ -46,7 +46,8 @@ public function definition()
'corrective_action_new_upload' => $this->faker->randomElement([true, false]),
'corrective_action_investigator_form' => $this->faker->randomElement([true, false]),
'corrective_action_comment' => $this->faker->word,
- 'corrective_action_applied' => $this->faker->randomElement([true, false])
+ 'corrective_action_applied' => $this->faker->randomElement([true, false]),
+ 'sent_files' => []
];
}
@@ -122,6 +123,15 @@ public function uploadDone()
});
}
+ public function sentFiles(array $sentFiles)
+ {
+ return $this->state(function (array $attributes) use ($sentFiles) {
+ return [
+ 'sent_files' => $sentFiles,
+ ];
+ });
+ }
+
public function configure()
{
return $this->afterMaking(function (Visit $visit) {
diff --git a/GaelO2/database/migrations/2023_09_19_193551_add_file_visit.php b/GaelO2/database/migrations/2023_09_19_193551_add_file_visit.php
new file mode 100644
index 000000000..337315e01
--- /dev/null
+++ b/GaelO2/database/migrations/2023_09_19_193551_add_file_visit.php
@@ -0,0 +1,35 @@
+json('sent_files')->nullable(true);
+ });
+
+ DB::table('visits')->whereNull('sent_files')->update(['sent_files'=>'{}']);
+
+ Schema::table('visits', function (Blueprint $table) {
+ $table->json('sent_files')->nullable(false)->change();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('visits', function (Blueprint $table) {
+ $table->dropColumn('sent_files');
+ });
+ }
+};
diff --git a/GaelO2/database/migrations/2023_10_16_221003_creatable_patient.php b/GaelO2/database/migrations/2023_10_16_221003_creatable_patient.php
new file mode 100644
index 000000000..cf369cfde
--- /dev/null
+++ b/GaelO2/database/migrations/2023_10_16_221003_creatable_patient.php
@@ -0,0 +1,28 @@
+boolean('creatable_patients_investigator')->default(false);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('studies', function (Blueprint $table) {
+ $table->dropColumn('creatable_patients_investigator');
+ });
+ }
+};
diff --git a/GaelO2/routes/api.php b/GaelO2/routes/api.php
index 1103910a1..b57ed25df 100644
--- a/GaelO2/routes/api.php
+++ b/GaelO2/routes/api.php
@@ -92,6 +92,7 @@
Route::get('studies/{studyName}/dicom-studies', [StudyController::class, 'getDicomStudiesFromStudy']);
Route::post('studies/{studyName}/send-reminder', [StudyController::class, 'sendReminder']);
Route::post('studies/{studyName}/ask-patient-creation', [StudyController::class, 'requestPatientCreation']);
+ Route::get('studies/{studyName}/creatable-patients', [StudyController::class, 'getCreatablePatients']);
Route::post('send-mail', [StudyController::class, 'sendMail']);
//Centers Routes
@@ -112,6 +113,7 @@
//VisitType Routes
Route::post('visit-groups/{visitGroupId}/visit-types', [VisitTypeController::class, 'createVisitType']);
Route::get('visit-types/{visitTypeId}', [VisitTypeController::class, 'getVisitType']);
+ Route::get('visit-types/{visitTypeId}/files/metadata', [VisitTypeController::class, 'getFileMetadataFromVisitType']);
Route::delete('visit-types/{visitTypeId}', [VisitTypeController::class, 'deleteVisitType']);
//Patients Routes
@@ -133,6 +135,9 @@
Route::post('visits/{id}/activate', [VisitController::class, 'reactivateVisit']);
Route::post('visit-types/{visitTypeId}/visits', [VisitController::class, 'createVisit']);
Route::get('visits/{id}', [VisitController::class, 'getVisit']);
+ Route::get('visits/{id}/files/{key}', [VisitController::class, 'getFileOfVisit']);
+ Route::post('visits/{id}/files/{key}', [VisitController::class, 'createFileOfVisit']);
+ Route::delete('visits/{id}/files/{key}', [VisitController::class, 'deleteFileOfVisit']);
//Local Form Routes
Route::get('visits/{id}/investigator-form', [ReviewController::class, 'getInvestigatorForm']);
@@ -148,8 +153,8 @@
Route::get('reviews/{id}', [ReviewController::class, 'getReviewForm']);
Route::delete('reviews/{id}', [ReviewController::class, 'deleteReviewForm']);
Route::patch('reviews/{id}/unlock', [ReviewController::class, 'unlockReviewForm']);
- Route::post('reviews/{id}/file/{key}', [ReviewController::class, 'createReviewFile']);
- Route::delete('reviews/{id}/file/{key}', [ReviewController::class, 'deleteReviewFile']);
+ Route::post('reviews/{id}/files/{key}', [ReviewController::class, 'createReviewFile']);
+ Route::delete('reviews/{id}/files/{key}', [ReviewController::class, 'deleteReviewFile']);
Route::get('visits/{visitId}/reviews', [ReviewController::class, 'getReviewsFromVisit']);
Route::get('studies/{studyName}/visits/{visitId}/reviewer-associated-data', [ReviewController::class, 'getAssociatedDataOfVisitForReviewer']);
@@ -194,7 +199,7 @@
Route::get('visits/{id}/dicoms/file', [DicomController::class, 'getVisitDicomsFile']);
Route::get('studies/{studyName}/export', [StudyController::class, 'exportStudyData']);
Route::post('studies/{studyName}/dicom-series/file', [DicomController::class, 'getSupervisorDicomsFile']);
- Route::get('reviews/{id}/file/{key}', [ReviewController::class, 'getReviewFile']);
+ Route::get('reviews/{id}/files/{key}', [ReviewController::class, 'getReviewFile']);
Route::get('dicom-series/{seriesInstanceUID}/nifti', [DicomController::class, 'getNiftiSeries']);
});
diff --git a/GaelO2/storage/fonts/.gitkeep b/GaelO2/storage/fonts/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/GaelO2/tests/Feature/TestPatients/ImportPatientTest.php b/GaelO2/tests/Feature/TestPatients/ImportPatientTest.php
index a473e8bdf..9810ef13f 100644
--- a/GaelO2/tests/Feature/TestPatients/ImportPatientTest.php
+++ b/GaelO2/tests/Feature/TestPatients/ImportPatientTest.php
@@ -14,199 +14,239 @@ class ImportPatientTest extends TestCase
{
use RefreshDatabase;
- protected function setUp() : void{
+ private Study $study;
+ private array $validPayload;
+
+ protected function setUp(): void
+ {
parent::setUp();
$this->artisan('db:seed');
$this->study = Study::factory()->patientCodeLength(14)->code('123')->create();
- $this->validPayload = [ ["code" => '12341231234123',
- "lastname" => "test",
- "firstname" => "test",
- "gender" => "M",
- "birthDay" => 1,
- "birthMonth" => 1,
- "birthYear" => 1998,
- "registrationDate" => '2011-10-05',
- "investigatorName" => "administrator",
- "centerCode" => 0,
- "inclusionStatus" => InclusionStatusEnum::INCLUDED->value
+ $this->validPayload = [[
+ "code" => '12341231234123',
+ "lastname" => "test",
+ "firstname" => "test",
+ "gender" => "M",
+ "birthDay" => 1,
+ "birthMonth" => 1,
+ "birthYear" => 1998,
+ "registrationDate" => '2011-10-05',
+ "investigatorName" => "administrator",
+ "centerCode" => 0,
+ "inclusionStatus" => InclusionStatusEnum::INCLUDED->value
]];
-
}
- public function testImportMultiplePatients() {
+ public function testImportMultiplePatients()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
- $this->validPayload = [ ["code" => '12341231234123',
- "lastname" => "test",
- "firstname" => "test",
- "gender" => "M",
- "birthDay" => 1,
- "birthMonth" => 1,
- "birthYear" => 1998,
- "registrationDate" => '2011-10-05',
- "investigatorName" => "administrator",
- "centerCode" => 0,
- "inclusionStatus" => InclusionStatusEnum::INCLUDED->value],
- ["code" => '12341231234124',
- "lastname" => "test",
- "firstname" => "test",
- "gender" => "M",
- "birthDay" => 1,
- "birthMonth" => 1,
- "birthYear" => 1998,
- "registrationDate" => '2011-10-06',
- "investigatorName" => "administrator",
- "centerCode" => 0,
- "inclusionStatus" => InclusionStatusEnum::INCLUDED->value],
- ["code" => '12341231234125',
- "lastname" => "test",
- "firstname" => "test",
- "gender" => "M",
- "birthDay" => 1,
- "birthMonth" => 1,
- "birthYear" => 1998,
- "registrationDate" => '2011-10-07',
- "investigatorName" => "administrator",
- "centerCode" => 0,
- "inclusionStatus" => InclusionStatusEnum::INCLUDED->value]
- ];
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $this->validPayload = [
+ [
+ "code" => '12341231234123',
+ "lastname" => "test",
+ "firstname" => "test",
+ "gender" => "M",
+ "birthDay" => 1,
+ "birthMonth" => 1,
+ "birthYear" => 1998,
+ "registrationDate" => '2011-10-05',
+ "investigatorName" => "administrator",
+ "centerCode" => 0,
+ "inclusionStatus" => InclusionStatusEnum::INCLUDED->value
+ ],
+ [
+ "code" => '12341231234124',
+ "lastname" => "test",
+ "firstname" => "test",
+ "gender" => "M",
+ "birthDay" => 1,
+ "birthMonth" => 1,
+ "birthYear" => 1998,
+ "registrationDate" => '2011-10-06',
+ "investigatorName" => "administrator",
+ "centerCode" => 0,
+ "inclusionStatus" => InclusionStatusEnum::INCLUDED->value
+ ],
+ [
+ "code" => '12341231234125',
+ "lastname" => "test",
+ "firstname" => "test",
+ "gender" => "M",
+ "birthDay" => 1,
+ "birthMonth" => 1,
+ "birthYear" => 1998,
+ "registrationDate" => '2011-10-07',
+ "investigatorName" => "administrator",
+ "centerCode" => 0,
+ "inclusionStatus" => InclusionStatusEnum::INCLUDED->value
+ ]
+ ];
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$resp->assertSuccessful();
- $this->assertEquals(3,sizeof($resp['success']));
- $this->assertEquals(0,sizeof($resp['fail']));
+ $this->assertEquals(3, sizeof($resp['success']));
+ $this->assertEquals(0, sizeof($resp['fail']));
- $patient1 = Patient::find($this->study->code.'12341231234123')->toArray();
+ $patient1 = Patient::find($this->study->code . '12341231234123')->toArray();
$this->assertEquals('2011-10-05T00:00:00.000000Z', $patient1['registration_date']);
}
- public function testImportPatient() {
+ public function testImportPatient()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
//Test patient creation
- $reponse1 = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload)->assertSuccessful();
- $this->assertEquals(1,sizeof($reponse1['success']));
- $this->assertEquals(0,sizeof($reponse1['fail']));
+ $reponse1 = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload)->assertSuccessful();
+ $this->assertEquals(1, sizeof($reponse1['success']));
+ $this->assertEquals(0, sizeof($reponse1['fail']));
//Test that copies of existing patients don't insert
- $response2 = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
- $this->assertEquals(0,sizeof($response2['success']));
- $this->assertEquals(1,sizeof($response2['fail']));
+ $response2 = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
+ $this->assertEquals(0, sizeof($response2['success']));
+ $this->assertEquals(1, sizeof($response2['fail']));
+ }
+
+ public function testImportPatientInvestigator()
+ {
+ $this->study->creatable_patients_investigator = true;
+ $this->study->save();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_INVESTIGATOR, $this->study->name);
+ $reponse1 = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Investigator', $this->validPayload)->assertSuccessful();
+ $this->assertEquals(1, sizeof($reponse1['success']));
+ $this->assertEquals(0, sizeof($reponse1['fail']));
+
}
- public function testImportPatientForbiddenNoRole(){
+ public function testImportPatientInvestigatorForbidden()
+ {
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_INVESTIGATOR, $this->study->name);
+ $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Investigator', $this->validPayload)->assertForbidden();
+ }
+
+ public function testImportPatientForbiddenNoRole()
+ {
AuthorizationTools::actAsAdmin(false);
- $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload)->assertStatus(403);
+ $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload)->assertStatus(403);
}
- public function testImportPatientForbiddenForAncillaryStudy(){
+ public function testImportPatientForbiddenForAncillaryStudy()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
$ancillaryStudies = Study::factory()->ancillaryOf($this->study->name)->create();
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $ancillaryStudies->name);
- $answer = $this->json('POST', '/api/studies/'.$ancillaryStudies->name.'/import-patients', $this->validPayload);
+ $answer = $this->json('POST', '/api/studies/' . $ancillaryStudies->name . '/import-patients?role=Supervisor', $this->validPayload);
$answer->assertStatus(403);
}
- public function testCreateWrongDayOfBirth() {
+ public function testCreateWrongDayOfBirth()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['birthDay'] = 0;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
//Check that inserting patient failed because day of birth was incorrect
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate day format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate day format'][0]);
$this->validPayload[0]['birthDay'] = 32;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate day format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate day format'][0]);
}
- public function testCreateWrongMonthOfBirth() {
+ public function testCreateWrongMonthOfBirth()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['birthMonth'] = 0;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
//Check that inserting patient failed because day of birth was incorrect
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate month format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate month format'][0]);
$this->validPayload[0]['birthMonth'] = 13;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate month format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate month format'][0]);
}
- public function testCreateWrongYearOfBirth() {
+ public function testCreateWrongYearOfBirth()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['birthYear'] = 1800;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
//Check that inserting patient failed because day of birth was incorrect
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate year format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate year format'][0]);
$this->validPayload[0]['birthYear'] = 3010;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Birthdate year format']);
$this->assertEquals(12341231234123, $resp['fail']['Incorrect Birthdate year format'][0]);
}
- public function testCreateAlreadyKnownPatient(){
+ public function testCreateAlreadyKnownPatient()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
- $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Existing Patient Code']);
$this->assertEquals(12341231234123, $resp['fail']['Existing Patient Code'][0]);
}
- public function testIncorrectPatientCodeLength(){
+ public function testIncorrectPatientCodeLength()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['code'] = '123';
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Incorrect Patient Code Length']);
$this->assertEquals(123, $resp['fail']['Incorrect Patient Code Length'][0]);
}
- public function testMissingInclusionDateWhileIncluded(){
+ public function testMissingInclusionDateWhileIncluded()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['registrationDate'] = '123';
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(0, count($resp['success']));
$this->assertNotEmpty($resp['fail']['Registration Date Missing or Invalid']);
$this->assertEquals(12341231234123, $resp['fail']['Registration Date Missing or Invalid'][0]);
}
- public function testMissingInclusionDateAllowedIfPreIncluded(){
+ public function testMissingInclusionDateAllowedIfPreIncluded()
+ {
$currentUserId = AuthorizationTools::actAsAdmin(false);
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $this->study->name);
$this->validPayload[0]['registrationDate'] = null;
$this->validPayload[0]['inclusionStatus'] = InclusionStatusEnum::PRE_INCLUDED->value;
- $resp = $this->json('POST', '/api/studies/'.$this->study->name.'/import-patients', $this->validPayload);
+ $resp = $this->json('POST', '/api/studies/' . $this->study->name . '/import-patients?role=Supervisor', $this->validPayload);
$this->assertEquals(1, count($resp['success']));
}
-
}
diff --git a/GaelO2/tests/Feature/TestReviewForm/GetFileFormTest.php b/GaelO2/tests/Feature/TestReviewForm/GetFileFormTest.php
index b022972f9..cae5c7e08 100644
--- a/GaelO2/tests/Feature/TestReviewForm/GetFileFormTest.php
+++ b/GaelO2/tests/Feature/TestReviewForm/GetFileFormTest.php
@@ -51,7 +51,7 @@ public function testGetFileOfForm(){
$review->sent_files = ['41' => $currentVisit['studyName'].'/'.'attached_review_file'.'/'.'review_1_41.csv'];
$review->save();
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $currentVisit['studyName'] );
- $response = $this->get('api/reviews/' . $review->id . '/file/41?role=Supervisor');
+ $response = $this->get('api/reviews/' . $review->id . '/files/41?role=Supervisor');
$response->assertSuccessful();
}
@@ -63,7 +63,7 @@ public function testGetFileOfFormShouldFailNoRole(){
$review = Review::factory()->userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
$review->sent_files = ['41' => $currentVisit['studyName'].'/'.'attached_review_file'.'/'.'review_1_41.csv'];
$review->save();
- $response = $this->get('api/reviews/' . $review->id . '/file/41?role=Supervisor');
+ $response = $this->get('api/reviews/' . $review->id . '/files/41?role=Supervisor');
$response->assertStatus(403);
}
@@ -75,7 +75,7 @@ public function testDeleteFileOfForm(){
$review = Review::factory()->userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
$review->sent_files = ['41' => $currentVisit['studyName'].'/'.'attached_review_file'.'/'.'review_1_41.csv'];
$review->save();
- $response = $this->delete('api/reviews/' . $review->id . '/file/41');
+ $response = $this->delete('api/reviews/' . $review->id . '/files/41');
$response->assertSuccessful();
}
@@ -85,7 +85,7 @@ public function testDeleteFileOfFormShouldFailNoRole(){
$review = Review::factory()->userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
$review->sent_files = ['41' => $currentVisit['studyName'].'/'.'attached_review_file'.'/'.'review_1_41.csv'];
$review->save();
- $response = $this->delete('api/reviews/' . $review->id . '/file/41');
+ $response = $this->delete('api/reviews/' . $review->id . '/files/41');
$response->assertStatus(403);
}
diff --git a/GaelO2/tests/Feature/TestReviewForm/UploadFileFormTest.php b/GaelO2/tests/Feature/TestReviewForm/UploadFileFormTest.php
index cf2b4d670..996d049ec 100644
--- a/GaelO2/tests/Feature/TestReviewForm/UploadFileFormTest.php
+++ b/GaelO2/tests/Feature/TestReviewForm/UploadFileFormTest.php
@@ -1,6 +1,5 @@
userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_INVESTIGATOR, $currentVisit['studyName'] );
AuthorizationTools::addAffiliatedCenter($currentUserId, $currentVisit['centerCode']);
- $response = $this->post('api/reviews/' . $review->id . '/file/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'text/csv']);
+ $response = $this->post('api/reviews/' . $review->id . '/files/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'text/csv']);
$response->assertSuccessful();
}
@@ -55,7 +54,7 @@ public function testUploadFileShouldFailNoRole()
$currentVisit = $this->createVisit();
$currentUserId = AuthorizationTools::actAsAdmin(false);
$review = Review::factory()->userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
- $response = $this->post('api/reviews/' . $review->id . '/file/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'text/csv']);
+ $response = $this->post('api/reviews/' . $review->id . '/files/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'text/csv']);
$response->assertStatus(403);
}
@@ -67,7 +66,7 @@ public function testUploadFileShouldFailWrongMime()
AuthorizationTools::addAffiliatedCenter($currentUserId, $currentVisit['centerCode']);
$review = Review::factory()->userId($currentUserId)->visitId($currentVisit['visitId'])->studyName($currentVisit['studyName'])->create();
AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_REVIEWER, $currentVisit['studyName'] );
- $response = $this->post('api/reviews/' . $review->id . '/file/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'image/png']);
+ $response = $this->post('api/reviews/' . $review->id . '/files/41', [base64_encode("testFileContent")], ['CONTENT_TYPE' => 'image/png']);
$response->assertStatus(400);
}
diff --git a/GaelO2/tests/Feature/TestStudy/CreateStudyTest.php b/GaelO2/tests/Feature/TestStudy/CreateStudyTest.php
index b8be40f67..9435cb022 100644
--- a/GaelO2/tests/Feature/TestStudy/CreateStudyTest.php
+++ b/GaelO2/tests/Feature/TestStudy/CreateStudyTest.php
@@ -23,7 +23,8 @@ protected function setUp(): void
'controllerShowAll' => true,
'monitorShowAll' => false,
'documentationMandatory' => false,
- 'contactEmail' => 'test@gaelo.fr'
+ 'contactEmail' => 'test@gaelo.fr',
+ 'creatablePatientsInvestigator' => false
];
}
diff --git a/GaelO2/tests/Feature/TestStudy/GetCreatablePatientsTest.php b/GaelO2/tests/Feature/TestStudy/GetCreatablePatientsTest.php
new file mode 100644
index 000000000..d7434e7f8
--- /dev/null
+++ b/GaelO2/tests/Feature/TestStudy/GetCreatablePatientsTest.php
@@ -0,0 +1,48 @@
+artisan('db:seed');
+ Study::factory()->name('TEST')->create();
+
+ $mockTestStudy = $this->partialMock(TEST::class, function (MockInterface $mock) {
+ $mock->shouldReceive('getExpectedPatients')
+ ->andReturn([new ExpectedPatient('1234', 0, 'Included')]);
+ });
+
+ $mockFramework = $this->partialMock(FrameworkAdapter::class, function (MockInterface $mock) use ($mockTestStudy) {
+ $mock->shouldReceive('make')
+ ->andReturn($mockTestStudy);
+ });
+
+
+ $this->instance(FrameworkAdapter::class, $mockFramework);
+ }
+
+ public function testGetCreatablePatient()
+ {
+
+ $userId = AuthorizationTools::actAsAdmin(true);
+ AuthorizationTools::addRoleToUser($userId, Constants::ROLE_INVESTIGATOR, "TEST");
+ $answer = $this->json('GET', '/api/studies/TEST/creatable-patients?role=Investigator');
+ $answer->assertSuccessful();
+ }
+}
diff --git a/GaelO2/tests/Feature/TestUser/ForgotPasswordTest.php b/GaelO2/tests/Feature/TestUser/ForgotPasswordTest.php
index f3eacb1af..fb44fcb31 100644
--- a/GaelO2/tests/Feature/TestUser/ForgotPasswordTest.php
+++ b/GaelO2/tests/Feature/TestUser/ForgotPasswordTest.php
@@ -74,6 +74,24 @@ public function testUpdatePassword()
$this->assertTrue(Hash::check($password, $user->fresh()->password));
}
+ public function testUpdatePasswordShouldPassEvenUppercase()
+ {
+ $user = User::factory()->create();
+
+ $token = Password::createToken($user);
+
+ $password = '>=5KBhxE=wWC';
+
+ $response = $this->post('api/tools/reset-password', [
+ 'token' => $token,
+ 'email' => strtoupper($user->email),
+ 'password' => $password,
+ 'password_confirmation' => $password
+ ]);
+
+ $this->assertTrue(Hash::check($password, $user->fresh()->password));
+ }
+
public function testUpdatePasswordShouldFailWrongToken()
{
$user = User::factory()->create();
diff --git a/GaelO2/tests/Feature/TestUser/LoginTest.php b/GaelO2/tests/Feature/TestUser/LoginTest.php
index a58cfe752..bc297a784 100644
--- a/GaelO2/tests/Feature/TestUser/LoginTest.php
+++ b/GaelO2/tests/Feature/TestUser/LoginTest.php
@@ -33,7 +33,20 @@ public function testLogin()
$this->assertEquals($content['onboarded'], true);
}
- public function testLoginSuccessButNotOnboaded()
+ public function testLoginShouldPassInsensitive()
+ {
+ $data = ['email'=> strtoupper('administrator@gaelo.fr'),
+ 'password'=> 'administrator'];
+ $adminDefaultUser = User::where('id', 1)->first();
+ $adminDefaultUser->onboarding_version= Config::get('app.onboarding_version');
+ $adminDefaultUser->save();
+ $response = $this->json('POST', '/api/login', $data)-> assertSuccessful();
+ $content= json_decode($response->content(), true);
+ $this->assertArrayHasKey('access_token', $content);
+ $this->assertEquals($content['onboarded'], true);
+ }
+
+ public function testLoginSuccessButNotOnboarded()
{
$data = ['email'=> 'administrator@gaelo.fr',
'password'=> 'administrator'];
diff --git a/GaelO2/tests/Feature/TestUser/UserTest.php b/GaelO2/tests/Feature/TestUser/UserTest.php
index b3483c0f2..72793461e 100644
--- a/GaelO2/tests/Feature/TestUser/UserTest.php
+++ b/GaelO2/tests/Feature/TestUser/UserTest.php
@@ -259,7 +259,7 @@ public function testGetUsersFromStudyAdministrator()
//Expect to have 5 users in the list
$this->assertEquals(5, sizeof($responseArray));
//Each User has full details
- $this->assertEquals(16, sizeof( array_keys($responseArray[0]) ));
+ $this->assertEquals(17, sizeof( array_keys($responseArray[0]) ));
}
public function testGetUsersFromStudySupervisor()
diff --git a/GaelO2/tests/Feature/TestVisitType/VisitTypeTest.php b/GaelO2/tests/Feature/TestVisitType/VisitTypeTest.php
index c1729df2b..6536c1002 100644
--- a/GaelO2/tests/Feature/TestVisitType/VisitTypeTest.php
+++ b/GaelO2/tests/Feature/TestVisitType/VisitTypeTest.php
@@ -2,6 +2,7 @@
namespace Tests\Feature\TestVisitType;
+use App\GaelO\Constants\Constants;
use App\Models\Patient;
use App\Models\Study;
use Tests\TestCase;
@@ -15,32 +16,32 @@ class VisitTypeTest extends TestCase
{
use RefreshDatabase;
- protected function setUp() : void {
+ protected function setUp(): void
+ {
parent::setUp();
$this->artisan('db:seed');
$this->visitGroup = VisitGroup::factory()->create();
$this->payload = [
- 'name'=>'Baseline',
- 'order'=>0,
- 'localFormNeeded'=>true,
- 'qcProbability'=>100,
- 'reviewProbability'=>100,
- 'optional'=>true,
- 'limitLowDays'=>5,
- 'limitUpDays'=>50,
- 'anonProfile'=>'Default',
- 'dicomConstraints'=>[]
+ 'name' => 'Baseline',
+ 'order' => 0,
+ 'localFormNeeded' => true,
+ 'qcProbability' => 100,
+ 'reviewProbability' => 100,
+ 'optional' => true,
+ 'limitLowDays' => 5,
+ 'limitUpDays' => 50,
+ 'anonProfile' => 'Default',
+ 'dicomConstraints' => []
];
-
}
public function testCreateVisitType()
{
AuthorizationTools::actAsAdmin(true);
$id = $this->visitGroup->id;
- $this->json('POST', 'api/visit-groups/'.$id.'/visit-types', $this->payload)->assertNoContent(201);
+ $this->json('POST', 'api/visit-groups/' . $id . '/visit-types', $this->payload)->assertNoContent(201);
$visitType = VisitType::where('name', 'Baseline')->get()->first();
$this->assertEquals(14, sizeOf($visitType->toArray()));
$this->assertEquals($this->payload['qcProbability'], $visitType->qc_probability);
@@ -54,8 +55,7 @@ public function testCreateVisitTypeShouldFailForAncillaryStudy()
$ancillaryStudy = Study::factory()->ancillaryOf($study->name)->create();
$visitGroup = VisitGroup::factory()->studyName($ancillaryStudy->name)->create();
$id = $visitGroup->id;
- $this->json('POST', 'api/visit-groups/'.$id.'/visit-types', $this->payload)->assertStatus(403);
-
+ $this->json('POST', 'api/visit-groups/' . $id . '/visit-types', $this->payload)->assertStatus(403);
}
public function testCreateVisitTypeShouldFailedBecauseAlreadyExistingName()
@@ -66,7 +66,7 @@ public function testCreateVisitTypeShouldFailedBecauseAlreadyExistingName()
$payload = $this->payload;
$payload['name'] = $visitType['name'];
- $this->json('POST', 'api/visit-groups/'.$visitType->visitGroup->id.'/visit-types', $payload)->assertStatus(409);
+ $this->json('POST', 'api/visit-groups/' . $visitType->visitGroup->id . '/visit-types', $payload)->assertStatus(409);
}
public function testCreateVisitTypeShouldFailedBecauseAlreadyExistingVisitsInStudy()
@@ -79,7 +79,7 @@ public function testCreateVisitTypeShouldFailedBecauseAlreadyExistingVisitsInStu
$visit = Visit::factory()->patientId($patient->id)->visitTypeId($visitType->id)->create();
$payload = $this->payload;
- $this->json('POST', 'api/visit-groups/'.$visit->visitType->visitGroup->id.'/visit-types', $payload)->assertStatus(409);
+ $this->json('POST', 'api/visit-groups/' . $visit->visitType->visitGroup->id . '/visit-types', $payload)->assertStatus(409);
}
public function testCreateVisitTypeForbiddenNotAdmin()
@@ -87,15 +87,16 @@ public function testCreateVisitTypeForbiddenNotAdmin()
AuthorizationTools::actAsAdmin(false);
$visitType = VisitType::factory()->create();
$id = $visitType->visitGroup->id;
- $this->json('POST', 'api/visit-groups/'.$id.'/visit-types', $this->payload)->assertStatus(403);
+ $this->json('POST', 'api/visit-groups/' . $id . '/visit-types', $this->payload)->assertStatus(403);
}
- public function testGetVisitType(){
+ public function testGetVisitType()
+ {
AuthorizationTools::actAsAdmin(true);
$visitType = VisitType::factory()->create();
- $answer = $this->json('GET', 'api/visit-types/'.$visitType->id);
+ $answer = $this->json('GET', 'api/visit-types/' . $visitType->id);
$answer->assertStatus(200);
$expectedKeys = [
@@ -114,7 +115,6 @@ public function testGetVisitType(){
];
$answer->assertJsonStructure($expectedKeys);
-
}
public function testGetVisitTypeForbiddenNotAdmin()
@@ -122,38 +122,61 @@ public function testGetVisitTypeForbiddenNotAdmin()
AuthorizationTools::actAsAdmin(false);
$visitType = VisitType::factory()->create();
- $this->json('GET', 'api/visit-types/'.$visitType->id)->assertStatus(403);
+ $this->json('GET', 'api/visit-types/' . $visitType->id)->assertStatus(403);
}
- public function testDeleteVisitType(){
+ public function testDeleteVisitType()
+ {
AuthorizationTools::actAsAdmin(true);
$visitGroup = VisitGroup::factory()->create();
$visitType = VisitType::factory()->visitGroupId($visitGroup->id)->create();
- $this->json('DELETE', 'api/visit-types/'.$visitType->id)->assertStatus(200);
+ $this->json('DELETE', 'api/visit-types/' . $visitType->id)->assertStatus(200);
}
- public function testDeleteVisitTypeForbiddenNotAdmin(){
+ public function testDeleteVisitTypeForbiddenNotAdmin()
+ {
AuthorizationTools::actAsAdmin(false);
$visitGroup = VisitGroup::factory()->create();
$visitType = VisitType::factory()->visitGroupId($visitGroup->id)->create();
- $this->json('DELETE', 'api/visit-types/'.$visitType->id)->assertStatus(403);
+ $this->json('DELETE', 'api/visit-types/' . $visitType->id)->assertStatus(403);
}
- public function testDeleteVisitTypeForbiddenForAncillaries(){
+ public function testDeleteVisitTypeForbiddenForAncillaries()
+ {
AuthorizationTools::actAsAdmin(true);
$study = Study::factory()->create();
$ancillaryStudy = Study::factory()->ancillaryOf($study->name)->create();
$visitGroup = VisitGroup::factory()->studyName($ancillaryStudy->name)->create();
$visitType = VisitType::factory()->visitGroupId($visitGroup->id)->create();
- $this->json('DELETE', 'api/visit-types/'.$visitType->id)->assertStatus(403);
+ $this->json('DELETE', 'api/visit-types/' . $visitType->id)->assertStatus(403);
}
- public function testDeleteVisitTypeShouldFailedBecauseHasChildVisit(){
+ public function testDeleteVisitTypeShouldFailedBecauseHasChildVisit()
+ {
AuthorizationTools::actAsAdmin(true);
$patient = Patient::factory()->create();
$visitGroup = VisitGroup::factory()->studyName($patient->study_name)->create();
$visitType = VisitType::factory()->visitGroupId($visitGroup->id)->create();
$visits = Visit::factory()->patientId($patient->id)->visitTypeId($visitType->id)->create();
- $this->json('DELETE', 'api/visit-types/'.$visits->first()->visitType->id)->assertStatus(403);
+ $this->json('DELETE', 'api/visit-types/' . $visits->first()->visitType->id)->assertStatus(403);
+ }
+
+ public function testGetFileMetadataOfVisitType()
+ {
+ $visitType = VisitType::factory()->create();
+ $userId = AuthorizationTools::actAsAdmin(false);
+ $studyName = $visitType->visitGroup->study_name;
+ AuthorizationTools::addRoleToUser($userId, Constants::ROLE_SUPERVISOR, $visitType->visitGroup->study_name);
+ $answer = $this->json('GET', 'api/visit-types/' . $visitType->id . '/files/metadata?studyName=' . $studyName . '&role=' . Constants::ROLE_SUPERVISOR);
+ $answer->assertStatus(200);
+ }
+
+ public function testGetFileMetadataOfVisitTypeShouldFailNoRole()
+ {
+ $visitType = VisitType::factory()->create();
+ $userId = AuthorizationTools::actAsAdmin(false);
+ $studyName = $visitType->visitGroup->study_name;
+ $answer = $this->json('GET', 'api/visit-types/' . $visitType->id . '/files/metadata?studyName=' . $studyName . '&role=' . Constants::ROLE_SUPERVISOR);
+ $answer->assertStatus(403);
}
}
diff --git a/GaelO2/tests/Feature/TestVisits/FileVisitTest.php b/GaelO2/tests/Feature/TestVisits/FileVisitTest.php
new file mode 100644
index 000000000..fd12f0d08
--- /dev/null
+++ b/GaelO2/tests/Feature/TestVisits/FileVisitTest.php
@@ -0,0 +1,112 @@
+artisan('db:seed');
+ Storage::fake();
+ }
+
+ private function createVisit()
+ {
+ $study = Study::factory()->name('TEST')->create();
+ $patient = Patient::factory()->studyName($study->name)->create();
+ $visitGroup = VisitGroup::factory()->studyName($study->name)->name('FDG')->create();
+ $visitType = VisitType::factory()->visitGroupId($visitGroup->id)->name('PET_0')->localFormNeeded()->create();
+ $path = $study->name . '/' . 'attached_visit_file' . '/' . 'visit_1_41.csv';
+ $visit = Visit::factory()->patientId($patient->id)->visitTypeId($visitType->id)->sentFiles(['41' => $path])->create();
+ Storage::put($path, "testcontent");
+ return [
+ 'studyName' => $study->name,
+ 'visitId' => $visit->id,
+ 'centerCode' => $patient->center_code
+ ];
+ }
+
+ public function testGetFileOfVisit()
+ {
+ $currentVisit = $this->createVisit();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_INVESTIGATOR, $currentVisit['studyName']);
+ AuthorizationTools::addAffiliatedCenter($currentUserId, $currentVisit['centerCode']);
+ $response = $this->get('api/visits/' . $currentVisit['visitId'] . '/files/41?role=Investigator&studyName=TEST');
+ $response->assertSuccessful();
+ }
+
+ public function testGetFileOfVisitShouldFailNoRole()
+ {
+ $currentVisit = $this->createVisit();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_INVESTIGATOR, $currentVisit['studyName']);
+ AuthorizationTools::addAffiliatedCenter($currentUserId, $currentVisit['centerCode']);
+ $response = $this->get('api/visits/' . $currentVisit['visitId'] . '/files/41?role=Supervisor&studyName=TEST');
+ $response->assertStatus(403);
+ }
+
+ public function testDeleteFileOfVisit()
+ {
+ $currentVisit = $this->createVisit();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $currentVisit['studyName']);
+ $visit = Visit::find($currentVisit['visitId']);
+ $visit->sent_files = ['41' => $currentVisit['studyName'] . '/' . 'attached_review_file' . '/' . 'review_1_41.csv'];
+ $visit->save();
+ $response = $this->delete('api/visits/' . $visit->id . '/files/41?studyName=TEST&role=Supervisor');
+ $response->assertSuccessful();
+ }
+
+ public function testDeleteFileOfVisitShouldFailNoRole()
+ {
+ $currentVisit = $this->createVisit();
+ AuthorizationTools::actAsAdmin(false);
+ $visit = Visit::find($currentVisit['visitId']);
+ $visit->sent_files = ['41' => $currentVisit['studyName'] . '/' . 'attached_review_file' . '/' . 'review_1_41.csv'];
+ $visit->save();
+ $response = $this->delete('api/visits/' . $visit->id . '/files/41?studyName=TEST&role=Supervisor');
+ $response->assertStatus(403);
+ }
+
+ public function testCreateFileOfVisit()
+ {
+
+ $currentVisit = $this->createVisit();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $currentVisit['studyName']);
+ $response = $this->post('api/visits/' . $currentVisit['visitId'] . '/files/prediction?studyName=TEST&role=Supervisor', ['content' => base64_encode("testFileContent"), "extension" => 'csv', 'contentType'=>'text/csv']);
+ $response->assertStatus(201);
+ }
+
+ public function testCreateFileOfVisitShouldFailWrongKey()
+ {
+
+ $currentVisit = $this->createVisit();
+ $currentUserId = AuthorizationTools::actAsAdmin(false);
+ AuthorizationTools::addRoleToUser($currentUserId, Constants::ROLE_SUPERVISOR, $currentVisit['studyName']);
+ $response = $this->post('api/visits/' . $currentVisit['visitId'] . '/files/wrong?studyName=TEST&role=Supervisor', ['content' => base64_encode("testFileContent"), 'contentType'=>'text/csv']);
+ $response->assertStatus(403);
+ }
+
+ public function testCreateFileOfVisitShouldFileNoRole()
+ {
+
+ $currentVisit = $this->createVisit();
+ AuthorizationTools::actAsAdmin(false);
+ $response = $this->post('api/visits/' . $currentVisit['visitId'] . '/files/prediction?studyName=TEST&role=Supervisor', ['content' => base64_encode("testFileContent"), 'contentType'=>'text/csv']);
+ $response->assertStatus(403);
+ }
+}
diff --git a/GaelO2/tests/Unit/TestJobs/JobGaelOProcessingTest.php b/GaelO2/tests/Unit/TestJobs/JobGaelOProcessingTest.php
deleted file mode 100644
index eca941148..000000000
--- a/GaelO2/tests/Unit/TestJobs/JobGaelOProcessingTest.php
+++ /dev/null
@@ -1,49 +0,0 @@
-artisan('db:seed');
- }
-
- public function testBatch(){
-
- //Bus::fake();
- Bus::fake();
-
- $job1 = new JobGaelOProcessing( ["3a84b7f7-d0c66087-d70b292e-0c585356-56b6ccb3"],'Nimportequoi','http://gaeloprocessing:8000');
- $job2 = new JobGaelOProcessing( ["3a84b7f7-d0c66087-d70b292e-0c585356-56b6ccb3"],'Nimportequoi','http://gaeloprocessing:8000');
-
- $batch = Bus::batch([
- $job1,
- $job2
- ])->then(function (Batch $batch) {
- // All jobs completed successfully...
- })->name('processing')->allowFailures()->dispatch();
-
- //dd($batch);
-
- Bus::assertBatched(function (PendingBatch $batch) {
- // Make sure you test the batch is dispatched
- return $batch->name === 'processing';
- });
-
- $this->assertEquals(2, $batch->totalJobs);
-
- }
-}
-
-
diff --git a/GaelO2/tests/Unit/TestJobs/JobQcReportTest.php b/GaelO2/tests/Unit/TestJobs/JobQcReportTest.php
index 2dc68b8fc..5bc735b8d 100644
--- a/GaelO2/tests/Unit/TestJobs/JobQcReportTest.php
+++ b/GaelO2/tests/Unit/TestJobs/JobQcReportTest.php
@@ -20,6 +20,8 @@
class JobQcReportTest extends TestCase
{
use RefreshDatabase;
+ private DicomSeriesRepository $orthancSeriesRepository;
+ private DicomStudy $orthancStudy;
protected function setUp(): void
{
diff --git a/GaelO2/tests/Unit/TestJobs/JobRadiomicsReportTest.php b/GaelO2/tests/Unit/TestJobs/JobRadiomicsReportTest.php
new file mode 100644
index 000000000..e0baacc9d
--- /dev/null
+++ b/GaelO2/tests/Unit/TestJobs/JobRadiomicsReportTest.php
@@ -0,0 +1,47 @@
+artisan('db:seed');
+ $this->study = Study::factory()->name("TEST")->create();
+ $this->visit = Visit::factory()->create();
+ $dicomStudy = DicomStudy::factory()->visitId($this->visit->id)->create();
+ $dicomSeries = DicomSeries::factory()->studyInstanceUID($dicomStudy->study_uid)->count(5)->create();
+
+
+ }
+
+ public function testTmtvInference() {
+ $this->markTestSkipped();
+ JobRadiomicsReport::dispatchSync($this->visit->id);
+ }
+
+ public function testTmtvInferenceFailMethods(){
+ Mail::fake();
+ $radiomicsReportJob = new JobRadiomicsReport($this->visit->id, 1);
+ $exception = new Exception('fakeError');
+ $radiomicsReportJob->failed($exception);
+ Mail::assertQueued(JobFailure::class);
+ }
+}
diff --git a/GaelO2/tests/Unit/TestRepositories/StudyRepositoryTest.php b/GaelO2/tests/Unit/TestRepositories/StudyRepositoryTest.php
index a6866c34b..e005f8fd4 100644
--- a/GaelO2/tests/Unit/TestRepositories/StudyRepositoryTest.php
+++ b/GaelO2/tests/Unit/TestRepositories/StudyRepositoryTest.php
@@ -26,21 +26,24 @@ protected function setUp(): void
$this->studyRepository = new StudyRepository(new Study());
}
- public function testCreateStudy(){
- $this->studyRepository->addStudy('myStudy', '12345', 5, 'contact@gaelo.fr',true, false, false, null);
+ public function testCreateStudy()
+ {
+ $this->studyRepository->addStudy('myStudy', '12345', 5, 'contact@gaelo.fr', true, false, false, null, false, false);
$studyEntity = Study::find('myStudy');
$this->assertEquals('myStudy', $studyEntity->name);
$this->assertEquals('12345', $studyEntity->code);
- $this->assertEquals( 5 , $studyEntity->patient_code_length);
- $this->assertEquals( 'contact@gaelo.fr' , $studyEntity->contact_email);
- $this->assertTrue( (bool) $studyEntity->controller_show_all);
- $this->assertFalse( (bool) $studyEntity->monitor_show_all);
- $this->assertFalse( (bool) $studyEntity->documentation_mandatory);
- $this->assertEquals( null , $studyEntity->ancillary_of);
+ $this->assertEquals(5, $studyEntity->patient_code_length);
+ $this->assertEquals('contact@gaelo.fr', $studyEntity->contact_email);
+ $this->assertTrue((bool) $studyEntity->controller_show_all);
+ $this->assertFalse((bool) $studyEntity->monitor_show_all);
+ $this->assertFalse((bool) $studyEntity->documentation_mandatory);
+ $this->assertEquals(null, $studyEntity->ancillary_of);
+ $this->assertFalse((bool) $studyEntity->creatable_patients_investigator);
}
- public function testIsExistingStudy(){
+ public function testIsExistingStudy()
+ {
$studyEntity = Study::factory()->create();
$answer = $this->studyRepository->isExistingStudyName($studyEntity->name);
$answer2 = $this->studyRepository->isExistingStudyName('NotExistingStudyName');
@@ -48,7 +51,8 @@ public function testIsExistingStudy(){
$this->assertFalse($answer2);
}
- public function testGetStudies(){
+ public function testGetStudies()
+ {
Study::factory()->create();
Study::factory()->create()->delete();
@@ -56,12 +60,12 @@ public function testGetStudies(){
$answer = $this->studyRepository->getStudies();
$answer2 = $this->studyRepository->getStudies(true);
- $this->assertEquals(1, sizeof($answer) );
- $this->assertEquals(2, sizeof($answer2) );
-
+ $this->assertEquals(1, sizeof($answer));
+ $this->assertEquals(2, sizeof($answer2));
}
- public function testGetStudyWithDetails(){
+ public function testGetStudyWithDetails()
+ {
$visitType = VisitType::factory()->create();
@@ -71,10 +75,10 @@ public function testGetStudyWithDetails(){
$this->assertArrayHasKey('visit_groups', $answer);
$this->assertArrayHasKey('visit_types', $answer['visit_groups'][0]);
-
}
- public function testGetAllStudiesWithDetails(){
+ public function testGetAllStudiesWithDetails()
+ {
VisitType::factory()->count(5)->create();
VisitType::factory()->create()->delete();
@@ -84,10 +88,10 @@ public function testGetAllStudiesWithDetails(){
$this->assertEquals(6, sizeof($answer));
$this->assertArrayHasKey('visit_groups', $answer[0]);
$this->assertArrayHasKey('visit_types', $answer[0]['visit_groups'][0]);
-
}
- public function testReactivateStudy(){
+ public function testReactivateStudy()
+ {
$study = Study::factory()->create();
$study->delete();
@@ -98,7 +102,8 @@ public function testReactivateStudy(){
$this->assertNull($updatedStudy['deleted_at']);
}
- public function testGetAncilariesStudies(){
+ public function testGetAncilariesStudies()
+ {
$study = Study::factory()->create();
Study::factory()->ancillaryOf($study->name)->count(5)->create();
@@ -106,7 +111,8 @@ public function testGetAncilariesStudies(){
$this->assertEquals(5, sizeof($ancilarriesStudies));
}
- public function testGetStatistics(){
+ public function testGetStatistics()
+ {
$study = Study::factory()->create();
$patients = Patient::factory()->count(30)->studyName($study->name)->create();
$visit = Visit::factory()->patientId($patients->first()->id)->create();
@@ -121,11 +127,7 @@ public function testGetStatistics(){
$this->assertEquals($statistics['patients_count'], 30);
$this->assertEquals($statistics['dicom_studies_count'], 1);
$this->assertEquals($statistics['dicom_series_count'], 5);
- $this->assertGreaterThan(0 , $statistics['dicom_instances_count']);
- $this->assertGreaterThan(0 , $statistics['dicom_disk_size']);
-
-
+ $this->assertGreaterThan(0, $statistics['dicom_instances_count']);
+ $this->assertGreaterThan(0, $statistics['dicom_disk_size']);
}
-
-
}
diff --git a/GaelO2/tests/Unit/TestRepositories/UserRepositoryTest.php b/GaelO2/tests/Unit/TestRepositories/UserRepositoryTest.php
index 3333261e5..4c4e5a0d1 100644
--- a/GaelO2/tests/Unit/TestRepositories/UserRepositoryTest.php
+++ b/GaelO2/tests/Unit/TestRepositories/UserRepositoryTest.php
@@ -161,6 +161,13 @@ public function testGetUserByUsername()
$this->assertNotNull($userEntity['deleted_at']);
}
+ public function testGetUserByEmailInsensitive()
+ {
+ $user = User::factory()->job(JobEnum::SUPERVISION->value)->create();
+ $userEntity = $this->userRepository->getUserByEmail(strtoupper($user->email), false);
+ $this->assertIsArray($userEntity);
+ }
+
public function testIsExistingEmail()
{
@@ -175,6 +182,18 @@ public function testIsExistingEmail()
$this->assertFalse($testNotExisting);
}
+ public function testIsExistingEmailInsensitive()
+ {
+
+ $user = User::factory()->create();
+ //Username test even if soft deleted user
+ $user->delete();
+
+ $testExisting = $this->userRepository->isExistingEmail(strtoupper($user->email));
+
+ $this->assertTrue($testExisting);
+ }
+
public function testGetAdministrators()
{
diff --git a/GaelO2/tests/Unit/TestRepositories/VisitRepositoryTest.php b/GaelO2/tests/Unit/TestRepositories/VisitRepositoryTest.php
index 0bdf5a2ac..fffaf50f6 100644
--- a/GaelO2/tests/Unit/TestRepositories/VisitRepositoryTest.php
+++ b/GaelO2/tests/Unit/TestRepositories/VisitRepositoryTest.php
@@ -459,4 +459,11 @@ public function testGetVisitOfPatientByVisitTypeName()
$this->expectException(ModelNotFoundException::class);
$this->visitRepository->getVisitOfPatientByVisitTypeName($patientId, $visitGroupName, $visitTypeName.'wrong', true, $studyName);
}
+
+ public function testUpdateVisitFiles(){
+ $visit = Visit::factory()->create();
+ $this->visitRepository->updateVisitFile($visit->id, ['myKey' => 'myFile.pdf'] );
+ $updatedVisit = Visit::find($visit->id);
+ $this->assertArrayHasKey('myKey', $updatedVisit['sent_files']);
+ }
}
diff --git a/GaelO2/tests/Unit/TestServices/GaelOProcessingServiceTest.php b/GaelO2/tests/Unit/TestServices/GaelOProcessingServiceTest.php
index 5443a6221..1c7264cd6 100644
--- a/GaelO2/tests/Unit/TestServices/GaelOProcessingServiceTest.php
+++ b/GaelO2/tests/Unit/TestServices/GaelOProcessingServiceTest.php
@@ -19,6 +19,7 @@ protected function setUp():void{
public function testSendDicom()
{
- $resultat=$this->gaeloProcessingService->sendDicom(["a97f5e66-bbff00d4-1639c63f-a3e1e53a-d4b5e553"]);
+ $path = getcwd() . "/tests/data/MR.zip";
+ $resultat=$this->gaeloProcessingService->createDicom($path);
}
}
diff --git a/GaelO2/tests/Unit/TestServices/PdfServiceTest.php b/GaelO2/tests/Unit/TestServices/PdfServiceTest.php
new file mode 100644
index 000000000..6b484a8c0
--- /dev/null
+++ b/GaelO2/tests/Unit/TestServices/PdfServiceTest.php
@@ -0,0 +1,25 @@
+pdfService = App::make(PdfServices::class);
+ }
+
+ public function testMakeRadiomicsPdf()
+ {
+ $filename = $this->pdfService->saveRadiomicsPdf('TEST', '12345', 'PET0', '07141995', ['tmtv41' => 55]);
+ $this->assertIsString($filename);
+ }
+
+}
diff --git a/GaelO2/tests/Unit/TestServices/VisitTreeTest.php b/GaelO2/tests/Unit/TestServices/VisitTreeTest.php
index a03338c2c..49da9148d 100644
--- a/GaelO2/tests/Unit/TestServices/VisitTreeTest.php
+++ b/GaelO2/tests/Unit/TestServices/VisitTreeTest.php
@@ -147,7 +147,9 @@ protected function setUp(): void
'monitor_show_all' => false,
'documentation_mandatory' => false,
'ancillary_of' => null,
- 'deleted_at' => null
+ 'deleted_at' => null,
+ 'creatable_patients_investigator' => false
+
]));
diff --git a/README.md b/README.md
index 2696edec5..b9959d5c8 100755
--- a/README.md
+++ b/README.md
@@ -29,5 +29,6 @@ node_modules/mjml/bin/mjml ./app/GaelO/views/mails/mjml/qc_report_buttons.mjml -
node_modules/mjml/bin/mjml ./app/GaelO/views/mails/mjml/qc_report_series.mjml -o ./app/GaelO/views/mails/mail_qc_report_series.blade.php
node_modules/mjml/bin/mjml ./app/GaelO/views/mails/mjml/qc_report_study.mjml -o ./app/GaelO/views/mails/mail_qc_report_study.blade.php
node_modules/mjml/bin/mjml ./app/GaelO/views/mails/mjml/qc_report_investigator_form.mjml -o ./app/GaelO/views/mails/mail_qc_report_investigator_form.blade.php
+node_modules/mjml/bin/mjml ./app/GaelO/views/mails/mjml/radiomics_report.mjml -o ./app/GaelO/views/mails/mail_radiomics_report.blade.php
```
In blade generated files, edit file to keep only body content (remove header...)