Passed
Push — master ( 6588d8...6bef90 )
by Alex
01:21
created

AtomODataWriter::writeServiceDocument()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 47
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 47
rs 9.0303
cc 3
eloc 29
nc 4
nop 1
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)..
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
73
        //but it's how WS DS works. See #94
74
        return in_array(MimeTypes::MIME_APPLICATION_XML, $parts)
75
               || in_array(MimeTypes::MIME_APPLICATION_ATOMSERVICE, $parts)
76
               || in_array(MimeTypes::MIME_APPLICATION_ATOM, $parts);
77
    }
78
79
    /**
80
     * Write the given OData model in a specific response format.
81
     *
82
     * @param ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content
83
     *
84
     * @return AtomODataWriter
85
     */
86
    public function write($model)
87
    {
88
        if ($model instanceof ODataURL) {
89
            return $this->writeURL($model);
90
        }
91
92
        if ($model instanceof ODataURLCollection) {
93
            return $this->writeURLCollection($model);
94
        }
95
96
        if ($model instanceof ODataPropertyContent) {
97
            return $this->writeProperties($model, true);
98
        }
99
100
        if ($model instanceof ODataFeed) {
101
            return $this->writeFeed($model, true);
102
        }
103
104
        if ($model instanceof ODataEntry) {
105
            return $this->writeEntry($model, true);
106
        }
107
108
        return $this;
109
    }
110
111
    /**
112
     * @param ODataURL $url the url to write
113
     *
114
     * @return AtomODataWriter
115
     */
116
    protected function writeURL(ODataURL $url)
117
    {
118
        $this->xmlWriter->startElement(ODataConstants::ATOM_URI_ELEMENT_NAME);
119
        $this->xmlWriter->writeAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_NAMESPACE);
120
        $this->xmlWriter->text($url->url);
121
        $this->xmlWriter->endElement();
122
123
        return $this;
124
    }
125
126
    /**
127
     * Begin write odata links.
128
     *
129
     * @param ODataURLCollection $urls Object of ODataUrlCollection to start writing collection of url
130
     *
131
     * @return AtomODataWriter
132
     */
133
    public function writeUrlCollection(ODataURLCollection $urls)
134
    {
135
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINKS_ELEMENT_NAME);
136
        $this->xmlWriter->writeAttribute(
137
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
138
            ODataConstants::ODATA_NAMESPACE
139
        );
140
        $this->xmlWriter->endAttribute();
141
        if ($urls->count != null) {
142
            $this->xmlWriter->writeAttributeNs(
143
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
144
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
145
                null,
146
                ODataConstants::ODATA_METADATA_NAMESPACE
147
            );
148
            $this->xmlWriter->endAttribute();
149
            $this->xmlWriter->startElementNs(
150
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
151
                ODataConstants::ROWCOUNT_ELEMENT,
152
                null
153
            );
154
            $this->xmlWriter->text($urls->count);
155
            $this->xmlWriter->endElement();
156
        }
157
        foreach ($urls->urls as $url) {
158
            $this->writeNodeValue(ODataConstants::ATOM_URI_ELEMENT_NAME, $url->url);
159
        }
160
161
        if ($urls->nextPageLink != null) {
162
            $this->writeLinkNode($urls->nextPageLink, false);
163
        }
164
        $this->xmlWriter->endElement();
165
166
        return $this;
167
    }
168
169
    /**
170
     * Begin write OData Feed.
171
     *
172
     * @param ODataFeed $feed       Object of OData feed to start writing feed
173
     * @param bool      $isTopLevel indicates if this is the top level feed in the response
174
     *
175
     * @return AtomODataWriter
176
     */
177
    protected function writeFeed(ODataFeed $feed, $isTopLevel = false)
178
    {
179
        $this->xmlWriter->startElement(ODataConstants::ATOM_FEED_ELEMENT_NAME);
180
        if ($isTopLevel) {
181
            $this->writeBaseUriAndDefaultNamespaces();
182
        }
183
184
        $this
185
            ->writeNodeAttributeValue(
186
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
187
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
188
                MimeTypes::MIME_TEXTTYPE,
189
                $feed->title
190
            )
191
            ->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $feed->id)
192
            ->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, date(DATE_ATOM))
193
            ->writeLinkNode($feed->selfLink, false);
194
195
        if ($feed->rowCount != null) {
196
            $this->xmlWriter->startElementNs(
197
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
198
                ODataConstants::ROWCOUNT_ELEMENT,
199
                null
200
            );
201
            $this->xmlWriter->text($feed->rowCount);
202
            $this->xmlWriter->endElement();
203
        }
