Alternation::parse()   B
last analyzed

Complexity

Conditions 8
Paths 4

Size

Total Lines 52
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 22
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 52
rs 8.4444

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * This file is part of Rivescript-php
4
 *
5
 * (c) Johnny Mast <[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\Triggers;
12
13
use Axiom\Rivescript\Cortex\Input;
14
use Axiom\Rivescript\Traits\Regex;
15
16
/**
17
 * Alternation class
18
 *
19
 * The Alternation class determines if a provided trigger
20
 * is an Alternation.
21
 *
22
 * PHP version 7.4 and higher.
23
 *
24
 * @category Core
25
 * @package  Cortext\Triggers
26
 * @author   Johnny Mast <[email protected]>
27
 * @license  https://opensource.org/licenses/MIT MIT
28
 * @link     https://github.com/axiom-labs/rivescript-php
29
 * @since    0.4.0
30
 */
31
class Alternation extends Trigger
32
{
33
    use Regex;
34
35
    /**
36
     * The Regex pattern to find sets
37
     * in the trigger.
38
     *
39
     * Note: This pattern ignores the set if a @ character
40
     * is inside to make sure we don't confuse them with arrays.
41
     *
42
     * @var string
43
     */
44
    protected string $pattern = "/(\()(?!\@)(.+?=*)(\))/ui";
45
46
    /**
47
     * Parse the trigger.
48
     *
49
     * @return bool|string
50
     */
51
    public function parse(string $trigger, Input $input): bool
52
    {
53
        if ($this->matchesPattern($this->pattern, $trigger) === true) {
54
            $triggerString = $trigger;
55
            $matches = $this->getMatchesFromPattern($this->pattern, $triggerString);
56
            $sets = [];
57
58
            /**
59
             * Replace every "set" in the trigger to their index number
60
             * found in the string.
61
             *
62
             * Example:
63
             *
64
             * "I (am|love) a robot. I like (my|style)"
65
             *
66
             * Will be replaced with:
67
             *
68
             * "I {0} a robot. I like {1}"
69
             */
70
            foreach ($matches as $index => $match) {
0 ignored issues
show
Bug introduced by
The expression $matches of type false is not traversable.
Loading history...
71
                $set = explode("|", $match[2]);
72
73
                if (count($set) > 0) {
74
                    $triggerString = str_replace($match[0], "{{$index}}", $triggerString);
75
                    $sets [] = $set;
76
                }
77
            }
78
79
            $combinations = $this->getCombinations(...$sets);
80
81
            if (count($combinations) > 0) {
82
                $sentences = [];
83
84
                foreach ($combinations as $combination) {
85
                    $tmp = $triggerString;
86
                    foreach ($combination as $index => $string) {
87
                        $tmp = str_replace("{{$index}}", $string, $tmp);
88
                    }
89
90
                    $sentences [] = trim($tmp);
91
                }
92
93
                $result = array_filter($sentences, static function (string $sentence) use ($input) {
94
                    return (strtolower($sentence) === strtolower($input->source()));
95
                });
96
97
                if (count($result) > 0) {
98
                    return $input->source();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $input->source() returns the type string which is incompatible with the type-hinted return boolean.
Loading history...
99
                }
100
            }
101
        }
102
        return false;
103
    }
104
105
    /**
106
     * Create a set of possible combinations for given arrays.
107
     *
108
     * Note: This function is taken from stackoverflow.com
109
     * first posted by Guilhermo Luna and later edited by user Amlette.
110
     *
111
     * @see https://stackoverflow.com/questions/8567082/how-to-generate-in-php-all-combinations-of-items-in-multiple-arrays/33259643#33259643
112
     *
113
     * @param array ...$arrays A set of arrays to combine.
114
     *
115
     * @return array|array[]
116
     *
117
     */
118
    private function getCombinations(array ...$arrays): array
119
    {
120
        $result = [[]];
121
        foreach ($arrays as $property => $property_values) {
122
            $tmp = [];
123
            foreach ($result as $result_item) {
124
                foreach ($property_values as $property_value) {
125
                    $tmp[] = array_merge($result_item, [$property => $property_value]);
126
                }
127
            }
128
            $result = $tmp;
129
        }
130
        return $result;
131
    }
132
}
133