Passed
Push — master ( 463105...84cd59 )
by Roberto
04:47
created

DOMImproved::loadXMLFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 9
ccs 0
cts 9
cp 0
rs 9.6666
cc 2
eloc 6
nc 2
nop 1
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 DOMElement;
19
20
class DOMImproved extends DOMDocument
21
{
22
    /**
23
     * @var array
24
     */
25
    public $error = [];
26
    
27
    /**
28
     * @param string $version
29
     * @param string $charset
30
     */
31
    public function __construct($version = '1.0', $charset = 'utf-8')
32
    {
33
        parent::__construct($version, $charset);
34
        $this->formatOutput = false;
35
        $this->preserveWhiteSpace = false;
36
    }
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->error[] = $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->error[] = '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 se existir ou string vazia se não
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 $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
        $content = trim($content);
158
        if ($obrigatorio && $content === '' && !$force) {
159
            $this->erros[] = "Preenchimento Obrigatório! [$name] $descricao";
0 ignored issues
show
Bug introduced by
The property erros 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...
160
        }
161
        if ($obrigatorio || $content !== '' || $force) {
162
            $content = htmlspecialchars($content, ENT_QUOTES);
163
            $temp = $this->createElement($name, $content);
164
            $parent->appendChild($temp);
165
        }
166
    }
167
    
168
    /**
169
     * Acrescenta DOMElement a pai DOMElement
170
     * Caso o pai esteja vazio retorna uma exception com a mensagem
171
     * O parametro "child" pode ser vazio
172
     * @param DOMElement $parent
173
     * @param DOMElement $child
174
     * @param string $msg
175
     * @return void
176
     */
177
    public function appChild(DOMElement &$parent, DOMElement $child = null, $msg = '')
178
    {
179
        if (empty($child)) {
180
            $this->erros[] = $msg;
181
            return;
182
        }
183
        $parent->appendChild($child);
184
    }
185
    
186
    /**
187
     * Append DOMElement from external documento to local Node
188
     * @param DOMElement $parent
189
     * @param DOMElement $child
190
     */
191
    public function appExternalChild(DOMElement &$parent, DOMElement $child)
192
    {
193
        $node = $this->importNode($child, true);
194
        $parent->appendChild($node);
195
    }
196
    
197
    /**
198
     * Append DOMElement from external documento to local Node
199
     * before existent node
200
     * @param DOMElement $parent
201
     * @param DOMElement $child
202
     * @param string $before
203
     * @return void
204
     */
205
    public function appExternalChildBefore(
206
        DOMElement &$parent,
207
        DOMElement $child,
208
        $before
209
    ) {
210
        if (empty($bnode = $parent->getElementsByTagName($before)->item(0))) {
211
            return;
212
        }
213
        $node = $this->importNode($child, true);
214
        $parent->insertBefore($node, $bnode);
215
    }
216
        
217
    /**
218
     * appChildBefore
219
     * Acrescenta DOMElement a pai DOMElement
220
     * Caso o pai esteja vazio retorna uma exception com a mensagem
221
     * O parametro "child" pode ser vazio
222
     * @param DOMElement $parent
223
     * @param DOMElement $child
224
     * @param string $before
225
     * @param string $msg
226
     * @return void
227
     */
228
    public function appChildBefore(DOMElement &$parent, DOMElement $child = null, $before = '', $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...
229
    {
230
        if (empty($child) ||
231
            empty($before) ||
232
            empty($bnode = $parent->getElementsByTagName($before)->item(0))
233
        ) {
234
            $this->error[] = "Node child vazio ou node <$before> não encontrado!!";
235
            return;
236
        }
237
        $parent->insertBefore($child, $bnode);
238
    }
239
    
240
    /**
241
     * addArrayChild
242
     * Adiciona a um DOMElemt parent, outros elementos passados em um array de DOMElements
243
     * @param DOMElement $parent
244
     * @param array $arr
245
     * @return int
246
     */
247
    public function addArrayChild(DOMElement &$parent, $arr)
248
    {
249
        $num = 0;
250
        if (! empty($arr) && ! empty($parent)) {
251
            foreach ($arr as $node) {
252
                $this->appChild($parent, $node, '');
253
                $num++;
254
            }
255
        }
256
        return $num;
257
    }
258
}
259