Test Failed
Push — master ( a1e735...534e7d )
by Bálint
13:42 queued 13s
created

JsonODataV1Writer::clear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
namespace POData\Writers\Json;
4
5
use POData\ObjectModel\ODataFeed;
6
use POData\ObjectModel\ODataEntry;
7
use POData\ObjectModel\ODataURLCollection;
8
use POData\ObjectModel\ODataURL;
9
use POData\ObjectModel\ODataLink;
10
use POData\ObjectModel\ODataPropertyContent;
11
use POData\ObjectModel\ODataBagContent;
12
use POData\ObjectModel\ODataProperty;
13
use POData\Writers\Json\JsonWriter;
14
use POData\Writers\IODataWriter;
15
use POData\Common\Version;
16
use POData\Common\ODataConstants;
17
use POData\Common\MimeTypes;
18
use POData\Common\ODataException;
19
use POData\Providers\ProvidersWrapper;
20
21
/**
22
 * Class JsonODataV1Writer is a writer for the json format in OData V1
23
 * @package POData\Writers\Json
24
 */
25
class JsonODataV1Writer implements IODataWriter
26
{
27
    /**
28
     * Json output writer.
29
     *
30
     */
31
    protected $_writer;
32
33
34
    protected $urlKey = ODataConstants::JSON_URI_STRING;
35
36
    /**
37
     * Constructs and initializes the Json output writer.
38
     *
39
     */
40
    public function __construct()
41
    {
42
        $this->_writer = new JsonWriter('');
43
    }
44
    
45
    public function clear()
46
    {
47
        $this->_writer->clear();
48
    }
49
50
    /**
51
     * Determines if the given writer is capable of writing the response or not
52
     * @param Version $responseVersion the OData version of the response
53
     * @param string $contentType the Content Type of the response
54
     * @return boolean true if the writer can handle the response, false otherwise
55
     */
56
    public function canHandle(Version $responseVersion, $contentType)
57
    {
58
        if ($responseVersion != Version::v1()) {
59
            return false;
60
        }
61
62
        $parts = explode(";", $contentType);
63
64
        return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts);
65
    }
66
67
    /**
68
     * Write the given OData model in a specific response format
69
     *
70
     * @param  ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content.
71
     *
72
     * @return JsonODataV1Writer
73
     */
74
    public function write($model) {
75
        // { "d" :
76
        $this->_writer
77
            ->startObjectScope()
78
            ->writeName("d");
79
80
81
        if ($model instanceof ODataURL) {
82
            $this->_writer->startObjectScope();
83
            $this->writeURL($model);
84
        } elseif ($model instanceof ODataURLCollection) {
85
            $this->_writer->startArrayScope();
86
            $this->writeURLCollection($model);
87
        } elseif ($model instanceof ODataPropertyContent) {
88
            $this->_writer->startObjectScope();
89
            $this->writeProperties($model);
90
        } elseif ($model instanceof ODataFeed) {
91
            $this->_writer->startArrayScope();
92
            $this->writeFeed($model);
93
        } elseif ($model instanceof ODataEntry) {
0 ignored issues
show
introduced by
$model is always a sub-type of POData\ObjectModel\ODataEntry.
Loading history...
94
            $this->_writer->startObjectScope();
95
            $this->writeEntry($model);
96
        }
97
98
99
        $this->_writer->endScope();
100
        $this->_writer->endScope();
101
102
        return $this;
103
    }
104
105
106
    /**
107
     * @param ODataURL $url the url to write
108
     *
109
     * @return JsonODataV1Writer
110
     */
111
    public function writeUrl(ODataURL $url)
112
    {
113
        $this->_writer
114
            ->writeName($this->urlKey)
115
            ->writeValue($url->url);
116
117
        return $this;
118
    }
119
120
    /**
121
     * begin write OData links
122
     *
123
     * @param ODataURLCollection $urls url collection to write
124
     *
125
     * @return JsonODataV1Writer
126
     */
127
    public function writeUrlCollection(ODataURLCollection $urls)
128
    {
129
        foreach ($urls->urls as $url) {
130
            $this->_writer->startObjectScope();
131
            $this->writeUrl($url);
132
            $this->_writer->endScope();
133
        }
134
        return $this;
135
    }
136
137
    /**
138
     * Start writing a feed
139
     *
140
     * @param ODataFeed $feed Feed to write
141
     *
142
     * @return JsonODataV1Writer
143
     */
