Passed
Pull Request — master (#116)
by Salim
22:43 queued 18:49
created

Orthanc::importFileGuzzle()   A

Complexity

Conditions 2
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 4
nop 1
dl 0
loc 13
rs 9.9666
c 0
b 0
f 0
1
<?php 
2
/**
3
 Copyright (C) 2018-2020 KANOUN Salim
4
 This program is free software; you can redistribute it and/or modify
5
 it under the terms of the Affero GNU General Public v.3 License as published by
6
 the Free Software Foundation;
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
 Affero GNU General Public Public for more details.
11
 You should have received a copy of the Affero GNU General Public Public along
12
 with this program; if not, write to the Free Software Foundation, Inc.,
13
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14
 */
15
16
use GuzzleHttp\Client;
0 ignored issues
show
Bug introduced by
The type GuzzleHttp\Client was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
18
/**
19
 * Main class for Orthanc communication, serve usefull APIs (get dicom tags, send to peer, download zip...)
20
 * 
21
 * If Orthanc is using HTTPS :
22
 * the php_openssl extension must exist and be enabled
23
 * In the php.ini file you should add this lines if not exists:
24
 * extension=php_openssl.dll
25
 * allow_url_fopen = On
26
*/
27
28
Class Orthanc {
29
	
30
	private $url;
31
	private $context;
32
	
33
	/**
34
	 * Build connexion string in Orthanc, boolean to connect with Orthanc Exposed or Orthanc PACS
35
	 * @param boolean $exposed
36
	 */
37
	public function __construct(bool $exposed=false) {
38
		//Set Time Limit at 3H as operation could be really long
39
		set_time_limit(10800);
40
41
		$this->client = new Client();
0 ignored issues
show
Bug Best Practice introduced by
The property client does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
42
		//Set address of Orthanc server
43
		if ($exposed) {
44
			$this->url=GAELO_ORTHANC_EXPOSED_INTERNAL_ADDRESS.':'.GAELO_ORTHANC_EXPOSED_INTERNAL_PORT;
45
			$this->login = GAELO_ORTHANC_EXPOSED_INTERNAL_LOGIN;
0 ignored issues
show
Bug Best Practice introduced by
The property login does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
46
			$this->password = GAELO_ORTHANC_EXPOSED_INTERNAL_PASSWORD;
0 ignored issues
show
Bug Best Practice introduced by
The property password does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
47
			$this->context=array(
48
				'http' => array(
49
					'header'  => "Authorization: Basic ".base64_encode(GAELO_ORTHANC_EXPOSED_INTERNAL_LOGIN.':'.GAELO_ORTHANC_EXPOSED_INTERNAL_PASSWORD)
50
	   			));
51
		}else {
52
			$this->url=GAELO_ORTHANC_PACS_ADDRESS.':'.GAELO_ORTHANC_PACS_PORT;
53
			$this->login = GAELO_ORTHANC_PACS_LOGIN;
54
			$this->password = GAELO_ORTHANC_PACS_PASSWORD;
55
			$this->context=array(
56
	   			'http' => array(
57
	   				'header'  => "Authorization: Basic ".base64_encode(GAELO_ORTHANC_PACS_LOGIN.':'.GAELO_ORTHANC_PACS_PASSWORD)
58
	   			) );
59
	   }
60
61
	}
62
	
63
	/**
64
	 * Return list of Peers declared in Orthanc
65
	 * @return mixed
66
	 */
67
	public function getPeers() {
68
		$context=stream_context_create($this->context);
69
		$json=file_get_contents($this->url.'/peers/', false, $context);
70
		$peers=json_decode($json, true);
71
		return $peers;
72
	}
73
	
74
	/**
75
	 * Search function in Orthanc, search the Patients/Studies/Series level in Orthanc and return the raw response in JSON
76
	 * @param string $level
77
	 * @param string $patientID
78
	 * @param string $patientName
79
	 * @param string $studyDate
80
	 * @param string $studyUID
81
	 * @param string $accessionNumber
82
	 * @param string $studyDescription
83
	 * @return string json
84
	 */
85
	public function searchInOrthanc(string $level, string $patientID, string $patientName, string $studyDate, string $studyUID, string $accessionNumber, string $studyDescription) {
86
		
87
		$queryDetails=array(
88
				'PatientID' => $patientID,
89
				'PatientName' => $patientName,
90
				'StudyDate' => $studyDate,
91
				'StudyInstanceUID' => $studyUID,
92
				'AccessionNumber'=> $accessionNumber,
93
				'StudyDescription'=> $studyDescription,
94
		);
95
		
96
		$query=array(
97
				'Level' => $level,
98
				'CaseSensitive' => false,
99
				'Expand' => false,
100
				'Query' => $queryDetails,
101
				
102
		);
103
		
104
		$opts=array('http' =>
105
				array(
106
						'method'  => 'POST',
107
						'content' => json_encode($query),
108
						'header'=>  ['Content-Type: application/json Accept: application/json ', $this->context['http']['header']]
109
				)
110
		);
111
112
		$context=stream_context_create($opts);
113
		$resultJson=file_get_contents($this->url.'/tools/find', false, $context);
114
		$result=json_decode($resultJson);
115
		
116
		return $result;
117
	}
118
	
119
	/**
120
	 * return the ZIP as temp file containing the Orthanc ID ressources dicoms
121
	 * @param array $uidList
122
	 * @return resource temporary file path
123
	 */
124
	public function getZipStream(array $uidList) {
125
	   
126
		if (!is_array($uidList)) {
0 ignored issues
show
introduced by
The condition is_array($uidList) is always true.
Loading history...
127
			$uidList=array($uidList);
128
		}
129
	    
130
		$opts=array('http' =>
131
			array(
132
				'method'  => 'POST',
133
				'content' => json_encode(array('Transcode'=>'1.2.840.10008.1.2.1', 'Resources' => $uidList)),
134
				'timeout' => 3600,
135
				'header'=>  ['Content-Type: application/json', 'Accept: application/zip', $this->context['http']['header']]
136
			)
137
		);
138
	    
139
		$context=stream_context_create($opts);
140
141
		$tempFile = tmpfile();
142
		stream_copy_to_stream ( fopen($this->url.'/tools/create-archive', 'rb', false, $context) , $tempFile);
0 ignored issues
show
Bug introduced by
It seems like $tempFile can also be of type false; however, parameter $dest of stream_copy_to_stream() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

142
		stream_copy_to_stream ( fopen($this->url.'/tools/create-archive', 'rb', false, $context) , /** @scrutinizer ignore-type */ $tempFile);
Loading history...
Bug introduced by
It seems like fopen($this->url . '/too... 'rb', false, $context) can also be of type false; however, parameter $source of stream_copy_to_stream() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

142
		stream_copy_to_stream ( /** @scrutinizer ignore-type */ fopen($this->url.'/tools/create-archive', 'rb', false, $context) , $tempFile);
Loading history...
143
	    
144
		return $tempFile;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $tempFile could also return false which is incompatible with the documented return type resource. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
145
	}
146
	
147
	
148
	/**
149
	 * Delete in Orthanc patients / study / series depending on Level and Orthanc ID
150
	 * @param  $level
151
	 * @param  $uidList
152
	 */
153
	public function deleteFromOrthanc(string $level, string $uid) {
154
	    
155
		$opts=array('http' =>
156
			array(
157
				'method'  => 'DELETE',
158
				'header'=>  ['Content-Type: application/json Accept: application/json', $this->context['http']['header']]
159
			)
160
		);
161
	    
162
		$context=stream_context_create($opts);
163
		file_get_contents($this->url.'/'.$level.'/'.$uid, false, $context);
164
	    
165
	}
166
	
167
	/**
168
	 * Add Peer declaration to Orthanc
169
	 * @param string $name name of the peer
170
	 * @param string $url URL with http / https and port
171
	 * @param string $username
172
	 * @param string $password
173
	 * @return mixed
174
	 */
175
	public function addPeer(string $name, string $url, string $username, string $password) {
176
	    
177
		$peerValues['Username']=$username;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$peerValues was never initialized. Although not strictly required by PHP, it is generally a good practice to add $peerValues = array(); before regardless.
Loading history...
178
		$peerValues['Password']=$password;
179
		$peerValues['Url']=$url;
180
		$opts=array('http' =>
181
			array(
182
				'method'  => 'PUT',
183
				'content' => json_encode($peerValues),
184
				'header'=>  ['Content-Type: application/json Accept: application/json ', $this->context['http']['header']]
185
			)
186
		);
187
	    
188
		$context=stream_context_create($opts);
189
		$resultJson=file_get_contents($this->url.'/peers/'.$name, false, $context);
190
	    
191
		$result=json_decode($resultJson);
192
		return $result;
193
	    
194
	}
195
	
196
	/**
197
	 * Remove Peer declaration from Orthanc
198
	 * @param string $name
199
	 */
200
	public function removePeer(string $name) {
201
	    
202
		$opts=array('http' =>
203
			array(
204
				'method'  => 'DELETE',
205
				'header'=>  ['Content-Type: application/json Accept: application/json ', $this->context['http']['header']]
206
			)
207
		);
208
	    
209
		$context=stream_context_create($opts);
210
		$resultJson=file_get_contents($this->url.'/peers/'.$name, false, $context);
211
	    
212
		$result=json_decode($resultJson);
213
	    
214
		return $result;
215
	}
216
	
217
	/**
218
	 * Remove all peers from orthanc
219
	 */
220
	public function removeAllPeers() {
221
	    
222
		$peers=$this->getPeers();
223
	    
224
		foreach ($peers as $peer) {
225
			$this->removePeer($peer);
226
		}
227
	    
228
	}
229
	
230
	/**
231
	 * Test if a peer has Orthanc Peer Accelerator
232
	 * @param string $peer
233
	 * @return boolean
234
	 */
235
	public function isPeerAccelerated(string $peer) {
236
		$context=stream_context_create($this->context);
237
		$json=file_get_contents($this->url.'/transfers/peers/', false, $context);
238
		$peersTest=json_decode($json, true);
239
	    
240
		if ($peersTest[$peer] == "installed") {
241
			return true;
242
		}
243
	    
244
		return false;
245
	}
246
	
247
	/**
248
	 * Send id list of DICOM to a peer
249
	 * @param string $peer
250
	 * @param array $ids
251
	 */
252
	public function sendToPeer(string $peer, array $ids) {
253
		
254
		$opts=array('http' =>
255
				array(
256
						'method'  => 'POST',
257
						"timeout" => 300, 
258
						'content' => json_encode($ids),
259
						'header'=>  ['Content-Type: application/json Accept: application/json', $this->context['http']['header']]
260
				)
261
		);
262
		
263
		$context=stream_context_create($opts);
264
		$result=file_get_contents($this->url.'/peers/'.$peer.'/store', false, $context);
265
		return $result;
266
	    
267
	}
268
	
269
	/**
270
	 * Send to Orthanc peer but asynchroneously
271
	 * @param string $peer
272
	 * @param array $ids
273
	 * @return string
274
	 */
275
	public function sendToPeerAsync(string $peer, array $ids) {
276
		$data['Synchronous']=false;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
277
		$data['Resources']=$ids;
278
	    
279
		$opts=array('http' =>
280
			array(
281
				'method'  => 'POST',
282
				'content' => json_encode($data),
283
				'header'=>  ['Content-Type: application/json Accept: application/json', $this->context['http']['header']]
284
			)
285
		);
286
	    
287
		$context=stream_context_create($opts);
288
		$result=file_get_contents($this->url.'/peers/'.$peer.'/store', false, $context);
289
		return $result;
290
	}
291
	
292
	/**
293
	 * Send to peer with transfers accelerator plugin
294
	 * @param string $peer
295
	 * @param array $ids
296
	 * @param bool $gzip
297
	 * @return string
298
	 */
299
	public function sendToPeerAsyncWithAccelerator(string $peer, array $ids, bool $gzip) {
300
	    
301
		//If Peer dosen't have accelerated transfers fall back to regular orthanc peer transfers
302
		if (!$this->isPeerAccelerated($peer)) {
303
			$answer=$this->sendToPeerAsync($peer, $ids);
304
			return $answer;
305
		}
306
	    
307
		if (!$gzip) $data['Compression']="none"; else $data['Compression']="gzip";
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
308
	    
309
		$data['Peer']=$peer;
310
	    
311
	    
312
		foreach ($ids as $serieID) {
313
			$resourceSeries['Level']="Series";
314
			$resourceSeries['ID']=$serieID;
315
			$data['Resources'][]=$resourceSeries;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $resourceSeries seems to be defined later in this foreach loop on line 313. Are you sure it is defined here?
Loading history...
316
		}
317
	    
318
		$opts=array('http' =>
319
			array(
320
				'method'  => 'POST',
321
				'content' => json_encode($data),
322
				'header'=>  ['Content-Type: application/json Accept: application/json', $this->context['http']['header']]
323
			)
324
		);
325
	    
326
		$context=stream_context_create($opts);
327
		$result=file_get_contents($this->url.'/transfers/send', false, $context);
328
	    
329
		return $result;
330
	    
331
	}
332
	
333
	/**
334
	 * Import a file in Orthanc using the POST API
335
	 * @param string $file (path)
336
	 * @return string
337
	 */
338
	public function importFile(string $file) {
339
	    
340
		try {
341
			$opts=array('http' =>
342
				array(
343
					'method'  => 'POST',
344
					'content' => file_get_contents($file),
345
					'header'=>  ['Content-Type: application/dicom Accept: application/json', "content-length: ".filesize($file), $this->context['http']['header']]
346
				)
347
			);
348
    	    
349
			$context=stream_context_create($opts);
350
			$result=file_get_contents($this->url.'/instances', false, $context);
351
    	    
352
		}catch (Exception $e1) {
353
			error_log("Error during import Dcm ".$e1->getMessage());
354
		}
355
		return $result;
356
357
	}
358
359
	/**
360
	 * This method has the advantage to stream the content and avoid running out memory
361
	 */
362
	public function importFileGuzzle(string $file){
363
		try{
364
			$body = fopen($file, 'r');
365
366
			$options = ['auth' => [$this->login, $this->password],
367
			'headers'  => ['content-type' => 'application/dicom', 'Accept' => 'application/json'],
368
			'body' => $body];
369
370
			$response = $this->client->request('POST', $this->url.'/instances' , $options);
371
			
372
			return (string) $response->getBody();
373
		} catch (Exception $e1) {
374
			error_log("Error during import Dcm ".$e1->getMessage());
375
		}
376
	}
377
378
	/**
379
	 * Anonymize a study ressources according to Anon Profile
380
	 * Return the Anonymized Orthanc ID
381
	 * @param string $studyID
382
	 * @param string $profile
383
	 * @param string $patientCode
384
	 * @param string $visitType
385
	 * @param string $studyName
386
	 * @return string
387
	 */
388
	public function Anonymize(string $studyID, string $profile, string $patientCode, string $visitType, string $studyName) {
389
	    
390
		$jsonAnonQuery=$this->buildAnonQuery($profile, $patientCode, $patientCode, $visitType, $studyName);
391
	    
392
		$opts=array('http' =>
393
			array(
394
				'method'  => 'POST',
395
				"timeout" => 300,
396
				'content' => json_encode($jsonAnonQuery),
397
				'header'=>  ['Content-Type: application/json Accept: application/json', $this->context['http']['header']]
398
			)
399
		);
400
	    
401
		$context=stream_context_create($opts);
402
403
		$result=file_get_contents($this->url."/studies/".$studyID."/anonymize", false, $context);
404
        
405
		//get the resulting Anonymized study Orthanc ID
406
		$anonAnswer=json_decode($result, true);
407
		$anonymizedID=$anonAnswer['ID'];
408
	    
409
		//Remove SC if any in the anonymized study
410
		$this->removeSC($anonymizedID);
411
	    
412
		return $anonymizedID;
413
	    
414
	}
415
	
416
	/**
417
	 * Build Anon Json post for Anon settings
418
	 * @param string $profile
419
	 * @param string $newPatientName
420
	 * @param string $newPatientID
421
	 * @param string $newStudyDescription
422
	 * @return string
423
	 */
424
	private function buildAnonQuery(string $profile, string $newPatientName, string $newPatientID, string $newStudyDescription, string $clinicalStudy) {
425
    	    
426
		$tagsObjects=[];
427
		if ($profile == "Default") {
428
			$date=TagAnon::KEEP;
429
			$body=TagAnon::KEEP;
430
            
431
			$tagsObjects[]=new TagAnon("0010,0030", TagAnon::REPLACE, "19000101"); // BirthDay
432
			$tagsObjects[]=new TagAnon("0008,1030", TagAnon::REPLACE, $newStudyDescription); //studyDescription
433
			$tagsObjects[]=new TagAnon("0008,103E", TagAnon::KEEP); //series Description
434
           
435
    
436
		}else if ($profile == "Full") {
437
			$date=TagAnon::CLEAR;
438
			$body=TagAnon::CLEAR;
439
            
440
			$tagsObjects[]=new TagAnon("0010,0030", TagAnon::REPLACE, "19000101"); // BirthDay
441
			$tagsObjects[]=new TagAnon("0008,1030", TagAnon::CLEAR); // studyDescription
442
			$tagsObjects[]=new TagAnon("0008,103E", TagAnon::CLEAR); //series Description
443
		}
444
        
445
		//List tags releted to Date
446
		$tagsObjects[]=new TagAnon("0008,0022", $date); // Acquisition Date
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $date does not seem to be defined for all execution paths leading up to this point.
Loading history...
447
		$tagsObjects[]=new TagAnon("0008,002A", $date); // Acquisition DateTime
448
		$tagsObjects[]=new TagAnon("0008,0032", $date); // Acquisition Time
449
		$tagsObjects[]=new TagAnon("0038,0020", $date); // Admitting Date
450
		$tagsObjects[]=new TagAnon("0038,0021", $date); // Admitting Time
451
		$tagsObjects[]=new TagAnon("0008,0035", $date); // Curve Time
452
		$tagsObjects[]=new TagAnon("0008,0025", $date); // Curve Date
453
		$tagsObjects[]=new TagAnon("0008,0023", $date); // Content Date
454
		$tagsObjects[]=new TagAnon("0008,0033", $date); // Content Time
455
		$tagsObjects[]=new TagAnon("0008,0024", $date); // Overlay Date
456
		$tagsObjects[]=new TagAnon("0008,0034", $date); // Overlay Time
457
		$tagsObjects[]=new TagAnon("0040,0244", $date); // ...Start Date
458
		$tagsObjects[]=new TagAnon("0040,0245", $date); // ...Start Time
459
		$tagsObjects[]=new TagAnon("0008,0021", $date); // Series Date
460
		$tagsObjects[]=new TagAnon("0008,0031", $date); // Series Time
461
		$tagsObjects[]=new TagAnon("0008,0020", $date); // Study Date
462
		$tagsObjects[]=new TagAnon("0008,0030", $date); // Study Time
463
		$tagsObjects[]=new TagAnon("0010,21D0", $date); // Last menstrual date
464
		$tagsObjects[]=new TagAnon("0008,0201", $date); // Timezone offset from UTC
465
		$tagsObjects[]=new TagAnon("0040,0002", $date); // Scheduled procedure step start date
466
		$tagsObjects[]=new TagAnon("0040,0003", $date); // Scheduled procedure step start time
467
		$tagsObjects[]=new TagAnon("0040,0004", $date); // Scheduled procedure step end date
468
		$tagsObjects[]=new TagAnon("0040,0005", $date); // Scheduled procedure step end time
469
    	
470
		// same for Body characteristics
471
		$tagsObjects[]=new TagAnon("0010,2160", $body); // Patient's ethnic group
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $body does not seem to be defined for all execution paths leading up to this point.
Loading history...
472
		$tagsObjects[]=new TagAnon("0010,21A0", $body); // Patient's smoking status
473
		$tagsObjects[]=new TagAnon("0010,0040", $body); // Patient's sex
474
		$tagsObjects[]=new TagAnon("0010,2203", $body); // Patient's sex neutered
475
		$tagsObjects[]=new TagAnon("0010,1010", $body); // Patient's age
476
		$tagsObjects[]=new TagAnon("0010,21C0", $body); // Patient's pregnancy status
477
		$tagsObjects[]=new TagAnon("0010,1020", $body); // Patient's size
478
		$tagsObjects[]=new TagAnon("0010,1030", $body); // Patient's weight
479
    
480
		//Others
481
		$tagsObjects[]=new TagAnon("0008,0050", TagAnon::REPLACE, $clinicalStudy); // Accession Number contains study name
482
		$tagsObjects[]=new TagAnon("0010,0020", TagAnon::REPLACE, $newPatientID); //new Patient Name
483
		$tagsObjects[]=new TagAnon("0010,0010", TagAnon::REPLACE, $newPatientName); //new Patient Name
484
    	
485
		// Keep some Private tags usefull for PET/CT or Scintigraphy
486
		$tagsObjects[]=new TagAnon("7053,1000", TagAnon::KEEP); //Phillips
487
		$tagsObjects[]=new TagAnon("7053,1009", TagAnon::KEEP); //Phillips
488
		$tagsObjects[]=new TagAnon("0009,103B", TagAnon::KEEP); //GE
489
		$tagsObjects[]=new TagAnon("0009,100D", TagAnon::KEEP); //GE
490
		$tagsObjects[]=new TagAnon("0011,1012", TagAnon::KEEP); //Other
491
    	
492
		$jsonArrayAnon=[];
493
		$jsonArrayAnon['KeepPrivateTags']=false;
494
		$jsonArrayAnon['Force']=true;
495
    	
496
		foreach ($tagsObjects as $tag) {
497
    	    
498
			if ($tag->choice == TagAnon::REPLACE) {
499
				$jsonArrayAnon['Replace'][$tag->tag]=$tag->newValue;
500
			}else if ($tag->choice == TagAnon::KEEP) {
501
				$jsonArrayAnon['Keep'][]=$tag->tag;
502
			}
503
            
504
		}
505
    	
506
		return $jsonArrayAnon;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $jsonArrayAnon returns the type array which is incompatible with the documented return type string.
Loading history...
507
    	
508
	}
509
    
510
	/**
511
	 * Remove secondary captures in the study
512
	 * @param string $orthancStudyID
513
	 */
514
	private function removeSC(string $orthancStudyID) {
515
    	
516
		$studyOrthanc=new Orthanc_Study($orthancStudyID, $this->url, $this->context);
517
		$studyOrthanc->retrieveStudyData();
518
		$seriesObjects=$studyOrthanc->orthancSeries;
519
		foreach ($seriesObjects as $serie) {
520
			if ($serie->isSecondaryCapture()) {
521
				$this->deleteFromOrthanc("series", $serie->serieOrthancID);
522
			}
523
		}
524
    	
525
	}
526
    
527
    
528
	/**
529
	 * Return JobId details (get request in Orthanc)
530
	 * @param String $jobId
531
	 * @return mixed
532
	 */
533
	public function getJobDetails(String $jobId) {
534
        
535
		$context=stream_context_create($this->context);
536
		$json=file_get_contents($this->url.'/jobs/'.$jobId, false, $context);
537
        
538
		return json_decode($json, true);
539
        
540
	}
541
542
}