1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace POData\Writers\Atom; |
4
|
|
|
|
5
|
|
|
use Carbon\Carbon as Carbon; |
6
|
|
|
use POData\Common\MimeTypes; |
7
|
|
|
use POData\Common\ODataConstants; |
8
|
|
|
use POData\Common\ODataException; |
9
|
|
|
use POData\Common\Version; |
10
|
|
|
use POData\ObjectModel\ODataBagContent; |
11
|
|
|
use POData\ObjectModel\ODataEntry; |
12
|
|
|
use POData\ObjectModel\ODataFeed; |
13
|
|
|
use POData\ObjectModel\ODataLink; |
14
|
|
|
use POData\ObjectModel\ODataProperty; |
15
|
|
|
use POData\ObjectModel\ODataPropertyContent; |
16
|
|
|
use POData\ObjectModel\ODataURL; |
17
|
|
|
use POData\ObjectModel\ODataURLCollection; |
18
|
|
|
use POData\Providers\ProvidersWrapper; |
19
|
|
|
use POData\Writers\IODataWriter; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Class AtomODataWriter. |
23
|
|
|
*/ |
24
|
|
|
class AtomODataWriter implements IODataWriter |
25
|
|
|
{ |
26
|
|
|
/** |
27
|
|
|
* Writer to which output (CSDL Document) is sent. |
28
|
|
|
* |
29
|
|
|
* @var \XMLWriter |
30
|
|
|
*/ |
31
|
|
|
public $xmlWriter; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* The service base uri. |
35
|
|
|
* |
36
|
|
|
* @var string |
37
|
|
|
*/ |
38
|
|
|
protected $baseUri; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Construct a new instance of AtomODataWriter. |
42
|
|
|
* |
43
|
|
|
* @param string $absoluteServiceUri The absolute service Uri |
44
|
|
|
*/ |
45
|
|
|
public function __construct($absoluteServiceUri) |
46
|
|
|
{ |
47
|
|
|
$final = substr($absoluteServiceUri, -1); |
48
|
|
|
if ('/' != $final) { |
49
|
|
|
$absoluteServiceUri .= '/'; |
50
|
|
|
} |
51
|
|
|
$this->baseUri = $absoluteServiceUri; |
52
|
|
|
|
53
|
|
|
$this->xmlWriter = new \XMLWriter(); |
54
|
|
|
$this->xmlWriter->openMemory(); |
55
|
|
|
$this->xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); |
56
|
|
|
$this->xmlWriter->setIndent(4); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Determines if the given writer is capable of writing the response or not. |
61
|
|
|
* |
62
|
|
|
* @param Version $responseVersion the OData version of the response |
63
|
|
|
* @param string $contentType the Content Type of the response |
64
|
|
|
* |
65
|
|
|
* @return bool true if the writer can handle the response, false otherwise |
66
|
|
|
*/ |
67
|
|
|
public function canHandle(Version $responseVersion, $contentType) |
68
|
|
|
{ |
69
|
|
|
$parts = explode(';', $contentType); |
70
|
|
|
|
71
|
|
|
//first 2 parts are for service documents, second part is for Resources |
72
|
|
|
//TODO: i'm not sold about this first part not being constrained to v1 (or maybe v2)..but it's how WS DS works. See #94 |
73
|
|
|
return in_array(MimeTypes::MIME_APPLICATION_XML, $parts) || in_array(MimeTypes::MIME_APPLICATION_ATOMSERVICE, $parts) || in_array(MimeTypes::MIME_APPLICATION_ATOM, $parts); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Write the given OData model in a specific response format. |
78
|
|
|
* |
79
|
|
|
* @param ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content |
80
|
|
|
* |
81
|
|
|
* @return AtomODataWriter |
82
|
|
|
*/ |
83
|
|
|
public function write($model) |
84
|
|
|
{ |
85
|
|
|
if ($model instanceof ODataURL) { |
86
|
|
|
return $this->writeURL($model); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
if ($model instanceof ODataURLCollection) { |
90
|
|
|
return $this->writeURLCollection($model); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
if ($model instanceof ODataPropertyContent) { |
94
|
|
|
return $this->writeProperties($model, true); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
if ($model instanceof ODataFeed) { |
98
|
|
|
return $this->writeFeed($model, true); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
if ($model instanceof ODataEntry) { |
102
|
|
|
return $this->writeEntry($model, true); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
return $this; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @param ODataURL $url the url to write |
110
|
|
|
* |
111
|
|
|
* @return AtomODataWriter |
112
|
|
|
*/ |
113
|
|
|
protected function writeURL(ODataURL $url) |
114
|
|
|
{ |
115
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_URI_ELEMENT_NAME); |
116
|
|
|
$this->xmlWriter->writeAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_NAMESPACE); |
117
|
|
|
$this->xmlWriter->text($url->url); |
118
|
|
|
$this->xmlWriter->endElement(); |
119
|
|
|
|
120
|
|
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Begin write odata links. |
125
|
|
|
* |
126
|
|
|
* @param ODataURLCollection $urls Object of ODataUrlCollection to start writing collection of url |
127
|
|
|
* |
128
|
|
|
* @return AtomODataWriter |
129
|
|
|
*/ |
130
|
|
|
public function writeUrlCollection(ODataURLCollection $urls) |
131
|
|
|
{ |
132
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_LINKS_ELEMENT_NAME); |
133
|
|
|
$this->xmlWriter->writeAttribute( |
134
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
135
|
|
|
ODataConstants::ODATA_NAMESPACE |
136
|
|
|
); |
137
|
|
|
$this->xmlWriter->endAttribute(); |
138
|
|
|
if ($urls->count != null) { |
139
|
|
|
$this->xmlWriter->writeAttributeNs( |
140
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
141
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
142
|
|
|
null, |
143
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE |
144
|
|
|
); |
145
|
|
|
$this->xmlWriter->endAttribute(); |
146
|
|
|
$this->xmlWriter->startElementNs( |
147
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
148
|
|
|
ODataConstants::ROWCOUNT_ELEMENT, |
149
|
|
|
null |
150
|
|
|
); |
151
|
|
|
$this->xmlWriter->text($urls->count); |
152
|
|
|
$this->xmlWriter->endElement(); |
153
|
|
|
} |
154
|
|
|
foreach ($urls->urls as $url) { |
155
|
|
|
$this->writeNodeValue(ODataConstants::ATOM_URI_ELEMENT_NAME, $url->url); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
if ($urls->nextPageLink != null) { |
159
|
|
|
$this->writeLinkNode($urls->nextPageLink, false); |
160
|
|
|
} |
161
|
|
|
$this->xmlWriter->endElement(); |
162
|
|
|
|
163
|
|
|
return $this; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Begin write OData Feed. |
168
|
|
|
* |
169
|
|
|
* @param ODataFeed $feed Object of OData feed to start writing feed |
170
|
|
|
* @param bool $isTopLevel indicates if this is the top level feed in the response |
171
|
|
|
* |
172
|
|
|
* @return AtomODataWriter |
173
|
|
|
*/ |
174
|
|
|
protected function writeFeed(ODataFeed $feed, $isTopLevel = false) |
175
|
|
|
{ |
176
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_FEED_ELEMENT_NAME); |
177
|
|
|
if ($isTopLevel) { |
178
|
|
|
$this->writeBaseUriAndDefaultNamespaces(); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$this |
182
|
|
|
->writeNodeAttributeValue( |
183
|
|
|
ODataConstants::ATOM_TITLE_ELELMET_NAME, |
184
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
185
|
|
|
MimeTypes::MIME_TEXTTYPE, |
186
|
|
|
$feed->title |
187
|
|
|
) |
188
|
|
|
->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $feed->id) |
189
|
|
|
->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, date(DATE_ATOM)) |
190
|
|
|
->writeLinkNode($feed->selfLink, false); |
191
|
|
|
|
192
|
|
|
if ($feed->rowCount != null) { |
193
|
|
|
$this->xmlWriter->startElementNs( |
194
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
195
|
|
|
ODataConstants::ROWCOUNT_ELEMENT, |
196
|
|
|
null |
197
|
|
|
); |
198
|
|
|
$this->xmlWriter->text($feed->rowCount); |
199
|
|
|
$this->xmlWriter->endElement(); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
foreach ($feed->entries as $entry) { |
203
|
|
|
$this->writeEntry($entry); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
if ($feed->nextPageLink != null) { |
207
|
|
|
$this->writeLinkNode($feed->nextPageLink, false); |
208
|
|
|
} |
209
|
|
|
$this->xmlWriter->endElement(); |
210
|
|
|
|
211
|
|
|
return $this; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Write top level entry. |
216
|
|
|
* |
217
|
|
|
* @param ODataEntry $entry Object of ODataEntry |
218
|
|
|
* @param bool $isTopLevel |
219
|
|
|
* |
220
|
|
|
* @return AtomODataWriter |
221
|
|
|
*/ |
222
|
|
|
protected function writeEntry(ODataEntry $entry, $isTopLevel = false) |
223
|
|
|
{ |
224
|
|
|
$this->writeBeginEntry($entry, $isTopLevel); |
225
|
|
|
foreach ($entry->links as $link) { |
226
|
|
|
$this->writeLink($link); |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
$this |
230
|
|
|
->preWriteProperties($entry) |
231
|
|
|
->writeProperties($entry->propertyContent) |
232
|
|
|
->postWriteProperties($entry); |
233
|
|
|
|
234
|
|
|
$this->xmlWriter->endElement(); |
235
|
|
|
|
236
|
|
|
return $this; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Start writing a entry. |
241
|
|
|
* |
242
|
|
|
* @param ODataEntry $entry Entry to write |
243
|
|
|
* @param bool $isTopLevel |
244
|
|
|
* |
245
|
|
|
* @return AtomODataWriter |
246
|
|
|
*/ |
247
|
|
|
protected function writeBeginEntry(ODataEntry $entry, $isTopLevel) |
248
|
|
|
{ |
249
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_ENTRY_ELEMENT_NAME); |
250
|
|
|
if ($isTopLevel) { |
251
|
|
|
$this->writeBaseUriAndDefaultNamespaces(); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
View Code Duplication |
if (!is_null($entry->eTag)) { |
|
|
|
|
255
|
|
|
$this->xmlWriter->startAttributeNs( |
256
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
257
|
|
|
ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME, |
258
|
|
|
null |
259
|
|
|
); |
260
|
|
|
$this->xmlWriter->text($entry->eTag); |
261
|
|
|
$this->xmlWriter->endAttribute(); |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$this |
265
|
|
|
->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $entry->id) |
266
|
|
|
->writeNodeAttributeValue( |
267
|
|
|
ODataConstants::ATOM_TITLE_ELELMET_NAME, |
268
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
269
|
|
|
MimeTypes::MIME_TEXTTYPE, |
270
|
|
|
$entry->title |
271
|
|
|
) |
272
|
|
|
->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, date(DATE_ATOM)); |
273
|
|
|
|
274
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_AUTHOR_ELEMENT_NAME); |
275
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_NAME_ELEMENT_NAME); |
276
|
|
|
$this->xmlWriter->endElement(); |
277
|
|
|
$this->xmlWriter->endElement(); |
278
|
|
|
|
279
|
|
|
|
280
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME); |
281
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME); |
282
|
|
|
$this->xmlWriter->text(ODataConstants::ATOM_EDIT_RELATION_ATTRIBUTE_VALUE); |
283
|
|
|
$this->xmlWriter->endAttribute(); |
284
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME); |
285
|
|
|
$this->xmlWriter->text($entry->title); |
286
|
|
|
$this->xmlWriter->endAttribute(); |
287
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME); |
288
|
|
|
if (is_string($entry->editLink)) { |
289
|
|
|
$this->xmlWriter->text($entry->editLink); |
290
|
|
|
} else { |
291
|
|
|
$this->xmlWriter->text($entry->editLink->url); |
292
|
|
|
} |
293
|
|
|
$this->xmlWriter->endAttribute(); |
294
|
|
|
|
295
|
|
|
$this->xmlWriter->endElement(); |
296
|
|
|
|
297
|
|
|
|
298
|
|
|
if ($entry->isMediaLinkEntry) { |
299
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME); |
300
|
|
View Code Duplication |
if ($entry->mediaLink->eTag != null) { |
|
|
|
|
301
|
|
|
$this->xmlWriter->startAttributeNs( |
302
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
303
|
|
|
ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME, |
304
|
|
|
null |
305
|
|
|
); |
306
|
|
|
$this->xmlWriter->text($entry->mediaLink->eTag); |
307
|
|
|
$this->xmlWriter->endAttribute(); |
308
|
|
|
} |
309
|
|
|
$this->xmlWriter->startAttribute( |
310
|
|
|
ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME |
311
|
|
|
); |
312
|
|
|
$this->xmlWriter->text(ODataConstants::ATOM_EDIT_MEDIA_RELATION_ATTRIBUTE_VALUE); |
313
|
|
|
$this->xmlWriter->endAttribute(); |
314
|
|
|
|
315
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME); |
316
|
|
|
$this->xmlWriter->text($entry->mediaLink->contentType); |
317
|
|
|
$this->xmlWriter->endAttribute(); |
318
|
|
|
|
319
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME); |
320
|
|
|
$this->xmlWriter->text($entry->mediaLink->name); |
321
|
|
|
$this->xmlWriter->endAttribute(); |
322
|
|
|
|
323
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME); |
324
|
|
|
$this->xmlWriter->text($entry->mediaLink->editLink); |
325
|
|
|
$this->xmlWriter->endAttribute(); |
326
|
|
|
$this->xmlWriter->endElement(); |
327
|
|
|
|
328
|
|
|
|
329
|
|
|
foreach ($entry->mediaLinks as $mediaLink) { |
330
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME); |
331
|
|
View Code Duplication |
if ($mediaLink->eTag != null) { |
|
|
|
|
332
|
|
|
$this->xmlWriter->startAttributeNs( |
333
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
334
|
|
|
ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME, |
335
|
|
|
null |
336
|
|
|
); |
337
|
|
|
$this->xmlWriter->text($mediaLink->eTag); |
338
|
|
|
$this->xmlWriter->endAttribute(); |
339
|
|
|
} |
340
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME); |
341
|
|
|
$this->xmlWriter->text( |
342
|
|
|
'http://schemas.microsoft.com/ado/2007/08/dataservices/mediaresource/' |
343
|
|
|
.$mediaLink->name |
344
|
|
|
); |
345
|
|
|
$this->xmlWriter->endAttribute(); |
346
|
|
|
|
347
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME); |
348
|
|
|
$this->xmlWriter->text($mediaLink->contentType); |
349
|
|
|
$this->xmlWriter->endAttribute(); |
350
|
|
|
|
351
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME); |
352
|
|
|
$this->xmlWriter->text($mediaLink->name); |
353
|
|
|
$this->xmlWriter->endAttribute(); |
354
|
|
|
|
355
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME); |
356
|
|
|
$this->xmlWriter->text($mediaLink->editLink); |
357
|
|
|
$this->xmlWriter->endAttribute(); |
358
|
|
|
$this->xmlWriter->endElement(); |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $this; |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* @param ODataLink $link Link to write |
367
|
|
|
* |
368
|
|
|
* @return AtomODataWriter |
369
|
|
|
*/ |
370
|
|
|
protected function writeLink(ODataLink $link) |
371
|
|
|
{ |
372
|
|
|
$this->writeLinkNode($link, $link->isExpanded); |
373
|
|
|
|
374
|
|
|
if ($link->isExpanded) { |
375
|
|
|
$this->xmlWriter->startElementNS( |
376
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
377
|
|
|
ODataConstants::ATOM_INLINE_ELEMENT_NAME, |
378
|
|
|
null |
379
|
|
|
); |
380
|
|
|
|
381
|
|
|
if (!is_null($link->expandedResult)) { |
382
|
|
|
if ($link->isCollection) { |
383
|
|
|
$this->writeFeed($link->expandedResult); |
|
|
|
|
384
|
|
|
} else { |
385
|
|
|
$this->writeEntry($link->expandedResult); |
|
|
|
|
386
|
|
|
} |
387
|
|
|
} |
388
|
|
|
|
389
|
|
|
$this->xmlWriter->endElement(); |
390
|
|
|
$this->xmlWriter->endElement(); |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
return $this; |
394
|
|
|
} |
395
|
|
|
|
396
|
|
|
/** |
397
|
|
|
* Write the given collection of properties. |
398
|
|
|
* (properties of an entity or complex type). |
399
|
|
|
* |
400
|
|
|
* @param ODataPropertyContent $properties Collection of properties |
401
|
|
|
* @param bool $topLevel indicates if this property content is the top level response to be written |
402
|
|
|
* |
403
|
|
|
* @return AtomODataWriter |
404
|
|
|
*/ |
405
|
|
|
protected function writeProperties(ODataPropertyContent $properties, $topLevel = false) |
406
|
|
|
{ |
407
|
|
|
foreach ($properties->properties as $property) { |
408
|
|
|
$this->beginWriteProperty($property, $topLevel); |
409
|
|
|
|
410
|
|
|
if ($property->value == null) { |
411
|
|
|
$this->writeNullValue($property); |
412
|
|
|
} elseif ($property->value instanceof ODataPropertyContent) { |
413
|
|
|
$this->writeProperties($property->value, false); |
414
|
|
|
} elseif ($property->value instanceof ODataBagContent) { |
415
|
|
|
$this->writeBagContent($property->value); |
416
|
|
|
} else { |
417
|
|
|
$value = $this->beforeWriteValue($property->value, $property->typeName); |
418
|
|
|
$this->xmlWriter->text($value); |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
$this->xmlWriter->endElement(); |
422
|
|
|
} |
423
|
|
|
|
424
|
|
|
return $this; |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* XML write a basic data type (string, number, boolean, null). |
429
|
|
|
* |
430
|
|
|
* @param string $value value to be written |
431
|
|
|
* @param string $type data type of the value |
432
|
|
|
* |
433
|
|
|
* @return string |
434
|
|
|
*/ |
435
|
|
|
protected function beforeWriteValue($value, $type = null) |
436
|
|
|
{ |
437
|
|
|
switch ($type) { |
438
|
|
|
case 'Edm.DateTime': |
439
|
|
|
$dateTime = new Carbon($value, new \DateTimeZone('UTC')); |
440
|
|
|
$result = $dateTime->format('Y-m-d\TH:i:s'); |
441
|
|
|
break; |
442
|
|
|
|
443
|
|
|
default: |
444
|
|
|
$result = $value; |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
return $result; |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Write the node which hold the entity properties as child. |
452
|
|
|
* |
453
|
|
|
* @param ODataEntry $entry ODataEntry object for pre writing properties |
454
|
|
|
* |
455
|
|
|
* @return AtomODataWriter |
456
|
|
|
*/ |
457
|
|
|
public function preWriteProperties(ODataEntry $entry) |
458
|
|
|
{ |
459
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_CATEGORY_ELEMENT_NAME); |
460
|
|
|
$this->xmlWriter->writeAttribute( |
461
|
|
|
ODataConstants::ATOM_CATEGORY_TERM_ATTRIBUTE_NAME, |
462
|
|
|
$entry->type |
463
|
|
|
); |
464
|
|
|
$this->xmlWriter->writeAttribute( |
465
|
|
|
ODataConstants::ATOM_CATEGORY_SCHEME_ATTRIBUTE_NAME, |
466
|
|
|
ODataConstants::ODATA_SCHEME_NAMESPACE |
467
|
|
|
); |
468
|
|
|
$this->xmlWriter->endElement(); |
469
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_CONTENT_ELEMENT_NAME); |
470
|
|
|
if ($entry->isMediaLinkEntry) { |
471
|
|
|
$this->xmlWriter->writeAttribute( |
472
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
473
|
|
|
$entry->mediaLink->contentType |
474
|
|
|
); |
475
|
|
|
$this->xmlWriter->writeAttribute( |
476
|
|
|
ODataConstants::ATOM_CONTENT_SRC_ATTRIBUTE_NAME, |
477
|
|
|
$entry->mediaLink->srcLink |
478
|
|
|
); |
479
|
|
|
$this->xmlWriter->endElement(); |
480
|
|
|
$this->xmlWriter->startElementNS( |
481
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
482
|
|
|
ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME, |
483
|
|
|
null |
484
|
|
|
); |
485
|
|
|
} else { |
486
|
|
|
$this->xmlWriter->writeAttribute( |
487
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
488
|
|
|
MimeTypes::MIME_APPLICATION_XML |
489
|
|
|
); |
490
|
|
|
$this->xmlWriter->startElementNS( |
491
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
492
|
|
|
ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME, |
493
|
|
|
null |
494
|
|
|
); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
return $this; |
498
|
|
|
} |
499
|
|
|
|
500
|
|
|
/** |
501
|
|
|
* Write a property. |
502
|
|
|
* |
503
|
|
|
* @param ODataProperty $property Property to be written |
504
|
|
|
* @param bool $isTopLevel is link top level or not |
505
|
|
|
* |
506
|
|
|
* @return AtomODataWriter |
507
|
|
|
*/ |
508
|
|
|
protected function beginWriteProperty(ODataProperty $property, $isTopLevel) |
509
|
|
|
{ |
510
|
|
|
$this->xmlWriter->startElementNS( |
511
|
|
|
ODataConstants::ODATA_NAMESPACE_PREFIX, |
512
|
|
|
$property->name, |
513
|
|
|
null |
514
|
|
|
); |
515
|
|
|
if ($property->typeName != null) { |
516
|
|
|
$this->xmlWriter->startAttributeNs( |
517
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
518
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
519
|
|
|
null |
520
|
|
|
); |
521
|
|
|
$this->xmlWriter->text($property->typeName); |
522
|
|
|
} |
523
|
|
|
if ($isTopLevel) { |
524
|
|
|
$this->xmlWriter->startAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX); |
525
|
|
|
$this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE); |
526
|
|
|
$this->xmlWriter->startAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_NAMESPACE_PREFIX, null); |
527
|
|
|
$this->xmlWriter->text(ODataConstants::ODATA_NAMESPACE); |
528
|
|
|
$this->xmlWriter->startAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, null); |
529
|
|
|
$this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE); |
530
|
|
|
} |
531
|
|
|
if ($property->typeName != null || $isTopLevel) { |
532
|
|
|
$this->xmlWriter->endAttribute(); |
533
|
|
|
} |
534
|
|
|
|
535
|
|
|
return $this; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
/** |
539
|
|
|
* Write after last property. |
540
|
|
|
* |
541
|
|
|
* @param ODataEntry $entry Entry object to post writing properties |
542
|
|
|
* |
543
|
|
|
* @return AtomODataWriter |
544
|
|
|
*/ |
545
|
|
|
public function postWriteProperties(ODataEntry $entry) |
546
|
|
|
{ |
547
|
|
|
if (!$entry->isMediaLinkEntry) { |
548
|
|
|
$this->xmlWriter->endElement(); |
549
|
|
|
} |
550
|
|
|
$this->xmlWriter->endElement(); |
551
|
|
|
|
552
|
|
|
return $this; |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
/** |
556
|
|
|
* Begin an item in a collection. |
557
|
|
|
* |
558
|
|
|
* @param ODataBagContent $bag Bag property object to begin write property |
559
|
|
|
* |
560
|
|
|
* @return AtomODataWriter |
561
|
|
|
*/ |
562
|
|
|
protected function writeBagContent(ODataBagContent $bag) |
563
|
|
|
{ |
564
|
|
|
foreach ($bag->propertyContents as $content) { |
565
|
|
|
if ($content instanceof ODataPropertyContent) { |
566
|
|
|
$this->xmlWriter->startElementNs( |
567
|
|
|
ODataConstants::ODATA_NAMESPACE_PREFIX, |
568
|
|
|
ODataConstants::COLLECTION_ELEMENT_NAME, |
569
|
|
|
null |
570
|
|
|
); |
571
|
|
|
$this->writeProperties($content); |
572
|
|
|
$this->xmlWriter->endElement(); |
573
|
|
|
} else { //probably just a primitive string |
574
|
|
|
$this->xmlWriter->startElementNs( |
575
|
|
|
ODataConstants::ODATA_NAMESPACE_PREFIX, |
576
|
|
|
ODataConstants::COLLECTION_ELEMENT_NAME, |
577
|
|
|
null |
578
|
|
|
); |
579
|
|
|
$this->xmlWriter->text($content); |
580
|
|
|
$this->xmlWriter->endElement(); |
581
|
|
|
} |
582
|
|
|
} |
583
|
|
|
|
584
|
|
|
return $this; |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
/** |
588
|
|
|
* Write null value. |
589
|
|
|
* |
590
|
|
|
* @param ODataProperty $property ODataProperty object to write null value |
591
|
|
|
* according to property type |
592
|
|
|
* |
593
|
|
|
* @return AtomODataWriter |
594
|
|
|
*/ |
595
|
|
|
protected function writeNullValue(ODataProperty $property) |
596
|
|
|
{ |
597
|
|
|
if (!(($property instanceof ODataBagContent) || ($property instanceof ODataPropertyContent))) { |
598
|
|
|
$this->xmlWriter->writeAttributeNs( |
599
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
600
|
|
|
ODataConstants::ATOM_NULL_ATTRIBUTE_NAME, |
601
|
|
|
null, |
602
|
|
|
ODataConstants::XML_TRUE_LITERAL |
603
|
|
|
); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
return $this; |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
/** |
610
|
|
|
* Get the final result as string. |
611
|
|
|
* |
612
|
|
|
* @return string output of requested data in Atom format |
613
|
|
|
*/ |
614
|
|
|
public function getOutput() |
615
|
|
|
{ |
616
|
|
|
$this->xmlWriter->endDocument(); |
617
|
|
|
|
618
|
|
|
return $this->xmlWriter->outputMemory(true); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
/** |
622
|
|
|
* Serialize the exception. |
623
|
|
|
* |
624
|
|
|
* @param ODataException $exception Exception to serialize |
625
|
|
|
* @param bool $serializeInnerException if set to true, |
626
|
|
|
* serialize the inner exception if $exception is an ODataException |
627
|
|
|
* |
628
|
|
|
* @return string |
629
|
|
|
*/ |
630
|
|
|
public static function serializeException(ODataException $exception, $serializeInnerException) |
|
|
|
|
631
|
|
|
{ |
632
|
|
|
$xmlWriter = new \XMLWriter(); |
633
|
|
|
$xmlWriter->openMemory(); |
634
|
|
|
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); |
635
|
|
|
$xmlWriter->setIndent(4); |
636
|
|
|
|
637
|
|
|
$xmlWriter->startElement(ODataConstants::XML_ERROR_ELEMENT_NAME); |
638
|
|
|
//$xmlWriter->writeAttributeNs( |
639
|
|
|
// ODataConstants::XMLNS_NAMESPACE_PREFIX, |
640
|
|
|
// ODataConstants::XML_NAMESPACE_PREFIX, |
641
|
|
|
// ODataConstants::XML_NAMESPACE, |
642
|
|
|
// null |
643
|
|
|
//); |
644
|
|
|
$xmlWriter->writeAttribute( |
645
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
646
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE |
647
|
|
|
); |
648
|
|
|
$xmlWriter->endAttribute(); |
649
|
|
|
$xmlWriter->startElement(ODataConstants::XML_ERROR_CODE_ELEMENT_NAME); |
650
|
|
|
if (null != $exception->getStatusCode()) { |
651
|
|
|
$xmlWriter->text($exception->getStatusCode()); |
652
|
|
|
} |
653
|
|
|
$xmlWriter->endElement(); |
654
|
|
|
$xmlWriter->startElement(ODataConstants::XML_ERROR_MESSAGE_ELEMENT_NAME); |
655
|
|
|
$xmlWriter->text($exception->getMessage()); |
656
|
|
|
$xmlWriter->endElement(); |
657
|
|
|
$xmlWriter->endElement(); |
658
|
|
|
$xmlWriter->endDocument(); |
659
|
|
|
|
660
|
|
|
return $xmlWriter->outputMemory(true); |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* Function to create element only contain value without argument. |
665
|
|
|
* |
666
|
|
|
* @param string $node Element name |
667
|
|
|
* @param string $value Element value |
668
|
|
|
* |
669
|
|
|
* @return AtomODataWriter |
670
|
|
|
*/ |
671
|
|
|
public function writeNodeValue($node, $value) |
672
|
|
|
{ |
673
|
|
|
$this->xmlWriter->startElement($node); |
674
|
|
|
$this->xmlWriter->text($value); |
675
|
|
|
$this->xmlWriter->endElement(); |
676
|
|
|
|
677
|
|
|
return $this; |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
/** |
681
|
|
|
* Function to create element with one attribute and value. |
682
|
|
|
* |
683
|
|
|
* @param string $node Element name |
684
|
|
|
* @param string $attribute Attribute name |
685
|
|
|
* @param string $attributeValue Attribute value |
686
|
|
|
* @param string $nodeValue Element value |
687
|
|
|
* |
688
|
|
|
* @return AtomODataWriter |
689
|
|
|
*/ |
690
|
|
|
public function writeNodeAttributeValue( |
691
|
|
|
$node, |
692
|
|
|
$attribute, |
693
|
|
|
$attributeValue, |
694
|
|
|
$nodeValue |
695
|
|
|
) { |
696
|
|
|
$this->xmlWriter->startElement($node); |
697
|
|
|
$this->xmlWriter->writeAttribute($attribute, $attributeValue); |
698
|
|
|
$this->xmlWriter->text($nodeValue); |
699
|
|
|
$this->xmlWriter->endElement(); |
700
|
|
|
|
701
|
|
|
return $this; |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* Function to create link element with arguments. |
706
|
|
|
* |
707
|
|
|
* @param ODataLink $link Link object to make link element |
708
|
|
|
* @param bool $isExpanded Is link expanded or not |
709
|
|
|
* |
710
|
|
|
* @return AtomODataWriter |
711
|
|
|
*/ |
712
|
|
|
protected function writeLinkNode(ODataLink $link, $isExpanded) |
713
|
|
|
{ |
714
|
|
|
$this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME); |
715
|
|
|
$this->xmlWriter->writeAttribute( |
716
|
|
|
ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME, |
717
|
|
|
$link->name |
718
|
|
|
); |
719
|
|
|
if ($link->type != null) { |
720
|
|
|
$this->xmlWriter->writeAttribute( |
721
|
|
|
ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME, |
722
|
|
|
$link->type |
723
|
|
|
); |
724
|
|
|
} |
725
|
|
|
if ($link->title != null) { |
726
|
|
|
$this->xmlWriter->writeAttribute( |
727
|
|
|
ODataConstants::ATOM_TITLE_ELELMET_NAME, |
728
|
|
|
$link->title |
729
|
|
|
); |
730
|
|
|
} |
731
|
|
|
$this->xmlWriter->writeAttribute( |
732
|
|
|
ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, |
733
|
|
|
$link->url |
734
|
|
|
); |
735
|
|
|
if (!$isExpanded) { |
736
|
|
|
$this->xmlWriter->endElement(); |
737
|
|
|
} |
738
|
|
|
|
739
|
|
|
return $this; |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
/** |
743
|
|
|
* Function to write base uri and default namespaces for top level elements. |
744
|
|
|
* |
745
|
|
|
* @return AtomODataWriter |
746
|
|
|
*/ |
747
|
|
|
public function writeBaseUriAndDefaultNamespaces() |
748
|
|
|
{ |
749
|
|
|
$this->xmlWriter->writeAttribute( |
750
|
|
|
ODataConstants::XML_BASE_ATTRIBUTE_NAME_WITH_PREFIX, |
751
|
|
|
$this->baseUri |
752
|
|
|
); |
753
|
|
|
$this->xmlWriter->writeAttributeNs( |
754
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
755
|
|
|
ODataConstants::ODATA_NAMESPACE_PREFIX, |
756
|
|
|
null, |
757
|
|
|
ODataConstants::ODATA_NAMESPACE |
758
|
|
|
); |
759
|
|
|
$this->xmlWriter->writeAttributeNs( |
760
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
761
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX, |
762
|
|
|
null, |
763
|
|
|
ODataConstants::ODATA_METADATA_NAMESPACE |
764
|
|
|
); |
765
|
|
|
$this->xmlWriter->writeAttribute( |
766
|
|
|
ODataConstants::XMLNS_NAMESPACE_PREFIX, |
767
|
|
|
ODataConstants::ATOM_NAMESPACE |
768
|
|
|
); |
769
|
|
|
|
770
|
|
|
return $this; |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
/** |
774
|
|
|
* XML prefix for the Atom namespace. |
775
|
|
|
* |
776
|
|
|
* @var string |
777
|
|
|
*/ |
778
|
|
|
const ATOM_NAMESPACE_PREFIX = 'atom'; |
779
|
|
|
|
780
|
|
|
/** |
781
|
|
|
* XML prefix for the Atom Publishing Protocol namespace. |
782
|
|
|
* |
783
|
|
|
* @var string |
784
|
|
|
*/ |
785
|
|
|
const APP_NAMESPACE_PREFIX = 'app'; |
786
|
|
|
|
787
|
|
|
/** |
788
|
|
|
* @param ProvidersWrapper $providers |
789
|
|
|
* |
790
|
|
|
* @return IODataWriter |
791
|
|
|
*/ |
792
|
|
|
public function writeServiceDocument(ProvidersWrapper $providers) |
793
|
|
|
{ |
794
|
|
|
$writer = $this->xmlWriter; |
795
|
|
|
$writer->startElementNs(null, ODataConstants::ATOM_PUBLISHING_SERVICE_ELEMENT_NAME, ODataConstants::APP_NAMESPACE); |
796
|
|
|
$writer->writeAttributeNs(ODataConstants::XML_NAMESPACE_PREFIX, ODataConstants::XML_BASE_ATTRIBUTE_NAME, null, $this->baseUri); |
797
|
|
|
$writer->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, self::ATOM_NAMESPACE_PREFIX, null, ODataConstants::ATOM_NAMESPACE); |
798
|
|
|
//$writer->writeAttributeNs(ODataConstants::XMLNS_NAMESPACE_PREFIX, self::APP_NAMESPACE_PREFIX, null, ODataConstants::APP_NAMESPACE); |
|
|
|
|
799
|
|
|
|
800
|
|
|
$writer->startElement(ODataConstants::ATOM_PUBLISHING_WORKSPACE_ELEMNT_NAME); |
801
|
|
|
$writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null); |
802
|
|
|
$writer->text(ODataConstants::ATOM_PUBLISHING_WORKSPACE_DEFAULT_VALUE); |
803
|
|
|
$writer->endElement(); |
804
|
|
|
foreach ($providers->getResourceSets() as $resourceSetWrapper) { |
805
|
|
|
$name = $resourceSetWrapper->getName(); |
806
|
|
|
$this->writeServiceDocumentNode($writer, $name); |
807
|
|
|
} |
808
|
|
|
foreach ($providers->getSingletons() as $single) { |
809
|
|
|
$name = $single->getName(); |
810
|
|
|
//start collection node |
811
|
|
|
$this->writeServiceDocumentNode($writer, $name); |
812
|
|
|
} |
813
|
|
|
|
814
|
|
|
//End workspace and service nodes |
815
|
|
|
$writer->endElement(); |
816
|
|
|
$writer->endElement(); |
817
|
|
|
|
818
|
|
|
return $this; |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
/** |
822
|
|
|
* @param $writer |
823
|
|
|
* @param $name |
824
|
|
|
*/ |
825
|
|
|
private function writeServiceDocumentNode(&$writer, $name) |
826
|
|
|
{ |
827
|
|
|
//start collection node |
828
|
|
|
$writer->startElement(ODataConstants::ATOM_PUBLISHING_COLLECTION_ELEMENT_NAME); |
829
|
|
|
$writer->writeAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, $name); |
830
|
|
|
//start title node |
831
|
|
|
$writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null); |
832
|
|
|
$writer->text($name); |
833
|
|
|
//end title node |
834
|
|
|
$writer->endElement(); |
835
|
|
|
//end collection node |
836
|
|
|
$writer->endElement(); |
837
|
|
|
} |
838
|
|
|
} |
839
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.