144
    protected function writeFeed(ODataFeed $feed)
145
    {
146
147
        foreach ($feed->entries as $entry) {
148
            $this->_writer->startObjectScope();
149
            $this->writeEntry($entry);
150
            $this->_writer->endScope();
151
        }
152
153
154
        return $this;
155
    }
156
157
158
159
160
    /**
161
     * @param ODataEntry $entry Entry to write
162
     *
163
     * @return JsonODataV1Writer
164
     */
165
    protected function writeEntry(ODataEntry $entry)
166
    {
167
168
        $this->writeEntryMetadata($entry);
169
        foreach ($entry->links as $link) {
170
            $this->writeLink($link);
171
        }
172
173
        $this->writeCustomProperties($entry->customProperties);
0 ignored issues
show
Bug introduced by
$entry->customProperties of type array is incompatible with the type POData\ObjectModel\ODataPropertyContent expected by parameter $properties of POData\Writers\Json\Json...writeCustomProperties(). ( Ignorable by Annotation )

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

173
        $this->writeCustomProperties(/** @scrutinizer ignore-type */ $entry->customProperties);
Loading history...
174
175
        $this->writeProperties($entry->propertyContent);
176
177
178
        return $this;
179
    }
180
181
    /**
182
     * Write metadata information for the entry.
183
     *
184
     * @param ODataEntry $entry Entry to write metadata for.
185
     *
186
     * @return JsonODataV1Writer
187
     */
188
    protected function writeEntryMetadata(ODataEntry $entry)
189
    {
190
        // __metadata : { uri: "Uri", type: "Type" [Media Link Properties] }
191
        if ($entry->id != null || $entry->type != null || $entry->eTag != null) {
192
            // "__metadata"
193
            $this->_writer
194
                ->writeName(ODataConstants::JSON_METADATA_STRING)
195
                ->startObjectScope();
196
197
            // Write uri value only for entity types
198
            if ($entry->id != null) {
199
                $this->_writer
200
                    ->writeName($this->urlKey)
201
                    ->writeValue($entry->id);
202
            }
203
204
            // Write the etag property, if the entry has etag properties.
205
            if ($entry->eTag != null) {
206
                $this->_writer
207
                    ->writeName(ODataConstants::JSON_ETAG_STRING)
208
                    ->writeValue($entry->eTag);
209
            }
210
211
            // Write the type property, if the entry has type properties.
212
            if ($entry->type != null) {
213
                $this->_writer
214
                    ->writeName(ODataConstants::JSON_TYPE_STRING)
215
                    ->writeValue($entry->type);
216
            }
217
        }
218
219
        // Media links.
220
        if ($entry->isMediaLinkEntry) {
221
            if ($entry->mediaLink != null) {
222
                $this->_writer
223
                    ->writeName(ODataConstants::JSON_EDITMEDIA_STRING)
224
                    ->writeValue($entry->mediaLink->editLink)
225
226
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
227
                    ->writeValue($entry->mediaLink->srcLink)
228
229
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
230
                    ->writeValue($entry->mediaLink->contentType);
231
232
                if ($entry->mediaLink->eTag != null) {
233
                    $this->_writer
234
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
235
                        ->writeValue($entry->mediaLink->eTag);
236
                }
237
238
                $this->_writer->endScope();
239
            }
240
241
            // writing named resource streams
242
            foreach ($entry->mediaLinks as $mediaLink) {
243
                $this->_writer
244
                    ->writeName($mediaLink->name)
245
                    ->startObjectScope()
246
247
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
248
                    ->writeValue($mediaLink->srcLink)
249
250
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
251
                    ->writeValue($mediaLink->contentType);
252
253
                if ($mediaLink->eTag != null) {
254
                    $this->_writer
255
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
256
                        ->writeValue($mediaLink->eTag);
257
                }
258
259
                $this->_writer->endScope();
260
            }
261
        } else {
262
            $this->_writer->endScope();
263
        }
264
265
        return $this;
266
    }
267
268
269
    /**
270
     * @param ODataLink $link Link to write.
271
     *
272
     * @return JsonODataV1Writer
273
     */
274
    protected function writeLink(ODataLink $link)
