AtomODataWriter::writeUrl()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace POData\Writers\Atom;
6
7
use DateTimeZone;
8
use Exception;
9
use POData\Common\MimeTypes;
10
use POData\Common\ODataConstants;
11
use POData\Common\ODataException;
12
use POData\Common\Version;
13
use POData\Configuration\ServiceConfiguration;
14
use POData\ObjectModel\IOData;
15
use POData\ObjectModel\ODataBagContent;
16
use POData\ObjectModel\ODataCategory;
17
use POData\ObjectModel\ODataEntry;
18
use POData\ObjectModel\ODataFeed;
19
use POData\ObjectModel\ODataLink;
20
use POData\ObjectModel\ODataProperty;
21
use POData\ObjectModel\ODataPropertyContent;
22
use POData\ObjectModel\ODataTitle;
23
use POData\ObjectModel\ODataURL;
24
use POData\ObjectModel\ODataURLCollection;
25
use POData\Providers\Metadata\Type\DateTime;
26
use POData\Providers\ProvidersWrapper;
27
use POData\Writers\IODataWriter;
28
use XMLWriter;
29
30
/**
31
 * Class AtomODataWriter.
32
 */
33
class AtomODataWriter implements IODataWriter
34
{
35
    /**
36
     * XML prefix for the Atom namespace.
37
     *
38
     * @var string
39
     */
40
    const ATOM_NAMESPACE_PREFIX = 'atom';
41
    /**
42
     * XML prefix for the Atom Publishing Protocol namespace.
43
     *
44
     * @var string
45
     */
46
    const APP_NAMESPACE_PREFIX = 'app';
47
48
    /*
49
     * Update time to insert into ODataEntry/ODataFeed fields
50
     * @var \DateTime;
51
     */
52
    /**
53
     * Writer to which output (CSDL Document) is sent.
54
     *
55
     * @var XMLWriter
56
     */
57
    public $xmlWriter;
58
    /**
59
     * The service base uri.
60
     *
61
     * @var string
62
     */
63
    protected $baseUri;
64
    private $updated;
65
66
    /**
67
     * Construct a new instance of AtomODataWriter.
68
     *
69
     * @param string $absoluteServiceUri The absolute service Uri
70
     */
71
    public function __construct(string $eol, bool $prettyPrint, $absoluteServiceUri = '')
72
    {
73
        $final = substr($absoluteServiceUri, -1);
74
        if ('/' != $final) {
75
            $absoluteServiceUri .= '/';
76
        }
77
        $this->baseUri = $absoluteServiceUri;
78
        $this->updated = DateTime::now();
79
80
        $this->xmlWriter = new XMLWriter();
81
        $this->xmlWriter->openMemory();
82
        $this->xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
83
        $this->xmlWriter->setIndent($prettyPrint);
84
        $this->xmlWriter->setIndentString($prettyPrint ? '    ' : '');
85
    }
86
87
    /**
88
     * Serialize the exception.
89
     *
90
     * @param ODataException $exception Exception to serialize
91
     *
92
     * @return string
93
     */
94
    public static function serializeException(ODataException $exception, ServiceConfiguration $config)
95
    {
96
        $xmlWriter = new XMLWriter();
97
        $xmlWriter->openMemory();
98
        $xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
99
        $xmlWriter->setIndent($config->getPrettyOutput());
100
        $xmlWriter->setIndentString($config->getPrettyOutput() ? '    ' : '');
101
102
        $xmlWriter->startElement(ODataConstants::XML_ERROR_ELEMENT_NAME);
103
        //$xmlWriter->writeAttributeNs(
104
        //    ODataConstants::XMLNS_NAMESPACE_PREFIX,
105
        //    ODataConstants::XML_NAMESPACE_PREFIX,
106
        //    ODataConstants::XML_NAMESPACE,
107
        //    null
108
        //);
109
        $xmlWriter->writeAttribute(
110
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
111
            ODataConstants::ODATA_METADATA_NAMESPACE
112
        );
113
        $xmlWriter->endAttribute();
114
        $xmlWriter->startElement(ODataConstants::XML_ERROR_CODE_ELEMENT_NAME);
115
        if (null != $exception->getStatusCode()) {
116
            $xmlWriter->text(strval($exception->getStatusCode()));
117
        }
118
        $xmlWriter->endElement();
119
        $xmlWriter->startElement(ODataConstants::XML_ERROR_MESSAGE_ELEMENT_NAME);
120
        $xmlWriter->text($exception->getMessage());
121
        $xmlWriter->endElement();
122
        $xmlWriter->endElement();
123
        $xmlWriter->endDocument();
124
125
        return $xmlWriter->outputMemory(true);
126
    }
127
128
    /**
129
     * Determines if the given writer is capable of writing the response or not.
130
     *
131
     * @param Version $responseVersion the OData version of the response
132
     * @param string  $contentType     the Content Type of the response
133
     *
134
     * @return bool true if the writer can handle the response, false otherwise
135
     */
136
    public function canHandle(Version $responseVersion, $contentType)
137
    {
138
        $parts = explode(';', $contentType);
139
140
        //first 2 parts are for service documents, second part is for Resources
141
        //TODO: i'm not sold about this first part not being constrained to v1 (or maybe v2)..
142
        //but it's how WS DS works. See #94
143
        return in_array(MimeTypes::MIME_APPLICATION_XML, $parts)
144
            || in_array(MimeTypes::MIME_APPLICATION_ATOMSERVICE, $parts)
145
            || in_array(MimeTypes::MIME_APPLICATION_ATOM, $parts);
146
    }
147
148
    /**
149
     * Write the given OData model in a specific response format.
150
     *
151
     * @param ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content
152
     *
153
     * @throws Exception
154
     * @return AtomODataWriter
155
     */
156
    public function write(IOData $model)
157
    {
158
        if ($model instanceof ODataURL) {
159
            return $this->writeUrl($model);
160
        }
161
162
        if ($model instanceof ODataURLCollection) {
163
            return $this->writeUrlCollection($model);
164
        }
165
166
        if ($model instanceof ODataPropertyContent) {
167
            return $this->writeProperties($model, true);
168
        }
169
170
        if ($model instanceof ODataFeed) {
171
            return $this->writeFeed($model, true);
172
        }
173
174
        if ($model instanceof ODataEntry) {
175
            return $this->writeEntry($model, true);
176
        }
177
178
        return $this;
179
    }
180
181
    /**
182
     * @param ODataURL $url the url to write
183
     *
184
     * @return AtomODataWriter
185
     */
186
    protected function writeUrl(ODataURL $url)
187
    {
188
        $this->xmlWriter->startElement(ODataConstants::ATOM_URI_ELEMENT_NAME);
189
        $this->xmlWriter->writeAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX, ODataConstants::ODATA_NAMESPACE);
190
        $this->xmlWriter->text($url->getUrl());
191
        $this->xmlWriter->endElement();
192
193
        return $this;
194
    }