204
205
        foreach ($feed->entries as $entry) {
206
            $this->writeEntry($entry);
207
        }
208
209
        if ($feed->nextPageLink != null) {
210
            $this->writeLinkNode($feed->nextPageLink, false);
211
        }
212
        $this->xmlWriter->endElement();
213
214
        return $this;
215
    }
216
217
    /**
218
     * Write top level entry.
219
     *
220
     * @param ODataEntry $entry      Object of ODataEntry
221
     * @param bool       $isTopLevel
222
     *
223
     * @return AtomODataWriter
224
     */
225
    protected function writeEntry(ODataEntry $entry, $isTopLevel = false)
226
    {
227
        $this->writeBeginEntry($entry, $isTopLevel);
228
        foreach ($entry->links as $link) {
229
            $this->writeLink($link);
230
        }
231
232
        $this
233
            ->preWriteProperties($entry)
234
            ->writeProperties($entry->propertyContent)
235
            ->postWriteProperties($entry);
236
237
        $this->xmlWriter->endElement();
238
239
        return $this;
240
    }
241
242
    /**
243
     * Start writing a entry.
244
     *
245
     * @param ODataEntry $entry      Entry to write
246
     * @param bool       $isTopLevel
247
     *
248
     * @return AtomODataWriter
249
     */
250
    protected function writeBeginEntry(ODataEntry $entry, $isTopLevel)
251
    {
252
        $this->xmlWriter->startElement(ODataConstants::ATOM_ENTRY_ELEMENT_NAME);
253
        if ($isTopLevel) {
254
            $this->writeBaseUriAndDefaultNamespaces();
255
        }
256
257
        if (null !== $entry->eTag) {
258
            $this->xmlWriter->startAttributeNs(
259
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
260
                ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
261
                null
262
            );
263
            $this->xmlWriter->text($entry->eTag);
264
            $this->xmlWriter->endAttribute();
265
        }
266
267
        $this
268
            ->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $entry->id)
269
            ->writeNodeAttributeValue(
270
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
271
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
272
                MimeTypes::MIME_TEXTTYPE,
273
                $entry->title
274
            )
275
            ->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, date(DATE_ATOM));
276
277
        $this->xmlWriter->startElement(ODataConstants::ATOM_AUTHOR_ELEMENT_NAME);
278
        $this->xmlWriter->startElement(ODataConstants::ATOM_NAME_ELEMENT_NAME);
279
        $this->xmlWriter->endElement();
280
        $this->xmlWriter->endElement();
281
282
283
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
284
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME);
285
        $this->xmlWriter->text(ODataConstants::ATOM_EDIT_RELATION_ATTRIBUTE_VALUE);
286
        $this->xmlWriter->endAttribute();
287
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
288
        $this->xmlWriter->text($entry->title);
289
        $this->xmlWriter->endAttribute();
290
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
291
        if (is_string($entry->editLink)) {
292
            $this->xmlWriter->text($entry->editLink);
293
        } else {
294
            $this->xmlWriter->text($entry->editLink->url);
295
        }
296
        $this->xmlWriter->endAttribute();
297
298
        $this->xmlWriter->endElement();
299
300
301
        if ($entry->isMediaLinkEntry) {
302
            $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
303 View Code Duplication
            if ($entry->mediaLink->eTag != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
304
                $this->xmlWriter->startAttributeNs(
305
                    ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
306
                    ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
307
                    null
308
                );
309
                $this->xmlWriter->text($entry->mediaLink->eTag);
310
                $this->xmlWriter->endAttribute();
311
            }
312
            $this->xmlWriter->startAttribute(
313
                ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME
314
            );
315
            $this->xmlWriter->text(ODataConstants::ATOM_EDIT_MEDIA_RELATION_ATTRIBUTE_VALUE);
316
            $this->xmlWriter->endAttribute();
317
318
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME);
319
            $this->xmlWriter->text($entry->mediaLink->contentType);
320
            $this->xmlWriter->endAttribute();
321
322
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
323
            $this->xmlWriter->text($entry->mediaLink->name);
324
            $this->xmlWriter->endAttribute();
325
326
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
327
            $this->xmlWriter->text($entry->mediaLink->editLink);
328
            $this->xmlWriter->endAttribute();
329
            $this->xmlWriter->endElement();
