Completed
Push — master ( 485884...fd37ea )
by Gallice
02:54
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 4
Bugs 0 Features 0
Metric Value
c 4
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;
4
5
use Tgallice\Wit\Exception\BadResponseException;
6
use Tgallice\Wit\Exception\ConversationException;
7
use Tgallice\Wit\Exception\InvalidStepException;
8
use Tgallice\Wit\Exception\MaxIterationException;
9
use Tgallice\Wit\Model\Context;
10
use Tgallice\Wit\Model\Step;
11
use Tgallice\Wit\Model\Step\Action;
12
use Tgallice\Wit\Model\Step\Merge;
13
use Tgallice\Wit\Model\Step\Message;
14
use Tgallice\Wit\Model\Step\Stop;
15
16
class Conversation
17
{
18
    const MAX_STEPS_ITERATION = 5;
19
20
    /**
21
     * @var API
22
     */
23
    private $api;
24
25
    /**
26
     * @var ActionMapping
27
     */
28
    private $actionMapping;
29
30 10
    public function __construct(Api $api, ActionMapping $actionMapping)
31
    {
32 10
        $this->api = $api;
33 10
        $this->actionMapping = $actionMapping;
34 10
    }
35
36
    /**
37
     * @param string $sessionId
38
     * @param string|null $message
39
     * @param Context|null $context
40
     * @param int $stepIteration
41
     *
42
     * @return Context The new Context
43
     */
44 9
    public function converse($sessionId, $message = null, Context $context = null, $stepIteration = self::MAX_STEPS_ITERATION)
45
    {
46 9
        $context = (null !== $context) ? $context : new Context();
47
48 9
        if ($stepIteration <= 0) {
49 1
            $error = new MaxIterationException("Max iteration exceeded");
50 1
            $this->actionMapping->error($sessionId, $context, $error);
51
52 1
            return $context;
53
        }
54
55
        try {
56 9
            $step = $this->getNextStep($sessionId, $message, $context);
57 9
        } catch (\Exception $e) {
58
            // Trigger the error action
59 2
            $stepData = $e instanceof ConversationException ? $e->getStepData() : [];
60 2
            $this->actionMapping->error($sessionId, $context, $e, $stepData);
61
62 2
            return new Context();
63
        }
64
65 7
        return $this->performStep($sessionId, $step, $context, $stepIteration);
66
    }
67
68
    /**
69
     * @param string $sessionId
70
     * @param string|null $message
71
     * @param Context $context
72
     *
73
     * @return Step Step object
74
     *
75
     * @throws BadResponseException
76
     * @throws ConversationException
77
     */
78 9
    private function getNextStep($sessionId, $message, Context $context)
79
    {
80 9
        $stepData = $this->api->getConverseNextStep($sessionId, $message, $context);
81
82 9
        if (null === $stepData) {
83 1
            $stepData = [];
84 1
        }
85
86 9
        if (isset($stepData['error'])) {
87 1
            throw new ConversationException($stepData['error'], $sessionId, $context, $stepData);
88
        }
89
90
        try {
91 8
            $step = StepFactory::create($stepData);
92 8
        } catch (InvalidStepException $e) {
93 1
            throw new ConversationException($e->getMessage(), $sessionId, $context, $e->getStepData());
94
        }
95
96 7
        return $step;
97
    }
98
99
    /**
100
     * @param $sessionId
101
     * @param Step $step
102
     * @param Context $context
103
     * @param int $currentIteration
104
     *
105
     * @return Context
106
     */
107 7
    private function performStep($sessionId, Step $step, Context $context, $currentIteration)
108
    {
109 7
        switch (true) {
110 7
            case $step instanceof Merge:
111 3
                $newContext = $this->actionMapping->merge($sessionId, $context, $step->getEntities());
112 3
                $context = $this->converse($sessionId, null, $newContext, --$currentIteration);
113 3
                break;
114 6
            case $step instanceof Message:
115 2
                $this->actionMapping->say($sessionId, $step->getMessage(), $context);
116 2
                break;
117 4
            case $step instanceof Action:
118 1
                $newContext = $this->actionMapping->action($sessionId, $step->getAction(), $context);
119 1
                $context = $this->converse($sessionId, null, $newContext, --$currentIteration);
120 1
                break;
121 4
            case $step instanceof Stop:
122 4
                $this->actionMapping->stop($sessionId, $context);
123 4
                break;
124
        }
125
126 7
        return $context;
127
    }
128
}
129