195
196
    /**
197
     * Begin write OData links.
198
     *
199
     * @param ODataURLCollection $urls Object of ODataUrlCollection to start writing collection of url
200
     *
201
     * @return AtomODataWriter
202
     */
203
    public function writeUrlCollection(ODataURLCollection $urls)
204
    {
205
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINKS_ELEMENT_NAME);
206
        $this->xmlWriter->writeAttribute(
207
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
208
            ODataConstants::ODATA_NAMESPACE
209
        );
210
        $this->xmlWriter->endAttribute();
211
        if ($urls->getCount() !== null) {
212
            $this->xmlWriter->writeAttributeNs(
213
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
214
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
215
                null,
216
                ODataConstants::ODATA_METADATA_NAMESPACE
217
            );
218
            $this->xmlWriter->endAttribute();
219
            $this->xmlWriter->startElementNs(
220
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
221
                ODataConstants::ROWCOUNT_ELEMENT,
222
                null
223
            );
224
            $this->xmlWriter->text(strval($urls->getCount()));
225
            $this->xmlWriter->endElement();
226
        }
227
        foreach ($urls->getUrls() as $url) {
228
            $this->writeNodeValue(ODataConstants::ATOM_URI_ELEMENT_NAME, $url->getUrl());
229
        }
230
231
        if ($urls->getNextPageLink() != null) {
232
            $this->writeLinkNode($urls->getNextPageLink(), false);
233
        }
