Import_Patient::addPatientToDatabase()   A
last analyzed

Complexity

Conditions 2
Paths 3

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 17
c 1
b 0
f 0
nc 3
nop 10
dl 0
loc 24
rs 9.7

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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