Passed
Push — master ( 485ee1...c03365 )
by Christopher
03:50
created

WriterContext::write()   A

Complexity

Conditions 6
Paths 24

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 15
nc 24
nop 2
dl 0
loc 25
rs 9.2222
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlgoWeb\ODataMetadata\Writer;
6
7
use AlgoWeb\ODataMetadata\MetadataV3\DomBase;
8
use AlgoWeb\ODataMetadata\MetadataV3\Edm\EdmBase;
9
use AlgoWeb\ODataMetadata\OdataVersions;
10
use DOMDocument;
11
use DOMElement;
12
13
class WriterContext
14
{
15
    private $namespaceContainer;
16
17
    private $odataVersion;
18
    /**
19
     * @var DOMDocument
20
     */
21
    private $baseDocument;
22
    /**
23
     * @var array<string,string>
24
     */
25
    private $namespaceRegister = [];
26
27
    public function __construct(OdataVersions $version, DOMDocument $document = null)
28
    {
29
        $this->odataVersion = $version;
30
        $this->baseDocument = $document ?? new DOMDocument();
31
        $this->namespaceContainer = new Namespaces($version);
32
        $this->registerNamespace('edmx', $this->getEdmxNamespace());
33
        $this->registerNamespaces();
34
    }
35
36
    public function getBaseDocument(): DOMDocument
37
    {
38
        return $this->baseDocument;
39
    }
40
41
    public function getEdmNamespace()
42
    {
43
        return $this->namespaceContainer->getEdmNamespace();
44
    }
45
    public function getEdmxNamespace()
46
    {
47
        return $this->namespaceContainer->getEdmxNamespace();
48
    }
49
    public function getMetadataNamespace()
50
    {
51
        return $this->namespaceContainer->getMetadataNamespace();
52
    }
53
    public function getDataServiceNamespace()
54
    {
55
        return $this->namespaceContainer->getDataServiceNamespace();
56
    }
57
    public function getAnnotationsNamespace()
58
    {
59
        return $this->namespaceContainer->getAnnotationsNamespace();
60
    }
61
    public function getOdataVersion():string
62
    {
63
        return strval($this->odataVersion);
64
    }
65
66
    public function registerNamespace($prefix, $namespace)
67
    {
68
        $this->namespaceRegister[$prefix] = $namespace;
69
    }
70
71
    public function getNamespaceForPrefix($prefix)
72
    {
73
        return $this->namespaceRegister[$prefix];
74
    }
75
76
    protected function createElement($namespace, $name): DOMElement
77
    {
78
        return $this->baseDocument->createElementNS($namespace, $name);
79
    }
80
81
    public function createEdmElement(string $name): DOMElement
82
    {
83
        return $this->createElement($this->getEdmNamespace(), $name);
84
    }
85
    public function createEdmxElement(string $name): DOMElement
86
    {
87
        return $this->createElement($this->getEdmxNamespace(), $name);
88
    }
89
90
    public function shouldWriteV2(): bool
91
    {
92
        return
93
            $this->odataVersion == OdataVersions::TWO() ||
94
            $this->odataVersion == OdataVersions::THREE();
95
    }
96
    public function shouldWriteV3(): bool
97
    {
98
        return $this->odataVersion == OdataVersions::THREE();
99
    }
100
    public function getXml()
101
    {
102
        return $this->baseDocument->saveXML();
103
    }
104
105
    /**
106
     * @param DomBase $rootNode
107
     * @param bool $isTopLevel
108
     * @return DOMElement
109
     */
110
    public function write(DomBase $rootNode, bool $isTopLevel = true): DOMElement
111
    {
112
        $prefix = null;
113
        $qualifiedName = $rootNode->getDomName();
114
        if (strpos($qualifiedName, ':') !== false) {
115
            $prefix = substr($qualifiedName, 0, strpos($qualifiedName, ':'));
116
        }
117
        $domElement = $this->baseDocument->createElementNS($this->getNamespaceForPrefix($prefix), $qualifiedName);
118
        if ($isTopLevel) {
119
            $this->setUpNamespaces($domElement);
120
        }
121
122
        $domElement->textContent = $rootNode->getTextContent();
123
124
        foreach ($rootNode->getAttributes($this) as $attribute) {
0 ignored issues
show
Unused Code introduced by
The call to AlgoWeb\ODataMetadata\Me...omBase::getAttributes() has too many arguments starting with $this. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
        foreach ($rootNode->/** @scrutinizer ignore-call */ getAttributes($this) as $attribute) {

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
125
            if ($this->shouldWrite($attribute)) {
126
                $attribute->apply($domElement, $this);
127
            }
128
        }
129
        foreach (array_filter($rootNode->getChildElements()) as $childNode) {
130
            $childElement = $this->write($childNode, false);
131
132
            $domElement->appendChild($childElement);
133
        }
134
        return $domElement;
135
    }
136
137
    protected function shouldWrite(IAttribute $attribute)
138
    {
139
        return
140
            (
141
                OdataVersions::TWO() == $attribute->getAttributeForVersion() && $this->shouldWriteV2() ||
142
                OdataVersions::THREE() == $attribute->getAttributeForVersion() && $this->shouldWriteV3() ||
143
                OdataVersions::ONE() == $attribute->getAttributeForVersion()
144
            ) &&
145
            !in_array($this->getOdataVersion(), $attribute->getAttributeProhibitedVersion());
146
    }
147
148
    private function registerNamespaces()
149
    {
150
        $this->registerNamespace(null, $this->getEdmNamespace());
151
        $this->registerNamespace("annotations", $this->getAnnotationsNamespace());
152
        $this->registerNamespace('metadata', $this->getMetadataNamespace());
153
        $this->registerNamespace('edmx', $this->getEdmxNamespace());
154
    }
155
156
    private function setUpNamespaces(DOMElement $rootElement)
157
    {
158
        foreach ($this->namespaceRegister as $prefix => $namespace) {
159
            $qualifiedName = $prefix === "" ? 'xmlns' : 'xmlns:' . $prefix;
160
            $rootElement->setAttributeNS(
161
                'http://www.w3.org/2000/xmlns/',
162
                $qualifiedName,
163
                $namespace
164
            );
165
        }
166
    }
167
}
168