234
        $this->xmlWriter->endElement();
235
236
        return $this;
237
    }
238
239
    /**
240
     * Function to create element only contain value without argument.
241
     *
242
     * @param string $node  Element name
243
     * @param string $value Element value
244
     *
245
     * @return AtomODataWriter
246
     */
247
    public function writeNodeValue($node, $value)
248
    {
249
        $this->xmlWriter->startElement($node);
250
        $this->xmlWriter->text($value ?? '');
251
        $this->xmlWriter->endElement();
252
253
        return $this;
254
    }
255
256
    /**
257
     * Function to create link element with arguments.
258
     *
259
     * @param ODataLink $link       Link object to make link element
260
     * @param bool      $isExpanded Is link expanded or not
261
     *
262
     * @return AtomODataWriter
263
     */
264
    protected function writeLinkNode(ODataLink $link, $isExpanded)
265
    {
266
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
267
        $this->xmlWriter->writeAttribute(
268
            ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME,
269
            $link->getName() ?? ''
270
        );
271
        if ($link->getType() != null) {
272
            $this->xmlWriter->writeAttribute(
273
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
274
                $link->getType() ?? ''
275
            );
276
        }
277
        if ($link->getTitle() != null) {
278
            $this->xmlWriter->writeAttribute(
279
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
280
                $link->getTitle() ?? ''
281
            );
282
        }
283
        $this->xmlWriter->writeAttribute(
284
            ODataConstants::ATOM_HREF_ATTRIBUTE_NAME,
285
            $link->getUrl() ?? ''
286
        );
287
        if (!$isExpanded) {
288
            $this->xmlWriter->endElement();
289
        }
290
291
        return $this;
292
    }
293
294
    /**
295
     * Write the given collection of properties.
296
     * (properties of an entity or complex type).
297
     *
298
     * @param ODataPropertyContent $properties Collection of properties
299
     * @param bool                 $topLevel   is this property content is the top level response to be written?
300
     *
301
     * @throws Exception
302
     * @return AtomODataWriter
303
     */
304
    protected function writeProperties(ODataPropertyContent $properties = null, $topLevel = false)
305
    {
306
        if (null !== $properties) {
307
            foreach ($properties as $property) {
308
                $this->beginWriteProperty($property, $topLevel);
309
310
                if ($property->getValue() == null) {
311
                    $this->writeNullValue($property);
312
                } elseif ($property->getValue() instanceof ODataPropertyContent) {
313
                    $this->writeProperties($property->getValue(), false);
314
                } elseif ($property->getValue() instanceof ODataBagContent) {
315
                    $this->writeBagContent($property->getValue());
316
                } else {
317
                    $value = $this->beforeWriteValue($property->getValue(), $property->getTypeName());
318
                    $this->xmlWriter->text(strval($value));
319
                }
320
321
                $this->xmlWriter->endElement();
322
            }
323
        }
324
325
        return $this;
326
    }
327
328
    /**
329
     * Write a property.
330
     *
331
     * @param ODataProperty $property   Property to be written
332
     * @param bool          $isTopLevel is link top level or not
333
     *
334
     * @return AtomODataWriter
335
     */
336
    protected function beginWriteProperty(ODataProperty $property, $isTopLevel)