330
331
332
            foreach ($entry->mediaLinks as $mediaLink) {
333
                $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
334 View Code Duplication
                if ($mediaLink->eTag != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
335
                    $this->xmlWriter->startAttributeNs(
336
                        ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
337
                        ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
338
                        null
339
                    );
340
                    $this->xmlWriter->text($mediaLink->eTag);
341
                    $this->xmlWriter->endAttribute();
342
                }
343
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME);
344
                $this->xmlWriter->text(
345
                    'http://schemas.microsoft.com/ado/2007/08/dataservices/mediaresource/'
346
                    .$mediaLink->name
347
                );
348
                $this->xmlWriter->endAttribute();
349
350
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME);
351
                $this->xmlWriter->text($mediaLink->contentType);
352
                $this->xmlWriter->endAttribute();
353
354
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
355
                $this->xmlWriter->text($mediaLink->name);
356
                $this->xmlWriter->endAttribute();
357
358
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
359
                $this->xmlWriter->text($mediaLink->editLink);
360
                $this->xmlWriter->endAttribute();
361
                $this->xmlWriter->endElement();
362
            }
363
        }
364
365
        return $this;
366
    }
367
368
    /**
369
     * @param ODataLink $link Link to write
370
     *
371
     * @return AtomODataWriter
372
     */
373
    protected function writeLink(ODataLink $link)
374
    {
375
        $this->writeLinkNode($link, $link->isExpanded);
376
377
        if ($link->isExpanded) {
378
            $this->xmlWriter->startElementNS(
379
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
380
                ODataConstants::ATOM_INLINE_ELEMENT_NAME,
381
                null
382
            );
383
384
            if (null !== $link->expandedResult) {
385
                if ($link->isCollection) {
386
                    $this->writeFeed($link->expandedResult);
0 ignored issues
show
Bug introduced by
It seems like $link->expandedResult can also be of type object<POData\ObjectModel\ODataEntry>; however, POData\Writers\Atom\AtomODataWriter::writeFeed() does only seem to accept object<POData\ObjectModel\ODataFeed>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
387
                } else {
388
                    $this->writeEntry($link->expandedResult);
0 ignored issues
show
Bug introduced by
It seems like $link->expandedResult can also be of type object<POData\ObjectModel\ODataFeed>; however, POData\Writers\Atom\AtomODataWriter::writeEntry() does only seem to accept object<POData\ObjectModel\ODataEntry>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
389
                }
390
            }
391
392
            $this->xmlWriter->endElement();
393
            $this->xmlWriter->endElement();
394
        }
395
396
        return $this;
397
    }
398
399
    /**
400
     * Write the given collection of properties.
401
     * (properties of an entity or complex type).
402
     *
403
     * @param ODataPropertyContent $properties Collection of properties
404
     * @param bool                 $topLevel   is this property content is the top level response to be written?
405
     *
406
     * @return AtomODataWriter
407
     */
408
    protected function writeProperties(ODataPropertyContent $properties, $topLevel = false)
409
    {
410
        foreach ($properties->properties as $property) {
411
            $this->beginWriteProperty($property, $topLevel);
412
413
            if ($property->value == null) {
414
                $this->writeNullValue($property);
415
            } elseif ($property->value instanceof ODataPropertyContent) {
416
                $this->writeProperties($property->value, false);
417
            } elseif ($property->value instanceof ODataBagContent) {
418
                $this->writeBagContent($property->value);
419
            } else {
420
                $value = $this->beforeWriteValue($property->value, $property->typeName);
421
                $this->xmlWriter->text($value);
422
            }
423
424
            $this->xmlWriter->endElement();
425
        }
426
427
        return $this;
428
    }
429
430
    /**
431
     * XML write a basic data type (string, number, boolean, null).
432
     *
433
     * @param string $value         value to be written
434
     * @param string $type|null     data type of the value
0 ignored issues
show
Bug introduced by
There is no parameter named $type|null. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
435
     *
436
     * @return string
437
     */
438
    protected function beforeWriteValue($value, $type = null)
439
    {
440
        switch ($type) {
441
            case 'Edm.DateTime':
442
                $dateTime = new Carbon($value, new \DateTimeZone('UTC'));
443
                $result = $dateTime->format('Y-m-d\TH:i:s');
444
                break;
445
446
            default:
447
                $result = $value;
448
        }
449
450
        return $result;
451
    }
452
453
    /**
454
     * Write the node which hold the entity properties as child.
455
     *
456
     * @param ODataEntry $entry ODataEntry object for pre writing properties
457
     *
458
     * @return AtomODataWriter
459
     */
