Passed
Pull Request — master (#2)
by Sergey
05:00
created

ApiExecService::getValidator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
/**
4
 * Created by PhpStorm.
5
 * Project: json_rpc_server
6
 * User: sv
7
 * Date: 25.06.19
8
 * Time: 7:54
9
 */
10
11
declare(strict_types=1);
12
13
namespace Onnov\JsonRpcServer\Service;
14
15
use JsonMapper;
16
use JsonMapper_Exception;
17
use Onnov\JsonRpcServer\ApiMethodInterface;
18
use Onnov\JsonRpcServer\Exception\InternalErrorException;
19
use Onnov\JsonRpcServer\Exception\MethodErrorException;
20
use Onnov\JsonRpcServer\Exception\MethodNotFoundException;
21
use Onnov\JsonRpcServer\Exception\ParseErrorException;
22
use Onnov\JsonRpcServer\Exception\RpcNumberException;
23
use Onnov\JsonRpcServer\Model\RpcModel;
24
use Onnov\JsonRpcServer\Model\RpcRequest;
25
use Onnov\JsonRpcServer\Model\RunModel;
26
use Onnov\JsonRpcServer\Traits\JsonHelperTrait;
27
use Onnov\JsonRpcServer\Validator\JsonRpcSchema;
28
use Onnov\JsonRpcServer\Validator\JsonSchemaValidator;
29
30
class ApiExecService
31
{
32 1
    use JsonHelperTrait;
33
34
    /** @var JsonSchemaValidator */
35
    protected $validator;
36
37
    /** @var JsonRpcSchema */
38
    protected $rpcSchema;
39
40
    /** @var JsonMapper */
41
    private $mapper;
42
43
    /**
44
     * ApiExecService constructor.
45
     *
46
     * @param JsonSchemaValidator $validator
47
     * @param JsonRpcSchema $rpcSchema
48
     * @param JsonMapper $mapper
49
     */
50 6
    public function __construct(
51
        JsonSchemaValidator $validator,
52
        JsonRpcSchema $rpcSchema,
53
        JsonMapper $mapper
54
    ) {
55 6
        $this->validator = $validator;
56 6
        $this->rpcSchema = $rpcSchema;
57 6
        $this->mapper = $mapper;
58 6
    }
59
60
    /**
61
     * @param RunModel $model
62
     * @param RpcModel $rpc
63
     *
64
     * @return mixed
65
     */
66 3
    public function exe(
67
        RunModel $model,
68
        RpcModel $rpc
69
    ) {
70 3
        $factory = $model->getApiFactory();
71 3
        $method = $rpc->getMethod();
72
        /** Проверим существование метода */
73 3
        if ($factory->has($method) === false) {
74 1
            throw new MethodNotFoundException(
75 1
                'Method "' . $method . '" not found'
76
            );
77
        }
78
79
        /** Создаем экземпляр класса
80
         *
81
         * @var ApiMethodInterface $class
82
         */
83 2
        $class = $factory->get($method);
84
85
        /** Проверим соответствие интерфейсу */
86 2
        $this->checkInterface($class, $method);
87
88
        /** Валидируем парамертры ЗАПРОСА */
89 2
        if ($class->requestSchema() !== null) {
90
            $this->getValidator()->validate(
91
                $class->requestSchema(),
92
                $rpc->getParams(),
93
                'requestParams'
94
            );
95
        }
96
97 2
        $paramsObject = null;
98 2
        if (method_exists($class, 'customParamsObject') && $class->customParamsObject() !== null) {
99
            try {
100
                $paramsObject = $this->getMapper()->map($rpc->getParams(), $class->customParamsObject());
101
            } catch (JsonMapper_Exception $e) {
102
                throw new ParseErrorException('', 0, $e->getPrevious());
103
            }
104
        }
105
106
        /** засетим в метод RpcRequest*/
107 2
        if (method_exists($class, 'setRpcRequest')) {
108 2
            $class->setRpcRequest(new RpcRequest($rpc, $paramsObject));
109
        }
110
111
        // Получим описанные ошибки метода
112 2
        $errors = [];
113 2
        if (method_exists($class, 'getError') && $class->getError() !== null) {
114
            $errors = $class->getError();
115
        }
116
117
        /** Выполним метод */
118
        try {
119 2
            $res = $class->execute()->getResult();
120
        } catch (RpcNumberException $e) {
121
            $code = 0;
122
            $message = 'Unknown error';
123
            if (isset($errors[$e->getCode()])) {
124
                $code = $e->getCode();
125
                $message = $errors[$e->getCode()];
126
            }
127
            throw new MethodErrorException($message, $code);
128
        }
129
130 2
        if ($model->isResponseCheck() && $class->responseSchema() !== null) {
131
            /** Валидируем парамертры ОТВЕТА */
132
            $this->getValidator()->validate(
133
                $class->responseSchema(),
134
                $res,
135
                'responseParams'
136
            );
137
        }
138
139 2
        return $res;
140
    }
141
142
    /**
143
     * @param ApiMethodInterface $class
144
     * @param string $method
145
     */
146 2
    private function checkInterface(ApiMethodInterface $class, string $method): void
147
    {
148
        // ???
149 2
        $interfaces = (array)class_implements($class);
150
        if (
151 2
            (bool)$interfaces === false
152 2
            || in_array(ApiMethodInterface::class, $interfaces, true) === false
153
        ) {
154
            throw new InternalErrorException(
155
                'Method "' . $method . '" does not match Interface'
156
            );
157
        }
158 2
    }
159
160
    /**
161
     * @return JsonSchemaValidator
162
     */
163
    public function getValidator(): JsonSchemaValidator
164
    {
165
        return $this->validator;
166
    }
167
168
    /**
169
     * @return JsonRpcSchema
170
     */
171
    public function getRpcSchema(): JsonRpcSchema
172
    {
173
        return $this->rpcSchema;
174
    }
175
176
    /**
177
     * @return JsonMapper
178
     */
179
    public function getMapper(): JsonMapper
180
    {
181
        return $this->mapper;
182
    }
183
}
184