Issues (18)

src/FtpSimpleClient.php (1 issue)

1
<?php
2
3
namespace Common\Tool;
4
5
/**
6
 * Simple FTP client class.
7
 *
8
 * Contains methods to:
9
 *  - create connection (ftp, ssl-ftp)
10
 *  - close connection
11
 *  - get connection
12
 *  - login
13
 *  - upload file from string
14
 *  - upload file from path
15
 *  - get the current directory name
16
 *  - change to the parent directory
17
 *  - change the current directory
18
 *  - remove a directory
19
 *  - create a directory
20
 *  - __call method to forward to native FTP functions.
21
 *    Example: "$ftpSimpleClient->delete($filePath)" will execute "ftp_delete($this->conn, $filePath)" function
22
 *
23
 * Usage example:
24
 *      $ftp = new \Common\Tool\FtpSimpleClient();
25
 *      $ftp->createConnection($host, $ssl, $port)->login($user, $pass)->chdir($directory);
26
 *      $ftp->putFromPath($filePath);
27
 *      $ftp->delete(basename($filePath));
28
 *      $ftp->closeConnection();
29
 */
30
class FtpSimpleClient
31
{
32
33
    /**
34
     * @var string $error Default exception error message mask
35
     */
36
    protected $error = 'FTP Error: %s!';
37
38
    /**
39
     * @var resource $conn Connection with the server
40
     */
41
    protected $conn;
42
43
    /**
44
     * Class constructor.
45
     *
46
     * @access public
47
     * @param boolean $ignore_user_abort Ignore user abort, true by default
48
     * @throws \Exception If ftp extension is not loaded.
49
     */
50
    public function __construct($ignore_user_abort = true)
51
    {
52
        if (!extension_loaded('ftp')) {
53
            throw new \Exception(sprintf($this->error, 'FTP extension is not loaded'));
54
        }
55
56
        ignore_user_abort($ignore_user_abort);
57
    }
58
59
    /**
60
     * Class destructor.
61
     *
62
     * @access public
63
     * @return void
64
     */
65
    public function __destruct()
66
    {
67
        $this->closeConnection();
68
    }
69
70
    /**
71
     * Overwrite maximum execution time limit.
72
     *
73
     * @access public
74
     * @param mixed $time Max execution time, unlimited by default
75
     * @return \Common\Tool\FtpSimpleClient
76
     */
77
    public function setMaxExecutionTimeLimit($time = 0)
78
    {
79
        if (null !== $time) {
80
            set_time_limit($time);
81
        }
82
83
        return $this;
84
    }
85
86
    /**
87
     * Opens a FTP or SSL-FTP connection.
88
     * Sets up stream resource on success or FALSE on error.
89
     *
90
     * @access public
91
     * @param string $host
92
     * @param boolean $ssl
93
     * @param int $port
94
     * @param int $timeout
95
     * @return \Common\Tool\FtpSimpleClient
96
     * @throws \Exception on failure
97
     */
98
    public function createConnection($host, $ssl = false, $port = 21, $timeout = 90)
99
    {
100
        if ($ssl === true) {
101
            $this->conn = ftp_ssl_connect($host, $port, $timeout);
102
        } else {
103
            $this->conn = ftp_connect($host, $port, $timeout);
104
        }
105
106
        if (!$this->conn) {
107
            throw new \Exception(sprintf($this->error, 'Can not connect'));
108
        }
109
110
        return $this;
111
    }
112
113
    /**
114
     * Close the active FTP or SSL-FTP connection.
115
     *
116
     * @access public
117
     */
118
    public function closeConnection()
119
    {
120
        if ($this->conn) {
121
            ftp_close($this->conn);
122
        }
123
    }
124
125
    /**
126
     * Get current active FTP or SSL-FTP connection.
127
     *
128
     * @access public
129
     * @return $conn resource
0 ignored issues
show
Documentation Bug introduced by
The doc comment $conn at position 0 could not be parsed: Unknown type name '$conn' at position 0 in $conn.
Loading history...
130
     */
131
    public function getConnection()
132
    {
133
        return $this->conn;
134
    }
135
136
    /**
137
     * Log in to an FTP connection
138
     *
139
     * @access public
140
     * @param string $username
141
     * @param string $password
142
     * @return \Common\Tool\FtpSimpleClient
143
     * @throws \Exception on failure
144
     */
145
    public function login($username = 'anonymous', $password = '')
146
    {
147
        $result = ftp_login($this->conn, $username, $password);
148
        if ($result === false) {
149
            throw new \Exception(sprintf($this->error, 'Login incorrect'));
150
        }
151
152
        return $this;
153
    }
154
155
    /**
156
     * Uploads a file to the server from a string
157
     *
158
     * @access public
159
     * @param string $remote_file
160
     * @param string $content
161
     * @return \Common\Tool\FtpSimpleClient
162
     * @throws \Exception on failure
163
     */
164
    public function putFromString($remote_file, $content)
165
    {
166
        $handle = fopen('php://temp', 'w');
167
        fwrite($handle, $content);
168
        rewind($handle);
169
        if (ftp_fput($this->conn, $remote_file, $handle, FTP_BINARY)) {
170
            return $this;
171
        }
172
173
        throw new \Exception(sprintf($this->error,
174
            'Unable to put the file "' . $remote_file . '"'
175
        ));
176
    }
177
178
    /**
179
     * Uploads a file to the server
180
     *
181
     * @access public
182
     * @param string $local_file
183
     * @return \Common\Tool\FtpSimpleClient
184
     * @throws \Exception on failure
185
     */
186
    public function putFromPath($local_file)
187
    {
188
        $remote_file = basename($local_file);
189
        $handle = fopen($local_file, 'r');
190
        if (ftp_fput($this->conn, $remote_file, $handle, FTP_BINARY)) {
191
            rewind($handle);
192
            return $this;
193
        }
194
195
        throw new \Exception(sprintf($this->error,
196
            'Unable to put the remote file from the local file "' . $local_file . '"'
197
        ));
198
    }
199
200
    /**
201
     * Get the current directory name
202
     *
203
     * @access public
204
     * @return string $result Current directory name
205
     * @throws \Exception on failure
206
     */
207
    public function pwd()
208
    {
209
        $result = ftp_pwd($this->conn);
210
        if ($result === false) {
211
            throw new \Exception(sprintf($this->error,
212
                'Unable to resolve the current directory'
213
            ));
214
        }
215
216
        return $result;
217
    }
218
219
    /**
220
     * Changes to the parent directory
221
     *
222
     * @access public
223
     * @return \Common\Tool\FtpSimpleClient
224
     * @throws \Exception on failure
225
     */
226
    public function cdup()
227
    {
228
        $result = ftp_cdup($this->conn);
229
        if ($result === false) {
230
            throw new \Exception(sprintf($this->error,
231
                'Unable to get parent folder'
232
            ));
233
        }
234
235
        return $this;
236
    }
237
238
    /**
239
     * Changes the current directory
240
     *
241
     * @access public
242
     * @param string $directory
243
     * @return \Common\Tool\FtpSimpleClient
244
     * @throws \Exception on failure
245
     */
246
    public function chdir(string $directory): self
247
    {
248
        $result = ftp_chdir($this->conn, $directory);
249
        if ($result === false) {
250
            throw new \Exception(sprintf($this->error,
251
                'Unable to change the current directory'
252
            ));
253
        }
254
255
        return $this;
256
    }
257
258
    /**
259
     * Removes a directory
260
     *
261
     * @access public
262
     * @param string $directory Directory
263
     * @return \Common\Tool\FtpSimpleClient
264
     * @throws \Exception on failure
265
     */
266
    public function rmdir($directory)
267
    {
268
        $result = ftp_rmdir($this->conn, $directory);
269
        if ($result === false) {
270
            throw new \Exception(sprintf($this->error,
271
                'Unable to remove directory'
272
            ));
273
        }
274
275
        return $this;
276
    }
277
278
    /**
279
     * Creates a directory
280
     *
281
     * @access public
282
     * @param string $directory Directory
283
     * @return string Newly created directory name
284
     * @throws \Exception on failure
285
     */
286
    public function mkdir($directory)
287
    {
288
        $result = ftp_mkdir($this->conn, $directory);
289
        if ($result === false) {
290
            throw new \Exception(sprintf($this->error,
291
                'Unable to create directory'
292
            ));
293
        }
294
295
        return $result;
296
    }
297
298
    /**
299
     * Check if a directory exist.
300
     *
301
     * @access public
302
     * @param string $directory
303
     * @return boolean
304
     * @throws \Exception on failure
305
     */
306
    public function isDir($directory)
307
    {
308
        $result = false;
309
310
        // Get current dir
311
        $pwd = ftp_pwd($this->conn);
312
        if ($pwd === false) {
313
            throw new \Exception(sprintf($this->error,
314
                'Unable to resolve the current directory'
315
            ));
316
        }
317
318
        // Check if needed directory exists
319
        if (ftp_chdir($this->conn, $directory)) {
320
            $result = true;
321
        }
322
323
        // Set up back currnet directory
324
        ftp_chdir($this->conn, $pwd);
325
326
        return $result;
327
    }
328
329
    /**
330
     * Forward the method call to FTP functions.
331
     * Note: set up function name without native "ftp_" prefix
332
     *
333
     * @access public
334
     * @param string $function Function name
335
     * @param array $arguments
336
     * @return mixed Return value of the callback
337
     * @throws \Exception When the function is not valid
338
     */
339
    public function __call($function, array $arguments)
340
    {
341
        $function = 'ftp_' . $function;
342
343
        if (function_exists($function)) {
344
            array_unshift($arguments, $this->conn);
345
            return call_user_func_array($function, $arguments);
346
        }
347
348
        throw new \Exception(sprintf($this->error,
349
            "{$function} is not a valid FTP function"
350
        ));
351
    }
352
353
}
354