Passed
Push — master ( 6b2979...464731 )
by Alex
04:00 queued 11s
created

JsonODataV1Writer::writeEntryMetadata()   B

Complexity

Conditions 10
Paths 48

Size

Total Lines 75
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 49
c 2
b 0
f 0
nc 48
nop 1
dl 0
loc 75
rs 7.246

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace POData\Writers\Json;
6
7
use Exception;
8
use POData\Common\MimeTypes;
9
use POData\Common\ODataConstants;
10
use POData\Common\ODataException;
11
use POData\Common\Version;
12
use POData\Configuration\ServiceConfiguration;
13
use POData\ObjectModel\ODataBagContent;
14
use POData\ObjectModel\ODataCategory;
15
use POData\ObjectModel\ODataEntry;
16
use POData\ObjectModel\ODataFeed;
17
use POData\ObjectModel\ODataLink;
18
use POData\ObjectModel\ODataProperty;
19
use POData\ObjectModel\ODataPropertyContent;
20
use POData\ObjectModel\ODataURL;
21
use POData\ObjectModel\ODataURLCollection;
22
use POData\Providers\ProvidersWrapper;
23
use POData\Writers\IODataWriter;
24
25
/**
26
 * Class JsonODataV1Writer is a writer for the json format in OData V1.
27
 */
