Skip to content

Commit 06051fb

Browse files
authored
Merge pull request #729 from Pixilib/GaelO2-dev
Gael o2 dev
2 parents ea994e9 + 02ec513 commit 06051fb

37 files changed

+1104
-944
lines changed

.github/workflows/php-stan.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ jobs:
3838
run: vendor/bin/phpstan analyse app/
3939
permissions:
4040
contents: read
41-
packages: write
41+
packages: read

.github/workflows/publish.yml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- GaelO2
77
- GaelO2-dev
8+
- new-export
89
tags:
910
- '*'
1011

.github/workflows/tests.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,5 @@ jobs:
7979
diff-storage: GaelO2_code_coverage
8080
permissions:
8181
contents: write
82-
packages: write
82+
packages: read
83+
pull-requests: write

GaelO2/app/GaelO/Adapters/HttpClientAdapter.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\GaelO\Interfaces\Adapters\HttpClientInterface;
66
use App\GaelO\Interfaces\Adapters\Psr7ResponseInterface;
77
use GuzzleHttp\Client;
8+
use GuzzleHttp\Exception\ConnectException;
89
use GuzzleHttp\Exception\RequestException;
910
use GuzzleHttp\Pool;
1011
use GuzzleHttp\Psr7\Request;
@@ -82,10 +83,10 @@ public function requestUploadArrayDicom(string $method, string $uri, array $file
8283
'fulfilled' => function (Response $response, $index) use (&$responseArray) {
8384
$responseArray[$index] = new Psr7ResponseAdapter($response);
8485
},
85-
'rejected' => function (RequestException $exception, $index) {
86+
'rejected' => function (RequestException|ConnectException $exception, $index) {
8687
$reason = "Error sending dicom to orthanc";
8788

88-
if ($exception->hasResponse()) {
89+
if ($exception instanceof RequestException && $exception->hasResponse()) {
8990
$reason = $exception->getResponse()->getStatusCode();
9091
Log::error($exception->getResponse()->getBody()->getContents());
9192
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace App\GaelO\Adapters;
4+
5+
use App\GaelO\Interfaces\Adapters\ZipStreamInterface;
6+
use Psr\Http\Message\StreamInterface;
7+
use ZipStream;
8+
9+
class ZipStreamAdapter implements ZipStreamInterface
10+
{
11+
12+
private ZipStream\ZipStream $zipStream;
13+
14+
public function init(string $filename): void
15+
{
16+
$this->zipStream = new ZipStream\ZipStream(
17+
outputName: $filename,
18+
sendHttpHeaders: true,
19+
);
20+
}
21+
22+
public function addFileFromString(string $filename, string $content): void
23+
{
24+
$this->zipStream->addFile(
25+
fileName: $filename,
26+
data: $content,
27+
);
28+
}
29+
30+
public function addFileFromStream(string $filename, $stream): void
31+
{
32+
$this->zipStream->addFileFromStream(
33+
fileName: $filename,
34+
stream: $stream,
35+
);
36+
}
37+
38+
public function finish()
39+
{
40+
return $this->zipStream->finish();
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace App\GaelO\Interfaces\Adapters;
4+
5+
use Psr\Http\Message\StreamInterface;
6+
7+
Interface ZipStreamInterface {
8+
public function init(string $filename): void;
9+
public function addFileFromString(string $filename, string $content): void;
10+
public function addFileFromStream(string $filename, $stream) :void;
11+
public function finish();
12+
}

GaelO2/app/GaelO/Services/ExportStudyService.php

+1-17
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public function exportInvestigatorForms(): void
216216
$this->groupReviewPerVisitType($investigatorForms, Constants::ROLE_INVESTIGATOR);
217217
}
218218

219-
public function exportAll() :void
219+
public function exportAllTables() :void
220220
{
221221
$this->exportPatientTable();
222222
$this->exportVisitTable();
@@ -225,7 +225,6 @@ public function exportAll() :void
225225
$this->exportReviewerForms();
226226
$this->exportTrackerTable();
227227
$this->exportUsersOfStudy();
228-
$this->exportAssociatedFiles();
229228
}
230229

231230
private function groupReviewPerVisitType(array $reviewEntities, string $role): void
@@ -303,21 +302,6 @@ public function exportTrackerTable(): void
303302
$this->exportStudyResults->setTrackerReviewResults($exportTrackerResult);
304303
}
305304

306-
public function exportAssociatedFiles(): void
307-
{
308-
$zip = new ZipArchive();
309-
$tempZip = tempnam(ini_get('upload_tmp_dir'), 'TMPZIP_' . $this->studyName . '_');
310-
$zip->open($tempZip, ZipArchive::OVERWRITE);
311-
//Add a file to create zip
312-
$zip->addFromString('Readme', 'Folder Containing associated files to study');
313-
//send stored file for this study
314-
Util::addStoredFilesInZipAndClose($zip, $this->studyName);
315-
316-
$exporFileResult = new ExportFileResults();
317-
$exporFileResult->addExportFile(ExportDataResults::EXPORT_TYPE_ZIP, $tempZip);
318-
$this->exportStudyResults->setExportFileResults($exporFileResult);
319-
}
320-
321305
public function getExportStudyResult(): ExportStudyResults
322306
{
323307
return $this->exportStudyResults;

GaelO2/app/GaelO/Services/FormService/ReviewFormService.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ private function doSpecificReviewDecisions()
105105

106106
//Send Notification emails
107107
if ($reviewStatus === ReviewStatusEnum::WAIT_ADJUDICATION->value) {
108-
$awaitingAdjudicationEvent = new AwaitingAdjudicationEvent($this->visitContext);
108+
$awaitingAdjudicationEvent = new AwaitingAdjudicationEvent($this->visitContext, $this->studyName);
109109
$studyObject = AbstractGaelOStudy::getSpecificStudyObject($this->studyName);
110110
$studyObject->onEventStudy($awaitingAdjudicationEvent);
111111
} else if ($reviewStatus === ReviewStatusEnum::DONE->value) {
112112
//In case of conclusion reached send conclusion (but not to uploader if ancillary study)
113-
$visitConcludedEvent = new VisitConcludedEvent($this->visitContext);
113+
$visitConcludedEvent = new VisitConcludedEvent($this->visitContext, $this->studyName);
114114
$visitConcludedEvent->setConclusion($conclusion);
115115
$visitConcludedEvent->setUploaderUserId($this->studyEntity->isAncillaryStudy() ? null : $this->uploaderId);
116116
$studyObject = AbstractGaelOStudy::getSpecificStudyObject($this->studyName);

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/AwaitingAdjudicationEvent.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
class AwaitingAdjudicationEvent extends BaseVisitEvent
66
{
77

8-
public function __construct(array $visitEntity)
8+
public function __construct(array $visitEntity, string $studyName)
99
{
10-
parent::__construct(GaelOStudyEventEnum::AWAITING_ADJUDICATION_EVENT, $visitEntity);
10+
parent::__construct(GaelOStudyEventEnum::AWAITING_ADJUDICATION_EVENT, $visitEntity, $studyName);
1111
}
1212
}

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/BaseStudyEvent.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
abstract class BaseStudyEvent
66
{
77
public GaelOStudyEventEnum $type;
8+
protected string $studyName;
89

9-
public function __construct(GaelOStudyEventEnum $type)
10+
public function __construct(GaelOStudyEventEnum $type, string $studyName)
1011
{
1112
$this->type = $type;
13+
$this->studyName = $studyName;
1214
}
1315
}

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/BaseVisitEvent.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ class BaseVisitEvent extends BaseStudyEvent
88
{
99
protected array $visitEntity;
1010

11-
public function __construct(GaelOStudyEventEnum $type, array $visitEntity)
11+
public function __construct(GaelOStudyEventEnum $type, array $visitEntity, string $studyName)
1212
{
13-
parent::__construct($type);
13+
parent::__construct($type, $studyName);
1414
$this->visitEntity = $visitEntity;
1515
}
1616

1717
public function getStudyName(): string
1818
{
19-
return $this->visitEntity['patient']['study_name'];
19+
return $this->studyName;
2020
}
2121

2222
public function getVisitId(): int

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/CorrectiveActionEvent.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ class CorrectiveActionEvent extends BaseVisitEvent
77
private int $userId;
88
private bool $correctiveActionDone;
99

10-
public function __construct(array $visitEntity)
10+
public function __construct(array $visitEntity, string $studyName)
1111
{
12-
parent::__construct(GaelOStudyEventEnum::CORRECTIVE_ACTION_EVENT, $visitEntity);
12+
parent::__construct(GaelOStudyEventEnum::CORRECTIVE_ACTION_EVENT, $visitEntity, $studyName);
1313
}
1414

1515
public function setCurrentUserId(int $userId): void

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/QCModifiedEvent.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ class QCModifiedEvent extends BaseVisitEvent
1212
private string $imageQcComment;
1313
private bool $reviewNeeded;
1414

15-
public function __construct(array $visitEntity)
15+
public function __construct(array $visitEntity, string $studyName)
1616
{
17-
parent::__construct(GaelOStudyEventEnum::QC_MODIFIED_EVENT, $visitEntity);
17+
parent::__construct(GaelOStudyEventEnum::QC_MODIFIED_EVENT, $visitEntity, $studyName);
1818
}
1919

2020
public function setCurrentUserId(int $userId): void

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitConcludedEvent.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ class VisitConcludedEvent extends BaseVisitEvent
77
private ?int $uploaderUserId;
88
private ?string $conclusion;
99

10-
public function __construct(array $visitEntity)
10+
public function __construct(array $visitEntity, string $studyName)
1111
{
12-
parent::__construct(GaelOStudyEventEnum::VISIT_CONCLUDED_EVENT, $visitEntity);
12+
parent::__construct(GaelOStudyEventEnum::VISIT_CONCLUDED_EVENT, $visitEntity, $studyName);
1313
}
1414

1515
public function setUploaderUserId(?int $userId): void

GaelO2/app/GaelO/Services/GaelOStudiesService/Events/VisitUploadedEvent.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ class VisitUploadedEvent extends BaseVisitEvent
77
private bool $reviewNeeded;
88
private int $uploaderUserId;
99

10-
public function __construct(array $visitEntity)
10+
public function __construct(array $visitEntity, string $studyName)
1111
{
12-
parent::__construct(GaelOStudyEventEnum::UPLOAD_VISIT_EVENT, $visitEntity);
12+
parent::__construct(GaelOStudyEventEnum::UPLOAD_VISIT_EVENT, $visitEntity, $studyName);
1313
}
1414

1515
public function setUploaderUserId(int $userId): void

GaelO2/app/GaelO/Services/VisitService.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ private function visitUploaded()
104104
}
105105

106106
//Notify of the upload done
107-
$visitUploadedEvent = new VisitUploadedEvent($visitEntity);
107+
$visitUploadedEvent = new VisitUploadedEvent($visitEntity, $studyName);
108108
$visitUploadedEvent->setReviewNeeded($reviewNeeded);
109109
$visitUploadedEvent->setUploaderUserId($this->currentUserId);
110110
$studyObject = AbstractGaelOStudy::getSpecificStudyObject($studyName);
@@ -135,7 +135,7 @@ public function editQc(string $stateQc, int $controllerId, ?bool $imageQc, ?bool
135135
$this->reviewStatusRepository->updateReviewAvailability($this->visitId, $studyName, true);
136136
}
137137

138-
$qcModifiedEvent = new QCModifiedEvent($visitEntity);
138+
$qcModifiedEvent = new QCModifiedEvent($visitEntity, $studyName);
139139
$qcModifiedEvent->setCurrentUserId($controllerId);
140140
$qcModifiedEvent->setQcStatus($stateQc);
141141
$qcModifiedEvent->setFormQcStatus($formQc ? 'Accepted ' : 'Refused');

GaelO2/app/GaelO/UseCases/ExportDatabase/ExportDatabase.php

+23-18
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
namespace App\GaelO\UseCases\ExportDatabase;
44

5+
use App\GaelO\Adapters\FrameworkAdapter;
6+
use App\GaelO\Adapters\ZipStreamAdapter;
57
use App\GaelO\Exceptions\AbstractGaelOException;
68
use App\GaelO\Exceptions\GaelOForbiddenException;
79
use App\GaelO\Interfaces\Adapters\DatabaseDumperInterface;
810
use App\GaelO\Services\AuthorizationService\AuthorizationUserService;
9-
use App\GaelO\Util;
1011
use Exception;
11-
use ZipArchive;
1212

1313
class ExportDatabase
1414
{
@@ -29,25 +29,9 @@ public function execute(ExportDatabaseRequest $exportDatabaseRequest, ExportData
2929
$this->checkAuthorization($exportDatabaseRequest->currentUserId);
3030
//Operation might be long, set max execution time to 30 minutes
3131
set_time_limit(1800);
32-
$zip = new ZipArchive();
33-
$tempZip = tempnam(ini_get('upload_tmp_dir'), 'TMPZIPDB_');
34-
$zip->open($tempZip, ZipArchive::OVERWRITE);
35-
36-
$filePathSql = tempnam(ini_get('upload_tmp_dir'), 'TMPDB_');
37-
$this->databaseDumperInterface->createDatabaseDumpFile($filePathSql);
38-
39-
$date = Date('Ymd_His');
40-
$zip->addFile($filePathSql, "export_database_$date.sql");
41-
42-
Util::addStoredFilesInZipAndClose($zip, null);
43-
44-
//Unlick after lock released by zip close
45-
unlink($filePathSql);
4632

4733
$exportDatabaseResponse->status = 200;
4834
$exportDatabaseResponse->statusText = 'OK';
49-
$exportDatabaseResponse->zipFile = $tempZip;
50-
$exportDatabaseResponse->fileName = "export_database_" . $date . ".zip";
5135
} catch (AbstractGaelOException $e) {
5236
$exportDatabaseResponse->status = $e->statusCode;
5337
$exportDatabaseResponse->statusText = $e->statusText;
@@ -63,4 +47,25 @@ private function checkAuthorization(int $userId): void
6347
throw new GaelOForbiddenException();
6448
}
6549
}
50+
51+
public function readExport()
52+
{
53+
$date = Date('Ymd_His');
54+
$zipStream = new ZipStreamAdapter();
55+
$zipStream->init("export_database_" . $date . ".zip");
56+
//send stored file for this study
57+
try {
58+
$filePathSql = tempnam(ini_get('upload_tmp_dir'), 'TMPDB_');
59+
$this->databaseDumperInterface->createDatabaseDumpFile($filePathSql);
60+
$zipStream->addFileFromStream("export_database_$date.sql", fopen($filePathSql, 'rb'), );
61+
$files = FrameworkAdapter::getStoredFiles();
62+
foreach ($files as $file) {
63+
$fileStream = FrameworkAdapter::getFile($file, true);
64+
$zipStream->addFileFromStream($file, $fileStream);
65+
}
66+
$zipStream->finish();
67+
} finally {
68+
unlink($filePathSql);
69+
}
70+
}
6671
}

GaelO2/app/GaelO/UseCases/ExportDatabase/ExportDatabaseResponse.php

-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,4 @@ class ExportDatabaseResponse
66
{
77
public int $status;
88
public string $statusText;
9-
public string $zipFile;
10-
public string $fileName;
119
}

GaelO2/app/GaelO/UseCases/ExportStudyData/ExportStudyData.php

+1-5
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,15 @@ public function execute(ExportStudyDataRequest $exportStudyDataRequest, ExportSt
2525
{
2626

2727
try {
28-
2928
$studyName = $exportStudyDataRequest->studyName;
3029

3130
$this->checkAuthorization($exportStudyDataRequest->currentUserId, $studyName);
3231

33-
//Operation might be long, set max execution time to 30 minutes
34-
set_time_limit(1800);
35-
3632
//Make this task continues even the users leave to prevent removing created temporary files
3733
ignore_user_abort(true);
3834

3935
$this->exportStudyService->setStudyName($studyName);
40-
$this->exportStudyService->exportAll();
36+
$this->exportStudyService->exportAllTables();
4137
$exportResults = $this->exportStudyService->getExportStudyResult();
4238

4339
$exportStudyDataResponse->zipFile = $exportResults->getResultsAsZip();

0 commit comments

Comments
 (0)