Test Setup Failed
Push — master ( 2bb3c0...689644 )
by Alex
04:15
created

AtomODataWriter   F

Complexity

Total Complexity 71

Size/Duplication

Total Lines 815
Duplicated Lines 3.31 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 71
c 2
b 0
f 1
lcom 1
cbo 13
dl 27
loc 815
rs 3.9024

24 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 2
A canHandle() 0 8 3
B write() 0 24 6
A writeURL() 0 9 1
B writeUrlCollection() 0 35 4
B writeFeed() 0 39 5
A writeEntry() 0 16 2
C writeBeginEntry() 27 117 8
B writeLink() 0 25 4
B writeProperties() 0 21 5
A beforeWriteValue() 0 14 2
B preWriteProperties() 0 42 2
B beginWriteProperty() 0 29 5
A postWriteProperties() 0 9 2
B writeBagContent() 0 24 3
A writeNullValue() 0 13 3
A getOutput() 0 6 1
B serializeException() 0 32 2
A writeNodeValue() 0 8 1
A writeNodeAttributeValue() 0 13 1
B writeLinkNode() 0 29 4
B writeBaseUriAndDefaultNamespaces() 0 25 1
B writeServiceDocument() 0 28 3
A writeServiceDocumentNode() 0 13 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AtomODataWriter often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AtomODataWriter, and based on these observations, apply Extract Interface, too.

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

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
799
800
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_WORKSPACE_ELEMNT_NAME);
801
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
802
        $writer->text(ODataConstants::ATOM_PUBLISHING_WORKSPACE_DEFAULT_VALUE);
803
        $writer->endElement();
804
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
805
            $name = $resourceSetWrapper->getName();
806
            $this->writeServiceDocumentNode($writer, $name);
807
        }
808
        foreach ($providers->getSingletons() as $single) {
809
            $name = $single->getName();
810
            //start collection node
811
            $this->writeServiceDocumentNode($writer, $name);
812
        }
813
814
        //End workspace and service nodes
815
        $writer->endElement();
816
        $writer->endElement();
817
818
        return $this;
819
    }
820
821
    /**
822
     * @param $writer
823
     * @param $name
824
     */
825
    private function writeServiceDocumentNode(&$writer, $name)
826
    {
827
        //start collection node
828
        $writer->startElement(ODataConstants::ATOM_PUBLISHING_COLLECTION_ELEMENT_NAME);
829
        $writer->writeAttribute(ODataConstants::ATOM_HREF_ATTRIBUTE_NAME, $name);
830
        //start title node
831
        $writer->startElementNs(self::ATOM_NAMESPACE_PREFIX, ODataConstants::ATOM_TITLE_ELELMET_NAME, null);
832
        $writer->text($name);
833
        //end title node
834
        $writer->endElement();
835
        //end collection node
836
        $writer->endElement();
837
    }
838
}
839