Passed
Push — master ( ef65fe...aab2bb )
by Brian
06:54
created

Parser::save()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
ccs 0
cts 3
cp 0
rs 10
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Bmatovu\Ussd;
4
5
use Bmatovu\Ussd\Contracts\AnswerableTag;
6
use Bmatovu\Ussd\Traits\ParserUtils;
7
use Illuminate\Support\Facades\Log;
8
9
class Parser
10
{
11
    use ParserUtils;
0 ignored issues
show
introduced by
The trait Bmatovu\Ussd\Traits\ParserUtils requires some properties which are not provided by Bmatovu\Ussd\Parser: $tagName, $attributes, $nodeValue
Loading history...
12
13
    protected \DOMXPath $xpath;
14
    protected string $sessionId;
15
    protected Store $store;
16 5
    protected bool $newSession = false;
17
18 5
    public function __construct(\DOMXPath|string $xpath, string $expression, string $sessionId)
19
    {
20
        $this->xpath = is_string($xpath) ? $this->xpathFromStr($xpath) : $xpath;
21 5
22 5
        // $config = Container::getInstance()->make('config');
23 5
        $store = config('ussd.cache.store', 'file');
24
        $ttl = config('ussd.cache.ttl', 120);
25 5
        $this->store = new Store($store, $ttl, $sessionId);
26 2
27
        if ($this->sessionExists($sessionId)) {
28
            return;
29 3
        }
30 3
31 3
        $this->newSession = true;
32 3
        $this->store->put('_session_id', $sessionId);
33 3
        $this->store->put('_answer', '');
34 3
        $this->store->put('_pre', '');
35 3
        $this->store->put('_exp', $expression);
36
        $this->store->put('_breakpoints', '[]');
37
    }
38
39
    public function save(array $options): self
40
    {
41
        foreach ($options as $key => $value) {
42
            $this->store->put($key, $value);
43
        }
44
45
        return $this;
46
    }
47 5
48
    public function parse(?string $userInput = ''): string
49
    {
50
        $answer = $this->getAnswer($userInput);
51 5
52
        if($this->newSession) {
53 5
            $inquiry = $this->doParse();
54 5
55
            if(! $answer) {
56
                return $inquiry;
57
            }
58
        }
59
60
        $answers = explode('*', $answer);
61 5
62
        foreach ($answers as $answer) {
63 5
            $inquiry = $this->doParse($answer);
64 5
        }
65
66
        return $inquiry;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $inquiry does not seem to be defined for all execution paths leading up to this point.
Loading history...
67 3
    }
68
69
    protected function doParse(?string $answer = ''): ?string
70 5
    {
71
        Log::debug("doParse({$answer})");
72 5
73
        $this->doProcess($answer);
74 5
75 5
        $exp = $this->store->get('_exp');
76
        $node = $this->xpath->query($exp)->item(0);
77 5
78 1
        if (! $node) {
79
            $this->doBreak();
80
        }
81 5
82
        $inquiry = $this->doRender();
83 3
84 1
        if (! $inquiry) {
85
            return $this->doParse($answer);
86
        }
87 3
88
        return $inquiry;
89
    }
90 5
91
    protected function doProcess(?string $answer): void
92 5
    {
93
        $pre = $this->store->get('_pre');
94 5
95 4
        if (! $pre) {
96
            return;
97
        }
98 2
99
        $preNode = $this->xpath->query($pre)->item(0);
100 2
101 2
        $tagName = $this->resolveTagName($preNode);
102
        $tag = $this->instantiateTag($tagName, [$preNode, $this->store]);
103 2
104 2
        if (! $tag instanceof AnswerableTag) {
105
            return;
106
        }
107
108
        $tag->process($answer);
109
    }
110 1
111
    protected function doBreak(): void
112 1
    {
113
        $exp = $this->store->get('_exp');
114 1
115
        $breakpoints = (array) json_decode((string) $this->store->get('_breakpoints'), true);
116 1
117
        if (! $breakpoints || ! isset($breakpoints[0][$exp])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $breakpoints of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
118
            throw new \Exception('Missing tag');
119
        }
120 1
121 1
        $breakpoint = array_shift($breakpoints);
122 1
        $this->store->put('_exp', $breakpoint[$exp]);
123
        $this->store->put('_breakpoints', json_encode($breakpoints));
124
    }
125 5
126
    protected function doRender(): ?string
127 5
    {
128
        $exp = $this->store->get('_exp');
129 5
130
        $node = $this->xpath->query($exp)->item(0);
131 5
132 5
        $tagName = $this->resolveTagName($node);
133 4
        $tag = $this->instantiateTag($tagName, [$node, $this->store]);
134
        $inquiry = $tag->handle();
135 3
136 3
        $exp = $this->store->get('_exp');
137
        $breakpoints = (array) json_decode((string) $this->store->get('_breakpoints'), true);
138 3
139
        if ($breakpoints && isset($breakpoints[0][$exp])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $breakpoints of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
140
            $breakpoint = array_shift($breakpoints);
141
            $this->store->put('_exp', $breakpoint[$exp]);
142
            $this->store->put('_breakpoints', json_encode($breakpoints));
143
        }
144 3
145
        return $inquiry;
146
    }
147
}
148