Completed
Push — master ( c731dd...0ae8dc )
by Gallice
42s
created

Conversation::getNextStep()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 9.2
cc 4
eloc 11
nc 6
nop 3
crap 4
1
<?php
2
3
namespace Tgallice\Wit\Api;
4
5
use Tgallice\Wit\ActionMapping;
6
use Tgallice\Wit\Api;
7
use Tgallice\Wit\Exception\BadResponseException;
8
use Tgallice\Wit\Exception\ConversationException;
9
use Tgallice\Wit\Exception\InvalidStepException;
10
use Tgallice\Wit\Exception\MaxIterationException;
11
use Tgallice\Wit\Model\Context;
12
use Tgallice\Wit\Model\Step;
13
use Tgallice\Wit\Model\Step\Action;
14
use Tgallice\Wit\Model\Step\Merge;
15
use Tgallice\Wit\Model\Step\Message;
16
use Tgallice\Wit\Model\Step\Stop;
17
use Tgallice\Wit\StepFactory;
18
19
class Conversation
20
{
21
    const MAX_STEPS_ITERATION = 5;
22
23
    /**
24
     * @var API
25
     */
26
    private $api;
27
28
    /**
29
     * @var ActionMapping
30
     */
31
    private $actionMapping;
32
33 10
    public function __construct(Api $api, ActionMapping $actionMapping)
34
    {
35 10
        $this->api = $api;
0 ignored issues
show
Documentation Bug introduced by
It seems like $api of type object<Tgallice\Wit\Api> is incompatible with the declared type object<Tgallice\Wit\Api\API> of property $api.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
36 10
        $this->actionMapping = $actionMapping;
37 10
    }
38
39
    /**
40
     * @param string $sessionId
41
     * @param string|null $message
42
     * @param Context|null $context
43
     * @param int $stepIteration
44
     *
45
     * @return Context The new Context
46
     */
47 9
    public function converse($sessionId, $message = null, Context $context = null, $stepIteration = self::MAX_STEPS_ITERATION)
48
    {
49 9
        $context = (null !== $context) ? $context : new Context();
50
51 9
        if ($stepIteration <= 0) {
52 1
            $error = new MaxIterationException("Max iteration exceeded");
53 1
            $this->actionMapping->error($sessionId, $context, $error);
54
55 1
            return $context;
56
        }
57
58
        try {
59 9
            $step = $this->getNextStep($sessionId, $message, $context);
60 9
        } catch (\Exception $e) {
61
            // Trigger the error action
62 2
            $stepData = $e instanceof ConversationException ? $e->getStepData() : [];
63 2
            $this->actionMapping->error($sessionId, $context, $e, $stepData);
64
65 2
            return new Context();
66
        }
67
68 7
        return $this->performStep($sessionId, $step, $context, $stepIteration);
69
    }
70
71
    /**
72
     * @param string $sessionId
73
     * @param string|null $message
74
     * @param Context $context
75
     *
76
     * @return Step Step object
77
     *
78
     * @throws BadResponseException
79
     * @throws ConversationException
80
     */
81 9
    private function getNextStep($sessionId, $message, Context $context)
82
    {
83 9
        $stepData = $this->api->getConverseNextStep($sessionId, $message, $context);
84
85 9
        if (null === $stepData) {
86 1
            $stepData = [];
87 1
        }
88
89 9
        if (isset($stepData['error'])) {
90 1
            throw new ConversationException($stepData['error'], $sessionId, $context, $stepData);
91
        }
92
93
        try {
94 8
            $step = StepFactory::create($stepData);
95 8
        } catch (InvalidStepException $e) {
96 1
            throw new ConversationException($e->getMessage(), $sessionId, $context, $e->getStepData());
97
        }
98
99 7
        return $step;
100
    }
101
102
    /**
103
     * @param $sessionId
104
     * @param Step $step
105
     * @param Context $context
106
     * @param int $currentIteration
107
     *
108
     * @return Context
109
     */
110 7
    private function performStep($sessionId, Step $step, Context $context, $currentIteration)
111
    {
112 7
        switch (true) {
113 7
            case $step instanceof Merge:
114 3
                $newContext = $this->actionMapping->merge($sessionId, $context, $step->getEntities());
115 3
                $context = $this->converse($sessionId, null, $newContext, --$currentIteration);
116 3
                break;
117 6
            case $step instanceof Message:
118 2
                $this->actionMapping->say($sessionId, $step->getMessage(), $context);
119 2
                break;
120 4
            case $step instanceof Action:
121 1
                $newContext = $this->actionMapping->action($sessionId, $step->getAction(), $context);
122 1
                $context = $this->converse($sessionId, null, $newContext, --$currentIteration);
123 1
                break;
124 4
            case $step instanceof Stop:
125 4
                $this->actionMapping->stop($sessionId, $context);
126 4
                break;
127
        }
128
129 7
        return $context;
130
    }
131
}
132