Completed
Push — master ( a2218e...0108a8 )
by Roberto
03:33 queued 10s
created

DOMImproved::insertAfter()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

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 10
c 0
b 0
f 0
cc 2
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|null $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 (empty($name)) {
174
            $this->errors[] = "O nome da TAG é Obrigatório!";
175
            return;
176
        }
177
        if (!$obrigatorio && $content === null) {
178
            return;
179
        } elseif ($obrigatorio && ($content === null || $content === '') && !$force) {
180
            $this->errors[] = "Preenchimento Obrigatório! [$name] $descricao";
181
        }
182
        $content = (string) $content;
183
        $content = trim($content);
184
        if ($obrigatorio || $content !== '' || $force) {
185
            $temp = $this->createElement($name, $content);
186
            $parent->appendChild($temp);
187
        }
188
    }
189
    
190
    /**
191
     * Acrescenta DOMElement a pai DOMElement
192
     * Caso o pai esteja vazio retorna uma exception com a mensagem
193
     * O parametro "child" pode ser null
194
     * @param DOMElement $parent
195
     * @param DOMElement|null $child
196
     * @param string $msg
197
     * @return void
198
     */
199
    public function appChild(DOMElement &$parent, DOMElement $child = null, $msg = '')
0 ignored issues
show
Unused Code introduced by
The parameter $msg 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...
200
    {
201
        if (empty($child)) {
202
            //$this->errors[] = $msg;
203
            return;
204
        }
205
        $parent->appendChild($child);
206
    }
207
    
208
    /**
209
     * Append DOMElement from external documento to local Node
210
     * @param \DOMElement $parent
211
     * @param \DOMElement $child
212
     * @return void
213
     */
214
    public function appExternalChild(DOMElement &$parent, DOMElement $child)
215
    {
216
        $node = $this->importNode($child, true);
217
        $parent->appendChild($node);
218
    }
219
    
220
    /**
221
     * Append DOMElement from external documento to local Node
222
     * before existent node
223
     * @param \DOMElement $parent
224
     * @param \DOMElement $child
225
     * @param string $before
226
     * @return void
227
     */
228
    public function appExternalChildBefore(
229
        DOMElement &$parent,
230
        DOMElement $child,
231
        $before
232
    ) {
233
        if (empty($bnode = $parent->getElementsByTagName($before)->item(0))) {
234
            return;
235
        }
236
        $node = $this->importNode($child, true);
237
        $parent->insertBefore($node, $bnode);
238
    }
239
        
240
    /**
241
     * appChildBefore
242
     * Acrescenta DOMElement a pai DOMElement
243
     * Caso o pai esteja vazio retorna uma exception com a mensagem
244
     * O parametro "child" pode ser vazio
245
     * @param \DOMElement $parent
246
     * @param \DOMElement $child
247
     * @param string $before
248
     * @param string $msg
249
     * @return void
250
     */
251
    public function appChildBefore(DOMElement &$parent, DOMElement $child = null, $before = '', $msg = '')
252
    {
253
        if (empty($child) ||
254
            empty($before) ||
255
            empty($bnode = $parent->getElementsByTagName($before)->item(0))
256
        ) {
257
            $this->errors[] = "$msg Node child vazio ou node <$before> não encontrado!!";
258
            return;
259
        }
260
        $parent->insertBefore($child, $bnode);
261
    }
262
    
263
    /**
264
     * addArrayChild
265
     * Adiciona a um DOMElemt parent, outros elementos passados em um array de DOMElements
266
     * @param \DOMElement $parent
267
     * @param array $arr
268
     * @return int
269
     */
270
    public function addArrayChild(DOMElement &$parent, $arr)
271
    {
272
        $num = 0;
273
        if (! empty($arr) && ! empty($parent)) {
274
            foreach ($arr as $node) {
275
                $this->appChild($parent, $node, '');
276
                $num++;
277
            }
278
        }
279
        return $num;
280
    }
281
}
282