337
    {
338
        $this->xmlWriter->startElementNs(
339
            ODataConstants::ODATA_NAMESPACE_PREFIX,
340
            $property->getName(),
341
            null
342
        );
343
        if (!empty($property->getTypeName())) {
344
            $this->xmlWriter->startAttributeNs(
345
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
346
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
347
                null
348
            );
349
            $this->xmlWriter->text($property->getTypeName());
350
        }
351
        if ($isTopLevel) {
352
            $this->xmlWriter->startAttribute(ODataConstants::XMLNS_NAMESPACE_PREFIX);
353
            $this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE);
354
            $this->xmlWriter->startAttributeNs(
355
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
356
                ODataConstants::ODATA_NAMESPACE_PREFIX,
357
                null
358
            );
359
            $this->xmlWriter->text(ODataConstants::ODATA_NAMESPACE);
360
            $this->xmlWriter->startAttributeNs(
361
                ODataConstants::XMLNS_NAMESPACE_PREFIX,
362
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
363
                null
364
            );
365
            $this->xmlWriter->text(ODataConstants::ODATA_METADATA_NAMESPACE);
366
        }
367
        if (!empty($property->getTypeName()) || $isTopLevel) {
368
            $this->xmlWriter->endAttribute();
369
        }
370
371
        return $this;
372
    }
373
374
    /**
375
     * Write null value.
376
     *
377
     * @param ODataProperty $property ODataProperty object to write null value
378
     *                                according to property type
379
     *
380
     * @return AtomODataWriter
381
     */
382
    protected function writeNullValue(ODataProperty $property)
383
    {
384
        $this->xmlWriter->writeAttributeNs(
385
            ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
386
            ODataConstants::ATOM_NULL_ATTRIBUTE_NAME,
387
            null,
388
            ODataConstants::XML_TRUE_LITERAL
389
        );
390
391
        return $this;
392
    }
393
394
    /**
395
     * Begin an item in a collection.
396
     *
397
     * @param ODataBagContent $bag Bag property object to begin write property
398
     *
399
     * @throws Exception
400
     * @return AtomODataWriter
401
     */
402
    protected function writeBagContent(ODataBagContent $bag)
403
    {
404
        foreach ($bag->getPropertyContents() as $content) {
405
            if ($content instanceof ODataPropertyContent) {
406
                $this->xmlWriter->startElementNs(
407
                    ODataConstants::ODATA_NAMESPACE_PREFIX,
408
                    ODataConstants::COLLECTION_ELEMENT_NAME,
409
                    null
410
                );
411
                $this->writeProperties($content);
412
                $this->xmlWriter->endElement();
413
            } else {
414
                //probably just a primitive string
415
                $this->xmlWriter->startElementNs(
416
                    ODataConstants::ODATA_NAMESPACE_PREFIX,
417
                    ODataConstants::COLLECTION_ELEMENT_NAME,
418
                    null
419
                );
420
                $this->xmlWriter->text($content);
421
                $this->xmlWriter->endElement();
422
            }
423
        }
424
425
        return $this;
426
    }
427
428
    /**
429
     * XML write a basic data type (string, number, boolean, null).
430
     *
431
     * @param string $value value to be written
432
     * @param string $type  |null data type of the value
433
     *
434
     * @throws Exception
435
     * @return string
436
     */
437
    protected function beforeWriteValue($value, $type = null)
438
    {
439
        switch ($type) {
440
            case 'Edm.DateTime':
441
                $dateTime = new \DateTime($value, new DateTimeZone('UTC'));
442
                $result   = $dateTime->format('Y-m-d\TH:i:s');
443
                break;
444
445
            default:
446
                $result = $value;
447
        }
448
449
        return $result;
450
    }
451
452
    /**
453
     * Begin write OData Feed.
454
     *
455
     * @param ODataFeed $feed       Object of OData feed to start writing feed
456
     * @param bool      $isTopLevel indicates if this is the top level feed in the response
457
     *
458
     * @throws Exception
459
     * @return AtomODataWriter
460
     */
461
    protected function writeFeed(ODataFeed $feed, $isTopLevel = false)
