InstinctPositron::getConfig()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Posibrain\Positron\Instinct;
3
4
use Monolog\Logger;
5
use Posibrain\Positron\Positron;
6
use Posibrain\TchatBotConfig;
7
use Posibrain\AnalysedRequest;
8
use Posibrain\TchatMessage;
9
10
/**
11
 *
12
 * @author Fylhan (http://fylhan.la-bnbox.fr)
13
 * @license LGPL-2.1+
14
 */
15
class InstinctPositron extends Positron
16
{
17
18
	private static $logger = NULL;
19
20
	private $config;
21
22
	private $brainManager;
23
24
	private $knowledges;
25
26
	private $matching;
27
28
	public function __construct($config, $params = array())
29
	{
30
		// Logger
31 View Code Duplication
		if (NULL == self::$logger) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
32
			self::$logger = new Logger(__CLASS__);
33
			if (! empty($params) && isset($params['loggerHandler'])) {
34
				self::$logger->pushHandler($params['loggerHandler']);
35
			}
36
		}
37
		
38
		// Brain Manager
39
		$this->config = $config;
40
		$this->brainManager = new BrainManager($params);
41
		
42
		// -- Load knowledge file
43
		$this->knowledges = $this->brainManager->loadBrain($this->config);
44
	}
45
46
	public function isBotTriggered(TchatMessage $request, $currentAnswer = true)
47
	{
48
		$content = $request->getMessage();
49
		$triggered = (NULL != $content);
50
		$identity = $this->knowledges->identity;
51
		// Triggered by specific rules
52
		if (isset($identity->trigger) && ! empty($identity->trigger)) {
53
			// Called by his name
54 View Code Duplication
			if (! empty($identity->trigger->called)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
				$triggered &= preg_match('!(?:^|\s|[_-])(' . implode('|', $identity->trigger->called) . ')(?:$|\s|[\'_-])!i', $content);
56
			}
57
			// Specific sentance
58 View Code Duplication
			if (! empty($identity->trigger->sentance)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
59
				$triggered &= preg_match('!(' . implode('|', $identity->trigger->sentance) . ')!i', $content);
60
			}
61
		}
62
		return $triggered;
63
	}
64
65
	public function generateSymbolicAnswer(AnalysedRequest $request, $memory, TchatMessage $currentAnswer = null)
66
	{
67
		$userMessage = $request->getMessage();
68
		$userName = $request->getName();
69
		$dateTime = $request->getDate();
0 ignored issues
show
Unused Code introduced by
$dateTime is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
70
		
71
		if (null == $this->knowledges) {
72
			return null;
73
		}
74
		
75
		$identity = $this->knowledges->identity;
76
		$synonyms = $this->knowledges->synonyms;
0 ignored issues
show
Unused Code introduced by
$synonyms is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
77
		$knowledge = $this->knowledges->keywords;
0 ignored issues
show
Unused Code introduced by
$knowledge is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
78
		
79
		// -- Generate reply
80
		// - Check User Message
81
		if (empty($userMessage)) {
82
			$message = 'Hello';
0 ignored issues
show
Unused Code introduced by
$message is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
83
		}
84
		
85
		// - Best keyword priority
86
		$keywordItem = $this->findBestPriorityKeyword($userName, $userMessage);
87
		
88
		// - Best variance for this keyword
89
		$varianceItem = $this->findBestVariance($userName, $userMessage, $keywordItem);
90
		$this->matching = $varianceItem;
91
		$response = $this->pickResponse($userName, $userMessage, $varianceItem);
92
		
93
		// if ('UTF-8' != $this->config->getCharset()) {}
94
		$currentAnswer = new TchatMessage($response, $identity->name);
95
		return $currentAnswer;
96
	}
97
98
	public function provideMeaning(AnalysedRequest $request, $memory, TchatMessage $answer, TchatMessage $currentAnswer = null)
99
	{
100
		if (null == $currentAnswer) {
101
			$currentAnswer = $answer;
102
		}
103
		$message = $currentAnswer->getMessage();
104
		// Post traitment
105
		if (strstr($message, '${time}')) {
106
			$nowDate = new \DateTime(null, new \DateTimeZone(! isset($this->knowledges->identity->timezone) ? 'Europe/Paris' : $this->knowledges->identity->timezone));
107
			$message = preg_replace('!\$\{time\}!i', $nowDate->format('H\hi'), $message);
108
		}
109
		if (strstr($message, '${name}')) {
110
			$message = preg_replace('!\$\{name\}!i', $this->knowledges->identity->name, $message);
111
		}
112
		if (strstr($message, '${conceptorName}')) {
113
			$message = preg_replace('!\$\{conceptorName\}!i', $this->knowledges->identity->conceptorName, $message);
114
		}
115
		if (strstr($message, '${userName}')) {
116
			$message = preg_replace('!\$\{userName\}!i', $request->getName(), $message);
117
		}
118
		if (! empty($this->matching->matchingData) && count($this->matching->matchingData) > 0) {
119
			foreach ($this->matching->matchingData as $i => $data) {
120
				$data = mb_strtolower($data[0]);
121
				$message = preg_replace('!\$\{' . $i . '\}!i', $data, $message);
122
				$message = preg_replace('!\$\{' . $i . '\|clean\}!i', parserUrl($data), $message);
123
				$message = preg_replace('!\$\{' . $i . '\|ucfirst\}!i', ucfirst($data), $message);
124
			}
125
		}
126
		if (! empty($this->matching->matchingKeyword) && count($this->matching->matchingKeyword) > 0) {
127
			$data = mb_strtolower($this->matching->matchingKeyword[0]);
128
			$message = preg_replace('!\$\{keyword\}!i', $data, $message);
129
		}
130
		
131
		$currentAnswer->setMessage($message);
132
		return $currentAnswer;
133
	}
