RsyncTransporter::ls()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
/*
4
 * This file is part of the Conveyor package.
5
 *
6
 * (c) Jeroen Fiege <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Webcreate\Conveyor\Transporter;
13
14
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
15
use Webcreate\Conveyor\Event\TransporterEvent;
16
use Webcreate\Conveyor\Event\TransporterEvents;
17
use Webcreate\Util\Cli;
18
19
class RsyncTransporter extends AbstractTransporter implements SshCapableTransporterInterface
20
{
21
    protected $cli;
22
    protected $_exists = array();
23
24 11
    public function __construct(EventDispatcherInterface $dispatcher, Cli $cli)
25
    {
26 11
        parent::__construct($dispatcher);
27
28 11
        $this->cli = $cli;
29 11
    }
30
31
    /**
32
     * Checks if a file or directory exists on the remote server
33
     *
34
     * @param  string $path remote source path
35
     * @return bool   true when the resource exists, false otherwise
36
     */
37 1 View Code Duplication
    public function exists($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
38
    {
39 1
        if (false === isset($this->_exists[$path])) {
40 1
            $remoteCommand = sprintf("test -e %s", $path);
41 1
            $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
42
43 1
            $exitCode = $this->cli->execute($commandline);
44
45 1
            $this->_exists[$path] = (0 === $exitCode);
46
        }
47
48 1
        return $this->_exists[$path];
49
    }
50
51
    /**
52
     * Create a directory on the remote server
53
     *
54
     * @param  string            $dest      remote path
55
     * @param  bool              $recursive
56
     * @throws \RuntimeException
57
     */
58 2
    public function mkdir($dest, $recursive = true)
59
    {
60 2
        $pwd = dirname($dest);
61 2
        if (true === $recursive && false === $this->exists($pwd)) {
62
            $this->mkdir($pwd);
63
        }
64
65 2
        $remoteCommand = sprintf("mkdir '%s'", $dest);
66 2
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
67
68 2
        $this->_exists[$dest] = true;
69
70 2
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_MKDIR, new TransporterEvent($this, $dest));
71
72 2
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
73
            throw new \RuntimeException($this->cli->getErrorOutput());
74
        }
75 2
    }
76
77
    /**
78
     * Retrieve file or directory from remote server
79
     *
80
     * @param  string            $src  remote source path
81
     * @param  string            $dest (optional) local destination path
82
     * @throws \RuntimeException
83
     * @return string
84
     */
85 2 View Code Duplication
    public function get($src, $dest = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87 2
        $realDest = $dest;
88
89 2
        if (null == $dest) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $dest of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
90
            $realDest = tempnam(sys_get_temp_dir(), basename($src));
91
        }
92
93 2
        $commandline = sprintf("rsync %s@%s:%s \"%s\"", $this->getUser(), $this->getHost(), $src, $realDest);
94
95 2
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_GET, new TransporterEvent($this, array('src' => $src, 'dest' => $dest)));
96
97 2
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
98
            throw new \RuntimeException($this->cli->getErrorOutput());
99
        }
100
101 2
        if (null == $dest) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $dest of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
102
            $content = file_get_contents($realDest);
103
            unlink($realDest);
104
105
            return $content;
106
        }
107 2
    }
108
109
    /**
110
     * Upload a file or directory to remote server
111
     *
112
     * @param  string                    $src  local source path
113
     * @param  string                    $dest remote destination path
114
     * @throws \RuntimeException
115
     * @throws \InvalidArgumentException
116
     */
117 2 View Code Duplication
    public function put($src, $dest)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
    {
119 2
        if (false === file_exists($src)) {
120 1
            throw new \InvalidArgumentException(sprintf('Resource \'%s\' does not exist', $src));
121
        }
122
123 1
        $pwd = dirname($dest);
124 1
        if (false === $this->exists($pwd)) {
125
            $this->mkdir($pwd);
126
        }
127
128 1
        $commandline = sprintf("rsync -az \"%s\" '%s@%s:%s'", $src, $this->getUser(), $this->getHost(), $dest);
129
130 1
        $this->_exists[$dest] = true;
131
132 1
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_PUT, new TransporterEvent($this, array('dest' => $dest, 'src' => $src)));
133
134 1
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
135
            throw new \RuntimeException($this->cli->getErrorOutput());
136
        }
137 1
    }
138
139
    /**
140
     * Upload a string to remote server
141
     *
142
     * @param  string            $content content
143
     * @param  string            $dest    remote destination path
144
     * @throws \RuntimeException
145
     */
