Completed
Pull Request — master (#60)
by Martin
04:23
created

XMLAdapter   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Dependencies 1

Test Coverage

Coverage 64%

Importance

Changes 0
Metric Value
wmc 14
cbo 1
dl 0
loc 93
ccs 32
cts 50
cp 0.64
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A load() 0 6 1
A createDom() 0 18 4
A dump() 0 21 4
A collectMetadata() 0 9 1
A getXmlErrors() 0 20 4
1
<?php
2
namespace Goetas\Twital\SourceAdapter;
3
4
use Goetas\Twital\SourceAdapter;
5
use Goetas\Twital\Template;
6
7
/**
8
 *
9
 * @author Asmir Mustafic <[email protected]>
10
 *
11
 */
12
class XMLAdapter implements SourceAdapter
13
{
14
    /**
15
     * {@inheritdoc}
16
     */
17 308
    public function load($source)
18
    {
19 308
        $dom = $this->createDom($source);
20
21 308
        return new Template($dom, $this->collectMetadata($dom, $source));
22
    }
23
24
    /**
25
     * {@inheritdoc}
26
     */
27 171
    public function dump(Template $template)
28
    {
29 171
        $metadata = $template->getMetadata();
30 171
        $dom = $template->getDocument();
31 171
        $dom->preserveWhiteSpace = true;
32 171
        $dom->formatOutput = false;
33
34 171
        if ($metadata['xmldeclaration']) {
35 1
            return $dom->saveXML();
36
        } else {
37 170
            $xml = '';
38 170
            foreach ($dom->childNodes as $node) {
39 169
                $xml .= $dom->saveXML($node);
40 169
                if ($node instanceof \DOMDocumentType) {
41 1
                    $xml .= PHP_EOL;
42 1
                }
43 170
            }
44
45 170
            return $xml;
46
        }
47
    }
48
49
    /**
50
     * Collect some metadata about $dom and $source
51
     * @param \DOMDocument $dom
52
     * @param string $source
53
     * @return mixed
54
     */
55 308
    protected function collectMetadata(\DOMDocument $dom, $source)
56
    {
57 308
        $metadata = array();
58
59 308
        $metadata['xmldeclaration'] = strpos(rtrim($source), '<?xml ') === 0;
60 308
        $metadata['doctype'] = !!$dom->doctype;
61
62 308
        return $metadata;
63
    }
64
65 308
    protected function createDom($source)
66
    {
67 308
        $internalErrors = libxml_use_internal_errors(true);
68 308
        $disableEntities = libxml_disable_entity_loader(true);
69 308
        libxml_clear_errors();
70
71 308
        $dom = new \DOMDocument('1.0', 'UTF-8');
72 308
        if ('' !== trim($source) && !$dom->loadXML($source, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
73
            libxml_disable_entity_loader($disableEntities);
74
75
            throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($internalErrors)));
76
        }
77
78 308
        libxml_use_internal_errors($internalErrors);
79 308
        libxml_disable_entity_loader($disableEntities);
80
81 308
        return $dom;
82
    }
83
84
    protected function getXmlErrors($internalErrors)
85
    {
86
        $errors = array();
87
        foreach (libxml_get_errors() as $error) {
88
            $errors[] = sprintf(
89
                '[%s %s] %s (in %s - line %d, column %d)',
90
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
91
                $error->code,
92
                trim($error->message),
93
                $error->file ? $error->file : 'n/a',
94
                $error->line,
95
                $error->column
96
            );
97
        }
98
99
        libxml_clear_errors();
100
        libxml_use_internal_errors($internalErrors);
101
102
        return $errors;
103
    }
104
}
105