462
    {
463
        $this->xmlWriter->startElement(ODataConstants::ATOM_FEED_ELEMENT_NAME);
464
        if ($isTopLevel) {
465
            $this->writeBaseUriAndDefaultNamespaces();
466
        }
467
468
        $effectiveTitle = $feed->getTitle()->getTitle();
469
        $this
470
            ->writeNodeAttributeValue(
471
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
472
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
473
                MimeTypes::MIME_TEXTTYPE,
474
                $effectiveTitle
475
            )
476
            ->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $feed->id)
477
            ->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, $this->getUpdated()->format(DATE_ATOM))
478
            ->writeLinkNode($feed->getSelfLink(), false);
0 ignored issues
show
Bug introduced by
It seems like $feed->getSelfLink() can also be of type null; however, parameter $link of POData\Writers\Atom\Atom...Writer::writeLinkNode() does only seem to accept POData\ObjectModel\ODataLink, maybe add an additional type check? ( Ignorable by Annotation )

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

478
            ->writeLinkNode(/** @scrutinizer ignore-type */ $feed->getSelfLink(), false);
Loading history...
479
480
        if ($feed->getRowCount() != null) {
481
            $this->xmlWriter->startElementNs(
482
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
483
                ODataConstants::ROWCOUNT_ELEMENT,
484
                null
485
            );
486
            $this->xmlWriter->text(strval($feed->getRowCount()));
487
            $this->xmlWriter->endElement();
488
        }
489
490
        foreach ($feed->getEntries() as $entry) {
491
            $this->writeEntry($entry);
492
        }
493
494
        if ($feed->getNextPageLink() != null) {
495
            $this->writeLinkNode($feed->getNextPageLink(), false);
496
        }
497
        $this->xmlWriter->endElement();
498
499
        return $this;
500
    }
501
502
    /**
503
     * Function to write base uri and default namespaces for top level elements.
504
     *
505
     * @return AtomODataWriter
506
     */
507
    public function writeBaseUriAndDefaultNamespaces()
508
    {
509
        $this->xmlWriter->writeAttribute(
510
            ODataConstants::XML_BASE_ATTRIBUTE_NAME_WITH_PREFIX,
511
            $this->baseUri
512
        );
513
        $this->xmlWriter->writeAttributeNs(
514
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
515
            ODataConstants::ODATA_NAMESPACE_PREFIX,
516
            null,
517
            ODataConstants::ODATA_NAMESPACE
518
        );
519
        $this->xmlWriter->writeAttributeNs(
520
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
521
            ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
522
            null,
523
            ODataConstants::ODATA_METADATA_NAMESPACE
524
        );
525
        $this->xmlWriter->writeAttribute(
526
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
527
            ODataConstants::ATOM_NAMESPACE
528
        );
529
530
        return $this;
531
    }
532
533
    /**
534
     * Function to create element with one attribute and value.
535
     *
536
     * @param string $node           Element name
537
     * @param string $attribute      Attribute name
538
     * @param string $attributeValue Attribute value
539
     * @param string $nodeValue      Element value
540
     *
541
     * @return AtomODataWriter
542
     */
543
    public function writeNodeAttributeValue(
544
        $node,
545
        $attribute,
546
        $attributeValue,
547
        $nodeValue
548
    ) {
549
        $this->xmlWriter->startElement($node);
550
        $this->xmlWriter->writeAttribute($attribute, $attributeValue);
551
        $this->xmlWriter->text($nodeValue ?? '');
552
        $this->xmlWriter->endElement();
553
554
        return $this;
555
    }
556
557
    /**
558
     * Get update timestamp.
559
     *
560
     * @return \DateTime
561
     */
562
    public function getUpdated()
563
    {
564
        return $this->updated;
565
    }
566
567
    /**
568
     * Write top level entry.
569
     *
570
     * @param ODataEntry $entry      Object of ODataEntry
571
     * @param bool       $isTopLevel
572
     *
573
     * @throws Exception
574
     * @return AtomODataWriter
575
     */