460
    public function preWriteProperties(ODataEntry $entry)
461
    {
462
        $this->xmlWriter->startElement(ODataConstants::ATOM_CATEGORY_ELEMENT_NAME);
463
        $this->xmlWriter->writeAttribute(
464
            ODataConstants::ATOM_CATEGORY_TERM_ATTRIBUTE_NAME,
465
            $entry->type
466
        );
467
        $this->xmlWriter->writeAttribute(
468
            ODataConstants::ATOM_CATEGORY_SCHEME_ATTRIBUTE_NAME,
469
            ODataConstants::ODATA_SCHEME_NAMESPACE
470
        );
471
        $this->xmlWriter->endElement();
472
        $this->xmlWriter->startElement(ODataConstants::ATOM_CONTENT_ELEMENT_NAME);
473
        if ($entry->isMediaLinkEntry) {
474
            $this->xmlWriter->writeAttribute(
475
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
476
                $entry->mediaLink->contentType
477
            );
478
            $this->xmlWriter->writeAttribute(
479
                ODataConstants::ATOM_CONTENT_SRC_ATTRIBUTE_NAME,
480
                $entry->mediaLink->srcLink
481
            );
482
            $this->xmlWriter->endElement();
483
            $this->xmlWriter->startElementNS(
484
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
485
                ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME,
486
                null
487
            );
488
        } else {
489
            $this->xmlWriter->writeAttribute(
490
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
491
                MimeTypes::MIME_APPLICATION_XML
492
            );
493
            $this->xmlWriter->startElementNS(
494
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
495
                ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME,
496
                null
497
            );
498
        }
499
500
        return $this;
501
    }
502
503
    /**
504
     * Write a property.
505
     *
506
     * @param ODataProperty $property   Property to be written
507
     * @param bool          $isTopLevel is link top level or not
508
     *
509
     * @return AtomODataWriter
510
     */
511
    protected function beginWriteProperty(ODataProperty $property, $isTopLevel)
512
    {
513
        $this->xmlWriter->startElementNS(
514
            ODataConstants::ODATA_NAMESPACE_PREFIX,
515
            $property->name,
516
            null
517
        );
518
        if ($property->typeName != null) {
519
            $this->xmlWriter->startAttributeNs(
520
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
521
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
522
                null
523
            );
524
            $this->xmlWriter->text($property->typeName);
525
        }
526
        if ($isTopLevel) {
527
            $this->xmlWriter->startAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX);
528
            $this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE);
529
            $this->xmlWriter->startAttributeNs(
530
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
531
                ODataConstants::ODATA_NAMESPACE_PREFIX,
532
                null
533
            );
534
            $this->xmlWriter->text(ODataConstants::ODATA_NAMESPACE);
535
            $this->xmlWriter->startAttributeNs(
536
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
537
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
538
                null
539
            );
540
            $this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE);
541
        }
542
        if ($property->typeName != null || $isTopLevel) {
543
            $this->xmlWriter->endAttribute();
544
        }
545
546
        return $this;
547
    }
548
549
    /**
550
     * Write after last property.
551
     *
552
     * @param ODataEntry $entry Entry object to post writing properties
553
     *
554
     * @return AtomODataWriter
555
     */
556
    public function postWriteProperties(ODataEntry $entry)
557
    {
558
        if (!$entry->isMediaLinkEntry) {
559
            $this->xmlWriter->endElement();
560
        }
561
        $this->xmlWriter->endElement();
562
563
        return $this;
564
    }
565
566
    /**
567
     * Begin an item in a collection.
568
     *
569
     * @param ODataBagContent $bag Bag property object to begin write property
570
     *
571
     * @return AtomODataWriter
572
     */
573
    protected function writeBagContent(ODataBagContent $bag)
574
    {
575
        foreach ($bag->propertyContents as $content) {
576
            if ($content instanceof ODataPropertyContent) {
577
                $this->xmlWriter->startElementNs(
578
                    ODataConstants::ODATA_NAMESPACE_PREFIX,
579
                    ODataConstants::COLLECTION_ELEMENT_NAME,
580
                    null
581
                );
582
                $this->writeProperties($content);
583
                $this->xmlWriter->endElement();
584
            } else {
585
                //probably just a primitive string
586
                $this->xmlWriter->startElementNs(
587
                    ODataConstants::ODATA_NAMESPACE_PREFIX,
588
                    ODataConstants::COLLECTION_ELEMENT_NAME,
589
                    null
590
                );
591
                $this->xmlWriter->text($content);
592
                $this->xmlWriter->endElement();
593
            }
594
        }
595
596
        return $this;
597
    }
