Reuse FTP connection if possible
 
	
	
	
	
	
	
		
		1 files added
	
		
		1 files modified
	
	
 
	
	
	
	
	
	
	
	
| New file | 
 |  |  | 
 |  |  | <?php | 
 |  |  | class FtpConnection { | 
 |  |  |     private static $instances = []; | 
 |  |  |     private $connection; | 
 |  |  | 	 | 
 |  |  |     static function create(string $host, int $port=21, string $user='anonymous', string $pass='anonymous') : FtpConnection { | 
 |  |  |         $key = $host."\0".$port."\0".$user."\0".$pass; | 
 |  |  |         if(!isset(self::$instances[$key])) { | 
 |  |  |             self::$instances[$key] = new FtpConnection($host, $port, $user, $pass); | 
 |  |  |         } | 
 |  |  |         return self::$instances[$key]; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     private function __construct(string $host, int $port=21, string $user, string $pass) { | 
 |  |  |         $this->connection = ftp_connect($host, $port, 10); | 
 |  |  |         if($this->connection === FALSE) { | 
 |  |  |             throw new Exception('FTP connection failed'); | 
 |  |  |         } | 
 |  |  |         if(!ftp_login($this->connection, $user, $pass)) { | 
 |  |  |             throw new Exception('FTP login failed'); | 
 |  |  |         } | 
 |  |  |         if(!ftp_pasv($this->connection, TRUE)) { | 
 |  |  |             throw new Exception('Passive FTP request failed'); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     public function __destruct() { | 
 |  |  |         ftp_close($this->connection); | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     public function size(string $file) : int { | 
 |  |  |         $remoteSize = ftp_size($this->connection, $file); | 
 |  |  |         if($remoteSize < 0) { | 
 |  |  |             throw new Exception('FTP file size fetch failed'); | 
 |  |  |         } | 
 |  |  |         return $remoteSize; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  | 	 | 
 |  |  |     public function mdtm(string $file) : int { | 
 |  |  |         $remoteTime = ftp_mdtm($this->connection, $file); | 
 |  |  |         if($remoteTime < 0) { | 
 |  |  |             throw new Exception('FTP modification time fetch failed'); | 
 |  |  |         } | 
 |  |  |         return $remoteTime; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     public function get(string $local_file, string $remote_file, int $mode = FTP_BINARY, int $resumepos = 0) : bool { | 
 |  |  |         $result = ftp_get($this->connection, $local_file, $remote_file, $mode, $resumepos); | 
 |  |  |         if($result === FALSE) { | 
 |  |  |             throw new Exception('FTP file get failed'); | 
 |  |  |         } | 
 |  |  |         return $result; | 
 |  |  |     } | 
 |  |  | } | 
 
 |  |  | 
 |  |  | <?php | 
 |  |  | require_once(__DIR__.'/FtpConnection.php'); | 
 |  |  |  | 
 |  |  | function ftp_fetch_if_newer($url, $file = NULL) { | 
 |  |  |     $url = parse_url($url); | 
 |  |  |     if(!isset($url['scheme']) || $url['scheme'] != 'ftp') { | 
 |  |  | 
 |  |  |         $localSize = filesize($file); | 
 |  |  |     } | 
 |  |  |      | 
 |  |  |     $ftp = ftp_connect($url['host'], $url['port'], 10); | 
 |  |  |     if($ftp === FALSE) { | 
 |  |  |         throw new Exception('FTP connection failed'); | 
 |  |  |     } | 
 |  |  |     if(!ftp_login($ftp, $url['user'], $url['pass'])) { | 
 |  |  |         throw new Exception('FTP login failed'); | 
 |  |  |     } | 
 |  |  |     if(!ftp_pasv($ftp, TRUE)) { | 
 |  |  |         throw new Exception('Passive FTP request failed'); | 
 |  |  |     } | 
 |  |  |     $remoteSize = ftp_size($ftp, $url['path']); | 
 |  |  |     if($remoteSize < 0) { | 
 |  |  |         throw new Exception('FTP file size fetch failed'); | 
 |  |  |     } | 
 |  |  |     $remoteTime = ftp_mdtm($ftp, $url['path']); | 
 |  |  |     if($remoteTime < 0) { | 
 |  |  |         throw new Exception('FTP modification time fetch failed'); | 
 |  |  |     } | 
 |  |  |     $ftp = FtpConnection::create($url['host'], $url['port'], $url['user'], $url['pass']); | 
 |  |  |     $remoteSize = $ftp->size($url['path']); | 
 |  |  |     $remoteTime = $ftp->mdtm($url['path']); | 
 |  |  |      | 
 |  |  |     $updated = FALSE; | 
 |  |  |      | 
 |  |  | 
 |  |  |         if(file_exists($file.'.tmp')) { | 
 |  |  |             unlink($file.'.tmp'); | 
 |  |  |         } | 
 |  |  |         if(ftp_get($ftp, $file.'.tmp', $url['path'], FTP_BINARY)) { | 
 |  |  |             touch($file.'.tmp', $remoteTime); | 
 |  |  |             if(!rename($file.'.tmp', $file)) { | 
 |  |  |                 throw new Exception('Temporary file rename failed'); | 
 |  |  |             } | 
 |  |  |             $updated = TRUE; | 
 |  |  |         $ftp->get($file.'.tmp', $url['path'], FTP_BINARY); | 
 |  |  |         touch($file.'.tmp', $remoteTime); | 
 |  |  |         if(!rename($file.'.tmp', $file)) { | 
 |  |  |             throw new Exception('Temporary file rename failed'); | 
 |  |  |         } | 
 |  |  |         $updated = TRUE; | 
 |  |  |     } | 
 |  |  | 	 | 
 |  |  |     ftp_close($ftp); | 
 |  |  |      | 
 |  |  |     return $updated; | 
 |  |  | } |