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

JsonODataV1Writer::serializeException()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 21
nc 2
nop 2
1
<?php
2
3
namespace POData\Writers\Json;
4
5
use POData\Common\MimeTypes;
6
use POData\Common\ODataConstants;
7
use POData\Common\ODataException;
8
use POData\Common\Version;
9
use POData\ObjectModel\ODataBagContent;
10
use POData\ObjectModel\ODataEntry;
11
use POData\ObjectModel\ODataFeed;
12
use POData\ObjectModel\ODataLink;
13
use POData\ObjectModel\ODataProperty;
14
use POData\ObjectModel\ODataPropertyContent;
15
use POData\ObjectModel\ODataURL;
16
use POData\ObjectModel\ODataURLCollection;
17
use POData\Providers\ProvidersWrapper;
18
use POData\Writers\IODataWriter;
19
20
/**
21
 * Class JsonODataV1Writer is a writer for the json format in OData V1.
22
 */
23
class JsonODataV1Writer implements IODataWriter
24
{
25
    /**
26
     * Json output writer.
27
     */
28
    protected $_writer;
29
30
    protected $urlKey = ODataConstants::JSON_URI_STRING;
31
32
    /**
33
     * Constructs and initializes the Json output writer.
34
     */
35
    public function __construct()
36
    {
37
        $this->_writer = new JsonWriter('');
38
    }
39
40
    /**
41
     * Determines if the given writer is capable of writing the response or not.
42
     *
43
     * @param Version $responseVersion the OData version of the response
44
     * @param string  $contentType     the Content Type of the response
45
     *
46
     * @return bool true if the writer can handle the response, false otherwise
47
     */
48 View Code Duplication
    public function canHandle(Version $responseVersion, $contentType)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
49
    {
50
        if ($responseVersion != Version::v1()) {
51
            return false;
52
        }
53
54
        $parts = explode(';', $contentType);
55
56
        return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts);
57
    }
58
59
    /**
60
     * Write the given OData model in a specific response format.
61
     *
62
     * @param ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content
63
     *
64
     * @return JsonODataV1Writer
65
     */
66 View Code Duplication
    public function write($model)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
67
    {
68
        // { "d" :
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
69
        $this->_writer
70
            ->startObjectScope()
71
            ->writeName('d');
72
73
        if ($model instanceof ODataURL) {
74
            $this->_writer->startObjectScope();
75
            $this->writeURL($model);
76
        } elseif ($model instanceof ODataURLCollection) {
77
            $this->_writer->startArrayScope();
78
            $this->writeURLCollection($model);
79
        } elseif ($model instanceof ODataPropertyContent) {
80
            $this->_writer->startObjectScope();
81
            $this->writeProperties($model);
82
        } elseif ($model instanceof ODataFeed) {
83
            $this->_writer->startArrayScope();
84
            $this->writeFeed($model);
85
        } elseif ($model instanceof ODataEntry) {
86
            $this->_writer->startObjectScope();
87
            $this->writeEntry($model);
88
        }
89
90
        $this->_writer->endScope();
91
        $this->_writer->endScope();
92
93
        return $this;
94
    }
95
96
    /**
97
     * @param ODataURL $url the url to write
98
     *
99
     * @return JsonODataV1Writer
100
     */
101
    public function writeUrl(ODataURL $url)
102
    {
103
        $this->_writer
104
            ->writeName($this->urlKey)
105
            ->writeValue($url->url);
106
107
        return $this;
108
    }
109
110
    /**
111
     * begin write OData links.
112
     *
113
     * @param ODataURLCollection $urls url collection to write
114
     *
115
     * @return JsonODataV1Writer
116
     */
117
    public function writeUrlCollection(ODataURLCollection $urls)
118
    {
119
        foreach ($urls->urls as $url) {
120
            $this->_writer->startObjectScope();
121
            $this->writeUrl($url);
122
            $this->_writer->endScope();
123
        }
124
125
        return $this;
126
    }
127
128
    /**
129
     * Start writing a feed.
130
     *
131
     * @param ODataFeed $feed Feed to write
132
     *
133
     * @return JsonODataV1Writer
134
     */
135
    protected function writeFeed(ODataFeed $feed)
136
    {
137
        foreach ($feed->entries as $entry) {
138
            $this->_writer->startObjectScope();
139
            $this->writeEntry($entry);
140
            $this->_writer->endScope();
141
        }
142
143
        return $this;
144
    }
145
146
    /**
147
     * @param ODataEntry $entry Entry to write
148
     *
149
     * @return JsonODataV1Writer
150
     */
151
    protected function writeEntry(ODataEntry $entry)
152
    {
153
        $this->writeEntryMetadata($entry);
154
        foreach ($entry->links as $link) {
155
            $this->writeLink($link);
156
        }
157
158
        $this->writeProperties($entry->propertyContent);
159
160
        return $this;
161
    }
