Completed
Pull Request — master (#140)
by
unknown
03:00
created

Sftp::setup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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