275
    {
276
277
        // "<linkname>" :
278
        $this->_writer->writeName($link->title);
279
280
        if ($link->isExpanded) {
281
            if (is_null($link->expandedResult)) {
282
                $this->_writer->writeValue("null");
283
            } else {
284
                $this->writeExpandedLink($link);
285
            }
286
        } else {
287
            $this->_writer
288
                ->startObjectScope()
289
                ->writeName(ODataConstants::JSON_DEFERRED_STRING)
290
                ->startObjectScope()
291
                ->writeName($this->urlKey)
292
                ->writeValue($link->url)
293
                ->endScope()
294
                ->endScope()
295
            ;
296
        }
297
298
        return $this;
299
    }
300
301
    protected function writeExpandedLink(ODataLink $link)
302
    {
303
        if ($link->isCollection) {
304
            $this->_writer->startArrayScope();
305
            $this->writeFeed($link->expandedResult);
0 ignored issues
show
Bug introduced by
It seems like $link->expandedResult can also be of type POData\ObjectModel\ODataEntry; however, parameter $feed of POData\Writers\Json\JsonODataV1Writer::writeFeed() does only seem to accept POData\ObjectModel\ODataFeed, maybe add an additional type check? ( Ignorable by Annotation )

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

305
            $this->writeFeed(/** @scrutinizer ignore-type */ $link->expandedResult);
Loading history...
306
        } else {
307
            $this->_writer->startObjectScope();
308
            $this->writeEntry($link->expandedResult);
0 ignored issues
show
Bug introduced by
It seems like $link->expandedResult can also be of type POData\ObjectModel\ODataFeed; however, parameter $entry of POData\Writers\Json\Json...aV1Writer::writeEntry() does only seem to accept POData\ObjectModel\ODataEntry, maybe add an additional type check? ( Ignorable by Annotation )

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

308
            $this->writeEntry(/** @scrutinizer ignore-type */ $link->expandedResult);
Loading history...
309
        }
310
311
        $this->_writer->endScope();
312
    }
313
314
315
    /**
316
     * Write the given collection of properties.
317
     * (properties of an entity or complex type)
318
     *
319
     * @param ODataPropertyContent $properties Collection of properties.
320
     *
321
     * @return JsonODataV1Writer
322
     */
323
    protected function writeCustomProperties(ODataPropertyContent $properties)
324
    {
325
        foreach ($properties->properties as $name => $property) {
326
327
            $this->writePropertyMeta($property);
328
            $this->_writer->writeName($property->name);
329
330
            if (is_null($property->value)) {
331
                $this->_writer->writeValue("null");
332
            } elseif ($property->value instanceof ODataPropertyContent) {
333
                $this->writeComplexProperty($property);
334
            } elseif ($property->value instanceof ODataBagContent) {
335
                $this->writeBagContent($property->value);
336
            } else {
337
                $this->_writer->writeValue($property->value, $property->typeName);
338
            }
339
        }
340
        return $this;
341
    }
342
343
344
    /**
345
     * Write the given collection of properties.
346
     * (properties of an entity or complex type)
347
     *
348
     * @param ODataPropertyContent $properties Collection of properties.
349
     *
350
     * @return JsonODataV1Writer
351
     */
352
    protected function writeProperties(ODataPropertyContent $properties)
353
    {
354
        foreach ($properties->properties as $property) {
355
356
            $this->writePropertyMeta($property);
357
            $this->_writer->writeName($property->name);
358
359
            if (is_null($property->value)) {
360
                $this->_writer->writeValue("null");
361
            } elseif ($property->value instanceof ODataPropertyContent) {
362
                $this->writeComplexProperty($property);
363
            } elseif ($property->value instanceof ODataBagContent) {
364
                $this->writeBagContent($property->value);
365
            } else {
366
                $this->_writer->writeValue($property->value, $property->typeName);
367
            }
368
369
        }
370
371
        return $this;
372
    }
373
374
375
    protected function writePropertyMeta(ODataProperty $property)
0 ignored issues
show
Unused Code introduced by
The parameter $property is not used and could be removed. ( Ignorable by Annotation )

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

375
    protected function writePropertyMeta(/** @scrutinizer ignore-unused */ ODataProperty $property)

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

Loading history...
376
    {
377
        return $this; //does nothing in v1 or v2, json light outputs stuff
378
    }
379
380
    /**
381
     * Begin write complex property.
382
     *
383
     * @param ODataProperty $property property to write.
384
     *
385
     * @return JsonODataV1Writer
386
     */
387
    protected function writeComplexProperty(ODataProperty $property)
