Passed
Push — master ( 0652b0...f7b146 )
by Roberto
02:18
created

DOMImproved   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 244
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 0

Test Coverage

Coverage 5.81%

Importance

Changes 0
Metric Value
wmc 36
lcom 2
cbo 0
dl 0
loc 244
ccs 5
cts 86
cp 0.0581
rs 8.8
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A loadXMLString() 0 11 3
A loadXMLFile() 0 9 2
A getNodeValue() 0 9 2
A getValue() 0 9 3
A getNode() 0 8 2
A getChave() 0 10 2
C addChild() 0 22 8
A appChild() 0 8 2
A appExternalChild() 0 5 1
A appExternalChildBefore() 0 11 2
A appChildBefore() 0 11 4
A addArrayChild() 0 11 4
1
<?php
2
3
namespace NFePHP\Common;
4
5
/**
6
 * Extends DOMDocument
7
 * @category   NFePHP
8
 * @package    NFePHP\Common\DOMImproved
9
 * @copyright  Copyright (c) 2008-2017
10
 * @license    http://www.gnu.org/licenses/lesser.html LGPL v3
11
 * @license    https://opensource.org/licenses/MIT MIT
12
 * @license    http://www.gnu.org/licenses/gpl.txt GPLv3+
13
 * @author     Roberto L. Machado <linux.rlm at gmail dot com>
14
 * @link       http://github.com/nfephp-org/sped-common for the canonical source repository
15
 */
