FTP_Reader::setSearchedFile()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
nc 1
nop 1
dl 0
loc 3
c 1
b 0
f 0
cc 1
rs 10
1
<?php
2
3
/**
4
 Copyright (C) 2018-2020 KANOUN Salim
5
 This program is free software; you can redistribute it and/or modify
6
 it under the terms of the Affero GNU General Public v.3 License as published by
7
 the Free Software Foundation;
8
 This program is distributed in the hope that it will be useful,
9
 but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
 Affero GNU General Public Public for more details.
12
 You should have received a copy of the Affero GNU General Public Public along
13
 with this program; if not, write to the Free Software Foundation, Inc.,
14
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
 */
16
17
/**
18
 * Access Data from FTP Source
19
 */
20
21
use phpseclib\Net\SFTP;
0 ignored issues
show
Bug introduced by
The type phpseclib\Net\SFTP 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...
22
23
class FTP_Reader
24
{
25
26
	public $ftpUsername;
27
	public $ftpPassword;
28
	public $ftpHost;
29
	public $ftpPort;
30
	public $ftpIsSftp;
31
	public $ftpFolder;
32
	public $ftpFileName;
33
	public $lastUpdateLimit;
34
	private $linkpdo;
35
36
	public function __construct($linkpdo)
37
	{
38
		$this->linkpdo=$linkpdo;
39
		$this->ftpFileName=null;
40
		$this->lastUpdateLimit=null;
41
		$this->ftpFolder='/';
42
	}
43
44
	/**
45
	 * 
46
	 */
47
	public function setFTPCredential(String $host, String $username, String $password, int $port=21, bool $ftpIsSftp=false)
48
	{
49
		$this->ftpHost=$host;
50
		$this->ftpUsername=$username;
51
		$this->ftpPassword=$password;
52
		$this->ftpPort=$port;
53
		$this->ftpIsSftp=$ftpIsSftp;
54
	}
55
56
	public function setFolder(String $folder)
57
	{
58
		$this->ftpFolder=$folder;
59
	}
60
61
	public function setSearchedFile(String $fileName)
62
	{
63
		$this->ftpFileName=$fileName;
64
	}
65
66
	/**
67
	 * Number of minutes the last update of files should be inferior
68
	 */
69
	public function setLastUpdateTimingLimit(int $lastUpdateLimit)
70
	{
71
		$this->lastUpdateLimit=$lastUpdateLimit;
72
	}
73
74
	private function selectWantedFiles(array $fileArray)
75
	{
76
		if ($this->ftpFileName != null) {
77
			$isAvailable=$this->isSearchedFileAvailable($fileArray);
78
			if ($isAvailable) {
79
				return array($this->ftpFileName);
80
			}else {
81
				throw new Exception('Target File Not Found');
82
			}
83
		}else {
84
			return $fileArray;
85
		}
86
	}
87
88
	private function isSearchedFileAvailable(array $fileArray)
89
	{
90
		return in_array($this->ftpFileName, $fileArray) ? true : false;
91
	}
92
93
	private function isLastUpdateInTimingLimit(int $mtimStamp)
94
	{
95
		//$lastUpdateTime=DateTime::createFromFormat('U', $mtim);
96
		$dateNow=new DateTime();
97
98
		if (($this->lastUpdateLimit != null) &&
99
			($dateNow->getTimestamp()-$mtimStamp) > ($this->lastUpdateLimit*60)
100
		) {
101
			throw new Exception('File last update too old');
102
		}
103
		return true;
104
	}
105
106
	/**
107
	 * Download the FTP folder taget and return an array of temporary dowloaded files
108
	 */
109
	public function getFilesFromFTP()
110
	{
111
112
		if ($this->ftpIsSftp) {
113
114
			$filesArray=$this->getSftp();
115
		}else {
116
			$filesArray=$this->getFtp();
117
			//$ftpConnect = ftp_ssl_connect ($this->ftpHost, $this->ftpPort) or die("Can't Connect to Server ".$this->ftpHost);
118
119
		}
120
121
		return $filesArray;
122
	}
123
124
	private function connectAndGoToFolder() {
125
126
		if ($this->ftpIsSftp) {
127
128
			$sftp=new SFTP($this->ftpHost);
129
			if (!$sftp->login($this->ftpUsername, $this->ftpPassword)) {
130
				throw new Exception('Login SFTP failed');
131
			}
132
    
133
			if (!$sftp->chdir($this->ftpFolder)) {
134
				throw new Exception("Can't reach SFTP Path Target");
135
			};
136
137
			return $sftp;
138
139
		}else {
140
141
			if (!$ftpConnect=ftp_connect($this->ftpHost, $this->ftpPort)) {
142
				throw new Exception('Cant Connect to Server'.$this->ftpHost);
143
			}
144
    
145
			if (!ftp_login($ftpConnect, $this->ftpUsername, $this->ftpPassword)) {
146
				ftp_close($ftpConnect);
147
				throw new Exception('Login failed');
148
			};
149
    
150
			//Move to the target folder
151
			if (!ftp_chdir($ftpConnect, $this->ftpFolder)) {
152
				ftp_close($ftpConnect);
153
				throw new Exception("Can't reach FTP Path Target");
154
			}
155
156
			return $ftpConnect;
157
158
		}
159
160
	}
161
162
	public function writeExportDataFile(String $fileName, String $file) {
163
164
		if ($this->ftpIsSftp) {
165
166
			$sftp=$this->connectAndGoToFolder();
167
168
			$result=$sftp->put($fileName, $file, SFTP::SOURCE_LOCAL_FILE);
169
170
			return $result;
171
172
		}else {      
173
174
			$ftp=$this->connectAndGoToFolder();
175
176
			$result=ftp_fput($ftp, $fileName, fopen($file, 'r'));
0 ignored issues
show
Bug introduced by
It seems like $ftp can also be of type phpseclib\Net\SFTP; however, parameter $ftp of ftp_fput() 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

176
			$result=ftp_fput(/** @scrutinizer ignore-type */ $ftp, $fileName, fopen($file, 'r'));
Loading history...
177
178
			return $result;
179
		}
180
181
182
	}
183
184
	private function getSftp()
185
	{
186
		$sftp=$this->connectAndGoToFolder();
187
188
		$fileArray=$sftp->nlist();
189
190
		//Remove . and ..
191
		$fileArray=array_filter($fileArray, function($file) {
0 ignored issues
show
Bug introduced by
It seems like $fileArray can also be of type false; however, parameter $array of array_filter() does only seem to accept array, 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

191
		$fileArray=array_filter(/** @scrutinizer ignore-type */ $fileArray, function($file) {
Loading history...
192
			if ($file == '.' || $file == '..') {
193
				return false;
194
			}else {
195
				return true;
196
			}
197
		});
198
        
199
200
201
		print_r($fileArray);
202
203
		$selectedFiles=$this->selectWantedFiles($fileArray);
204
205
		$resultFileArray=[];
206
207
		foreach ($selectedFiles as $fileInFtp) {
208
			$fileState=$sftp->stat($fileInFtp);
209
			$this->isLastUpdateInTimingLimit($fileState['mtime']);
210
			print_r($fileState);
211
			$temp=fopen(sys_get_temp_dir().DIRECTORY_SEPARATOR.$fileInFtp, 'w');
212
			//Retrieve File from SFTP
213
			$sftp->get($fileInFtp, $temp);
0 ignored issues
show
Bug introduced by
$temp of type resource is incompatible with the type string expected by parameter $local_file of phpseclib\Net\SFTP::get(). ( Ignorable by Annotation )

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

213
			$sftp->get($fileInFtp, /** @scrutinizer ignore-type */ $temp);
Loading history...
214
			fclose($temp);
215
			//Store resulting file in array
216
			$resultFileArray[]=sys_get_temp_dir().DIRECTORY_SEPARATOR.$fileInFtp;
217
		}
218
219
		return $resultFileArray;
220
	}
221
222
	private function getFtp()
223
	{
224
		$ftpConnect=$this->connectAndGoToFolder();
225
226
		// Get files in the ftp folder
227
		$fileArray=ftp_nlist($ftpConnect, ".");
0 ignored issues
show
Bug introduced by
It seems like $ftpConnect can also be of type phpseclib\Net\SFTP; however, parameter $ftp of ftp_nlist() 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

227
		$fileArray=ftp_nlist(/** @scrutinizer ignore-type */ $ftpConnect, ".");
Loading history...
228
229
		//Remove . and ..
230
		$fileArray=array_filter($fileArray, function($file) {
231
			if ($file == '.' || $file == '..') {
232
				return false;
233
			}else {
234
				return true;
235
			}
236
		});
237
238
		$selectedFiles=$this->selectWantedFiles($fileArray);
239
240
		$resultFileArray=[];
241
242
		foreach ($selectedFiles as $fileInFtp) {
243
			$temp=fopen(sys_get_temp_dir().DIRECTORY_SEPARATOR.$fileInFtp, 'w');
244
			ftp_fget($ftpConnect, $temp, $fileInFtp);
0 ignored issues
show
Bug introduced by
It seems like $ftpConnect can also be of type phpseclib\Net\SFTP; however, parameter $ftp of ftp_fget() 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

244
			ftp_fget(/** @scrutinizer ignore-type */ $ftpConnect, $temp, $fileInFtp);
Loading history...
245
			fclose($temp);
246
			//Store resulting file in array
247
			$resultFileArray[]=sys_get_temp_dir().DIRECTORY_SEPARATOR.$fileInFtp;
248
		}
249
250
		ftp_close($ftpConnect);
0 ignored issues
show
Bug introduced by
It seems like $ftpConnect can also be of type phpseclib\Net\SFTP; however, parameter $ftp of ftp_close() 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

250
		ftp_close(/** @scrutinizer ignore-type */ $ftpConnect);
Loading history...
251
252
		return $resultFileArray;
253
	}
254
255
	/**
256
	 * Transform Text file with # separator to an associative array
257
	 */
258
	public static function parseLysarcTxt(String $txt)
259
	{
260
		//Erase last empty new line
261
		$txt=rtrim($txt);
262
		//Divided text in row by splitting new line
263
		$lines=explode("\n", $txt);
264
265
		$titles=[];
266
		$results=[];
267
268
		for ($i=0; $i < sizeOf($lines); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
269
			//remove return new line and last #
270
			$lines[$i]=rtrim($lines[$i]);
271
			$lines[$i]=rtrim($lines[$i], '#');
272
			//split string in columns
273
			$columns=explode("#", $lines[$i]);
274
			if ($i == 0) {
275
				//First line is column definition
276
				$titles=$columns;
277
			}else {
278
				$patient=[];
279
				//For each column associate data into an associative array
280
				for ($j=0; $j < sizeof($columns); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
281
					$patient[$titles[$j]]=$columns[$j];
282
				}
283
				$results[]=$patient;
284
			}
285
		}
286
287
		return $results;
288
	}
289
290
291
	function sendFailedReadFTP($exceptionMessage) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
292
		try {
293
			$email=new Send_Email($this->linkpdo);
294
			$email->setMessage("FTP Process Has failed <br> Reason : ".$exceptionMessage);
295
			$email->setSubject('FTP Process Failed');
296
			$email->addAminEmails();
297
			$email->sendEmail();
298
		}catch (Exception $e) {
299
			echo('sendEmailException');
300
			echo($e->getMessage());
301
		}
302
303
    
304
	}
305
306
307
	/**
308
	 * Return files from a local folder
309
	 * @param string $folder
310
	 * @return string[]
311
	 */
312
	/*
313
    public static function getFilesFromFolder(string $folder)
314
    {
315
316
        $scanned_directory = array_diff(scandir($folder), array('..', '.'));
317
318
        $resultFileArray = [];
319
        foreach ($scanned_directory as $file) {
320
321
            $resultFileArray[] = $folder . DIRECTORY_SEPARATOR . $file;
322
        }
323
324
        return $resultFileArray;
325
    }
326
    */
327
}
328