28
class JsonODataV1Writer implements IODataWriter
29
{
30
    /**
31
     * Json output writer.
32
     */
33
    protected $writer;
34
35
    protected $urlKey = ODataConstants::JSON_URI_STRING;
36
37
    /**
38
     * Constructs and initializes the Json output writer.
39
     */
40
    public function __construct(string $eol, bool $prettyPrint)
41
    {
42
        $this->writer = new JsonWriter('', $eol, $prettyPrint);
43
    }
44
45
    /**
46
     * serialize exception.
47
     *
48
     * @param ODataException $exception Exception to serialize
49
     *
50
     * serialize the inner exception if $exception is an ODataException
51
     *
52
     * @throws Exception
53
     * @return string
54
     */
55
    public static function serializeException(ODataException $exception, ServiceConfiguration $config)
56
    {
57
        $writer = new JsonWriter('', $config->getLineEndings(), $config->getPrettyOutput());
58
        // Wrapper for error.
59
        $writer
60
            ->startObjectScope()
61
            ->writeName(ODataConstants::JSON_ERROR)// "error"
62
            ->startObjectScope();
63
64
        // "code"
65
        if (null !== $exception->getCode()) {
66
            $writer
67
                ->writeName(ODataConstants::JSON_ERROR_CODE)
68
                ->writeValue($exception->getCode());
69
        }
70
71
        // "message"
72
        $writer
73
            ->writeName(ODataConstants::JSON_ERROR_MESSAGE)
74
            ->startObjectScope()
75
            ->writeName(ODataConstants::XML_LANG_ATTRIBUTE_NAME)// "lang"
76
            ->writeValue('en-US')
77
            ->writeName(ODataConstants::JSON_ERROR_VALUE)
78
            ->writeValue($exception->getMessage())
79
            ->endScope()
80
            ->endScope()
81
            ->endScope();
82
83
        return $writer->getJsonOutput();
84
    }
85
86
    /**
87
     * Determines if the given writer is capable of writing the response or not.
88
     *
89
     * @param Version $responseVersion the OData version of the response
90
     * @param string  $contentType     the Content Type of the response
91
     *
92
     * @return bool true if the writer can handle the response, false otherwise
93
     */
94
    public function canHandle(Version $responseVersion, $contentType)
95
    {
96
        if ($responseVersion != Version::v1()) {
97
            return false;
98
        }
99
100
        $parts = explode(';', $contentType);
101
102
        return in_array(MimeTypes::MIME_APPLICATION_JSON, $parts);
103
    }
104
105
    /**
106
     * Write the given OData model in a specific response format.
107
     *
108
     * @param ODataURL|ODataURLCollection|ODataPropertyContent|ODataFeed|ODataEntry $model Object of requested content
109
     *
110
     * @throws Exception
111
     * @return JsonODataV1Writer
112
     */
113
    public function write($model)
114
    {
115
        // { "d" :
116
        $this->writer
117
            ->startObjectScope()
118
            ->writeName('d');
119
120
        if ($model instanceof ODataURL) {
121
            $this->writer->startObjectScope();
122
            $this->writeUrl($model);
123
        } elseif ($model instanceof ODataURLCollection) {
124
            $this->writer->startArrayScope();
125
            $this->writeUrlCollection($model);
126
        } elseif ($model instanceof ODataPropertyContent) {
127
            $this->writer->startObjectScope();
128
            $this->writeProperties($model);
129
        } elseif ($model instanceof ODataFeed) {
130
            $this->writer->startArrayScope();
131
            $this->writeFeed($model);
132
        } elseif ($model instanceof ODataEntry) {
0 ignored issues
show
introduced by
$model is always a sub-type of POData\ObjectModel\ODataEntry.
Loading history...
133
            $this->writer->startObjectScope();
134
            $this->writeEntry($model);
135
        }
136
137
        $this->writer->endScope();
138
        $this->writer->endScope();
139
140
        return $this;
141
    }
142
143
    /**
144
     * @param ODataURL $url the url to write
145
     *
146
     * @throws Exception
147
     * @return JsonODataV1Writer
148
     */
149
    public function writeUrl(ODataURL $url)
150
    {
151
        $this->writer
152
            ->writeName($this->urlKey)
153
            ->writeValue($url->getUrl());
154
155
        return $this;
156
    }
157
158
    /**
159
     * begin write OData links.
160
     *
161
     * @param ODataURLCollection $urls url collection to write
162
     *
163
     * @throws Exception
164
     * @return JsonODataV1Writer
165
     */
166
    public function writeUrlCollection(ODataURLCollection $urls)
167
    {
168
        foreach ($urls->getUrls() as $url) {
169
            $this->writer->startObjectScope();
170
            $this->writeUrl($url);
171
            $this->writer->endScope();
172
        }
173
174
        return $this;
175
    }
176
177
    /**
178
     * Write the given collection of properties.
179
     * (properties of an entity or complex type).
180
     *
181
     * @param ODataPropertyContent $properties Collection of properties
182
     *
183
     * @throws Exception
184
     * @return JsonODataV1Writer
185
     */
186
    protected function writeProperties(ODataPropertyContent $properties = null)
187
    {
188
        if (null !== $properties) {
189
            foreach ($properties as $property) {
190
                $this->writePropertyMeta($property);
191
                $this->writer->writeName($property->getName());
192
193
                if ($property->getValue() == null) {
194
                    $this->writer->writeValue('null');
195
                } elseif ($property->getValue() instanceof ODataPropertyContent) {
196
                    $this->writeComplexProperty($property);
197
                } elseif ($property->getValue() instanceof ODataBagContent) {
198
                    $this->writeBagContent($property->getValue());
199
                } else {
200
                    $this->writer->writeValue($property->getValue(), $property->getTypeName());
201
                }
202
            }
203
        }
204
205
        return $this;
206
    }
207
208
    /**
209
     * @param  ODataProperty $property
210
     * @return $this
211
     */
212
    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

212
    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...
213
    {
214
        return $this; //does nothing in v1 or v2, json light outputs stuff
215
    }
216
217
    /**
218
     * Begin write complex property.
219
     *
220
     * @param ODataProperty $property property to write
221
     *
222
     * @throws Exception
223
     * @return JsonODataV1Writer
224
     */
225
    protected function writeComplexProperty(ODataProperty $property)
226
    {
227
        $this->writer
228
            // {
229
            ->startObjectScope()
230
            // __metadata : { Type : "typename" }
231
            ->writeName(ODataConstants::JSON_METADATA_STRING)
232
            ->startObjectScope()
233
            ->writeName(ODataConstants::JSON_TYPE_STRING)
234
            ->writeValue($property->getTypeName())
235
            ->endScope();
236
237
        $this->writeProperties($property->getValue());
0 ignored issues
show
Bug introduced by
It seems like $property->getValue() can also be of type POData\ObjectModel\ODataBagContent; however, parameter $properties of POData\Writers\Json\Json...iter::writeProperties() does only seem to accept POData\ObjectModel\ODataPropertyContent|null, 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

237
        $this->writeProperties(/** @scrutinizer ignore-type */ $property->getValue());
Loading history...
238
239
        $this->writer->endScope();
240
241
        return $this;
242
    }
243
244
    /**
245
     * Begin an item in a collection.
246
     *
247
     * @param ODataBagContent $bag bag property to write
248
     *
249
     * @throws Exception
250
     * @return JsonODataV1Writer
251
     */
252
    protected function writeBagContent(ODataBagContent $bag)
253
    {
254
        $this->writer
255
            ->startObjectScope()// {
256
            ->writeName(ODataConstants::JSON_METADATA_STRING)//__metadata : { Type : "typename" }
257
            ->startObjectScope()
258
            ->writeName(ODataConstants::JSON_TYPE_STRING)
259
            ->writeValue($bag->getType())
260
            ->endScope()// }
261
            ->writeName(ODataConstants::JSON_RESULT_NAME)// "__results":
262
            ->startArrayScope(); // [
263
264
        foreach ($bag->getPropertyContents() as $content) {
265
            if ($content instanceof ODataPropertyContent) {
266
                $this->writer->startObjectScope();
267
                $this->writeProperties($content);
268
                $this->writer->endScope();
269
            } else {
270
                // retrieving the collection datatype in order
271
                //to write in json specific format, with in chords or not
272
                preg_match('#\((.*?)\)#', $bag->getType(), $type);
273
                $this->writer->writeValue($content, $type[1]);
274
            }
275
        }
276
277
        $this->writer
278
            ->endScope()// ]
279
            ->endScope(); // }
280
        return $this;
281
    }
282
283
    /**
284
     * Start writing a feed.
285
     *
286
     * @param ODataFeed $feed Feed to write
287
     *
288
     * @throws Exception
289
     * @return JsonODataV1Writer
290
     */
291
    protected function writeFeed(ODataFeed $feed)
292
    {
293
        foreach ($feed->getEntries() as $entry) {
294
            $this->writer->startObjectScope();
295
            $this->writeEntry($entry);
296
            $this->writer->endScope();
297
        }
298
299
        return $this;
300
    }
301
302
    /**
303
     * @param ODataEntry $entry Entry to write
304
     *
305
     * @throws Exception
306
     * @return JsonODataV1Writer
307
     */
308
    protected function writeEntry(ODataEntry $entry)
309
    {
310
        $this->writeEntryMetadata($entry);
311
        foreach ($entry->getLinks() as $link) {
312
            $this->writeLink($link);
313
        }
314
315
        $this->writeProperties($entry->propertyContent);
316
317
        return $this;
318
    }
319
320
    /**
321
     * Write metadata information for the entry.
322
     *
323
     * @param ODataEntry $entry Entry to write metadata for
324
     *
325
     * @throws Exception
326
     * @return JsonODataV1Writer
327
     */
328
    protected function writeEntryMetadata(ODataEntry $entry)
329
    {
330
        // "__metadata"
331
        $this->writer
332
            ->writeName(ODataConstants::JSON_METADATA_STRING)
333
            ->startObjectScope();
334
        // __metadata : { uri: "Uri", type: "Type" [Media Link Properties] }
335
        $hasId   = !empty($entry->id);
336
        $hasType = !empty($entry->type);
337
        $hasEtag = !empty($entry->eTag);
338
        // Write uri value only for entity types
339
        if ($hasId) {
340
            $this->writer
341
                ->writeName($this->urlKey)
342
                ->writeValue($entry->id);
343
        }
344
345
        // Write the etag property, if the entry has etag properties.
346
        if ($hasEtag) {
347
            $this->writer
348
                ->writeName(ODataConstants::JSON_ETAG_STRING)
349
                ->writeValue($entry->eTag);
350
        }
351
352
        // Write the type property, if the entry has type properties.
353
        if ($hasType) {
354
            $value = $entry->type instanceof ODataCategory ? $entry->type->getTerm() : $entry->type;
0 ignored issues
show
introduced by
$entry->type is always a sub-type of POData\ObjectModel\ODataCategory.
Loading history...
355
            $this->writer
356
                ->writeName(ODataConstants::JSON_TYPE_STRING)
357
                ->writeValue($value);
358
        }
359
360
        // Media links.
361
        if ($entry->isMediaLinkEntry) {
362
            if ($entry->mediaLink != null) {
363
                $this->writer
364
                    ->writeName(ODataConstants::JSON_EDITMEDIA_STRING)
365
                    ->writeValue($entry->mediaLink->editLink)
366
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
367
                    ->writeValue($entry->mediaLink->srcLink)
368
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
369
                    ->writeValue($entry->mediaLink->contentType);
370
371
                if ($entry->mediaLink->eTag != null) {
372
                    $this->writer
373
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
374
                        ->writeValue($entry->mediaLink->eTag);
375
                }
376
377
                $this->writer->endScope();
378
            }
379
380
            // writing named resource streams
381
            foreach ($entry->mediaLinks as $mediaLink) {
382
                $this->writer
383
                    ->writeName($mediaLink->name)
384
                    ->startObjectScope()
385
                    ->writeName(ODataConstants::JSON_MEDIASRC_STRING)
386
                    ->writeValue($mediaLink->srcLink)
387
                    ->writeName(ODataConstants::JSON_CONTENTTYPE_STRING)
388
                    ->writeValue($mediaLink->contentType);
389
390
                if ($mediaLink->eTag != null) {
391
                    $this->writer
392
                        ->writeName(ODataConstants::JSON_MEDIAETAG_STRING)
393
                        ->writeValue($mediaLink->eTag);
394
                }
395
396
                $this->writer->endScope();
397
            }
398
        } else {
399
            $this->writer->endScope();
400
        }
401
402
        return $this;
403
    }
404
405
    /**
406
     * @param ODataLink $link Link to write
407
     *
408
     * @throws Exception
409
     * @return JsonODataV1Writer
410
     */
411
    protected function writeLink(ODataLink $link)
412
    {
413
414
        // "<linkname>" :
415
        $this->writer->writeName($link->getTitle());
416
417
        if ($link->isExpanded()) {
418
            if (null === $link->getExpandedResult() || null === $link->getExpandedResult()->getData()) {
419
                $this->writer->writeValue('null');
420
            } else {
421
                $this->writeExpandedLink($link);
422
            }
423
        } else {
424
            $this->writer
425
                ->startObjectScope()
426
                ->writeName(ODataConstants::JSON_DEFERRED_STRING)
427
                ->startObjectScope()
428
                ->writeName($this->urlKey)
429
                ->writeValue($link->getUrl())
430
                ->endScope()
431
                ->endScope();
432
        }
433
434
        return $this;
435
    }
436
437
    /**
438
     * @param  ODataLink $link
439
     * @throws Exception
440
     */
441
    protected function writeExpandedLink(ODataLink $link)
442
    {
443
        if ($link->isCollection()) {
444
            $this->writer->startArrayScope();
445
            $this->writeFeed($link->getExpandedResult()->getFeed());
446
        } else {
447
            $this->writer->startObjectScope();
448
            $this->writeEntry($link->getExpandedResult()->getEntry());
449
        }
450
451
        $this->writer->endScope();
452
    }
453
454
    /**
455
     * Get the Json final output.
456
     *
457
     * @return string
458
     */
459
    public function getOutput()
460
    {
461
        return $this->writer->getJsonOutput();
462
    }
463
464
    /**
465
     * @param ProvidersWrapper $providers
466
     *
467
     * @throws Exception
468
     * @return IODataWriter
469
     */
470
    public function writeServiceDocument(ProvidersWrapper $providers)
471
    {
472
        $writer = $this->writer;
473
        $writer
474
            ->startObjectScope()// {
475
            ->writeName('d')//  "d" :
476
            ->startObjectScope()// {
477
            ->writeName(ODataConstants::ENTITY_SET)// "EntitySets"
478
            ->startArrayScope() // [
479
        ;
480
481
        foreach ($providers->getResourceSets() as $resourceSetWrapper) {
482
            $writer->writeValue($resourceSetWrapper->getName());
483
        }
484
        foreach ($providers->getSingletons() as $singleton) {
485
            $writer->writeValue($singleton->getName());
486
        }
487
488
        $writer
489
            ->endScope()// ]
490
            ->endScope()// }
491
            ->endScope() // }
492
        ;
493
494
        return $this;
495
    }
496
}
497