576
    protected function writeEntry(ODataEntry $entry, $isTopLevel = false)
577
    {
578
        $this->writeBeginEntry($entry, $isTopLevel);
579
        foreach ($entry->links as $link) {
580
            $this->writeLink($link);
581
        }
582
583
        $this
584
            ->preWriteProperties($entry)
585
            ->writeProperties($entry->propertyContent)
586
            ->postWriteProperties($entry);
587
588
        $this->xmlWriter->endElement();
589
590
        return $this;
591
    }
592
593
    /**
594
     * Start writing a entry.
595
     *
596
     * @param ODataEntry $entry      Entry to write
597
     * @param bool       $isTopLevel
598
     *
599
     * @return AtomODataWriter
600
     */
601
    protected function writeBeginEntry(ODataEntry $entry, $isTopLevel)
602
    {
603
        $this->xmlWriter->startElement(ODataConstants::ATOM_ENTRY_ELEMENT_NAME);
604
        if ($isTopLevel) {
605
            $this->writeBaseUriAndDefaultNamespaces();
606
        }
607
608
        if (null !== $entry->eTag) {
609
            $this->xmlWriter->startAttributeNs(
610
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
611
                ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
612
                null
613
            );
614
            $this->xmlWriter->text($entry->eTag);
615
            $this->xmlWriter->endAttribute();
616
        }
617
618
        $effectiveTitle = $entry->getTitle()->getTitle();
619
        $this
620
            ->writeNodeValue(ODataConstants::ATOM_ID_ELEMENT_NAME, $entry->id)
621
            ->writeNodeAttributeValue(
622
                ODataConstants::ATOM_TITLE_ELELMET_NAME,
623
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
624
                MimeTypes::MIME_TEXTTYPE,
625
                $effectiveTitle
626
            )
627
            ->writeNodeValue(ODataConstants::ATOM_UPDATED_ELEMENT_NAME, $this->getUpdated()->format(DATE_ATOM));
628
629
        $this->xmlWriter->startElement(ODataConstants::ATOM_AUTHOR_ELEMENT_NAME);
630
        $this->xmlWriter->startElement(ODataConstants::ATOM_NAME_ELEMENT_NAME);
631
        $this->xmlWriter->endElement();
632
        $this->xmlWriter->endElement();
633
634
635
        $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
636
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME);
637
        $this->xmlWriter->text(ODataConstants::ATOM_EDIT_RELATION_ATTRIBUTE_VALUE);
638
        $this->xmlWriter->endAttribute();
639
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
640
        $this->xmlWriter->text(strval($effectiveTitle));
641
        $this->xmlWriter->endAttribute();
642
        $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
643
        if (null === $entry->editLink || is_string($entry->editLink)) {
644
            $this->xmlWriter->text(strval($entry->editLink));
645
        } else {
646
            $this->xmlWriter->text($entry->editLink->getUrl());
647
        }
648
        $this->xmlWriter->endAttribute();
649
650
        $this->xmlWriter->endElement();
651
652
653
        if ($entry->isMediaLinkEntry) {
654
            $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
655
            if ($entry->mediaLink->eTag != null) {
656
                $this->xmlWriter->startAttributeNs(
657
                    ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
658
                    ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
659
                    null
660
                );
661
                $this->xmlWriter->text(strval($entry->mediaLink->eTag));
662
                $this->xmlWriter->endAttribute();
663
            }
664
            $this->xmlWriter->startAttribute(
665
                ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME
666
            );
667
            $this->xmlWriter->text(ODataConstants::ATOM_EDIT_MEDIA_RELATION_ATTRIBUTE_VALUE);
668
            $this->xmlWriter->endAttribute();
669
670
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME);
671
            $this->xmlWriter->text($entry->mediaLink->contentType);
672
            $this->xmlWriter->endAttribute();
673
674
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
675
            $this->xmlWriter->text($entry->mediaLink->name);
676
            $this->xmlWriter->endAttribute();
677
678
            $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
