Ftp   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 197
rs 10
c 0
b 0
f 0
wmc 29

16 Methods

Rating   Name   Duplication   Size   Complexity  
A makeDir() 0 8 4
A isSsl() 0 2 1
A getServer() 0 2 1
A isPassive() 0 2 1
A delete() 0 8 4
A getConnectionResource() 0 2 1
A handleRetention() 0 13 3
A __construct() 0 7 1
A close() 0 2 1
A getTransferMode() 0 2 1
A getType() 0 2 1
B connect() 0 25 6
A get() 0 2 1
A getUsername() 0 2 1
A getItemsList() 0 2 1
A put() 0 2 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: nicolas
5
 * Date: 09/02/17
6
 * Time: 23:06
7
 */
8
9
namespace Devgiants\Storage;
10
11
12
use Devgiants\Configuration\ApplicationConfiguration;
13
use Devgiants\Configuration\ConfigurationManager;
14
use Devgiants\Model\Storage;
15
use Devgiants\Model\StorageInterface;
16
use Symfony\Component\Config\Definition\Exception\Exception;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Config...ion\Exception\Exception 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
class Ftp extends Storage {
19
	/**
20
	 * @var resource the FTP connection resource
21
	 */
22
	protected $connectionResource;
23
	/**
24
	 * @var string $server
25
	 */
26
	protected $server;
27
	/**
28
	 * @var string $username
29
	 */
30
	protected $username;
31
	/**
32
	 * @var string $password
33
	 */
34
	protected $password;
35
	/**
36
	 * @var bool $passive
37
	 */
38
39
	protected $passive;
40
	/**
41
	 * @var bool $ssl
42
	 */
43
	protected $ssl;
44
	/**
45
	 * @var int $transferMode
46
	 */
47
	protected $transferMode;
48
49
	/**
50
	 * FtpManager constructor.
51
	 *
52
	 * @param array $options
53
	 */
54
	public function __construct( $options ) {
55
		$this->server       = $options[ ApplicationConfiguration::SERVER ];
56
		$this->username     = $options[ ApplicationConfiguration::USER ];
57
		$this->password     = $options[ ApplicationConfiguration::PASSWORD ];
58
		$this->passive      = $options[ ApplicationConfiguration::PASSIVE ];
59
		$this->ssl          = $options[ ApplicationConfiguration::SSL ];
60
		$this->transferMode = $options[ ApplicationConfiguration::TRANSFER ];
61
	}
62
63
	/**
64
	 * @return resource
65
	 */
66
	public function getConnectionResource() {
67
		return $this->connectionResource;
68
	}
69
70
	/**
71
	 * @return string
72
	 */
73
	public function getServer() {
74
		return $this->server;
75
	}
76
77
	/**
78
	 * @return string
79
	 */
80
	public function getUsername() {
81
		return $this->username;
82
	}
83
84
	/**
85
	 * @return boolean
86
	 */
87
	public function isPassive() {
88
		return $this->passive;
89
	}
90
91
	/**
92
	 * @return boolean
93
	 */
94
	public function isSsl() {
95
		return $this->ssl;
96
	}
97
98
	/**
99
	 * @return int
100
	 */
101
	public function getTransferMode() {
102
		return $this->transferMode;
103
	}
104
105
	/**
106
	 * Establish FTP connection
107
	 * @throws Exception
108
	 */
109
	public function connect() {
110
111
		// Handle SSL connection
112
		if ( $this->ssl === true ) {
113
			$this->connectionResource = ftp_ssl_connect( $this->server );
114
		} else {
115
			$this->connectionResource = ftp_connect( $this->server );
116
		}
117
118
		if ( ! $this->connectionResource ) {
119
			throw new Exception( "Impossible to establish connection on FTP server {$this->server} with username {$this->username} (SSL = {$this->ssl})" );
120
		}
121
122
		// Try to login
123
		$loginResult = ftp_login( $this->connectionResource, $this->username, $this->password );
124
125
		// If login successful
126
		if ( $loginResult ) {
127
			// Set passive mode according to configuration
128
			if ( $this->passive === true ) {
129
				ftp_pasv( $this->connectionResource, true );
130
			}
131
		}
132
		if ( ! $loginResult ) {
133
			throw new Exception( "Impossible to authenticate on FTP server {$this->server} with username {$this->username} (SSL = {$this->ssl})" );
134
		}
135
	}
136
137
	/**
138
	 * @inheritdoc
139
	 */
140
	public function put( $localPath, $remotePath, array $params = null ) {
141
		return ftp_put( $this->connectionResource, $remotePath, $localPath, $this->transferMode );
142
	}
143
144
	/**
145
	 * @inheritdoc
146
	 */
147
	public function getItemsList( $remotePath, array $params = null ) {
148
		return ftp_nlist( $this->connectionResource, $remotePath );
149
	}
150
151
	/**
152
	 * @inheritdoc
153
	 */
154
	public function get( $remotePath, $localPath, array $params = null ) {
155
		return ftp_get( $this->connectionResource, $localPath, $remotePath, FTP_BINARY );
156
	}
157
158
	/**
159
	 * @inheritdoc
160
	 * // TODO handle recursive
161
	 */
162
	public function delete( $path, $recursive = true ) {
163
		if ( @ftp_delete( $this->connectionResource, $path ) === false ) {
164
			if ( $children = @ftp_nlist( $this->connectionResource, $path ) ) {
165
				foreach ( $children as $p ) {
166
					$this->delete( $p, $recursive );
167
				}
168
			}
169
			@ftp_rmdir( $this->connectionResource, $path );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ftp_rmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

169
			/** @scrutinizer ignore-unhandled */ @ftp_rmdir( $this->connectionResource, $path );

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
170
		}
171
	}
172
173
	/**
174
	 * @inheritdoc
175
	 * // TODO handle recursive
176
	 */
177
	public function makeDir( $path, $recursive = true ) {
178
		$parts = explode( '/', $path );
179
180
		foreach ( $parts as $part ) {
181
			if ( ! empty( $part ) && ! @ftp_chdir( $this->connectionResource, $path ) ) {
182
				// TODO find how to correctly specify folder to not trigger warning
183
				@ftp_mkdir( $this->connectionResource, $part );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ftp_mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

183
				/** @scrutinizer ignore-unhandled */ @ftp_mkdir( $this->connectionResource, $part );

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
184
				ftp_chdir( $this->connectionResource, $part );
185
			}
186
		}
187
	}
188
189
	/**
190
	 * @inheritdoc
191
	 */
192
	public function handleRetention( int $retention, array $params = null ) {
193
		// TODO find best way for configurable architecture
194
		// Goes back to timestamps folders list
195
		ftp_chdir( $this->connectionResource, '../' );
196
		$timestampDirs = ftp_nlist( $this->connectionResource, "." );
197
		if ( count( $timestampDirs ) > $retention ) {
198
199
			sort( $timestampDirs );
200
			$folderNumberToRemove = count( $timestampDirs ) - $retention;
201
202
			// Prune older directories
203
			for ( $i = 0; $i < $folderNumberToRemove; $i ++ ) {
204
				$this->delete( $timestampDirs[ $i ] );
205
			}
206
		}
207
	}
208
209
	public function close() {
210
		ftp_close( $this->connectionResource );
211
	}
212
213
	public static function getType() {
214
		return 'FTP';
215
	}
216
}