Completed
Push — master ( 324b02...0c1c20 )
by Christopher
02:14
created

WriterContext::write()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
c 0
b 0
f 0
rs 8.8817
cc 6
nc 24
nop 2
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
//TODO: gotta find a better way to special case this in DataService.
124
        foreach ($rootNode->/** @scrutinizer ignore-call */ getAttributes($this) as $attribute) {
0 ignored issues
show
Unused Code introduced by
The call to DomBase::getAttributes() has too many arguments starting with $this.

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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

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