146 1 View Code Duplication
    public function putContent($content, $dest)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
    {
148 1
        $temp_file = tempnam(sys_get_temp_dir(), 'rsync' . time());
149
150 1
        file_put_contents($temp_file, $content);
151
152 1
        $commandline = sprintf("rsync -a \"%s\" '%s@%s:%s'", $temp_file, $this->getUser(), $this->getHost(), $dest);
153
154 1
        $this->_exists[$dest] = true;
155
156 1
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_PUT_CONTENT, new TransporterEvent($this, array('dest' => $dest, 'src' => $temp_file, 'content' => $content)));
157
158 1
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
159
            @unlink($temp_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
160
161
            throw new \RuntimeException($this->cli->getErrorOutput());
162
        }
163
164 1
        @unlink($temp_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
165 1
    }
166
167
    /**
168
     * Creates a symlink on the remote server
169
     *
170
     * @param $src
171
     * @param $dest
172
     * @throws \RuntimeException
173
     * @return mixed
174
     */
175 1
    public function symlink($src, $dest)
176
    {
177 1
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_SYMLINK, new TransporterEvent($this, array('dest' => $dest, 'src' => $src)));
178
179
        // make src an absolute path
180 1
        if (0 !== strpos($src, '/')) {
181 1
            $remoteCommand = 'pwd';
182 1
            $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
183
184 1
            if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
185
                throw new \RuntimeException($this->cli->getErrorOutput());
186
            }
187
188 1
            $pwd = trim($this->cli->getOutput());
189
190 1
            $src = $pwd . '/' . $src;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $src. This often makes code more readable.
Loading history...
191
        }
192
193 1
        $remoteCommand = sprintf("ln -s -f %s %s", $src, $dest);
194 1
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
195
196 1
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
197
            throw new \RuntimeException($this->cli->getErrorOutput());
198
        }
199 1
    }
200
201
    /**
202
     * Checks for symlink on the remote server
203
     *
204
     * @param $dest
205
     * @return bool
206
     */
207 View Code Duplication
    public function isSymlink($dest)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
208
    {
209
        $remoteCommand = sprintf("readlink %s", $dest);
210
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
211
212
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
213
            return false;
214
        }
215
216
        return ('' !== trim($this->cli->getOutput()));
217
    }
218
219
    /**
220
     * Copies a file/directory on the remote host
221
     *
222
     * @param  string            $src
223
     * @param  string            $dest
224
     * @param  bool              $recursive
225
     * @throws \RuntimeException
226
     * @return mixed
227
     */
228 1
    public function copy($src, $dest, $recursive = true)
229
    {
230 1
        $recursiveFlag = ($recursive ? 'r' : '');
231
232 1
        $remoteCommand = sprintf("cp -{$recursiveFlag}f %s %s", $src, $dest);
233 1
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
234
235 1
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_COPY, new TransporterEvent($this, array('dest' => $dest, 'src' => $src)));
236
237 1
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
238
            throw new \RuntimeException($this->cli->getErrorOutput());
239
        }
240 1
    }
241
242
    /**
243
     * Removes a file/directory on the remote host
244
     *
245
     * @param  string            $path
246
     * @param  bool              $recursive
247
     * @throws \RuntimeException
248
     * @return mixed
249
     */
250 1 View Code Duplication
    public function remove($path, $recursive = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
251
    {
252 1
        $recursiveFlag = ($recursive ? 'r' : '');
253
254 1
        $remoteCommand = sprintf("rm -{$recursiveFlag}f %s", $path);
255 1
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $remoteCommand);
256
257 1
        $this->dispatcher->dispatch(TransporterEvents::TRANSPORTER_REMOVE, new TransporterEvent($this, array('path' => $path)));
258
259 1
        if ($this->cli->execute($commandline)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
260
            throw new \RuntimeException($this->cli->getErrorOutput());
261
        }
262 1
    }
263
264
    /**
265
     * @todo this is just a simple implementation which should be improved
266
     *
267
     * @param $command
268
     * @param  null              $callback
269
     * @throws \RuntimeException
270
     */
271 View Code Duplication
    public function exec($command, $callback = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
272
    {
273
        $commandline   = sprintf("ssh %s@%s \"%s\"", $this->getUser(), $this->getHost(), $command);
274
275
        if ($this->cli->execute($commandline, $callback)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->cli->execute($commandline, $callback) of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
276
            throw new \RuntimeException($this->cli->getErrorOutput());
277
        }
278
    }
279
280
    /**
281
     * Lists files and directories
282
     *
283
     * returns an array with the following format:
284
     *
285
     * array(
286
     *   'filename' => array(
287
     *     'type' => 'directory', // or 'file'
288
     *     'mtime' => new \DateTime(),
289
     *   ),
290
     * );
291
     *
292
     * @param  string            $path
293
     * @throws \RuntimeException
294
     * @return array
295
     */
296
    public function ls($path)
0 ignored issues
show
Coding Style introduced by
This method's name is shorter than the configured minimum length of 3 characters.

Even though PHP does not care about the name of your methods, it is generally a good practice to choose method names which can be easily understood by other human readers.

Loading history...
297
    {
298
        throw new \RuntimeException('Listing of files and directories is not supported (yet)');
299
    }
300
}
301