Passed
Pull Request — master (#2)
by Sergey
04:32
created

ApiExecService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 3
crap 1
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
        try {
113 2
            $res = $class->execute()->getResult();
114
        } catch (RpcNumberException $e) {
115
            $code = 0;
116
            $message = 'Unknown error';
117
            $errors = $model->getErrors();
118
            if (isset($errors[$e->getCode()])) {
119
                $code = $e->getCode();
120
                $message = $errors[$e->getCode()];
121
            }
122
            throw new MethodErrorException($message, $code);
123
        }
124
125 2
        if ($model->isResponseCheck() && $class->responseSchema() !== null) {
126
            /** Валидируем парамертры ОТВЕТА */
127
            $this->getValidator()->validate(
128
                $class->responseSchema(),
129
                $res,
130
                'responseParams'
131
            );
132
        }
133
134 2
        return $res;
135
    }
136
137
    /**
138
     * @param ApiMethodInterface $class
139
     * @param string $method
140
     */
141 2
    private function checkInterface(ApiMethodInterface $class, string $method): void
142
    {
143
        // ???
144 2
        $interfaces = (array)class_implements($class);
145
        if (
146 2
            (bool)$interfaces === false
147 2
            || in_array(ApiMethodInterface::class, $interfaces, true) === false
148
        ) {
149
            throw new InternalErrorException(
150
                'Method "' . $method . '" does not match Interface'
151
            );
152
        }
153 2
    }
154
155
    /**
156
     * @return JsonSchemaValidator
157
     */
158
    public function getValidator(): JsonSchemaValidator
159
    {
160
        return $this->validator;
161
    }
162
163
    /**
164
     * @return JsonRpcSchema
165
     */
166
    public function getRpcSchema(): JsonRpcSchema
167
    {
168
        return $this->rpcSchema;
169
    }
170
171
    /**
172
     * @return JsonMapper
173
     */
174
    public function getMapper(): JsonMapper
175
    {
176
        return $this->mapper;
177
    }
178
}
179