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