Completed
Push — master ( e7d66f...77a53e )
by Roberto
04:50 queued 02:26
created

SoapBase::__destruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace NFePHP\Common\Soap;
4
5
/**
6
 * Soap base class
7
 *
8
 * @category  NFePHP
9
 * @package   NFePHP\Common\Soap\SoapBase
10
 * @copyright NFePHP Copyright (c) 2017
11
 * @license   http://www.gnu.org/licenses/lgpl.txt LGPLv3+
12
 * @license   https://opensource.org/licenses/MIT MIT
13
 * @license   http://www.gnu.org/licenses/gpl.txt GPLv3+
14
 * @author    Roberto L. Machado <linux.rlm at gmail dot com>
15
 * @link      http://github.com/nfephp-org/sped-nfse for the canonical source repository
16
 */
17
18
use NFePHP\Common\Certificate;
19
use NFePHP\Common\Soap\SoapInterface;
20
use NFePHP\Common\Exception\SoapException;
21
use NFePHP\Common\Exception\RuntimeException;
22
use NFePHP\Common\Strings;
23
use League\Flysystem\Filesystem;
24
use League\Flysystem\Adapter\Local;
25
use Psr\Log\LoggerInterface;
26
27
abstract class SoapBase implements SoapInterface
28
{
29
    //soap parameters
30
    protected $connection;
31
    protected $soapprotocol = self::SSL_DEFAULT;
32
    /**
33
     * @var int
34
     */
35
    protected $soaptimeout = 20;
36
    /**
37
     * @var string
38
     */
39
    protected $proxyIP;
40
    /**
41
     * @var string
42
     */
43
    protected $proxyPort;
44
    /**
45
     * @var string
46
     */
47
    protected $proxyUser;
48
    /**
49
     * @var string
50
     */
51
    protected $proxyPass;
52
    /**
53
     * @var array
54
     */
55
    protected $prefixes = [1 => 'soapenv', 2 => 'soap'];
56
    //certificate parameters
57
    /**
58
     * @var Certificate
59
     */
60
    protected $certificate;
61
    /**
62
     * @var string
63
     */
64
    protected $tempdir;
65
    /**
66
     * @var string
67
     */
68
    protected $certsdir;
69
    /**
70
     * @var string
71
     */
72
    protected $debugdir;
73
    protected $prifile;
74
    protected $pubfile;
75
    protected $certfile;
76
    protected $casefaz; //certificates from webservices
77
    /**
78
     * @var bool
79
     */
80
    protected $disablesec = false;
81
    //log info
82
    public $responseHead;
83
    public $responseBody;
84
    public $requestHead;
85
    public $requestBody;
86
    public $soaperror;
87
    /**
88
     * @var array
89
     */
90
    public $soapinfo = [];
91
    /**
92
     * @var bool
93
     */
94
    public $debugmode = false;
95
    //flysystem
96
    protected $adapter;
97
    protected $filesystem;
98
99
    /**
100
     * Constructor
101
     * @param Certificate $certificate
102
     * @param LoggerInterface $logger
103
     */
104 2
    public function __construct(Certificate $certificate = null, LoggerInterface $logger = null)
105
    {
106 2
        $this->logger = $logger;
0 ignored issues
show
Bug introduced by
The property logger does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
107 2
        $this->certificate = $certificate;
108 2
        $this->setTemporaryFolder(sys_get_temp_dir() . '/sped/');
109 2
    }
110
    
111
    /**
112
     * Destructor
113
     * Clean temporary files
114
     */
115 2
    public function __destruct()
116
    {
117 2
        $this->removeTemporarilyFiles($this->certsdir);
118 2
    }
119
    
120
    /**
121
     * Disables the security checking of host and peer certificates
122
     * @param bool $flag
123
     */
124 1
    public function disableSecurity($flag = false)
125
    {
126 1
        $this->disablesec = $flag;
127 1
        return $this->disablesec;
128
    }
129
130
    /**
131
     * Load path to CA and enable to use on SOAP
132
     * @param string $capath
133
     */
134
    public function loadCA($capath)
135
    {
136
        if (is_file($capath)) {
137
            $this->casefaz = $capath;
138
        }
139
    }
140
    
141
    /**
142
     * Set another temporayfolder for saving certificates for SOAP utilization
143
     * @param string $folderRealPath
144
     */
145 2
    public function setTemporaryFolder($folderRealPath)
146
    {
147 2
        $this->tempdir = $folderRealPath;
148 2
        $this->setLocalFolder($folderRealPath);
149 2
    }
150
    
151
    /**
152
     * Set Local folder for flysystem
153
     * @param string $folder
154
     */
155 2
    protected function setLocalFolder($folder = '')
156
    {
157 2
        $this->adapter = new Local($folder);
158 2
        $this->filesystem = new Filesystem($this->adapter);
159 2
    }
160
161
    /**
162
     * Set debug mode, this mode will save soap envelopes in temporary directory
163
     * @param bool $value
164
     */
165
    public function setDebugMode($value = false)
166
    {
167
        $this->debugmode = $value;
168
    }
169
    
170
    /**
171
     * Set certificate class for SSL comunications
172
     * @param Certificate $certificate
173
     */
174
    public function loadCertificate(Certificate $certificate)
175
    {
176
        $this->certificate = $certificate;
177
    }
178
    
179
    /**
180
     * Set logger class
181
     * @param LoggerInterface $logger
182
     */
183
    public function loadLogger(LoggerInterface $logger)
184
    {
185
        return $this->logger = $logger;
186
    }
187
    
188
    /**
189
     * Set timeout for communication
190
     * @param int $timesecs
191
     */
192
    public function timeout($timesecs)
193
    {
194
        return $this->soaptimeout = $timesecs;
195
    }
196
    
197
    /**
198
     * Set security protocol
199
     * @param int $protocol
200
     * @return type Description
201
     */
202
    public function protocol($protocol = self::SSL_DEFAULT)
203
    {
204
        return $this->soapprotocol = $protocol;
205
    }
206
    
207
    /**
208
     * Set prefixes
209
     * @param string $prefixes
210
     */
211
    public function setSoapPrefix($prefixes)
212
    {
213
        $this->prefixes = $prefixes;
0 ignored issues
show
Documentation Bug introduced by
It seems like $prefixes of type string is incompatible with the declared type array of property $prefixes.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
214
    }
215
    
216
    /**
217
     * Set proxy parameters
218
     * @param string $ip
219
     * @param int $port
220
     * @param string $user
221
     * @param string $password
222
     */
223
    public function proxy($ip, $port, $user, $password)
224
    {
225
        $this->proxyIP = $ip;
226
        $this->proxyPort = $port;
0 ignored issues
show
Documentation Bug introduced by
The property $proxyPort was declared of type string, but $port is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
227
        $this->proxyUser = $user;
228
        $this->proxyPass = $password;
229
    }
230
    
231
    /**
232
     * Send message to webservice
233
     */
234
    abstract public function send(
235
        $url,
236
        $operation = '',
237
        $action = '',
238
        $soapver = SOAP_1_2,
239
        $parameters = [],
240
        $namespaces = [],
241
        $request = '',
242
        $soapheader = null
243
    );
244
    
245
    /**
246
     * Mount soap envelope
247
     * @param string $request
248
     * @param string $operation
249
     * @param array $namespaces
250
     * @param \SOAPHeader $header
251
     * @return string
252
     */
253
    protected function makeEnvelopeSoap(
254
        $request,
255
        $operation,
0 ignored issues
show
Unused Code introduced by
The parameter $operation is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
256
        $namespaces,
257
        $soapver = SOAP_1_2,
258
        $header = null
259
    ) {
260
        $prefix = $this->prefixes[$soapver];
261
        $envelope = "<$prefix:Envelope";
262
        foreach ($namespaces as $key => $value) {
263
            $envelope .= " $key=\"$value\"";
264
        }
265
        $envelope .= ">";
266
        $soapheader = "<$prefix:Header/>";
267
        if (!empty($header)) {
268
            $ns = !empty($header->namespace) ? $header->namespace : '';
0 ignored issues
show
Bug introduced by
The property namespace does not seem to exist in SoapHeader.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
269
            $name = $header->name;
0 ignored issues
show
Bug introduced by
The property name does not seem to exist in SoapHeader.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
270
            $soapheader = "<$prefix:Header>";
271
            $soapheader .= "<$name xmlns=\"$ns\">";
272
            foreach ($header->data as $key => $value) {
0 ignored issues
show
Bug introduced by
The property data does not seem to exist in SoapHeader.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
273
                $soapheader .= "<$key>$value</$key>";
274
            }
275
            $soapheader .= "</$name></$prefix:Header>";
276
        }
277
        $envelope .= $soapheader;
278
        $envelope .= "<$prefix:Body>$request</$prefix:Body>"
279
            . "</$prefix:Envelope>";
280
        return $envelope;
281
    }
282
    
283
    /**
284
     * Temporarily saves the certificate keys for use cURL or SoapClient
285
     */
286
    public function saveTemporarilyKeyFiles()
287
    {
288
        if (!is_object($this->certificate)) {
289
            throw new RuntimeException(
290
                'Certificate not found.'
291
            );
292
        }
293
        $this->certsdir = $this->certificate->getCnpj() . '/certs/';
294
        $this->prifile = $this->certsdir. Strings::randomString(10).'.pem';
295
        $this->pubfile = $this->certsdir . Strings::randomString(10).'.pem';
296
        $this->certfile = $this->certsdir . Strings::randomString(10).'.pem';
297
        $ret = true;
298
        $ret &= $this->filesystem->put(
299
            $this->prifile,
300
            $this->certificate->privateKey
301
        );
302
        $ret &= $this->filesystem->put(
303
            $this->pubfile,
304
            $this->certificate->publicKey
305
        );
306
        $ret &= $this->filesystem->put(
307
            $this->certfile,
308
            "{$this->certificate}"
309
        );
310
        if (!$ret) {
311
            throw new RuntimeException(
312
                'Unable to save temporary key files in folder.'
313
            );
314
        }
315
    }
316
    
317
    /**
318
     * Delete all files in folder
319
     */
320 2
    public function removeTemporarilyFiles($folder)
321
    {
322 2
        $contents = $this->filesystem->listContents($folder, true);
323 2
        foreach ($contents as $item) {
324
            if ($item['type'] == 'file') {
325
                $this->filesystem->delete($item['path']);
326
            }
327
        }
328 2
    }
329
    
330
    /**
331
     * Save request envelope and response for debug reasons
332
     * @param string $operation
333
     * @param string $request
334
     * @param string $response
335
     * @return void
336
     */
337
    public function saveDebugFiles($operation, $request, $response)
338
    {
339
        if (!$this->debugmode) {
340
            return;
341
        }
342
        $this->debugdir = $this->certificate->getCnpj() . '/debug/';
343
        $now = \DateTime::createFromFormat('U.u', microtime(true));
344
        $time = substr($now->format("ymdHisu"), 0, 16);
345
        try {
346
            $this->filesystem->put(
347
                $this->debugdir . $time . "_" . $operation . "_sol.txt",
348
                $request
349
            );
350
            $this->filesystem->put(
351
                $this->debugdir . $time . "_" . $operation . "_res.txt",
352
                $response
353
            );
354
        } catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class NFePHP\Common\Soap\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
355
            throw new RuntimeException(
356
                'Unable to create debug files.'
357
            );
358
        }
359
    }
360
}
361