Completed
Pull Request — behat-2.x (#43)
by Timothée
02:50
created

Xml::xpath()   C

Complexity

Conditions 10
Paths 12

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 24
rs 5.2164
cc 10
eloc 15
nc 12
nop 1

How to fix   Complexity   

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 Rezzza\RestApiBehatExtension\Xml;
4
5
class Xml
6
{
7
    private $content;
8
9
    public function __construct($content)
10
    {
11
        $this->parseXml($content);
12
        $this->content = $content;
13
    }
14
15
    public function read()
16
    {
17
        return $this->content;
18
    }
19
20
    public function pretty()
21
    {
22
        $dom = $this->parseXml($this->content);
23
        $dom->formatOutput = true;
24
25
        return $dom->saveXml();
26
    }
27
28
    public function isEqual(Xml $xml)
29
    {
30
        return $this->parseXml($this->content)->saveXml() === $this->parseXml($xml->read())->saveXml();
31
    }
32
33
    public function getNamespaces()
34
    {
35
        return simplexml_import_dom($this->parseXml($this->content))->getNamespaces(true);
36
    }
37
38
    public function xpath($element)
39
    {
40
        $dom = $this->parseXml($this->content);
41
        $xpath = new \DOMXpath($dom);
42
        $namespaces = $this->getNamespaces();
43
        $defaultNamespaceUri = $dom->lookupNamespaceURI(null);
44
        $defaultNamespacePrefix = $defaultNamespaceUri ? $dom->lookupPrefix($defaultNamespaceUri) : null;
45
        foreach ($namespaces as $prefix => $namespace) {
46
            if (empty($prefix) && empty($defaultNamespacePrefix) && !empty($defaultNamespaceUri)) {
47
                $prefix = 'rootns';
48
            }
49
            $xpath->registerNamespace($prefix, $namespace);
50
        }
51
52
        // "fix" queries to the default namespace if any namespaces are defined
53
        if (!empty($namespaces) && empty($defaultNamespacePrefix) && !empty($defaultNamespaceUri)) {
54
            for ($i=0; $i < 2; ++$i) {
55
                $element = preg_replace('/\/(\w+)(\[[^]]+\])?\//', '/rootns:$1$2/', $element);
56
            }
57
            $element = preg_replace('/\/(\w+)(\[[^]]+\])?$/', '/rootns:$1$2', $element);
58
        }
59
60
        return $xpath->query($element);
61
    }
62
63
    private function parseXml($content)
64
    {
65
        $dom = new \DomDocument();
66
        $dom->strictErrorChecking = false;
67
        $dom->validateOnParse = false;
68
        $dom->preserveWhiteSpace = false;
69
        $dom->formatOutput = false;
70
        $dom->loadXML($content, LIBXML_PARSEHUGE);
71
        $error = libxml_get_last_error();
72
        if (!empty($error)) {
73
            // https://bugs.php.net/bug.php?id=46465
74
            if ($error->message != 'Validation failed: no DTD found !') {
75
                throw new \DomException($error->message . ' at line ' . $error->line);
76
            }
77
        }
78
79
        return $dom;
80
    }
81
}
82