|
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) { |
|
|
|
|
|
|
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
|
|
|
|
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
@ignorePhpDoc annotation to the duplicate definition and it will be ignored.