Completed
Push — master ( 21563f...50178b )
by Denis
02:07
created

Processor::setMapper()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace PhpJsonRpc\Server;
4
5
use PhpJsonRpc\Core\Call\CallUnit;
6
use PhpJsonRpc\Core\Call\CallError;
7
use PhpJsonRpc\Core\Call\CallNotification;
8
use PhpJsonRpc\Core\CallSpecifier;
9
use PhpJsonRpc\Core\Result\AbstractResult;
10
use PhpJsonRpc\Core\Result\ResultError;
11
use PhpJsonRpc\Core\Result\ResultNotification;
12
use PhpJsonRpc\Core\Result\ResultUnit;
13
use PhpJsonRpc\Core\ResultSpecifier;
14
use PhpJsonRpc\Error\JsonRpcException;
15
use PhpJsonRpc\Error\MethodNotFoundException;
16
17
class Processor
18
{
19
    /**
20
     * @var array
21
     */
22
    private $handlers = [];
23
24
    /**
25
     * @var MapperInterface
26
     */
27
    private $mapper;
28
29
    /**
30
     * @var Invoker
31
     */
32
    private $invoker;
33
34
    /**
35
     * Processor constructor.
36
     */
37
    public function __construct()
38
    {
39
        $this->mapper  = new Mapper();
40
        $this->invoker = new Invoker();
41
    }
42
43
    /**
44
     * @param mixed $object
45
     */
46
    public function addHandler($object)
47
    {
48
        if (!is_object($object)) {
49
            throw new \DomainException('Expected object');
50
        }
51
52
        $key = get_class($object);
53
        $this->handlers[$key] = $object;
54
    }
55
56
    /**
57
     * @param MapperInterface $mapper
58
     */
59
    public function setMapper(MapperInterface $mapper)
60
    {
61
        $this->mapper = $mapper;
62
    }
63
64
    /**
65
     * @param CallSpecifier $specifier
66
     * @return ResultSpecifier
67
     */
68
    public function process(CallSpecifier $specifier): ResultSpecifier
69
    {
70
        $resultUnits = [];
71
        $callUnits   = $specifier->getUnits();
72
73
        foreach ($callUnits as $unit) {
74
            if ($unit instanceof CallUnit) {
75
                $resultUnits[] = $this->handleCallUnit($unit);
76
            } elseif ($unit instanceof CallNotification) {
77
                $resultUnits[] = $this->handleNotificationUnit($unit);
78
            } else {
79
                $resultUnits[] = $this->handleErrorUnit($unit);
80
            }
81
        }
82
83
        return new ResultSpecifier($resultUnits, $specifier->isSingleCall());
84
    }
85
86
    /**
87
     * @param CallUnit $unit
88
     * @return AbstractResult
89
     */
90
    private function handleCallUnit(CallUnit $unit): AbstractResult
91
    {
92
        try {
93
            list($class, $method) = $this->getClassAndMethod($unit->getRawMethod());
94
            $result = $this->invoker->invoke($this->handlers[$class], $method, $unit->getRawParams());
95
        } catch (JsonRpcException $exception) {
96
            return new ResultError($unit->getRawId(), $exception);
97
        }
98
99
        return new ResultUnit($unit->getRawId(), $result);
100
    }
101
102
    /**
103
     * @param CallNotification $unit
104
     * @return AbstractResult
105
     */
106
    private function handleNotificationUnit(CallNotification $unit): AbstractResult
107
    {
108
        try {
109
            list($class, $method) = $this->getClassAndMethod($unit->getRawMethod());
110
            $this->invoker->invoke($this->handlers[$class], $method, $unit->getRawParams());
111
        } catch (JsonRpcException $exception) {
112
            return new ResultError(null, $exception);
113
        }
114
115
        return new ResultNotification();
116
    }
117
118
    /**
119
     * @param CallError $unit
120
     * @return AbstractResult
121
     */
122
    private function handleErrorUnit(CallError $unit): AbstractResult
123
    {
124
        return new ResultError(null, $unit->getBaseException());
125
    }
126
127
    /**
128
     * @param string $requestedMethod
129
     * @return array
130
     * @throws MethodNotFoundException
131
     */
132
    private function getClassAndMethod(string $requestedMethod)
133
    {
134
        list($class, $method) = $this->mapper->getClassAndMethod($requestedMethod);
135
136
        if ($class && array_key_exists($class, $this->handlers) && method_exists($this->handlers[$class], $method)) {
137
            return [$class, $method];
138
        }
139
140
        throw new MethodNotFoundException();
141
    }
142
}
143