Passed
Push — master ( 55ced3...b98498 )
by Radu
02:14
created

AbstractClientRequest::verify()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
namespace WebServCo\Api;
3
4
use WebServCo\Api\JsonApi\Structure;
5
use WebServCo\Framework\Exceptions\HttpException;
6
7
abstract class AbstractClientRequest
8
{
9
    protected $allowMultipleDataObjects;
10
    protected $request;
11
    protected $processRequestData;
12
    protected $requestData;
13
14
    const MSG_TPL_INVALID = 'Invalid data: %s';
15
    const MSG_TPL_REQUIRED = 'Missing required data: %s';
16
17
    public function __construct(
18
        \WebServCo\Framework\Interfaces\RequestInterface $request
19
    ) {
20
        $this->allowMultipleDataObjects = false;
21
        $this->request = $request;
22
        $requestMethod = $this->request->getMethod();
23
        if (in_array($requestMethod, [\WebServCo\Framework\Http::METHOD_POST])) {
24
            $this->processRequestData = true;
25
            $this->requestData = json_decode($this->request->getBody(), true);
26
        }
27
    }
28
29
    protected function verify()
30
    {
31
        $this->verifyContentType();
32
        if ($this->processRequestData) {
33
            $this->verifyRequestData();
34
        }
35
        return true;
36
    }
37
38
    protected function verifyContentType()
39
    {
40
        $contentType = $this->request->getContentType();
41
        $parts = explode(';', $contentType);
42
        if ($parts[0] != Structure::CONTENT_TYPE) {
43
            throw new \WebServCo\Framework\Exceptions\UnsupportedMediaTypeException('Unsupported content type');
44
        }
45
        return true;
46
    }
47
48
    protected function verifyRequestData()
49
    {
50
        if (!is_array($this->requestData)) {
51
            throw new HttpException(sprintf(self::MSG_TPL_INVALID, 'root object'));
52
        }
53
        foreach (['jsonapi', 'data'] as $item) {
54
            if (!isset($this->requestData[$item])) {
55
                throw new HttpException(sprintf(self::MSG_TPL_REQUIRED, $item));
56
            }
57
        }
58
        if (!isset($this->requestData['jsonapi']['version'])) {
59
            throw new HttpException(sprintf(self::MSG_TPL_REQUIRED, 'jsonapi.version'));
60
        }
61
        if ($this->requestData['jsonapi']['version'] != Structure::VERSION) {
62
            throw new HttpException(
63
                sprintf('Unsupported JSON API version: %s', $this->requestData['jsonapi']['version'])
64
            );
65
        }
66
        if (!is_array($this->requestData['data'])) {
67
            throw new HttpException(sprintf(self::MSG_TPL_INVALID, 'data'));
68
        }
69
        $key = key($this->requestData['data']);
70
        if (0 === $key) { //multiple data objects
71
            if (!$this->allowMultipleDataObjects) {
72
                throw new HttpException('Multiple data objects not allowed for this endpoint');
73
            }
74
            foreach ($this->requestData['data'] as $item) {
75
                $this->verifyData($item);
76
            }
77
        } else { // single data object
78
            $this->verifyData($this->requestData['data']);
79
        }
80
        $this->verifyMeta();
81
82
        return true;
83
    }
84
85
    protected function verifyData($data)
86
    {
87
        foreach (['type', 'attributes'] as $item) {
88
            if (!isset($data[$item])) {
89
                throw new HttpException(sprintf(self::MSG_TPL_REQUIRED, sprintf('data.%s', $item)));
90
            }
91
        }
92
        if (empty($data['type'])) {
93
            throw new HttpException(sprintf(self::MSG_TPL_REQUIRED, 'data.type'));
94
        }
95
        if (!is_array($data['attributes'])) {
96
            throw new HttpException(sprintf(self::MSG_TPL_INVALID, 'data.attributes'));
97
        }
98
99
        return true;
100
    }
101
102
    protected function verifyMeta()
103
    {
104
        if (isset($this->requestData['meta'])) { // meta is optional
105
            if (!is_array($this->requestData['meta'])) {
106
                throw new HttpException(sprintf(self::MSG_TPL_INVALID, 'meta'));
107
            }
108
        }
109
    }
110
}
111