598
599
    /**
600
     * Write null value.
601
     *
602
     * @param ODataProperty $property ODataProperty object to write null value
603
     *                                according to property type
604
     *
605
     * @return AtomODataWriter
606
     */
607
    protected function writeNullValue(ODataProperty $property)
608
    {
609
        if (!(($property instanceof ODataBagContent) || ($property instanceof ODataPropertyContent))) {
610
            $this->xmlWriter->writeAttributeNs(
611
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
612
                ODataConstants::ATOM_NULL_ATTRIBUTE_NAME,
613
                null,
614
                ODataConstants::XML_TRUE_LITERAL
615
            );
616
        }
617
618
        return $this;
619
    }
620
621
    /**
622
     * Get the final result as string.
623
     *
624
     * @return string output of requested data in Atom format
625
     */
626
    public function getOutput()
627
    {
628
        $this->xmlWriter->endDocument();
629
630
        return $this->xmlWriter->outputMemory(true);
631
    }
632
633
    /**
634
     * Serialize the exception.
635
     *
636
     * @param ODataException $exception               Exception to serialize
637
     * @param bool           $serializeInnerException if set to true,
638
     *                                                serialize the inner exception if $exception is an ODataException
639
     *
640
     * @return string
641
     */
642
    public static function serializeException(ODataException $exception, $serializeInnerException)
0 ignored issues
show
Unused Code introduced by
The parameter $serializeInnerException is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
643
    {
644
        $xmlWriter = new \XMLWriter();
645
        $xmlWriter->openMemory();
646
        $xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
647
        $xmlWriter->setIndent(4);
648
649
        $xmlWriter->startElement(ODataConstants::XML_ERROR_ELEMENT_NAME);
650
        //$xmlWriter->writeAttributeNs(
651
        //    ODataConstants::XMLNS_NAMESPACE_PREFIX,
652
        //    ODataConstants::XML_NAMESPACE_PREFIX,
653
        //    ODataConstants::XML_NAMESPACE,
654
        //    null
655
        //);
656
        $xmlWriter->writeAttribute(
657
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
658
            ODataConstants::ODATA_METADATA_NAMESPACE
659
        );
660
        $xmlWriter->endAttribute();
661
        $xmlWriter->startElement(ODataConstants::XML_ERROR_CODE_ELEMENT_NAME);
662
        if (null != $exception->getStatusCode()) {
663
            $xmlWriter->text($exception->getStatusCode());
664
        }
665
        $xmlWriter->endElement();
666
        $xmlWriter->startElement(ODataConstants::XML_ERROR_MESSAGE_ELEMENT_NAME);
667
        $xmlWriter->text($exception->getMessage());
668
        $xmlWriter->endElement();
669
        $xmlWriter->endElement();
670
        $xmlWriter->endDocument();
671
672
        return $xmlWriter->outputMemory(true);
673
    }
674
675
    /**
676
     * Function to create element only contain value without argument.
677
     *
678
     * @param string $node  Element name
679
     * @param string $value Element value
680
     *
681
     * @return AtomODataWriter
682
     */
683
    public function writeNodeValue($node, $value)
684
    {
685
        $this->xmlWriter->startElement($node);
686
        $this->xmlWriter->text($value);
687
        $this->xmlWriter->endElement();
688
689
        return $this;
690
    }
691
692
    /**
693
     * Function to create element with one attribute and value.
694
     *
695
     * @param string $node           Element name
696
     * @param string $attribute      Attribute name
697
     * @param string $attributeValue Attribute value
698
     * @param string $nodeValue      Element value
699
     *
700
     * @return AtomODataWriter
701
     */
702
    public function writeNodeAttributeValue(
703
        $node,
704
        $attribute,
705
        $attributeValue,
706
        $nodeValue
707
    ) {
708
        $this->xmlWriter->startElement($node);
709
        $this->xmlWriter->writeAttribute($attribute, $attributeValue);
710
        $this->xmlWriter->text($nodeValue);
711
        $this->xmlWriter->endElement();
712
713
        return $this;
714
    }
715
716
    /**
717
     * Function to create link element with arguments.
718
     *
719
     * @param ODataLink $link       Link object to make link element
720
     * @param bool      $isExpanded Is link expanded or not
721
     *
722
     * @return AtomODataWriter
723
     */
724
    protected function writeLinkNode(ODataLink $link, $isExpanded)
