Completed
Push — master ( a73f05...990803 )
by Sebastian
04:56
created

Sftp::getProtocolName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
namespace phpbu\App\Backup\Sync;
3
4
use phpbu\App\Util\Str;
5
use phpseclib;
6
use phpbu\App\Result;
7
use phpbu\App\Backup\Target;
8
9
/**
10
 * Sftp sync
11
 *
12
 * @package    phpbu
13
 * @subpackage Backup
14
 * @author     Sebastian Feldmann <[email protected]>
15
 * @copyright  Sebastian Feldmann <[email protected]>
16
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
17
 * @link       http://phpbu.de/
18
 * @since      Class available since Release 1.0.0
19
 */
20
class Sftp extends Xtp implements Simulator
21
{
22
    /**
23
     * Check for required loaded libraries or extensions.
24
     *
25
     * @throws \phpbu\App\Backup\Sync\Exception
26
     */
27 7
    protected function checkRequirements()
28
    {
29 7
        if (!class_exists('\\phpseclib\\Net\\SFTP')) {
30
            throw new Exception('phpseclib not installed - use composer to install "phpseclib/phpseclib" version 2.x');
31
        }
32 7
    }
33
34
    /**
35
     * Return implemented (*)TP protocol name.
36
     *
37
     * @return string
38
     */
39 1
    protected function getProtocolName()
40
    {
41 1
        return 'SFTP';
42
    }
43
44
    /**
45
     * (non-PHPDoc)
46
     *
47
     * @see    \phpbu\App\Backup\Sync::sync()
48
     * @param  \phpbu\App\Backup\Target $target
49
     * @param  \phpbu\App\Result        $result
50
     * @throws \phpbu\App\Backup\Sync\Exception
51
     */
52 1
    public function sync(Target $target, Result $result)
53
    {
54 1
        $sftp           = $this->login();
55 1
        $remoteFilename = $target->getFilename();
56 1
        $localFile      = $target->getPathname();
57
58 1
        foreach ($this->getRemoteDirectoryList() as $dir) {
59 1
            if (!$sftp->is_dir($dir)) {
60 1
                $result->debug(sprintf('creating remote dir \'%s\'', $dir));
61 1
                $sftp->mkdir($dir);
62
            }
63 1
            $result->debug(sprintf('change to remote dir \'%s\'', $dir));
64 1
            $sftp->chdir($dir);
65
        }
66
67 1
        $result->debug(sprintf('store file \'%s\' as \'%s\'', $localFile, $remoteFilename));
68 1
        $result->debug(sprintf('last error \'%s\'', $sftp->getLastSFTPError()));
69
70 1
        if (!$sftp->put($remoteFilename, $localFile, phpseclib\Net\SFTP::SOURCE_LOCAL_FILE)) {
71
            throw new Exception(sprintf('error uploading file: %s - %s', $localFile, $sftp->getLastSFTPError()));
72
        }
73 1
    }
74
75
    /**
76
     * Create a sftp handle.
77
     *
78
     * @return \phpseclib\Net\SFTP
79
     * @throws \phpbu\App\Backup\Sync\Exception
80
     */
81
    protected function login() : phpseclib\Net\SFTP
82
    {
83
        // silence phpseclib
84
        $old  = error_reporting(0);
85
        $sftp = new phpseclib\Net\SFTP($this->host);
86 View Code Duplication
        if (!$sftp->login($this->user, $this->password)) {
87
            error_reporting($old);
88
            throw new Exception(
89
                sprintf(
90
                    'authentication failed for %s@%s%s',
91
                    $this->user,
92
                    $this->host,
93
                    empty($this->password) ? '' : ' with password ****'
94
                )
95
            );
96
        }
97
        // restore old error reporting
98
        error_reporting($old);
99
100
        return $sftp;
101
    }
102
103
    /**
104
     * Return list of remote directories to travers.
105
     *
106
     * @return array
107
     */
108 1
    private function getRemoteDirectoryList() : array
109
    {
110 1
        $remoteDirs = [];
111 1
        if (!empty($this->remotePath)) {
112 1
            $remoteDirs = explode('/', $this->remotePath);
113
            // fix empty first array element for absolute path
114 1
            if (Str::hasLeadingSlash($this->remotePath)) {
115 1
                $remoteDirs[0] = '/';
116
            }
117 1
            $remoteDirs = array_filter($remoteDirs);
118
        }
119 1
        return $remoteDirs;
120
    }
121
}
122