Completed
Push — release/1.0 ( b153f9...a3ef24 )
by Johnny
02:08
created

Ftp::write()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
c 2
b 0
f 2
dl 0
loc 22
rs 8.6738
cc 5
eloc 15
nc 5
nop 1
1
<?php
2
namespace Redbox\Scan\Adapter;
3
use Symfony\Component\Yaml;
4
use Redbox\Scan\Exception;
5
use Redbox\Scan\Report;
6
7
/**
8
 * Read and write files from a given ftp location.
9
 * see examples/ftp.php for a demonstration.
10
 *
11
 * @package Redbox\Scan\Adapter
12
 */
13
class Ftp implements AdapterInterface
14
{
15
    const FTP_MODE_ASCII  = FTP_ASCII;
16
    const FTP_MODE_BINARY = FTP_BINARY;
17
18
    protected $host     = '';
19
    protected $username = '';
20
    protected $password = '';
21
    protected $filename = '';
22
    protected $port     = 21;
23
24
    protected $timeout  = 90;
25
    protected $handle   = null;
26
27
    /**
28
     * You might think just connect to the ftp server from the constructor
29
     * but psr-4 dictates that autoloadable classes MUST NOT...
30
     *
31
     * Quote:
32
     * Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.
33
     *
34
     * So we need to use authenticate() after we construct.
35
     *
36
     * @param string $host
37
     * @param string $username
38
     * @param string $password
39
     * @param string $filename
40
     * @param int $port;
0 ignored issues
show
Bug introduced by
There is no parameter named $port;. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
41
     * @param int $timeout
42
     */
43
    public function __construct($host = "", $username = "", $password = "", $filename = "", $port = 21, $timeout = 90)
44
    {
45
        $this->host     = $host;
46
        $this->username = $username;
47
        $this->password = $password;
48
        $this->filename = $filename;
49
        $this->timeout  = $timeout;
50
        $this->port     = $port;
51
    }
52
53
    /**
54
     * We should be so nice to terminate the construction of we are done.
55
     */
56
    public function __destruct() {
57
        if ($this->handle) {
58
            ftp_close($this->handle);
59
        }
60
    }
61
62
    public function authenticate()
63
    {
64
65
        set_error_handler(
66
            function () {
67
            }
68
        );
69
70
        $this->handle  = ftp_connect($this->host, $this->port, $this->timeout);
71
        $authenticated = ftp_login($this->handle, $this->username, $this->password);
72
73
        restore_error_handler();
74
75
        if ($this->handle === false) {
76
            throw new Exception\RuntimeException('Could not connect to host: '.$this->host);
77
        }
78
79
        if ($authenticated == false) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
80
            throw new Exception\RuntimeException('Could not connect to host: '.$this->host);
81
        }
82
        return true;
83
    }
84
85
    /**
86
     * Read the previous scan results from the file system.
87
     *
88
     * @return array
89
     */
90
    public function read() {
91
        if (!$this->handle === false)
92
            return false;
93
94
        $stream = fopen('php://memory', 'w');
95
        if (!$stream)
96
            return false;
97
98
        $data   = '';
99
        if ($ret = ftp_nb_fget($this->handle, $stream, $this->filename, self::FTP_MODE_ASCII)) {
100
            while ($ret === FTP_MOREDATA) {
101
                rewind($stream);
102
                $data .=  stream_get_contents($stream);
103
                $ret = ftp_nb_continue($this->handle);
104
            }
105
            if ($ret != FTP_FINISHED) {
106
               return false;
107
            } else {
108
                $data = Yaml\Yaml::parse($data);
109
                return $data;
110
            }
111
        }
112
        return false;
113
    }
114
115
    // TODO: This should be an universial exception
116
    /**
117
     * Write the report to the filesystem so we can reuse it
118
     * at a later stace when we invoke Redbox\Scan\ScanService's scan() method.
119
     *
120
     * @param Report\Report|null $report
121
     * @return bool
122
     */
123
    public function write(Report\Report $report = null) {
124
        if ($this->handle === false)
125
            return false;
126
127
        if ($report) {
128
129
            $stream = fopen('php://memory', 'w+');
130
            if (!$stream) return false;
131
            $data = $report->toArray();
132
            $data = Yaml\Yaml::dump($data, 99);
133
134
            fwrite($stream, $data);
135
            rewind($stream);
136
137
            if(ftp_fput($this->handle, $this->filename, $stream, self::FTP_MODE_ASCII)) {
138
                return true;
139
            } else {
140
                return false;
141
            }
142
        }
143
        return false;
144
    }
145
146
}