162
163
    /**
164
     * Write metadata information for the entry.
165
     *
166
     * @param ODataEntry $entry Entry to write metadata for
167
     *
168
     * @return JsonODataV1Writer
169
     */
170
    protected function writeEntryMetadata(ODataEntry $entry)
171
    {
172
        // __metadata : { uri: "Uri", type: "Type" [Media Link Properties] }
173
        if ($entry->id != null || $entry->type != null || $entry->eTag != null) {
174
            // "__metadata"
175
            $this->_writer
176
                ->writeName(ODataConstants::JSON_METADATA_STRING)
177
                ->startObjectScope();
178
179
            // Write uri value only for entity types
180
            if ($entry->id != null) {
181
                $this->_writer
182
                    ->writeName($this->urlKey)
183
                    ->writeValue($entry->id);
184
            }
185
186
            // Write the etag property, if the entry has etag properties.
187
            if ($entry->eTag != null) {
188
                $this->_writer
189
                    ->writeName(ODataConstants::JSON_ETAG_STRING)
190
                    ->writeValue($entry->eTag);
191
            }
192
193
            // Write the type property, if the entry has type properties.
194
            if ($entry->type != null) {
195
                $this->_writer
196
                    ->writeName(ODataConstants::JSON_TYPE_STRING)
197
                    ->writeValue($entry->type);
198
            }
199
        }
200
201
        // Media links.
202
        if ($entry->isMediaLinkEntry) {
203
            if ($entry->mediaLink != null) {
204
                $this->_writer
205
                    ->writeName(ODataConstants::JSON_EDITMEDIA_STRING)
206
                    ->writeValue($entry->mediaLink->editLink)
207
208
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
209
                    ->writeValue($entry->mediaLink->srcLink)
210
211
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
212
                    ->writeValue($entry->mediaLink->contentType);
213
214
                if ($entry->mediaLink->eTag != null) {
215
                    $this->_writer
216
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
217
                        ->writeValue($entry->mediaLink->eTag);
218
                }
219
220
                $this->_writer->endScope();
221
            }
222
223
            // writing named resource streams
224
            foreach ($entry->mediaLinks as $mediaLink) {
225
                $this->_writer
226
                    ->writeName($mediaLink->name)
227
                    ->startObjectScope()
228
229
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
230
                    ->writeValue($mediaLink->srcLink)
231
232
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
233
                    ->writeValue($mediaLink->contentType);
234
235
                if ($mediaLink->eTag != null) {
236
                    $this->_writer
237
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
238
                        ->writeValue($mediaLink->eTag);
239
                }
240
241
                $this->_writer->endScope();
242
            }
243
        } else {
244
            $this->_writer->endScope();
245
        }
246
247
        return $this;
248
    }
249
250
    /**
251
     * @param ODataLink $link Link to write
252
     *
253
     * @return JsonODataV1Writer
254
     */
255
    protected function writeLink(ODataLink $link)
256
    {
257
258
        // "<linkname>" :
259
        $this->_writer->writeName($link->title);
260
261
        if ($link->isExpanded) {
262
            if (is_null($link->expandedResult)) {
263
                $this->_writer->writeValue('null');
264
            } else {
265
                $this->writeExpandedLink($link);
266
            }
267
        } else {
268
            $this->_writer
269
                ->startObjectScope()
270
                ->writeName(ODataConstants::JSON_DEFERRED_STRING)
271
                ->startObjectScope()
272
                ->writeName($this->urlKey)
273
                ->writeValue($link->url)
274
                ->endScope()
275
                ->endScope();
276
        }
277
278
        return $this;
279
    }
280
281 View Code Duplication
    protected function writeExpandedLink(ODataLink $link)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