16
17
use DOMDocument;
18
use DOMElement;
19
20
class DOMImproved extends DOMDocument
21
{
22
    /**
23
     * @var array
24
     */
25
    public $errors = [];
26
    
27
    /**
28
     * @param string $version
29
     * @param string $charset
30
     */
31 1
    public function __construct($version = '1.0', $charset = 'utf-8')
32
    {
33 1
        parent::__construct($version, $charset);
34 1
        $this->formatOutput = false;
35 1
        $this->preserveWhiteSpace = false;
36 1
    }
37
    
38
    /**
39
     * Loads string in DOMDocument
40
     * @param string $content content of xml
41
     * @return bool
42
     */
43
    public function loadXMLString($content)
44
    {
45
        $msg = "O arquivo indicado não é um XML ou contêm B.O.M. no inicio do arquivo !";
46
        if (substr($content, 0, 1) != '<' ||
47
            !$this->loadXML($content, LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG)
48
        ) {
49
            $this->errors[] = $msg;
50
            return false;
51
        }
52
        return true;
53
    }
54
    
55
    /**
56
     * Load xml from path
57
     * @param string $filename
58
     * @return bool
59
     */
60
    public function loadXMLFile($filename)
61
    {
62
        if (!is_file($filename)) {
63
            $this->errors[] = 'Arquivo não encontrado!';
64
            return false;
65
        }
66
        $content = file_get_contents($filename);
67
        $this->loadXMLString($content);
68
    }
69
            
70
    /**
71
     * Extrai o valor do node DOM
72
     * @param string $nodeName identificador da TAG do xml
73
     * @param int $itemNum numero do item a ser retornado
74
     * @param string $extraTextBefore prefixo do retorno
75
     * @param string $extraTextAfter sufixo do retorno
76
     * @return string
77
     */
78
    public function getNodeValue($nodeName, $itemNum = 0, $extraTextBefore = '', $extraTextAfter = '')
79
    {
80
        $node = $this->getElementsByTagName($nodeName)->item($itemNum);
81
        if (isset($node)) {
82
            $texto = html_entity_decode(trim($node->nodeValue), ENT_QUOTES, 'UTF-8');
83
            return $extraTextBefore . $texto . $extraTextAfter;
84
        }
85
        return '';
86
    }
87
    
88
    /**
89
     * getValue
90
     * @param DOMElement $node
91
     * @param string $name
92
     * @return string
93
     */
94
    public function getValue(DOMElement $node, $name)
95
    {
96
        if (empty($node)) {
97
            return '';
98
        }
99
        $texto = !empty($node->getElementsByTagName($name)->item(0)->nodeValue) ?
100
            $node->getElementsByTagName($name)->item(0)->nodeValue : '';
101
        return html_entity_decode($texto, ENT_QUOTES, 'UTF-8');
102
    }
103
    
104
    /**
105
     * getNode
106
     * Retorna o node solicitado
107
     * @param string $nodeName
108
     * @param integer $itemNum
109
     * @return DOMElement | string
110
     */
111
    public function getNode($nodeName, $itemNum = 0)
112
    {
113
        $node = $this->getElementsByTagName($nodeName)->item($itemNum);
114
        if (isset($node)) {
115
            return $node;
116
        }
117
        return '';
0 ignored issues
show
Bug Best Practice introduced by
The return type of return ''; (string) is incompatible with the return type documented by NFePHP\Common\DOMImproved::getNode of type DOMElement.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
118
    }
119
    
120
    /**
121
     * getChave
122
     * @param string $nodeName
123
     * @return string
124
     */
125
    public function getChave($nodeName = 'infNFe')
126
    {
127
        $node = $this->getElementsByTagName($nodeName)->item(0);
128
        if (! empty($node)) {
129
            $chaveId = $node->getAttribute("Id");
130
            $chave =  preg_replace('/[^0-9]/', '', $chaveId);
131
            return $chave;
132
        }
133
        return '';
134
    }
135
    
136
    /**
137
     * addChild
138
     * Adiciona um elemento ao node xml passado como referencia
139
     * Serão inclusos erros na array $erros[] sempre que a tag for obrigatória e
140
     * nenhum parâmetro for passado na variável $content e $force for false
141
     * @param DOMElement $parent
142
     * @param string $name
143
     * @param string|float|null $content
144
     * @param boolean $obrigatorio
145
     * @param string $descricao
146
     * @param boolean $force força a criação do elemento mesmo sem dados e não considera como erro
147
     * @return void
148
     */
149
    public function addChild(
150
        DOMElement &$parent,
151
        $name,
152
        $content,
153
        $obrigatorio = false,
154
        $descricao = '',
155
        $force = false
156
    ) {
157
        if ($content === null) {
158
            return;
159
        }
160
        $content = (string) $content;
161
        $content = trim($content);
162
        if ($obrigatorio && $content === '' && !$force) {
163
            $this->errors[] = "Preenchimento Obrigatório! [$name] $descricao";
164
        }
165
        if ($obrigatorio || $content !== '' || $force) {
166
            $content = htmlspecialchars($content, ENT_QUOTES);
167
            $temp = $this->createElement($name, $content);
168
            $parent->appendChild($temp);
169
        }
170
    }
171
    
172
    /**
173
     * Acrescenta DOMElement a pai DOMElement
174
     * Caso o pai esteja vazio retorna uma exception com a mensagem
175
     * O parametro "child" pode ser vazio
176
     * @param DOMElement $parent
177
     * @param DOMElement $child
178
     * @param string $msg
179
     * @return void
180
     */
181
    public function appChild(DOMElement &$parent, DOMElement $child = null, $msg = '')
182
    {
183
        if (empty($child)) {
184
            $this->errors[] = $msg;
185
            return;
186
        }
187
        $parent->appendChild($child);
188
    }
189
    
190
    /**
191
     * Append DOMElement from external documento to local Node
192
     * @param DOMElement $parent
193
     * @param DOMElement $child
194
     * @return void
195
     */
196
    public function appExternalChild(DOMElement &$parent, DOMElement $child)
197
    {
198
        $node = $this->importNode($child, true);
199
        $parent->appendChild($node);
200
    }
201
    
202
    /**
203
     * Append DOMElement from external documento to local Node
204
     * before existent node
205
     * @param DOMElement $parent
206
     * @param DOMElement $child
207
     * @param string $before
208
     * @return void
209
     */
210
    public function appExternalChildBefore(
211
        DOMElement &$parent,
212
        DOMElement $child,
213
        $before
214
    ) {
215
        if (empty($bnode = $parent->getElementsByTagName($before)->item(0))) {
216
            return;
217
        }
218
        $node = $this->importNode($child, true);
219
        $parent->insertBefore($node, $bnode);
220
    }
221
        
222
    /**
223
     * appChildBefore
224
     * Acrescenta DOMElement a pai DOMElement
225
     * Caso o pai esteja vazio retorna uma exception com a mensagem
226
     * O parametro "child" pode ser vazio
227
     * @param DOMElement $parent
228
     * @param DOMElement $child
229
     * @param string $before
230
     * @param string $msg
231
     * @return void
232
     */
233
    public function appChildBefore(DOMElement &$parent, DOMElement $child = null, $before = '', $msg = '')
234
    {
235
        if (empty($child) ||
236
            empty($before) ||
237
            empty($bnode = $parent->getElementsByTagName($before)->item(0))
238
        ) {
239
            $this->errors[] = "$msg Node child vazio ou node <$before> não encontrado!!";
240
            return;
241
        }
242
        $parent->insertBefore($child, $bnode);
243
    }
244
    
245
    /**
246
     * addArrayChild
247
     * Adiciona a um DOMElemt parent, outros elementos passados em um array de DOMElements
248
     * @param DOMElement $parent
249
     * @param array $arr
250
     * @return int
251
     */
252
    public function addArrayChild(DOMElement &$parent, $arr)
253
    {
254
        $num = 0;
255
        if (! empty($arr) && ! empty($parent)) {
256
            foreach ($arr as $node) {
257
                $this->appChild($parent, $node, '');
258
                $num++;
259
            }
260
        }
261
        return $num;
262
    }
263
}
264