Import_Patient::buildErrorAnswer()   A
last analyzed

Complexity

Conditions 5
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 2
nop 0
dl 0
loc 19
rs 9.5555
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
/**
17
 * Import patient in study (import data from Json structured file)
18
 */
19
20
class Import_Patient {
21
22
	private $originalJson;
23
	private $linkpdo;
24
	public $sucessList;
25
	public $failList;
26
	private $study;
27
	private $studyObject;
28
	
29
	public function __construct($originalJson, $study, $linkpdo) {
30
		$this->linkpdo=$linkpdo;
31
		//Store the JSON file and the target study
32
		$this->originalJson=$originalJson;
33
		$this->study=$study;
34
		$this->studyObject=new Study($study, $linkpdo);
35
	}
36
37
	public function readJson() {
38
		$jsonImport=json_decode($this->originalJson, true);
39
		
40
		//For each patient from the array list
41
		foreach ($jsonImport as $patient) {
42
			//Get patient info
43
			$patientNumber=$patient['patientNumber'];
44
			$patientLastName=$patient['lastName'];
45
			$patientFirstName=$patient['firstName'];
46
			$patientGender=$patient['gender'];
47
			$patientInvestigatorNumCenter=$patient['investigatorNumCenter'];
48
			$patientDateOfBirth=$patient['dateOfBirth'];
49
			$patientInvestigatorName=$patient['investigatorName'];
50
			$patientRegistrationDate=$this->parseRegistrationDate($patient['registrationDate']);
51
		    
52
			//Check condition before import
53
			$isNewPatient=$this->isNewPatient($patientNumber);
54
			$isCorrectPatientNumberLenght=$this->isCorrectPatientNumberLenght($patientNumber);
55
			$isExistingCenter=$this->isExistingCenter($patientInvestigatorNumCenter);
56
			$isPrefixCorrect=$this->isCorrectPrefix($patientNumber);
57
			
58
			if ($isNewPatient && $isCorrectPatientNumberLenght && $isPrefixCorrect && $isExistingCenter && !empty($patientRegistrationDate)) {
59
				//Store in DB
60
				$birthDateArray=explode("/", $patientDateOfBirth);
61
				if (GAELO_DATE_FORMAT == 'm.d.Y') {
62
					$birthDay=intval($birthDateArray[1]);
63
					$birthMonth=intval($birthDateArray[0]);
64
				}else if (GAELO_DATE_FORMAT == 'd.m.Y') {
65
					$birthDay=intval($birthDateArray[0]);
66
					$birthMonth=intval($birthDateArray[1]);
67
				}
68
				$birthYear=intval($birthDateArray[2]);
69
			    
70
				$insertddb=$this->addPatientToDatabase($patientNumber, $patientLastName, $patientFirstName, $patientGender,
71
					$patientInvestigatorNumCenter, $patientRegistrationDate, $birthDay, $birthMonth, $birthYear, $patientInvestigatorName);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $birthDay does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $birthMonth does not seem to be defined for all execution paths leading up to this point.
Loading history...
72
				
73
				//Store the patient result import process in this object
74
				if ($insertddb) {
75
						$this->sucessList[]=$patientNumber;
76
				}else {
77
					$patientFailed['PatientNumber']=$patientNumber;
78
					$patientFailed['Reason']="Can't write to DB, wrong date or other wrong input";
79
					$this->failList[]=$patientFailed;
80
				}
81
82
			//If conditions not met, add to the fail list with the respective error reason
83
			}else {
84
			    
85
				if (!$isExistingCenter) {
86
					if (empty($patientInvestigatorNumCenter)) {
87
						$this->failList['Missing Num Center'][]=$patientNumber;
88
					}else {
89
						$this->failList['Unknown Center'][]=$patientNumber;
90
					}
91
92
				}else if (!$isCorrectPatientNumberLenght) {
93
					$this->failList['Wrong PatientNumber length'][]=$patientNumber;
94
				    
95
				}else if (!$isNewPatient) {
96
					if( !empty($patientRegistrationDate) ){
97
						$updated = $this->tryUpdateRegistrationDate($patientNumber, $patientRegistrationDate->format('Y-m-d'));
98
						if($updated){
99
							$this->sucessList[]=$patientNumber.' - Updated Registration Date';
100
						}else{
101
							$this->failList['Patient already in Database'][]=$patientNumber;
102
						}
103
					}else{
104
						$this->failList['Patient already in Database'][]=$patientNumber;
105
					}
106
					
107
				    
108
				}else if (empty($patientRegistrationDate)) {
109
					$this->failList['Empty Registration Date'][]=$patientNumber;
110
				}else if (!$isPrefixCorrect) {
111
					$this->failList['Wrong Patient Code Prefix'][]=$patientNumber;
112
				}
113
				
114
				
115
			}
116
117
		}
118
119
	}
120
121
	private function tryUpdateRegistrationDate($patientNumber, $patientRegistrationDate){
122
		$patientObject = new Patient($patientNumber, $this->linkpdo);
123
		//If patient with default registration date, update to the new one
124
		if($patientObject->patientRegistrationDate == '1900-01-01' && $patientRegistrationDate !== $patientObject->patientRegistrationDate ) {
125
			$patientObject->editPatientRegistrationDate($patientRegistrationDate);
126
			return true;
127
		}
128
129
		return false;
130
131
	}
132
	
133
	/**
134
	 * Parse registration date according to plateform preference (french or US format)
135
	 * @param string $registrationDate
136
	 * @return NULL|DateTime
137
	 */
138
	private function parseRegistrationDate(?string $registrationDate) {
139
		$dateNbArray=explode('/', $registrationDate);
0 ignored issues
show
Bug introduced by
It seems like $registrationDate can also be of type null; however, parameter $string of explode() does only seem to accept string, 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

139
		$dateNbArray=explode('/', /** @scrutinizer ignore-type */ $registrationDate);
Loading history...
140
	    
141
		if (GAELO_DATE_FORMAT == 'm.d.Y') {
142
			$registrationDay=intval($dateNbArray[1]);
143
			$registrationMonth=intval($dateNbArray[0]);
144
		}else if (GAELO_DATE_FORMAT == 'd.m.Y') {
145
			$registrationDay=intval($dateNbArray[0]);
146
			$registrationMonth=intval($dateNbArray[1]);
147
		}
148
	    
149
		$registrationYear=intval($dateNbArray[2]);
150
	    
151
		if ($registrationDay == 0 || $registrationMonth == 0 || $registrationYear == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $registrationDay does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $registrationMonth does not seem to be defined for all execution paths leading up to this point.
Loading history...
152
			return null;
153
		}
154
	    
155
		try {
156
			$dateResult=new DateTime($registrationYear.'-'.$registrationMonth.'-'.$registrationDay);
157
		}catch (Exception $e) {
158
			return null;
159
		}
160
		return $dateResult;
161
	   
162
	}
163
164
	/**
165
	 * Check that the importing patient is not already known in the system
166
	 * NB : Each patient code should be unique (across study), patient number should include a study identifier
167
	 * @param $patientCode
168
	 * @return boolean
169
	 */
170
	private function isNewPatient($patientCode) {
171
		try {
172
			new Patient($patientCode, $this->linkpdo);
173
		}catch (Exception $e1) {
174
			return true;
175
		}
176
	    
177
		return false;
178
	}
179
180
	/**
181
	 * Check that patient number has the correct lenght
182
	 * @param $patientNumber
183
	 * @return boolean
184
	 */
185
	private function isCorrectPatientNumberLenght($patientNumber) {
186
		$lenghtImport=strlen($patientNumber);
187
		
188
		if ($lenghtImport == GAELO_PATIENT_CODE_LENGHT) {
189
			return true;
190
		}else {
191
			return false;
192
		}
193
	}
194
195
	private function isCorrectPrefix($patientNumber) {
196
		//If no prefix return true
197
		if (empty($this->studyObject->patientCodePrefix)) {
198
			return true;
199
		}
200
		//test that patient code start with study prefix
201
		$patientNumberString=strval($patientNumber);
202
		$studyPrefixString=strval($this->studyObject->patientCodePrefix);
203
		return $this->startsWith($patientNumberString, $studyPrefixString);
204
205
	}
206
207
	private function startsWith(string $string, string $startString) { 
208
		$len=strlen($startString); 
209
		return (substr($string, 0, $len) === $startString); 
210
	} 
211
212
	/**
213
	 * Check that patient's center is one of known center in the plateform
214
	 * @param $patientNumCenter
215
	 * @return boolean
216
	 */
217
	private function isExistingCenter($patientNumCenter) {
218
		if (is_null($patientNumCenter) || strlen($patientNumCenter) == 0) {
219
			return false;
220
		}
221
	    
222
		try {
223
			new Center($this->linkpdo, $patientNumCenter);
224
		}catch (Exception $e1) {
225
			return false;
226
		}
227
	    
228
		return true;
229
	}
230
231
	/**
232
	 * Write the patient in the database
233
	 * @param  $patientNumber
234
	 * @param  $patientLastName
235
	 * @param  $patientFirstName
236
	 * @param  $patientGender
237
	 * @param  $patientInvestigatorCenter
238
	 * @param  $patientInvestigatorNumCenter
239
	 * @param  $dateRegistration
240
	 * @param  $patientDateOfBirth
241
	 * @param  $patientInvestigatorName
242
	 * @return boolean
243
	 */
244
	private function addPatientToDatabase($patientNumber, string $patientLastName, string $patientFirstName, string $patientGender
245
		, $patientInvestigatorNumCenter, $dateRegistration, $patientBirthDay, $patientBirthMonth, $patientBirthYear, string $patientInvestigatorName) {
246
		
247
		try {
248
			$insert_bdd=$this->linkpdo->prepare('INSERT INTO patients(study, code, first_name, last_name, gender, birth_day, birth_month, birth_year, registration_date, investigator_name, center)
249
			VALUES(:study, :code, :first_name, :last_name, :gender, :birth_day, :birth_month, :birth_year, :registration_date, :investigator_name, :center)');
250
			
251
			$insert_bdd->execute(array('code' => $patientNumber,
252
													'first_name' => @strtoupper($patientFirstName[0]),
253
													'last_name' => @strtoupper($patientLastName[0]),
254
													'gender' => @strtoupper($patientGender[0]),
255
													'birth_day' => $patientBirthDay,
256
													'birth_month' => $patientBirthMonth,
257
													'birth_year' => $patientBirthYear,
258
													'registration_date' => $dateRegistration->format('Y-m-d'),
259
													'investigator_name' => $patientInvestigatorName,
260
													'center' => $patientInvestigatorNumCenter,
261
													'study' => $this->study));
262
			$success=true;
263
		}catch (Exception $e) {
264
			$success=false;
265
		}
266
267
		return $success;
268
269
	}
270
	
271
	public function getHTMLImportAnswer() {
272
		return $this->buildSuccessAnswer().$this->buildErrorAnswer();
273
	}
274
	
275
	public function getTextImportAnswer() {
276
		//Prepare Html2PlainText for email validity (both version to enhance spam validation)
277
		$htmlMessageObject=new \Html2Text\Html2Text($this->getHTMLImportAnswer());
0 ignored issues
show
Bug introduced by
The type Html2Text\Html2Text 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...
278
		return $htmlMessageObject->getText();
279
	    
280
	}
281
	
282
	/**
283
	 * Build HTML for error answer
284
	 * @return string
285
	 */
286
	private function buildErrorAnswer() {
287
		//List of failed patients
288
		$failReport='Failed Patients: <br>';
289
		if (!empty($this->failList)) {
290
			foreach ($this->failList as $key=>$value) {
291
				if (!empty($value)) {
292
					$failReport=$failReport.$key.':<br>';
293
					if (is_array($value)) {
294
						$failReport=$failReport.implode('<br>', $value).'<br>';
295
					}else {
296
						$failReport=$failReport.$value.'<br>';
297
					}
298
				}
299
			}
300
		}else {
301
			$failReport=$failReport.' None <br>';
302
		}
303
	    
304
		return $failReport;
305
	}
306
	
307
	/**
308
	 * Generate HTML for sucess answer
309
	 * @return string
310
	 */
311
	private function buildSuccessAnswer() {
312
		//List of succeded patients
313
		$successReport='Success Patients: <br>';
314
		if (!empty($this->sucessList)) {
315
			foreach ($this->sucessList as $value) {
316
				$success=$value;
317
				$successReport=$successReport.$success.'<br>';
318
			}
319
		}else {
320
			$successReport=$successReport.' None <br>';
321
		}
322
	    
323
		return $successReport;
324
	}
325
326
}
327