725
    {
726
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
727
        $this->xmlWriter->writeAttribute(
728
            ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME,
729
            $link->name
730
        );
731
        if ($link->type != null) {
732
            $this->xmlWriter->writeAttribute(
733
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
734
                $link->type
735
            );
736
        }
737
        if ($link->title != null) {
738
            $this->xmlWriter->writeAttribute(
739
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
740
                $link->title
741
            );
742
        }
743
        $this->xmlWriter->writeAttribute(
744
            ODataConstants::ATOM_HREF_ATTRIBUTE_NAME,
745
            $link->url
746
        );
747
        if (!$isExpanded) {
748
            $this->xmlWriter->endElement();
749
        }
750
751
        return $this;
752
    }
753
754
    /**
755
     * Function to write base uri and default namespaces for top level elements.
756
     *
757
     * @return AtomODataWriter
758
     */
759
    public function writeBaseUriAndDefaultNamespaces()
760
    {
761
        $this->xmlWriter->writeAttribute(
762
            ODataConstants::XML_BASE_ATTRIBUTE_NAME_WITH_PREFIX,
763
            $this->baseUri
764
        );
765
        $this->xmlWriter->writeAttributeNs(
766
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
767
            ODataConstants::ODATA_NAMESPACE_PREFIX,
768
            null,
769
            ODataConstants::ODATA_NAMESPACE
770
        );
771
        $this->xmlWriter->writeAttributeNs(
772
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
773
            ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
774
            null,
775
            ODataConstants::ODATA_METADATA_NAMESPACE
776
        );
777
        $this->xmlWriter->writeAttribute(
778
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
779
            ODataConstants::ATOM_NAMESPACE
780
        );
781
782
        return $this;
783
    }
784
785
    /**
786
     * XML prefix for the Atom namespace.
787
     *
788
     * @var string
789
     */
790
    const ATOM_NAMESPACE_PREFIX = 'atom';
791
792
    /**
793
     * XML prefix for the Atom Publishing Protocol namespace.
794
     *
795
     * @var string
796
     */
797
    const APP_NAMESPACE_PREFIX = 'app';
798
799
    /**
800
     * @param ProvidersWrapper $providers
801
     *
802
     * @return IODataWriter
803
     */
804
    public function writeServiceDocument(ProvidersWrapper $providers)
805
    {
806
        $writer = $this->xmlWriter;
807
        $writer->startElementNs(
808
            null,
809
            ODataConstants::ATOM_PUBLISHING_SERVICE_ELEMENT_NAME,
810
            ODataConstants::APP_NAMESPACE
811
        );
812
        $writer->writeAttributeNs(
813
            ODataConstants::XML_NAMESPACE_PREFIX,
814
            ODataConstants::XML_BASE_ATTRIBUTE_NAME,
815
            null,
816
            $this->baseUri
817
        );
818
        $writer->writeAttributeNs(
819
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
820
            self::ATOM_NAMESPACE_PREFIX,
821
            null,
822
            ODataConstants::ATOM_NAMESPACE
823
        );
824
        //$writer->writeAttributeNs(
825
        //ODataConstants::XMLNS_NAMESPACE_PREFIX,
826
        //self::APP_NAMESPACE_PREFIX,
827
        //null,
828
        //ODataConstants::APP_NAMESPACE
829
        //);
830
831
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_WORKSPACE_ELEMNT_NAME);
832
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
833
        $writer->text(ODataConstants::ATOM_PUBLISHING_WORKSPACE_DEFAULT_VALUE);
834
        $writer->endElement();
835
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
836
            $name = $resourceSetWrapper->getName();
837
            $this->writeServiceDocumentNode($writer, $name);
838
        }
839
        foreach ($providers->getSingletons() as $single) {
840
            $name = $single->getName();
841
            //start collection node
842
            $this->writeServiceDocumentNode($writer, $name);
843
        }
844
845
        //End workspace and service nodes
846
        $writer->endElement();
847
        $writer->endElement();
848
849
        return $this;
850
    }
851
852
    /**
853
     * @param $writer
854
     * @param $name
855
     */
856
    private function writeServiceDocumentNode(&$writer, $name)
857
    {
858
        //start collection node
859
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_COLLECTION_ELEMENT_NAME);
860
        $writer->writeAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, $name);
861
        //start title node
862
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
863
        $writer->text($name);
864
        //end title node
865
        $writer->endElement();
866
        //end collection node
867
        $writer->endElement();
868
    }
869
}
870