Test Failed
Pull Request — master (#7)
by
unknown
11:40
created

JsonODataV1Writer::writeCustomProperties()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 18
rs 9.5555
c 0
b 0
f 0
cc 5
nc 5
nop 1
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
    /**
46
     * Determines if the given writer is capable of writing the response or not
47
     * @param Version $responseVersion the OData version of the response
48
     * @param string $contentType the Content Type of the response
49
     * @return boolean true if the writer can handle the response, false otherwise
50
     */
51
    public function canHandle(Version $responseVersion, $contentType)
52
    {
53
        if ($responseVersion != Version::v1()) {
54
            return false;
55
        }
56
57
        $parts = explode(";", $contentType);
58
59
        return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts);
60
    }
61
62
    /**
63
     * Write the given OData model in a specific response format
64
     *
65
     * @param  ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content.
66
     *
67
     * @return JsonODataV1Writer
68
     */
69
    public function write($model) {
70
        // { "d" :
71
        $this->_writer
72
            ->startObjectScope()
73
            ->writeName("d");
74
75
76
        if ($model instanceof ODataURL) {
77
            $this->_writer->startObjectScope();
78
            $this->writeURL($model);
79
        } elseif ($model instanceof ODataURLCollection) {
80
            $this->_writer->startArrayScope();
81
            $this->writeURLCollection($model);
82
        } elseif ($model instanceof ODataPropertyContent) {
83
            $this->_writer->startObjectScope();
84
            $this->writeProperties($model);
85
        } elseif ($model instanceof ODataFeed) {
86
            $this->_writer->startArrayScope();
87
            $this->writeFeed($model);
88
        } elseif ($model instanceof ODataEntry) {
0 ignored issues
show
introduced by
$model is always a sub-type of POData\ObjectModel\ODataEntry.
Loading history...
89
            $this->_writer->startObjectScope();
90
            $this->writeEntry($model);
91
        }
92
93
94
        $this->_writer->endScope();
95
        $this->_writer->endScope();
96
97
        return $this;
98
    }
99
100
101
    /**
102
     * @param ODataURL $url the url to write
103
     *
104
     * @return JsonODataV1Writer
105
     */
106
    public function writeUrl(ODataURL $url)
107
    {
108
        $this->_writer
109
            ->writeName($this->urlKey)
110
            ->writeValue($url->url);
111
112
        return $this;
113
    }
114
115
    /**
116
     * begin write OData links
117
     *
118
     * @param ODataURLCollection $urls url collection to write
119
     *
120
     * @return JsonODataV1Writer
121
     */
122
    public function writeUrlCollection(ODataURLCollection $urls)
123
    {
124
        foreach ($urls->urls as $url) {
125
            $this->_writer->startObjectScope();
126
            $this->writeUrl($url);
127
            $this->_writer->endScope();
128
        }
129
        return $this;
130
    }
131
132
    /**
133
     * Start writing a feed
134
     *
135
     * @param ODataFeed $feed Feed to write
136
     *
137
     * @return JsonODataV1Writer
138
     */
139
    protected function writeFeed(ODataFeed $feed)
140
    {
141
142
        foreach ($feed->entries as $entry) {
143
            $this->_writer->startObjectScope();
144
            $this->writeEntry($entry);
145
            $this->_writer->endScope();
146
        }
147
148
149
        return $this;
150
    }
151
152
153
154
155
    /**
156
     * @param ODataEntry $entry Entry to write
157
     *
158
     * @return JsonODataV1Writer
159
     */
160
    protected function writeEntry(ODataEntry $entry)
161
    {
162
163
        $this->writeEntryMetadata($entry);
164
        foreach ($entry->links as $link) {
165
            $this->writeLink($link);
166
        }
167
168
        $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

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

300
            $this->writeFeed(/** @scrutinizer ignore-type */ $link->expandedResult);
Loading history...
301
        } else {
302
            $this->_writer->startObjectScope();
303
            $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

303
            $this->writeEntry(/** @scrutinizer ignore-type */ $link->expandedResult);
Loading history...
304
        }
