Passed
Push — master ( e62ad0...8c869c )
by Roberto
02:36
created

DOMImproved::insertAfter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 2
crap 6
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 DOMNode;
19
use DOMElement;
20
21
class DOMImproved extends DOMDocument
22
{
23
    /**
24
     * @var array
25
     */
26
    public $errors = [];
27
    
28
    /**
29
     * @param string $version
30
     * @param string $charset
31
     */
32 1
    public function __construct($version = '1.0', $charset = 'utf-8')
33
    {
34 1
        parent::__construct($version, $charset);
35 1
        $this->formatOutput = false;
36 1
        $this->preserveWhiteSpace = false;
37 1
    }
38
    
39
    /**
40
     * Insert node AFTER reference node
41
     * @param \DOMNode $newNode
42
     * @param \DOMNode $referenceNode
43
     * @return \DOMNode
44
     */
45
    public function insertAfter(\DOMNode $newNode, \DOMNode $referenceNode)
46
    {
47
        if ($referenceNode->nextSibling === null) {
48
            return $referenceNode->parentNode->appendChild($newNode);
49
        } else {
50
            return $referenceNode->parentNode->insertBefore($newNode, $referenceNode->nextSibling);
51
        }
52
    }
53
    
54
    /**
55
     * Loads string in DOMDocument
56
     * @param string $content content of xml
57
     * @return bool
58
     */
59
    public function loadXMLString($content)
60
    {
61
        $msg = "O arquivo indicado não é um XML ou contêm B.O.M. no inicio do arquivo !";
62
        if (substr($content, 0, 1) != '<' ||
63
            !$this->loadXML($content, LIBXML_NOBLANKS | LIBXML_NOEMPTYTAG)
64
        ) {
65
            $this->errors[] = $msg;
66
            return false;
67
        }
68
        return true;
69
    }
70
    
71
    /**
72
     * Load xml from path
73
     * @param string $filename
74
     * @return bool
75
     */
76
    public function loadXMLFile($filename)
77
    {
78
        if (!is_file($filename)) {
79
            $this->errors[] = 'Arquivo não encontrado!';
80
            return false;
81
        }
82
        $content = file_get_contents($filename);
83
        $this->loadXMLString($content);
84
    }
85
            
86
    /**
87
     * Extrai o valor do node DOM
88
     * @param string $nodeName identificador da TAG do xml
89
     * @param int $itemNum numero do item a ser retornado
90
     * @param string $extraTextBefore prefixo do retorno
91
     * @param string $extraTextAfter sufixo do retorno
92
     * @return string
93
     */
94
    public function getNodeValue($nodeName, $itemNum = 0, $extraTextBefore = '', $extraTextAfter = '')
95
    {
96
        $node = $this->getElementsByTagName($nodeName)->item($itemNum);
97
        if (isset($node)) {
98
            $texto = html_entity_decode(trim($node->nodeValue), ENT_QUOTES, 'UTF-8');
99
            return $extraTextBefore . $texto . $extraTextAfter;
100
        }
101
        return '';
102
    }
103
    
104
    /**
105
     * getValue
106
     * @param DOMElement $node
107
     * @param string $name
108
     * @return string
109
     */
110
    public function getValue(DOMElement $node, $name)
111
    {
112
        if (empty($node)) {
113
            return '';
114
        }
115
        $texto = !empty($node->getElementsByTagName($name)->item(0)->nodeValue) ?
116
            $node->getElementsByTagName($name)->item(0)->nodeValue : '';
117
        return html_entity_decode($texto, ENT_QUOTES, 'UTF-8');
118
    }
119
    
120
    /**
121
     * getNode
122
     * Retorna o node solicitado
123
     * @param string $nodeName
124
     * @param integer $itemNum
125
     * @return DOMElement | string
126
     */
127
    public function getNode($nodeName, $itemNum = 0)
128
    {
129
        $node = $this->getElementsByTagName($nodeName)->item($itemNum);
130
        if (isset($node)) {
131
            return $node;
132
        }
133
        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...
134
    }
135
    
136
    /**
137
     * getChave
138
     * @param string $nodeName
139
     * @return string
140
     */
141
    public function getChave($nodeName = 'infNFe')
142
    {
143
        $node = $this->getElementsByTagName($nodeName)->item(0);
144
        if (! empty($node)) {
145
            $chaveId = $node->getAttribute("Id");
146
            $chave =  preg_replace('/[^0-9]/', '', $chaveId);
147
            return $chave;
148
        }
149
        return '';
150
    }
151
    
152
    /**
153
     * addChild
154
     * Adiciona um elemento ao node xml passado como referencia
155
     * Serão inclusos erros na array $erros[] sempre que a tag for obrigatória e
156
     * nenhum parâmetro for passado na variável $content e $force for false
157
     * @param \DOMElement $parent
158
     * @param string $name
159
     * @param string|float|null $content
160
     * @param boolean $obrigatorio
161
     * @param string $descricao
162
     * @param boolean $force força a criação do elemento mesmo sem dados e não considera como erro
163
     * @return void
164
     */
165
    public function addChild(
166
        DOMElement &$parent,
167
        $name,
168
        $content,
169
        $obrigatorio = false,
170
        $descricao = '',
171
        $force = false
172
    ) {
173
        if ($content === null) {
174
            return;
175
        }
176
        $content = (string) $content;
177
        $content = trim($content);
178
        if ($obrigatorio && $content === '' && !$force) {
179
            $this->errors[] = "Preenchimento Obrigatório! [$name] $descricao";
180
        }
181
        if ($obrigatorio || $content !== '' || $force) {
182
            $content = htmlspecialchars($content, ENT_QUOTES);
183
            $temp = $this->createElement($name, $content);
184
            $parent->appendChild($temp);
185
        }
186
    }
187
    
188
    /**
189
     * Acrescenta DOMElement a pai DOMElement
190
     * Caso o pai esteja vazio retorna uma exception com a mensagem
191
     * O parametro "child" pode ser vazio
192
     * @param DOMElement $parent
193
     * @param DOMElement $child
194
     * @param string $msg
195
     * @return void
196
     */
197
    public function appChild(DOMElement &$parent, DOMElement $child = null, $msg = '')
198
    {
199
        if (empty($child)) {
200
            $this->errors[] = $msg;
201
            return;
202
        }
203
        $parent->appendChild($child);
204
    }
205
    
206
    /**
207
     * Append DOMElement from external documento to local Node
208
     * @param \DOMElement $parent
209
     * @param \DOMElement $child
210
     * @return void
211
     */
212
    public function appExternalChild(DOMElement &$parent, DOMElement $child)
213
    {
214
        $node = $this->importNode($child, true);
215
        $parent->appendChild($node);
216
    }
217
    
218
    /**
219
     * Append DOMElement from external documento to local Node
220
     * before existent node
221
     * @param \DOMElement $parent
222
     * @param \DOMElement $child
223
     * @param string $before
224
     * @return void
225
     */
226
    public function appExternalChildBefore(
227
        DOMElement &$parent,
228
        DOMElement $child,
229
        $before
230
    ) {
231
        if (empty($bnode = $parent->getElementsByTagName($before)->item(0))) {
232
            return;
233
        }
234
        $node = $this->importNode($child, true);
235
        $parent->insertBefore($node, $bnode);
236
    }
237
        
238
    /**
239
     * appChildBefore
240
     * Acrescenta DOMElement a pai DOMElement
241
     * Caso o pai esteja vazio retorna uma exception com a mensagem
242
     * O parametro "child" pode ser vazio
243
     * @param \DOMElement $parent
244
     * @param \DOMElement $child
245
     * @param string $before
246
     * @param string $msg
247
     * @return void
248
     */
249
    public function appChildBefore(DOMElement &$parent, DOMElement $child = null, $before = '', $msg = '')
250
    {
251
        if (empty($child) ||
252
            empty($before) ||
253
            empty($bnode = $parent->getElementsByTagName($before)->item(0))
254
        ) {
255
            $this->errors[] = "$msg Node child vazio ou node <$before> não encontrado!!";
256
            return;
257
        }
258
        $parent->insertBefore($child, $bnode);
259
    }
260
    
261
    /**
262
     * addArrayChild
263
     * Adiciona a um DOMElemt parent, outros elementos passados em um array de DOMElements
264
     * @param \DOMElement $parent
265
     * @param array $arr
266
     * @return int
267
     */
268
    public function addArrayChild(DOMElement &$parent, $arr)
269
    {
270
        $num = 0;
271
        if (! empty($arr) && ! empty($parent)) {
272
            foreach ($arr as $node) {
273
                $this->appChild($parent, $node, '');
274
                $num++;
275
            }
276
        }
277
        return $num;
278
    }
279
}
280