679
            $this->xmlWriter->text($entry->mediaLink->editLink);
680
            $this->xmlWriter->endAttribute();
681
            $this->xmlWriter->endElement();
682
683
684
            foreach ($entry->mediaLinks as $mediaLink) {
685
                $this->xmlWriter->startElement(ODataConstants::ATOM_LINK_ELEMENT_NAME);
686
                if ($mediaLink->eTag != null) {
687
                    $this->xmlWriter->startAttributeNs(
688
                        ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
689
                        ODataConstants::ATOM_ETAG_ATTRIBUTE_NAME,
690
                        null
691
                    );
692
                    $this->xmlWriter->text($mediaLink->eTag);
693
                    $this->xmlWriter->endAttribute();
694
                }
695
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_LINK_RELATION_ATTRIBUTE_NAME);
696
                $this->xmlWriter->text($mediaLink->rel);
697
                $this->xmlWriter->endAttribute();
698
699
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME);
700
                $this->xmlWriter->text($mediaLink->contentType);
701
                $this->xmlWriter->endAttribute();
702
703
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_TITLE_ELELMET_NAME);
704
                $this->xmlWriter->text($mediaLink->name);
705
                $this->xmlWriter->endAttribute();
706
707
                $this->xmlWriter->startAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME);
708
                $this->xmlWriter->text($mediaLink->editLink);
709
                $this->xmlWriter->endAttribute();
710
                $this->xmlWriter->endElement();
711
            }
712
        }
713
714
        return $this;
715
    }
716
717
    /**
718
     * @param ODataLink $link Link to write
719
     *
720
     * @throws Exception
721
     * @return AtomODataWriter
722
     */
723
    protected function writeLink(ODataLink $link)
724
    {
725
        $this->writeLinkNode($link, $link->isExpanded());
726
727
        if ($link->isExpanded()) {
728
            $this->xmlWriter->startElementNs(
729
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
730
                ODataConstants::ATOM_INLINE_ELEMENT_NAME,
731
                null
732
            );
733
734
            if (null !== $link->getExpandedResult() && null != $link->getExpandedResult()->getData()) {
735
                if ($link->isCollection()) {
736
                    $this->writeFeed($link->getExpandedResult()->getFeed());
737
                } else {
738
                    $this->writeEntry($link->getExpandedResult()->getEntry());
739
                }
740
            }
741
742
            $this->xmlWriter->endElement();
743
            $this->xmlWriter->endElement();
744
        }
745
746
        return $this;
747
    }
748
749
    /**
750
     * Write after last property.
751
     *
752
     * @param ODataEntry $entry Entry object to post writing properties
753
     *
754
     * @return AtomODataWriter
755
     */
756
    public function postWriteProperties(ODataEntry $entry)
757
    {
758
        if (true !== $entry->isMediaLinkEntry) {
759
            $this->xmlWriter->endElement();
760
        }
761
        $this->xmlWriter->endElement();
762
763
        return $this;
764
    }
765
766
    /**
767
     * Write the node which hold the entity properties as child.
768
     *
769
     * @param ODataEntry $entry ODataEntry object for pre writing properties
770
     *
771
     * @return AtomODataWriter
772
     */
773
    public function preWriteProperties(ODataEntry $entry)