282
    {
283
        if ($link->isCollection) {
284
            $this->_writer->startArrayScope();
285
            $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\Json\JsonODataV1Writer::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...
286
        } else {
287
            $this->_writer->startObjectScope();
288
            $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\Json\Json...aV1Writer::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...
289
        }
290
291
        $this->_writer->endScope();
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
     *
300
     * @return JsonODataV1Writer
301
     */
302
    protected function writeProperties(ODataPropertyContent $properties)
303
    {
304
        foreach ($properties->properties as $property) {
305
            $this->writePropertyMeta($property);
306
            $this->_writer->writeName($property->name);
307
308
            if ($property->value == null) {
309
                $this->_writer->writeValue('null');
310
            } elseif ($property->value instanceof ODataPropertyContent) {
311
                $this->writeComplexProperty($property);
312
            } elseif ($property->value instanceof ODataBagContent) {
313
                $this->writeBagContent($property->value);
314
            } else {
315
                $this->_writer->writeValue($property->value, $property->typeName);
316
            }
317
        }
318
319
        return $this;
320
    }
321
322
    protected function writePropertyMeta(ODataProperty $property)
323
    {
324
        return $this; //does nothing in v1 or v2, json light outputs stuff
325
    }
326
327
    /**
328
     * Begin write complex property.
329
     *
330
     * @param ODataProperty $property property to write
331
     *
332
     * @return JsonODataV1Writer
333
     */
334
    protected function writeComplexProperty(ODataProperty $property)
335
    {
336
        $this->_writer
337
            // {
338
            ->startObjectScope()
339
340
            // __metadata : { Type : "typename" }
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% 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...
341
            ->writeName(ODataConstants::JSON_METADATA_STRING)
342
            ->startObjectScope()
343
            ->writeName(ODataConstants::JSON_TYPE_STRING)
344
            ->writeValue($property->typeName)
345
            ->endScope();
346
347
        $this->writeProperties($property->value);
0 ignored issues
show
Bug introduced by
It seems like $property->value can also be of type object<POData\ObjectModel\ODataBagContent> or string; however, POData\Writers\Json\Json...iter::writeProperties() does only seem to accept object<POData\ObjectModel\ODataPropertyContent>, 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...
348
349
        $this->_writer->endScope();
350
351
        return $this;
352
    }
353
354
    /**
355
     * Begin an item in a collection.
356
     *
357
     * @param ODataBagContent $bag bag property to write
358
     *
359
     * @return JsonODataV1Writer
360
     */
361
    protected function writeBagContent(ODataBagContent $bag)
362
    {
363
        $this->_writer
364
            ->startObjectScope() // {
365
            ->writeName(ODataConstants::JSON_METADATA_STRING) //__metadata : { Type : "typename" }
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% 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...
366
            ->startObjectScope()
367
368
            ->writeName(ODataConstants::JSON_TYPE_STRING)
369
            ->writeValue($bag->type)
370
            ->endScope()  // }
371
            ->writeName(ODataConstants::JSON_RESULT_NAME) // "__results":
372
            ->startArrayScope(); // [
373
374 View Code Duplication
        foreach ($bag->propertyContents as $content) {
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...
375
            if ($content instanceof ODataPropertyContent) {
376
                $this->_writer->startObjectScope();
377
                $this->writeProperties($content);
378
                $this->_writer->endScope();
379
            } else {
380
                // retrieving the collection datatype in order
381
                //to write in json specific format, with in chords or not
382
                preg_match('#\((.*?)\)#', $bag->type, $type);
383
                $this->_writer->writeValue($content, $type[1]);
384
            }
385
        }
386
387
        $this->_writer
388
            ->endScope()  // ]
389
            ->endScope(); // }
390
        return $this;
391
    }
392
393
    /**
394
     * serialize exception.
395
     *
396
     * @param ODataException $exception               Exception to serialize
397
     * @param bool           $serializeInnerException if set to true
398
     *
399
     * serialize the inner exception if $exception is an ODataException
400
     *
401
     * @return string
402
     */
403
    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...
404
    {
405
        $writer = new JsonWriter('');
406
        // Wrapper for error.
407
        $writer
408
            ->startObjectScope()
409
            ->writeName(ODataConstants::JSON_ERROR) // "error"
410
            ->startObjectScope();
411
412
        // "code"
413
        if ($exception->getCode() != null) {
414
            $writer
415
                ->writeName(ODataConstants::JSON_ERROR_CODE)
416
                ->writeValue($exception->getCode());
417
        }
418
419
        // "message"
420
        $writer
421
            ->writeName(ODataConstants::JSON_ERROR_MESSAGE)
422
            ->startObjectScope()
423
            ->writeName(ODataConstants::XML_LANG_ATTRIBUTE_NAME) // "lang"
424
            ->writeValue('en-US')
425
            ->writeName(ODataConstants::JSON_ERROR_VALUE)
426
            ->writeValue($exception->getMessage())
427
428
            ->endScope()
429
            ->endScope()
430
            ->endScope();
431
432
        return $writer->getJsonOutput();
433
    }
434
435
    /**
436
     * Get the Json final output.
437
     *
438
     * @return string
439
     */
440
    public function getOutput()
441
    {
442
        return $this->_writer->getJsonOutput();
443
    }
444
445
    /**
446
     * @param ProvidersWrapper $providers
447
     *
448
     * @return IODataWriter
449
     */
450
    public function writeServiceDocument(ProvidersWrapper $providers)
451
    {
452
        $writer = $this->_writer;
453
        $writer
454
            ->startObjectScope() // {
455
            ->writeName('d') //  "d" :
456
            ->startObjectScope() // {
457
            ->writeName(ODataConstants::ENTITY_SET) // "EntitySets"
458
            ->startArrayScope() // [
459
        ;
460
461
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
462
            $writer->writeValue($resourceSetWrapper->getName());
463
        }
464
        foreach ($providers->getSingletons() as $singleton) {
465
            $writer->writeValue($singleton->getName());
466
        }
467
468
        $writer
469
            ->endScope() // ]
470
            ->endScope() // }
471
            ->endScope() // }
472
        ;
473
474
        return $this;
475
    }
476
}
477