388
    {
389
390
        $this->_writer
391
            // {
392
            ->startObjectScope()
393
394
            // __metadata : { Type : "typename" }
395
            ->writeName(ODataConstants::JSON_METADATA_STRING)
396
            ->startObjectScope()
397
            ->writeName(ODataConstants::JSON_TYPE_STRING)
398
            ->writeValue($property->typeName)
399
            ->endScope();
400
401
        $this->writeProperties($property->value);
402
403
        $this->_writer->endScope();
404
405
        return $this;
406
    }
407
408
409
    /**
410
     * Begin an item in a collection
411
     *
412
     * @param ODataBagContent $bag bag property to write
413
     *
414
     * @return JsonODataV1Writer
415
     */
416
    protected function writeBagContent(ODataBagContent $bag)
417
    {
418
419
        $this->_writer
420
            ->startObjectScope() // {
421
            ->writeName(ODataConstants::JSON_METADATA_STRING) //__metadata : { Type : "typename" }
422
            ->startObjectScope()
423
424
            ->writeName(ODataConstants::JSON_TYPE_STRING)
425
            ->writeValue($bag->type)
426
            ->endScope()  // }
427
            ->writeName(ODataConstants::JSON_RESULT_NAME) // "__results":
428
            ->startArrayScope(); // [
429
430
        foreach ($bag->propertyContents as $content) {
431
            if ($content instanceof ODataPropertyContent) {
432
                $this->_writer->startObjectScope();
433
                $this->writeProperties($content);
434
                $this->_writer->endScope();
435
            } else {
436
                // retrieving the collection datatype in order
437
                //to write in json specific format, with in chords or not
438
                preg_match('#\((.*?)\)#', $bag->type, $type);
439
                $this->_writer->writeValue($content, $type[1]);
440
            }
441
        }
442
443
444
        $this->_writer
445
            ->endScope()  // ]
446
            ->endScope(); // }
447
        return $this;
448
    }
449
450
451
452
453
    /**
454
     * serialize exception.
455
     *
456
     * @param ODataException $exception              Exception to serialize
457
     * @param Boolean        $serializeInnerException if set to true
458
     *
459
     * serialize the inner exception if $exception is an ODataException.
460
     *
461
     * @return string
462
     */
463
    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. ( Ignorable by Annotation )

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

463
    public static function serializeException(ODataException $exception, /** @scrutinizer ignore-unused */ $serializeInnerException)

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

Loading history...
464
    {
465
        $writer = new JsonWriter('');
466
        // Wrapper for error.
467
        $writer
468
            ->startObjectScope()
469
            ->writeName(ODataConstants::JSON_ERROR) // "error"
470
            ->startObjectScope();
471
472
        // "code"
473
        if ($exception->getCode() != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $exception->getCode() of type integer|mixed against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
474
            $writer
475
                ->writeName(ODataConstants::JSON_ERROR_CODE)
476
                ->writeValue($exception->getCode());
477
        }
478
479
        // "message"
480
        $writer
481
            ->writeName(ODataConstants::JSON_ERROR_MESSAGE)
482
            ->startObjectScope()
483
            ->writeName(ODataConstants::XML_LANG_ATTRIBUTE_NAME) // "lang"
484
            ->writeValue('en-US')
485
            ->writeName(ODataConstants::JSON_ERROR_VALUE)
486
            ->writeValue($exception->getMessage())
487
488
            ->endScope()
489
            ->endScope()
490
            ->endScope();
491
492
        return $writer->getJsonOutput();
493
    }
494
495
496
497
    /**
498
     * Get the Json final output.
499
     *
500
     * @return string
501
     */
502
    public function getOutput()
503
    {
504
        return $this->_writer->getJsonOutput();
505
    }
506
507
508
    /**
509
     * @param ProvidersWrapper $providers
510
     * @return IODataWriter
511
     */
512
    public function writeServiceDocument(ProvidersWrapper $providers) {
513
        $writer = $this->_writer;
514
        $writer
515
            ->startObjectScope() // {
516
            ->writeName("d") //  "d" :
517
            ->startObjectScope() // {
518
            ->writeName(ODataConstants::ENTITY_SET) // "EntitySets"
519
            ->startArrayScope() // [
520
        ;
521
522
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
523
            $writer->writeValue($resourceSetWrapper->getName());
524
        }
525
526
        $writer
527
            ->endScope() // ]
528
            ->endScope() // }
529
            ->endScope() // }
530
        ;
531
532
        return $this;
533
534
    }
535
}
536