AbstractFtpAdapter::getUsername()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 2
eloc 2
nc 2
nop 0
crap 2
1
<?php
2
3
namespace League\Flysystem\Adapter;
4
5
use DateTime;
6
use League\Flysystem\AdapterInterface;
7
use League\Flysystem\Config;
8
use League\Flysystem\NotSupportedException;
9
use RuntimeException;
10
11
abstract class AbstractFtpAdapter extends AbstractAdapter
12
{
13
    /**
14
     * @var mixed
15
     */
16
    protected $connection;
17
18
    /**
19
     * @var string
20
     */
21
    protected $host;
22
23
    /**
24
     * @var int
25
     */
26
    protected $port = 21;
27
28
    /**
29
     * @var string|null
30
     */
31
    protected $username;
32
33
    /**
34
     * @var string|null
35
     */
36
    protected $password;
37
38
    /**
39
     * @var bool
40
     */
41
    protected $ssl = false;
42
43
    /**
44
     * @var int
45
     */
46
    protected $timeout = 90;
47
48
    /**
49
     * @var bool
50
     */
51
    protected $passive = true;
52
53
    /**
54
     * @var string
55
     */
56
    protected $separator = '/';
57
58
    /**
59
     * @var string|null
60
     */
61
    protected $root;
62
63
    /**
64
     * @var int
65
     */
66
    protected $permPublic = 0744;
67
68
    /**
69
     * @var int
70
     */
71
    protected $permPrivate = 0700;
72
73
    /**
74
     * @var array
75
     */
76
    protected $configurable = array();
77
78
    /**
79
     * @var string
80
     */
81
    protected $systemType;
82
83
    /**
84
     * @var bool
85
     */
86
    protected $alternativeRecursion = false;
87
88
    /**
89
     * Constructor.
90
     *
91
     * @param array $config
92
     */
93 96
    public function __construct(array $config)
94
    {
95 96
        $this->setConfig($config);
96 96
    }
97
98
    /**
99
     * Set the config.
100
     *
101
     * @param array $config
102
     *
103
     * @return $this
104
     */
105 96
    public function setConfig(array $config)
106
    {
107 96
        foreach ($this->configurable as $setting) {
108 96
            if ( ! isset($config[$setting])) {
109 96
                continue;
110
            }
111
112 96
            $method = 'set' . ucfirst($setting);
113
114 96
            if (method_exists($this, $method)) {
115 96
                $this->$method($config[$setting]);
116 96
            }
117 96
        }
118
119 96
        return $this;
120
    }
121
122
    /**
123
     * Returns the host.
124
     *
125
     * @return string
126
     */
127 90
    public function getHost()
128
    {
129 90
        return $this->host;
130
    }
131
132
    /**
133
     * Set the host.
134
     *
135
     * @param string $host
136
     *
137
     * @return $this
138
     */
139 96
    public function setHost($host)
140
    {
141 96
        $this->host = $host;
142
143 96
        return $this;
144
    }
145
146
    /**
147
     * Set the public permission value.
148
     *
149
     * @param int $permPublic
150
     *
151
     * @return $this
152
     */
153 78
    public function setPermPublic($permPublic)
154
    {
155 78
        $this->permPublic = $permPublic;
156
157 78
        return $this;
158
    }
159
160
    /**
161
     * Set the private permission value.
162
     *
163
     * @param int $permPrivate
164
     *
165
     * @return $this
166
     */
167 78
    public function setPermPrivate($permPrivate)
168
    {
169 78
        $this->permPrivate = $permPrivate;
170
171 78
        return $this;
172
    }
173
174
    /**
175
     * Returns the ftp port.
176
     *
177
     * @return int
178
     */
179 90
    public function getPort()
180
    {
181 90
        return $this->port;
182
    }
183
184
    /**
185
     * Returns the root folder to work from.
186
     *
187
     * @return string
188
     */
189 78
    public function getRoot()
190
    {
191 78
        return $this->root;
192
    }
193
194
    /**
195
     * Set the ftp port.
196
     *
197
     * @param int|string $port
198
     *
199
     * @return $this
200
     */
201 78
    public function setPort($port)
202
    {
203 78
        $this->port = (int) $port;
204
205 78
        return $this;
206
    }
207
208
    /**
209
     * Set the root folder to work from.
210
     *
211
     * @param string $root
212
     *
213
     * @return $this
214
     */
215 87
    public function setRoot($root)
216
    {
217 87
        $this->root = rtrim($root, '\\/') . $this->separator;
218
219 87
        return $this;
220
    }
221
222
    /**
223
     * Returns the ftp username.
224
     *
225
     * @return string username
226
     */
227 84
    public function getUsername()
228
    {
229 84
        return empty($this->username) ? 'anonymous' : $this->username;
230
    }
231
232
    /**
233
     * Set ftp username.
234
     *
235
     * @param string $username
236
     *
237
     * @return $this
238
     */
239 78
    public function setUsername($username)
240
    {
241 78
        $this->username = $username;
242
243 78
        return $this;
244
    }
245
246
    /**
247
     * Returns the password.
248
     *
249
     * @return string password
250
     */
251 84
    public function getPassword()
252
    {
253 84
        return $this->password;
254
    }
255
256
    /**
257
     * Set the ftp password.
258
     *
259
     * @param string $password
260
     *
261
     * @return $this
262
     */
263 78
    public function setPassword($password)
264
    {
265 78
        $this->password = $password;
266
267 78
        return $this;
268
    }
269
270
    /**
271
     * Returns the amount of seconds before the connection will timeout.
272
     *
273
     * @return int
274
     */
275 90
    public function getTimeout()
276
    {
277 90
        return $this->timeout;
278
    }
279
280
    /**
281
     * Set the amount of seconds before the connection should timeout.
282
     *
283
     * @param int $timeout
284
     *
285
     * @return $this
286
     */
287 78
    public function setTimeout($timeout)
288
    {
289 78
        $this->timeout = (int) $timeout;
290
291 78
        return $this;
292
    }
293
294
    /**
295
     * Return the FTP system type.
296
     *
297
     * @return string
298
     */
299 3
    public function getSystemType()
300
    {
301 3
        return $this->systemType;
302
    }
303
304
    /**
305
     * Set the FTP system type (windows or unix).
306
     *
307
     * @param string $systemType
308
     *
309
     * @return $this
310
     */
311 15
    public function setSystemType($systemType)
312
    {
313 15
        $this->systemType = strtolower($systemType);
314
315 15
        return $this;
316
    }
317
318
    /**
319
     * @inheritdoc
320
     */
321 27
    public function listContents($directory = '', $recursive = false)
322
    {
323 27
        return $this->listDirectoryContents($directory, $recursive);
324
    }
325
326
    abstract protected function listDirectoryContents($directory, $recursive = false);
327
328
    /**
329
     * Normalize a directory listing.
330
     *
331
     * @param array  $listing
332
     * @param string $prefix
333
     *
334
     * @return array directory listing
335
     */
336 21
    protected function normalizeListing(array $listing, $prefix = '')
337
    {
338 21
        $base = $prefix;
339 21
        $result = array();
340 21
        $listing = $this->removeDotDirectories($listing);
341
342 21
        while ($item = array_shift($listing)) {
343 21
            if (preg_match('#^.*:$#', $item)) {
344 9
                $base = trim($item, ':');
345 9
                continue;
346
            }
347
348 21
            $result[] = $this->normalizeObject($item, $base);
349 18
        }
350
351 18
        return $this->sortListing($result);
352
    }
353
354
    /**
355
     * Sort a directory listing.
356
     *
357
     * @param array $result
358
     *
359
     * @return array sorted listing
360
     */
361 18
    protected function sortListing(array $result)
362
    {
363
        $compare = function ($one, $two) {
364 12
            return strnatcmp($one['path'], $two['path']);
365 18
        };
366
367 18
        usort($result, $compare);
368
369 18
        return $result;
370
    }
371
372
    /**
373
     * Normalize a file entry.
374
     *
375
     * @param string $item
376
     * @param string $base
377
     *
378
     * @return array normalized file array
379
     *
380
     * @throws NotSupportedException
381
     */
382 42
    protected function normalizeObject($item, $base)
383
    {
384 42
        $systemType = $this->systemType ?: $this->detectSystemType($item);
385
386 42
        if ($systemType === 'unix') {
387 33
            return $this->normalizeUnixObject($item, $base);
388 9
        } elseif ($systemType === 'windows') {
389 6
            return $this->normalizeWindowsObject($item, $base);
390
        }
391
392 3
        throw NotSupportedException::forFtpSystemType($systemType);
393
    }
394
395
    /**
396
     * Normalize a Unix file entry.
397
     *
398
     * @param string $item
399
     * @param string $base
400
     *
401
     * @return array normalized file array
402
     */
403 33
    protected function normalizeUnixObject($item, $base)
404
    {
405 33
        $item = preg_replace('#\s+#', ' ', trim($item), 7);
406
407 33
        if (count(explode(' ', $item, 9)) !== 9) {
408 3
            throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
409
        }
410
411 30
        list($permissions, /* $number */, /* $owner */, /* $group */, $size, /* $month */, /* $day */, /* $time*/, $name) = explode(' ', $item, 9);
412 30
        $type = $this->detectType($permissions);
413 30
        $path = empty($base) ? $name : $base . $this->separator . $name;
414
415 30
        if ($type === 'dir') {
416 12
            return compact('type', 'path');
417
        }
418
419 30
        $permissions = $this->normalizePermissions($permissions);
420 30
        $visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
421 30
        $size = (int) $size;
422
423 30
        return compact('type', 'path', 'visibility', 'size');
424
    }
425
426
    /**
427
     * Normalize a Windows/DOS file entry.
428
     *
429
     * @param string $item
430
     * @param string $base
431
     *
432
     * @return array normalized file array
433
     */
434 6
    protected function normalizeWindowsObject($item, $base)
435
    {
436 6
        $item = preg_replace('#\s+#', ' ', trim($item), 3);
437
438 6
        if (count(explode(' ', $item, 4)) !== 4) {
439 3
            throw new RuntimeException("Metadata can't be parsed from item '$item' , not enough parts.");
440
        }
441
442 3
        list($date, $time, $size, $name) = explode(' ', $item, 4);
443 3
        $path = empty($base) ? $name : $base . $this->separator . $name;
444
445
        // Check for the correct date/time format
446 3
        $format = strlen($date) === 8 ? 'm-d-yH:iA' : 'Y-m-dH:i';
447 3
        $dt = DateTime::createFromFormat($format, $date . $time);
448 3
        $timestamp = $dt ? $dt->getTimestamp() : (int) strtotime("$date $time");
449
450 3
        if ($size === '<DIR>') {
451 3
            $type = 'dir';
452
453 3
            return compact('type', 'path', 'timestamp');
454
        }
455
456 3
        $type = 'file';
457 3
        $visibility = AdapterInterface::VISIBILITY_PUBLIC;
458 3
        $size = (int) $size;
459
460 3
        return compact('type', 'path', 'visibility', 'size', 'timestamp');
461
    }
462
463
    /**
464
     * Get the system type from a listing item.
465
     *
466
     * @param string $item
467
     *
468
     * @return string the system type
469
     */
470 33
    protected function detectSystemType($item)
471
    {
472 33
        return preg_match('/^[0-9]{2,4}-[0-9]{2}-[0-9]{2}/', $item) ? 'windows' : 'unix';
473
    }
474
475
    /**
476
     * Get the file type from the permissions.
477
     *
478
     * @param string $permissions
479
     *
480
     * @return string file type
481
     */
482 30
    protected function detectType($permissions)
483
    {
484 30
        return substr($permissions, 0, 1) === 'd' ? 'dir' : 'file';
485
    }
486
487
    /**
488
     * Normalize a permissions string.
489
     *
490
     * @param string $permissions
491
     *
492
     * @return int
493
     */
494 30
    protected function normalizePermissions($permissions)
495
    {
496
        // remove the type identifier
497 30
        $permissions = substr($permissions, 1);
498
499
        // map the string rights to the numeric counterparts
500 30
        $map = array('-' => '0', 'r' => '4', 'w' => '2', 'x' => '1');
501 30
        $permissions = strtr($permissions, $map);
502
503
        // split up the permission groups
504 30
        $parts = str_split($permissions, 3);
505
506
        // convert the groups
507
        $mapper = function ($part) {
508 30
            return array_sum(str_split($part));
509 30
        };
510
511
        // get the sum of the groups
512 30
        return array_sum(array_map($mapper, $parts));
513
    }
514
515
    /**
516
     * Filter out dot-directories.
517
     *
518
     * @param array $list
519
     *
520
     * @return array
521
     */
522
    public function removeDotDirectories(array $list)
523
    {
524 21
        $filter = function ($line) {
525 21
            if ( ! empty($line) && ! preg_match('#.* \.(\.)?$|^total#', $line)) {
526 21
                return true;
527
            }
528
529 18
            return false;
530 21
        };
531
532 21
        return array_filter($list, $filter);
533
    }
534
535
    /**
536
     * @inheritdoc
537
     */
538 9
    public function has($path)
539
    {
540 9
        return $this->getMetadata($path);
541
    }
542
543
    /**
544
     * @inheritdoc
545
     */
546 6
    public function getSize($path)
547
    {
548 6
        return $this->getMetadata($path);
549
    }
550
551
    /**
552
     * @inheritdoc
553
     */
554 6
    public function getVisibility($path)
555
    {
556 6
        return $this->getMetadata($path);
557
    }
558
559
    /**
560
     * Ensure a directory exists.
561
     *
562
     * @param string $dirname
563
     */
564 9
    public function ensureDirectory($dirname)
565
    {
566 9
        if ( ! empty($dirname) && ! $this->has($dirname)) {
567 3
            $this->createDir($dirname, new Config());
568 3
        }
569 9
    }
570
571
    /**
572
     * @return mixed
573
     */
574 63
    public function getConnection()
575
    {
576 63
        if ( ! $this->isConnected()) {
577 63
            $this->disconnect();
578 63
            $this->connect();
579 63
        }
580
581 63
        return $this->connection;
582
    }
583
584
    /**
585
     * Get the public permission value.
586
     *
587
     * @return int
588
     */
589 6
    public function getPermPublic()
590
    {
591 6
        return $this->permPublic;
592
    }
593
594
    /**
595
     * Get the private permission value.
596
     *
597
     * @return int
598
     */
599 6
    public function getPermPrivate()
600
    {
601 6
        return $this->permPrivate;
602
    }
603
604
    /**
605
     * Disconnect on destruction.
606
     */
607 96
    public function __destruct()
608
    {
609 96
        $this->disconnect();
610 96
    }
611
612
    /**
613
     * Establish a connection.
614
     */
615
    abstract public function connect();
616
617
    /**
618
     * Close the connection.
619
     */
620
    abstract public function disconnect();
621
622
    /**
623
     * Check if a connection is active.
624
     *
625
     * @return bool
626
     */
627
    abstract public function isConnected();
628
}
629