134
135
	public function beautifyAnswer(AnalysedRequest $request, $memory, TchatMessage $answer, TchatMessage $currentAnswer = null)
136
	{
137
		if (null == $currentAnswer) {
138
			$currentAnswer = $answer;
139
		}
140
		$currentAnswer->setMessage(preg_replace('!(bonjour)!i', '<strong>$1</strong>', ucfirst($currentAnswer->getMessage())));
141
		return $currentAnswer;
142
	}
143
144
	private function findBestPriorityKeyword($userName, $message)
0 ignored issues
show
Unused Code introduced by
The parameter $userName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
145
	{
146
		$bestPriority = - 1;
147
		$matchingKeywordItem = '';
148
		// Loop over keywords
149
		foreach ($this->knowledges->keywords as $keywordItem) {
150
			// Better priority and matching keyword (or it is the default one)
151
			if ($keywordItem->priority > $bestPriority && (empty($keywordItem->keyword) || preg_match('!(?:^|\s|[_-])(' . implode('|', $keywordItem->keyword) . ')(?:$|\s|[\'_,;:-])!i', $message, $matching))) {
152
				$bestPriority = $keywordItem->priority;
153
				$matchingKeywordItem = $keywordItem;
154
				if (! empty($matching)) {
155
					array_shift($matching);
156
					$matchingKeywordItem->matchingKeyword = $matching;
157
				}
158
			}
159
		}
160
		return $matchingKeywordItem;
161
	}
162
163
	private function findBestVariance($userName, $message, $keyword)
0 ignored issues
show
Unused Code introduced by
The parameter $userName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
164
	{
165
		// Verify
166
		if (empty($keyword)) {
167
			self::$logger->addError('Hum, this keyword item is kind of empty', $keyword);
168
			return;
169
		}
170
		
171
		$bestPriority = - 1;
172
		$matchingVarianceItem;
0 ignored issues
show
Bug introduced by
The variable $matchingVarianceItem seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
173
		// Search best variance
174
		if (! empty($keyword->variances)) {
175
			foreach ($keyword->variances as $varianceItem) {
176
				$varianceSize = strlen($varianceItem->variance);
177
				if ($varianceSize > $bestPriority && preg_match_all('!' . $varianceItem->varianceRegexable . '!is', $message, $matching)) {
178
					$bestPriority = $varianceSize;
179
					$matchingVarianceItem = $varianceItem;
180
					if (! empty($matching)) {
181
						array_shift($matching);
182
						$matchingVarianceItem->matchingData = $matching;
183
					}
184
				}
185
			}
186
		}
187
		// No variance found? Use default responses
188
		if (empty($matchingVarianceItem->responses)) {
189
			@$matchingVarianceItem->responses = $keyword->defaultResponses;
0 ignored issues
show
Bug introduced by
The variable $matchingVarianceItem does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
190
		}
191
		$matchingVarianceItem->matchingKeyword = @$keyword->matchingKeyword;
192
		return $matchingVarianceItem;
193
	}
194
195
	private function pickResponse($userName, $userMessage, $varianceItem)
0 ignored issues
show
Unused Code introduced by
The parameter $userName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $userMessage is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
196
	{
197
		// Verify
198
		if (empty($varianceItem->responses)) {
199
			return 'Ouch !';
200
		}
201
		
202
		// Select random response
203
		$index = mt_rand(0, count($varianceItem->responses) - 1);
204
		$response = $varianceItem->responses[$index];
205
		return $response;
206
	}
207
208
	public function getKnowledges()
209
	{
210
		return $this->knowledges;
211
	}
212
213
	public function setKnowledges($knowledges)
214
	{
215
		$this->knowledges = $knowledges;
216
	}
217
218
	public function getConfig()
219
	{
220
		return $this->config;
221
	}
222
223
	public function setConfig($config)
224
	{
225
		$this->config = $config;
226
	}
227
228
	public function setBrainManager($brainManager)
229
	{
230
		$this->brainManager = $brainManager;
231
	}
232
}
233