305
306
        $this->_writer->endScope();
307
    }
308
309
310
    /**
311
     * Write the given collection of properties.
312
     * (properties of an entity or complex type)
313
     *
314
     * @param ODataPropertyContent $properties Collection of properties.
315
     *
316
     * @return JsonODataV1Writer
317
     */
318
    protected function writeCustomProperties(ODataPropertyContent $properties)
319
    {
320
        foreach ($properties->properties as $name => $property) {
321
322
            $this->writePropertyMeta($property);
323
            $this->_writer->writeName($property->name);
324
325
            if ($property->value == null) {
326
                $this->_writer->writeValue("null");
327
            } elseif ($property->value instanceof ODataPropertyContent) {
328
                $this->writeComplexProperty($property);
329
            } elseif ($property->value instanceof ODataBagContent) {
330
                $this->writeBagContent($property->value);
331
            } else {
332
                $this->_writer->writeValue($property->value, $property->typeName);
333
            }
334
        }
335
        return $this;
336
    }
337
338
339
    /**
340
     * Write the given collection of properties.
341
     * (properties of an entity or complex type)
342
     *
343
     * @param ODataPropertyContent $properties Collection of properties.
344
     *
345
     * @return JsonODataV1Writer
346
     */
347
    protected function writeProperties(ODataPropertyContent $properties)
348
    {
349
        foreach ($properties->properties as $property) {
350
351
            $this->writePropertyMeta($property);
352
            $this->_writer->writeName($property->name);
353
354
            if ($property->value == null) {
355
                $this->_writer->writeValue("null");
356
            } elseif ($property->value instanceof ODataPropertyContent) {
357
                $this->writeComplexProperty($property);
358
            } elseif ($property->value instanceof ODataBagContent) {
359
                $this->writeBagContent($property->value);
360
            } else {
361
                $this->_writer->writeValue($property->value, $property->typeName);
362
            }
363
364
        }
365
366
        return $this;
367
    }
368
369
370
    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

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

458
    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...
459
    {
460
        $writer = new JsonWriter('');
461
        // Wrapper for error.
462
        $writer
463
            ->startObjectScope()
464
            ->writeName(ODataConstants::JSON_ERROR) // "error"
465
            ->startObjectScope();
466
467
        // "code"
468
        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...
469
            $writer
470
                ->writeName(ODataConstants::JSON_ERROR_CODE)
471
                ->writeValue($exception->getCode());
472
        }
473
474
        // "message"
475
        $writer
476
            ->writeName(ODataConstants::JSON_ERROR_MESSAGE)
477
            ->startObjectScope()
478
            ->writeName(ODataConstants::XML_LANG_ATTRIBUTE_NAME) // "lang"
479
            ->writeValue('en-US')
480
            ->writeName(ODataConstants::JSON_ERROR_VALUE)
481
            ->writeValue($exception->getMessage())
482
483
            ->endScope()
484
            ->endScope()
485
            ->endScope();
486
487
        return $writer->getJsonOutput();
488
    }
489
490
491
  
492
    /**
493
     * Get the Json final output.
494
     *
495
     * @return string
496
     */
497
    public function getOutput()
498
    {
499
        return $this->_writer->getJsonOutput();
500
    }
501
502
503
    /**
504
     * @param ProvidersWrapper $providers
505
     * @return IODataWriter
506
     */
507
    public function writeServiceDocument(ProvidersWrapper $providers) {
508
        $writer = $this->_writer;
509
        $writer
510
            ->startObjectScope() // {
511
            ->writeName("d") //  "d" :
512
            ->startObjectScope() // {
513
            ->writeName(ODataConstants::ENTITY_SET) // "EntitySets"
514
            ->startArrayScope() // [
515
        ;
516
517
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
518
            $writer->writeValue($resourceSetWrapper->getName());
519
        }
520
521
        $writer
522
            ->endScope() // ]
523
            ->endScope() // }
524
            ->endScope() // }
525
        ;
526
527
        return $this;
528
529
    }
530
}