Completed
Pull Request — master (#227)
by Roberto
03:27
created

Factory::__construct()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 53

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 5.0536

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 27
cts 31
cp 0.871
rs 8.7143
c 0
b 0
f 0
cc 5
nc 6
nop 4
crap 5.0536

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace NFePHP\eSocial\Common;
4
5
use DateTime;
6
use DOMDocument;
7
use DOMElement;
8
use JsonSchema\Validator as JsonValid;
9
use NFePHP\Common\Certificate;
10
use NFePHP\Common\DOMImproved as Dom;
11
use NFePHP\Common\Signer;
12
use NFePHP\Common\Strings;
13
use NFePHP\Common\Validator;
14
use stdClass;
15
16
abstract class Factory
17
{
18
    /**
19
     * @var int
20
     */
21
    public $tpInsc;
22
    /**
23
     * @var string
24
     */
25
    public $nrInsc;
26
    /**
27
     * @var string
28
     */
29
    public $nmRazao;
30
    /**
31
     * @var DateTime
32
     */
33
    public $date;
34
    /**
35
     * @var int
36
     */
37
    public $tpAmb;
38
    /**
39
     * @var int
40
     */
41
    public $procEmi = 1; //1- Aplicativo do empregador
42
    /**
43
     * @var string
44
     */
45
    public $verProc;
46
    /**
47
     * @var string
48
     */
49
    public $layout;
50
    /**
51
     * @var string
52
     */
53
    public $layoutStr;
54
    /**
55
     * @var string
56
     */
57
    public $schema;
58
    /**
59
     * @var string
60
     */
61
    public $jsonschema;
62
    /**
63
     * @var string
64
     */
65
    public $evtid;
66
    /**
67
     * @var string
68
     */
69
    protected $xmlns = "http://www.esocial.gov.br/schema/evt/";
70
    /**
71
     * @var Dom
72
     */
73
    protected $dom;
74
    /**
75
     * @var stdClass
76
     */
77
    protected $std;
78
    /**
79
     * @var string
80
     */
81
    protected $xml;
82
    /**
83
     * @var DOMElement
84
     */
85
    protected $eSocial;
86
    /**
87
     * @var DOMElement
88
     */
89
    protected $node;
90
    /**
91
     * @var array
92
     */
93
    protected $parameters = [];
94
    /**
95
     * @var string
96
     */
97
    protected $evtName;
98
    /**
99
     * @var string
100
     */
101
    protected $evtAlias;
102
    /**
103
     * @var Certificate | null
104
     */
105
    protected $certificate;
106
    
107
    /**
108
     * Constructor
109
     * @param string $config
110
     * @param stdClass $std
111
     * @param Certificate $certificate | null
112
     * @param string $date
113
     */
114 5
    public function __construct(
115
        $config,
116
        stdClass $std,
117
        Certificate $certificate = null,
118
        $date = ''
119
    ) {
120
        //set properties from config
121 5
        $stdConf    = json_decode($config);
122 5
        $this->date = new DateTime();
123 5
        if (! empty($date)) {
124 5
            $this->date = new DateTime($date);
125
        }
126 5
        $this->tpAmb = $stdConf->tpAmb;
127 5
        $this->verProc = $stdConf->verProc;
128 5
        $this->layout = $stdConf->eventoVersion;
129 5
        $this->tpInsc = $stdConf->empregador->tpInsc;
130 5
        $this->nrInsc = $stdConf->empregador->nrInsc;
131 5
        $this->nmRazao = $stdConf->empregador->nmRazao;
132 5
        $this->layoutStr = $this->strLayoutVer($this->layout);
133 5
        $this->certificate = $certificate;
134 5
        if (empty($std) || ! is_object($std)) {
135
            throw new \InvalidArgumentException(
136
                'Você deve passar os parâmetros num stdClass.'
137
            );
138
        }
139 5
        $this->jsonschema = realpath(
140
            __DIR__
141 5
            ."/../../jsonSchemes/$this->layoutStr/"
142 5
            .$this->evtName
143 5
            .".schema"
144
        );
145 5
        $this->schema = realpath(
146
            __DIR__
147 5
            ."/../../schemes/$this->layoutStr/"
148 5
            .$this->evtName
149 5
            .".xsd"
150
        );
151 5
        if (empty($this->schema)) {
152
            throw new \InvalidArgumentException(
153
                'Schemas não localizados, verifique de passou as versões '
154
                    . 'corretamente no config.'
155
            );
156
        }
157
        //convert all data fields to lower case
158 5
        $this->std = $this->propertiesToLower($std);
159
        //validate input data with schema
160 5
        $this->validInputData($this->std);
161
        //Adding forgotten or unnecessary fields.
162
        //This is done for standardization purposes.
163
        //Fields with no value will not be included by the builder.
164
        //$this->std = $this->standardizeProperties($this->std);
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
165 5
        $this->init();
166 5
    }
167
168
    /**
169
     * Stringfy layout number
170
     * @param string $layout
171
     * @return string
172
     */
173 5
    protected function strLayoutVer($layout)
174
    {
175 5
        $fils = explode('.', $layout);
176 5
        $str  = 'v';
177 5
        foreach ($fils as $fil) {
178 5
            $str .= str_pad($fil, 2, '0', STR_PAD_LEFT).'_';
179
        }
180 5
        return substr($str, 0, -1);
181
    }
182
183
    /**
184
     * Change properties names of stdClass to lower case
185
     * @param stdClass $data
186
     * @return stdClass
187
     */
188 5
    protected static function propertiesToLower(stdClass $data)
189
    {
190 5
        $properties = get_object_vars($data);
191 5
        $clone      = new stdClass();
192 5
        foreach ($properties as $key => $value) {
193 5
            if ($value instanceof stdClass) {
194
                $value = self::propertiesToLower($value);
195
            }
196 5
            $nk           = strtolower($key);
197 5
            $clone->{$nk} = $value;
198
        }
199 5
        return $clone;
200
    }
201
202
    /**
203
     * Validation json data from json Schema
204
     * @param stdClass $data
205
     * @return boolean
206
     * @throws \RuntimeException
207
     */
208 5
    protected function validInputData($data)
209
    {
210 5
        if (! is_file($this->jsonschema)) {
211
            return true;
212
        }
213 5
        $validator = new JsonValid();
214 5
        $validator->check($data, (object) ['$ref' => 'file://'.$this->jsonschema]);
215 5
        if (! $validator->isValid()) {
216
            $msg = "JSON does not validate. Violations:\n";
217
            foreach ($validator->getErrors() as $error) {
218
                $msg .= sprintf("[%s] %s\n", $error['property'], $error['message']);
219
            }
220
            throw new \RuntimeException($msg);
221
        }
222
223 5
        return true;
224
    }
225
226
    /**
227
     * Initialize DOM
228
     */
229 5
    protected function init()
230
    {
231 5
        if (empty($this->dom)) {
232 5
            $this->dom = new Dom('1.0', 'UTF-8');
233 5
            $this->dom->preserveWhiteSpace = false;
234 5
            $this->dom->formatOutput = false;
235
            $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
236 5
                . "<eSocial xmlns=\"$this->xmlns"
237 5
                . $this->evtName
238 5
                . "/$this->layoutStr\">"
239 5
                . "</eSocial>";
240 5
            $this->dom->loadXML($xml);
241 5
            $this->eSocial = $this->dom->getElementsByTagName('eSocial')->item(0);
242 5
            $this->evtid = FactoryId::build(
243 5
                $this->tpInsc,
244 5
                $this->nrInsc,
245 5
                $this->date,
246 5
                $this->std->sequencial
247
            );
248 5
            $this->node = $this->dom->createElement($this->evtName);
249 5
            $att = $this->dom->createAttribute('Id');
250 5
            $att->value = $this->evtid;
251 5
            $this->node->appendChild($att);
252
253 5
            $ideEmpregador = $this->dom->createElement("ideEmpregador");
254 5
            $this->dom->addChild(
255
                $ideEmpregador,
256 5
                "tpInsc",
257 5
                "$this->tpInsc",
258 5
                true
259
            );
260 5
            $this->dom->addChild(
261
                $ideEmpregador,
262 5
                "nrInsc",
263 5
                $this->nrInsc,
264 5
                true
265
            );
266 5
            $this->node->appendChild($ideEmpregador);
267
        }
268 5
    }
269
    
270
    /**
271
     * Returns alias for event
272
     * @return string
273
     */
274
    public function alias()
275
    {
276
        return $this->evtAlias;
277
    }
278
279
    /**
280
     * Returns Certificate::class
281
     * @return Certificate|null
282
     */
283
    public function getCertificate()
284
    {
285
        return $this->certificate;
286
    }
287
    
288
    /**
289
     * Set Certificate::class
290
     * @param Certificate $certificate
291
     */
292
    public function setCertificate(Certificate $certificate)
293
    {
294
        $this->certificate = $certificate;
295
    }
296
297
    /**
298
     * Return xml of event
299
     * @return string
300
     */
301 1
    public function toXML()
302
    {
303 1
        $this->init();
304 1
        if (empty($this->xml)) {
305 1
            $this->toNode();
306
        }
307 1
        return $this->clearXml($this->xml);
308
    }
309
310
    abstract protected function toNode();
311
312
    /**
313
     * Remove XML declaration from XML string
314
     * @param string $xml
315
     * @return string
316
     */
317 1
    protected function clearXml($xml)
318
    {
319 1
        $dom = new DOMDocument('1.0', 'UTF-8');
320 1
        $dom->formatOutput = false;
321 1
        $dom->preserveWhiteSpace = false;
322 1
        $dom->loadXML($xml);
323 1
        return $dom->saveXML($dom->documentElement);
324
    }
325
326
    /**
327
     * Convert xml of event to array
328
     * @return array
329
     */
330 1
    public function toArray()
331
    {
332 1
        return json_decode($this->toJson(), true);
333
    }
334
335
    /**
336
     * Convert xml to json string
337
     * @return string
338
     */
339 2
    public function toJson()
340
    {
341 2
        return json_encode($this->std);
342
    }
343
344
    /**
345
     * Returns stdClass
346
     * @return stdClass
347
     */
348 1
    public function toStd()
349
    {
350 1
        return $this->std;
351
    }
352
353
    /**
354
     * Adjust missing properties form original data according schema
355
     * @param \stdClass $data
356
     * @return \stdClass
357
     */
358
    public function standardizeProperties(stdClass $data)
359
    {
360
        if (! is_file($this->jsonschema)) {
361
            return $data;
362
        }
363
        $jsonSchemaObj = json_decode(file_get_contents($this->jsonschema));
364
        $sc = new ParamsStandardize($jsonSchemaObj);
365
        return $sc->stdData($data);
366
    }
367
368
    /**
369
     * Sign and validate XML with XSD, can throw Exception
370
     */
371 1
    protected function sign()
372
    {
373 1
        $xml = $this->dom->saveXML($this->eSocial);
374 1
        $xml = Strings::clearXmlString($xml);
375 1
        if (! empty($this->certificate)) {
376 1
            $xml = Signer::sign(
377 1
                $this->certificate,
378
                $xml,
379 1
                'eSocial',
380 1
                '',
381 1
                OPENSSL_ALGO_SHA256,
382 1
                [true, false, null, null]
383
            );
384
            //validation by XSD schema throw Exception if dont pass
385 1
            Validator::isValid($xml, $this->schema);
386
        }
387 1
        $this->xml = $xml;
388 1
    }
389
}
390