Passed
Pull Request — feature/behat (#14)
by Yo
02:39 queued 10s
created

RawRequestSerializer::populateItem()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 6
nop 2
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 4
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace Yoanm\JsonRpcServer\Infra\Serialization;
4
5
use Yoanm\JsonRpcServer\App\Serialization\RequestDenormalizer;
6
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcInvalidRequestException;
7
use Yoanm\JsonRpcServer\Domain\Exception\JsonRpcParseErrorException;
8
use Yoanm\JsonRpcServer\Infra\RawObject\JsonRpcRawRequest;
9
10
/**
11
 * Class RawRequestSerializer
12
 */
13
class RawRequestSerializer
14
{
15
    /** @var RequestDenormalizer */
16
    private $requestDenormalizer;
17
18
    /**
19
     * @param RequestDenormalizer $requestDenormalizer
20
     */
21 28
    public function __construct(RequestDenormalizer $requestDenormalizer)
22
    {
23 28
        $this->requestDenormalizer = $requestDenormalizer;
24 28
    }
25
26
    /**
27
     * @param string $content
28
     *
29
     * @return JsonRpcRawRequest
30
     */
31 7
    public function deserialize(string $content) : JsonRpcRawRequest
32
    {
33 7
        return $this->denormalize(
34 7
            $this->decode($content)
35
        );
36
    }
37
38
    /**
39
     * @param string $requestContent
40
     *
41
     * @return array Decoded content
42
     *
43
     * @throws JsonRpcParseErrorException
44
     */
45 19
    public function decode(string $requestContent) : array
46
    {
47 19
        $decodedContent = json_decode($requestContent, true);
48
49
        // Check if parsing is ok => Parse error
50 19
        if (JSON_ERROR_NONE !== json_last_error()) {
51 1
            throw new JsonRpcParseErrorException(
52 1
                $requestContent,
53 1
                json_last_error(),
54 1
                json_last_error_msg()
55
            );
56
        }
57
58
        // Content must be either an array (normal request) or an array of array (batch request)
59
        //  => so must be an array
60
        // In case it's a batch call, at least one sub request must exist
61
        // and in case not, some required properties must exist
62
        // => array must have at least one child
63 18
        if (!is_array($decodedContent) || count($decodedContent) === 0) {
64 4
            throw new JsonRpcInvalidRequestException($requestContent);
65
        }
66
67 14
        return $decodedContent;
68
    }
69
70
    /**
71
     * @param array $decodedContent
72
     *
73
     * @return JsonRpcRawRequest
74
     */
75 16
    public function denormalize(array $decodedContent) : JsonRpcRawRequest
76
    {
77 16
        $isBatch = $this->guessBatchOrNot($decodedContent);
78
79 16
        $rawRequest = new JsonRpcRawRequest($isBatch);
80
81 16
        $this->populateItem($rawRequest, $decodedContent);
82
83 16
        return $rawRequest;
84
    }
85
86
    /**
87
     * @param array $decodedContent
88
     *
89
     * @return bool
90
     */
91 16
    private function guessBatchOrNot(array $decodedContent)
92
    {
93 16
        $isBatch = true;
94
        // Loop over each items
95
        // -> In case it's a valid batch request -> all keys will have numeric type -> iterations = Number of requests
96
        // -> In case it's a valid normal request -> all keys will have string type -> iterations = 1 (stopped on #1)
97
        // => Better performance for normal request (Probably most of requests)
98 16
        foreach ($decodedContent as $key => $item) {
99
            // At least a key is a string (that do not contain an int)
100 16
            if (!is_int($key)) {
101 13
                $isBatch = false;
102 16
                break;
103
            }
104
        }
105
106 16
        return $isBatch;
107
    }
108
109
    /**
110
     * @param JsonRpcRawRequest $rawRequest
111
     * @param array $decodedContent
112
     */
113 16
    private function populateItem(JsonRpcRawRequest $rawRequest, array $decodedContent)
114
    {
115
        // convert to array in any cases for simpler use
116 16
        $itemList = $rawRequest->isBatch() ? $decodedContent : [$decodedContent];
117 16
        foreach ($itemList as $item) {
118
            // Safely denormalize items
119
            try {
120 16
                $rawRequest->addRequestItem(
121 16
                    $this->requestDenormalizer->denormalize($item)
122
                );
123 2
            } catch (\Exception $exception) {
124 16
                $rawRequest->addExceptionItem($exception);
125
            }
126
        }
127 16
    }
128
}
129