Passed
Push — master ( a3f2ba...d44e36 )
by Johnny
08:16
created

Output::processTopic()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 40
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 23
c 0
b 0
f 0
nc 5
nop 0
dl 0
loc 40
rs 8.9297
1
<?php
2
/*
3
 * This file is part of Rivescript-php
4
 *
5
 * (c) Shea Lewis <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Axiom\Rivescript\Cortex;
12
13
use Axiom\Rivescript\Cortex\ResponseQueue\ResponseQueueItem;
14
use Axiom\Rivescript\Traits\Regex;
15
use Axiom\Rivescript\Traits\Tags;
16
17
/**
18
 * Output class
19
 *
20
 * This class is responsible for generating the
21
 * bot response.
22
 *
23
 * PHP version 7.4 and higher.
24
 *
25
 * @category Core
26
 * @package  Cortext
27
 * @author   Shea Lewis <[email protected]>
28
 * @license  https://opensource.org/licenses/MIT MIT
29
 * @link     https://github.com/axiom-labs/rivescript-php
30
 * @since    0.3.0
31
 */
32
class Output
33
{
34
35
    use Regex;
36
    use Tags;
0 ignored issues
show
introduced by
The trait Axiom\Rivescript\Traits\Tags requires some properties which are not provided by Axiom\Rivescript\Cortex\Output: $memory, $input
Loading history...
37
38
    /**
39
     * The output string
40
     *
41
     * @var string
42
     */
43
    protected string $output = '';
44
45
    /**
46
     * Keep track of the recursion
47
     * in the output.
48
     *
49
     * @var int
50
     */
51
    protected int $recursion = 0;
52
53
    /**
54
     * Process the correct output response by the interpreter.
55
     *
56
     * @return string
57
     */
58
    public function process(): string
59
    {
60
        $triggers = synapse()->brain->topic()->triggers();
0 ignored issues
show
Unused Code introduced by
The assignment to $triggers is dead and can be removed.
Loading history...
61
        $begin = synapse()->brain->topic("__begin__");
62
63
        $this->output = "";
64
65
66
        /**
67
         * 1. Check if topic is valid
68
         * 2. Process the triggers
69
         * 3. if valid trigger
70
         *   - Check if response is redirect
71
         *   -
72
         */
73
        if ($begin) {
74
            synapse()->rivescript->say("Begin label found. Starting processing.");
75
76
            $request = $begin->triggers()->get("request");
77
78
            if ($request) {
79
                $this->output = $request['responses']->process();
80
81
                if ($begin->isOk() === false) {
82
                    return $this->output;
83
                }
84
            }
85
        }
86
87
88
        return $this->processTopic();
89
90
        return trim($this->output);
0 ignored issues
show
Unused Code introduced by
return trim($this->output) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
91
    }
92
93
    protected function processTopic(): string
94
    {
95
        $topic = synapse()->memory->shortTerm()->get('topic') ?? 'random';
96
        $triggers = synapse()->brain->topic($topic)->triggers();
97
98
        foreach ($triggers as $trigger => $data) {
99
            $valid = $this->isValidTrigger($trigger);
100
101
            if ($valid === true) {
102
                synapse()->rivescript->say("Found trigger {$trigger}...");
103
                synapse()->memory->shortTerm()->put('trigger', $trigger);
104
105
                $response = $this->getValidResponse($trigger);
106
107
                if ($response) {
108
                    if ($response->isChangingTopic() === true) {
109
                        // validate target or continue
110
                        synapse()->rivescript->warn("Topic change detected.");
111
                        break;
112
                    } else {
113
                        $output = $response->getValue();
114
115
                        if ($output) {
116
                            $this->output .= $output;
117
                        }
118
                    }
119
                } else {
120
                    synapse()->rivescript->warn("Could not find a valid response for trigger \":trigger\"", [
121
                        "trigger" => $trigger
122
                    ]);
123
                }
124
            } else {
125
                synapse()->rivescript->warn("Could not find a valid trigger \":trigger\"", [
126
                    "trigger" => $trigger
127
                ]);
128
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
129
            }
130
        }
131
132
        return trim($this->output);
133
    }
134
135
136
    /**
137
     * Search through available triggers to find a possible match.
138
     *
139
     * @param string $trigger The trigger to find responses for.
140
     *
141
     * @return bool
142
     */
143
    protected function isValidTrigger(string $trigger): bool
144
    {
145
        $triggers = synapse()->triggers;
146
        foreach ($triggers as $class) {
147
            $triggerClass = "\\Axiom\\Rivescript\\Cortex\\Triggers\\{$class}";
148
            $triggerInstance = new $triggerClass(synapse()->input);
149
150
            $found = $triggerInstance->parse($trigger, synapse()->input);
151
152
            if ($found) {
153
                return true;
154
            }
155
        }
156
157
        return false;
158
    }
159
160
    /**
161
     * Search through available triggers to find a possible match.
162
     *
163
     * @param string $trigger The trigger to find responses for.
164
     *
165
     * @return void
166
     */
167
    protected function searchTriggers2(string $trigger): void
168
    {
169
        synapse()->triggers->each(
170
            function ($class) use ($trigger) {
171
                $triggerClass = "\\Axiom\\Rivescript\\Cortex\\Triggers\\$class";
172
                $triggerInstance = new $triggerClass(synapse()->input);
173
174
                $found = $triggerInstance->parse($trigger, synapse()->input);
175
176
                if ($found === true) {
177
                    synapse()->rivescript->say("Found trigger {$trigger} van {$triggerClass}...");
178
                    synapse()->memory->shortTerm()->put('trigger', $trigger);
179
                    $this->output .= $this->getResponse($trigger);
180
                    return false;
181
                }
182
            }
183
        );
184
    }
185
186
187
    protected function getValidResponse(string $trigger)
188
    {
189
        $originalTrigger = synapse()->brain->topic()->triggers()->get($trigger);
190
        $queueItem = null;
191
192
        if ($originalTrigger['responses']) {
193
            $queueItem = $originalTrigger['responses']->process();
194
195
            if ($queueItem) {
196
                $queueItem->parse();
197
            }
198
        }
199
200
        return $queueItem;
201
    }
202
203
    /**
204
     * Fetch a response from the found trigger.
205
     *
206
     * @param string $trigger The trigger to get a response for.
207
     *
208
     * @return string
209
     */
210
    protected function getResponse(string $trigger)
211
    {
212
213
        $topic = synapse()->memory->shortTerm()->get('topic') ?? 'random';
214
        $originalTrigger = synapse()->brain->topic($topic)->triggers()->get($trigger);
215
216
217
//        // FIXME: Temp fix for rsts
218
//        if (isset($originalTrigger['responses']) === false) {
219
//            synapse()->rivescript->say("No response found.");
220
//            $this->output = "";
221
//            return $this->output;
222
//        }
223
224
        /**
225
         * Get the best suitable response from
226
         * the ResponseQueue.
227
         */
228
        $queueItem = $originalTrigger['responses']->process();
0 ignored issues
show
Unused Code introduced by
The assignment to $queueItem is dead and can be removed.
Loading history...
229
        // $queueItem = $this->parseResponse($response);
230
231
        /**
232
         * It could be possible that tags have altered the trigger.
233
         * If so evaluate possible changes.
234
         */
235
//
236
        $processedTrigger = synapse()->brain->topic()->triggers()->get($trigger, null);
0 ignored issues
show
Unused Code introduced by
The assignment to $processedTrigger is dead and can be removed.
Loading history...
237
//        $processedTopic = synapse()->memory->shortTerm()->get('topic') ?? 'random';
238
239
//        if ($topic !== $processedTopic) {
240
//            synapse()->rivescript->warn("topic changed from :old to :new.", [
241
//                "old" => $topic,
242
//                "new" => synapse()->memory->shortTerm()->get('topic'),
243
//            ]);
244
//        }
245
//
246
//        if (isset($processedTrigger['redirect'])) {
247
//            $valid = $this->isValidTrigger($processedTrigger['redirect']);
248
//
249
//
250
//            if ($valid === true) {
251
//                synapse()->rivescript->warn("Searching for trigger :trigger in topic :topic", ['trigger' => $processedTrigger["redirect"], 'topic' => $topic]);
252
//
253
//                $input = new Input($processedTrigger["redirect"], "local-user");
254
//                synapse()->input = $input;
255
//
256
//                return $this->searchTriggers2($processedTrigger['redirect']);
257
//            } else {
258
//                // FIXME: Tiggers wild wildcards end up in here. We need to fix this.
259
//
260
//                $trigger = $processedTrigger['redirect'];
261
//
262
////                if ($trigger == 'set test name test' || $trigger == 'test x') {
263
////                    return $output;
264
////                }
265
//                synapse()->rivescript->warn("Topic :new was not found. Restoring topic :old", [
266
//                    "new" => $processedTrigger['redirect'],
267
//                    "old" => synapse()->memory->shortTerm()->get('topic'),
268
//                ]);
269
//
270
//                synapse()->input = new Input($trigger, "local-user");
271
//
272
////                $newTrigger = synapse()->memory->shortTerm()->get('trigger');
273
//
274
//
275
//                print_r('Trigger -->' . $trigger . "<\n");
276
////                print_r('newTrigger -->' . $newTrigger . "<\n");
277
//                synapse()->memory->shortTerm()->put("topic", null);
278
//
279
//                return '@'.$this->processTopic( null );
280
//           //     return $this->getResponse($trigger);
281
//            }
282
//        }
283
//
284
//        return $output;
285
    }
286
}
287