Completed
Pull Request — feature/app (#9)
by Yo
01:41
created

RawRequestSerializer::decode()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 20
ccs 10
cts 10
cp 1
crap 3
rs 9.4285
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
    const KEY_JSON_RPC = 'json-rpc';
16
    const KEY_ID = 'id';
17
    const KEY_METHOD = 'method';
18
    const KEY_PARAM_LIST = 'params';
19
20
    /** @var RequestDenormalizer */
21
    private $requestDenormalizer;
22
23
    /**
24
     * @param RequestDenormalizer $requestDenormalizer
25
     */
26 28
    public function __construct(RequestDenormalizer $requestDenormalizer)
27
    {
28 28
        $this->requestDenormalizer = $requestDenormalizer;
29 28
    }
30
31
    /**
32
     * @param string $content
33
     *
34
     * @return JsonRpcRawRequest
35
     */
36 7
    public function deserialize(string $content) : JsonRpcRawRequest
37
    {
38 7
        return $this->denormalize(
39 7
            $this->decode($content)
40
        );
41
    }
42
43
    /**
44
     * @param string $requestContent
45
     *
46
     * @return array Decoded content
47
     *
48
     * @throws JsonRpcParseErrorException
49
     */
50 19
    public function decode(string $requestContent) : array
51
    {
52 19
        $decodedContent = json_decode($requestContent, true);
53
54
        // Check if parsing is ok => Parse error
55 19
        if (JSON_ERROR_NONE !== json_last_error()) {
56 1
            throw new JsonRpcParseErrorException(
57 1
                $requestContent,
58 1
                json_last_error(),
59 1
                json_last_error_msg()
60
            );
61
        }
62
63
        // Content must be either an array (normal request) or an array of array (batch request)
64
        //  => so must be an array
65 18
        if (!is_array($decodedContent)) {
66 4
            throw new JsonRpcInvalidRequestException($requestContent);
67
        }
68
69 14
        return $decodedContent;
70
    }
71
72
    /**
73
     * @param array $decodedContent
74
     *
75
     * @return JsonRpcRawRequest
76
     */
77 16
    public function denormalize(array $decodedContent) : JsonRpcRawRequest
78
    {
79 16
        $isBatch = true;
80
        // Loop over each items
81
        // -> In case it's a valid batch request -> all keys will have numeric type -> iterations = Number of requests
82
        // -> In case it's a valid normal request -> all keys will have string type -> iterations = 1 (stopped on #1)
83
        // => Better performance for normal request (Probably most of requests)
84 16
        foreach ($decodedContent as $key => $item) {
85
            // At least a key is a string (that do not contain an int)
86 16
            if (!is_int($key)) {
87 13
                $isBatch = false;
88 16
                break;
89
            }
90
        }
91
92 16
        $rawRequest = new JsonRpcRawRequest($isBatch);
93
94
        // convert to array in any cases for simpler use
95 16
        $itemList = $isBatch ? $decodedContent : [$decodedContent];
96 16
        foreach ($itemList as $item) {
97
            // Safely denormalize items
98
            try {
99 16
                $rawRequest->addRequestItem(
100 16
                    $this->requestDenormalizer->denormalize($item)
101
                );
102 2
            } catch (\Exception $exception) {
103 16
                $rawRequest->addExceptionItem($exception);
104
            }
105
        }
106
107 16
        return $rawRequest;
108
    }
109
}
110