774
    {
775
        $effectiveType = $entry->type instanceof ODataCategory ? $entry->type->getTerm() : $entry->type;
776
        $this->xmlWriter->startElement(ODataConstants::ATOM_CATEGORY_ELEMENT_NAME);
777
        $this->xmlWriter->writeAttribute(
778
            ODataConstants::ATOM_CATEGORY_TERM_ATTRIBUTE_NAME,
779
            strval($effectiveType)
780
        );
781
        $this->xmlWriter->writeAttribute(
782
            ODataConstants::ATOM_CATEGORY_SCHEME_ATTRIBUTE_NAME,
783
            ODataConstants::ODATA_SCHEME_NAMESPACE
784
        );
785
        $this->xmlWriter->endElement();
786
        $this->xmlWriter->startElement(ODataConstants::ATOM_CONTENT_ELEMENT_NAME);
787
        if ($entry->isMediaLinkEntry) {
788
            $this->xmlWriter->writeAttribute(
789
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
790
                $entry->mediaLink->contentType
791
            );
792
            $this->xmlWriter->writeAttribute(
793
                ODataConstants::ATOM_CONTENT_SRC_ATTRIBUTE_NAME,
794
                strval($entry->mediaLink->srcLink)
795
            );
796
            $this->xmlWriter->endElement();
797
            $this->xmlWriter->startElementNs(
798
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
799
                ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME,
800
                null
801
            );
802
        } else {
803
            $this->xmlWriter->writeAttribute(
804
                ODataConstants::ATOM_TYPE_ATTRIBUTE_NAME,
805
                MimeTypes::MIME_APPLICATION_XML
806
            );
807
            $this->xmlWriter->startElementNs(
808
                ODataConstants::ODATA_METADATA_NAMESPACE_PREFIX,
809
                ODataConstants::ATOM_PROPERTIES_ELEMENT_NAME,
810
                null
811
            );
812
        }
813
814
        return $this;
815
    }
816
817
    /**
818
     * Get the final result as string.
819
     *
820
     * @return string output of requested data in Atom format
821
     */
822
    public function getOutput()
823
    {
824
        $this->xmlWriter->endDocument();
825
826
        return $this->xmlWriter->outputMemory(true);
827
    }
828
829
    /**
830
     * @param ProvidersWrapper $providers
831
     *
832
     * @throws ODataException
833
     * @return IODataWriter
834
     */
835
    public function writeServiceDocument(ProvidersWrapper $providers)
836
    {
837
        $writer = $this->xmlWriter;
838
        $writer->startElementNs(
839
            null,
840
            ODataConstants::ATOM_PUBLISHING_SERVICE_ELEMENT_NAME,
841
            ODataConstants::APP_NAMESPACE
842
        );
843
        $writer->writeAttributeNs(
844
            ODataConstants::XML_NAMESPACE_PREFIX,
845
            ODataConstants::XML_BASE_ATTRIBUTE_NAME,
846
            null,
847
            $this->baseUri
848
        );
849
        $writer->writeAttributeNs(
850
            ODataConstants::XMLNS_NAMESPACE_PREFIX,
851
            self::ATOM_NAMESPACE_PREFIX,
852
            null,
853
            ODataConstants::ATOM_NAMESPACE
854
        );
855
        //$writer->writeAttributeNs(
856
        //ODataConstants::XMLNS_NAMESPACE_PREFIX,
857
        //self::APP_NAMESPACE_PREFIX,
858
        //null,
859
        //ODataConstants::APP_NAMESPACE
860
        //);
861
862
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_WORKSPACE_ELEMNT_NAME);
863
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
864
        $writer->text(ODataConstants::ATOM_PUBLISHING_WORKSPACE_DEFAULT_VALUE);
865
        $writer->endElement();
866
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
867
            $name = $resourceSetWrapper->getName();
868
            $this->writeServiceDocumentNode($writer, $name);
869
        }
870
        foreach ($providers->getSingletons() as $single) {
871
            $name = $single->getName();
872
            //start collection node
873
            $this->writeServiceDocumentNode($writer, $name);
874
        }
875
876
        //End workspace and service nodes
877
        $writer->endElement();
878
        $writer->endElement();
879
880
        return $this;
881
    }
882
883
    /**
884
     * @param XMLWriter $writer
885
     * @param $name
886
     */
887
    private function writeServiceDocumentNode(&$writer, $name)
888
    {
889
        //start collection node
890
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_COLLECTION_ELEMENT_NAME);
891
        $writer->writeAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, $name);
892
        //start title node
893
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
894
        $writer->text($name);
895
        //end title node
896
        $writer->endElement();
897
        //end collection node
898
        $writer->endElement();
899
    }
900
}
901