BrainManager::getSynonyms()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
rs 9.4285
cc 3
eloc 4
nc 3
nop 2
1
<?php
2
namespace Posibrain\Positron\Instinct;
3
4
use Seld\JsonLint\JsonParser;
5
use Seld\JsonLint\ParsingException;
6
use Monolog\Logger;
7
include_once (__DIR__ . '/../../../tools.php');
8
9
/**
10
 *
11
 * @author Fylhan (http://fylhan.la-bnbox.fr)
12
 * @license LGPL-2.1+
13
 */
14
class BrainManager implements IBrainManager
15
{
16
17
	private static $logger = NULL;
18
19
	public function __construct($params = array())
20
	{
21
		// Logger
22 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...
23
			self::$logger = new Logger(__CLASS__);
24
			if (! empty($params) && isset($params['loggerHandler'])) {
25
				self::$logger->pushHandler($params['loggerHandler']);
26
			}
27
		}
28
	}
29
30
	/**
31
	 * @Override
32
	 */
33
	public function loadBrain($config)
34
	{
35
		if ('dev' == MODE || ! is_file($config->getComputedKnowledgePath())) {
36
			if (! $this->generateKnowledgeCache($config)) {
37
				self::$logger->addWarning('Can\'t load knowledge', $config);
38
				$knowledges = $this->loadJsonFile($config->getNoKnowledgePath());
39
				return $knowledges;
40
			}
41
		}
42
		$knowledges = $this->loadJsonFile($config->getComputedKnowledgePath(), $config->getCharset());
43
		return $knowledges;
44
	}
45
46
	/**
47
	 * Generate a pre-configured JSON file with already regexable string
48
	 *
49
	 * Thanks to this benchmark: http://techblog.procurios.nl/k/news/view/34972/14863/cache-a-large-array-json-serialize-or-var_export.html
50
	 * I now know that JSON and serialization are similar in terms of speed performance, and I prefer JSON here
51
	 * We may use var_exports (cost of an include until it is created), but it didn't work, and this is not quicker apparently
52
	 */
53
	public function generateKnowledgeCache($config)
54
	{
55
		// -- Load JSON knowledge
56
		$identity = $this->loadJsonFile($config->getIdentityPath(), $config->getCharset());
57
		$synonyms = $this->loadJsonFile($config->getSynonymsPath(), $config->getCharset());
58
		$knowledge = $this->loadJsonFile($config->getKnowledgePath(), $config->getCharset());
59
		
60
		if (NULL == $identity || NULL == $synonyms || NULL == $knowledge) {
61
			return false;
62
		}
63
		
64
		foreach ($knowledge->keywords as $k => $keyword) {
65
			// Pre-compute keyword
66
			$keyword->keyword = preg_replace('!\$\{name\}!U', $identity->name, $keyword->keyword);
67
			$keyword->keyword = preg_replace('!\$\{pseudo\}!U', $identity->pseudo, $keyword->keyword);
68
			$keyword->keyword = preg_replace('!\$\{conceptorName\}!U', $identity->conceptorName, $keyword->keyword);
69
			// Pre-compute synonyms
70
			if (! empty($keyword->variances)) {
71
				$keywordSynonyms = $keyword->keyword;
72
				$variances = $keyword->variances;
73
				$size = count($variances);
74
				for ($i = 0; $i < $size; $i ++) {
75
					$keyword->variances[$i]->varianceRegexable = preg_replace('!\$\{keyword\}!U', '(' . implode('|', $keywordSynonyms) . ')', $variances[$i]->variance);
76
					$keyword->variances[$i]->varianceRegexable = preg_replace('!\$\{name\}!U', $identity->name, $variances[$i]->varianceRegexable);
77
					$keyword->variances[$i]->varianceRegexable = preg_replace('!\$\{pseudo\}!U', $identity->pseudo, $variances[$i]->varianceRegexable);
78
					$keyword->variances[$i]->varianceRegexable = preg_replace('!\$\{conceptorName\}!U', $identity->conceptorName, $variances[$i]->varianceRegexable);
79
					preg_match_all('!@\{([^\}]+)\}!U', $keyword->variances[$i]->varianceRegexable, $matchingSynonyms);
80
					if (NULL != $matchingSynonyms && ! empty($matchingSynonyms) && ! empty($matchingSynonyms[1])) {
81
						foreach ($matchingSynonyms[1] as $synonym) {
82
							$keyword->variances[$i]->varianceRegexable = preg_replace('!@\{' . $synonym . '\}!U', '(' . implode('|', $this->getSynonyms($synonym, $synonyms->synonyms)) . ')', $keyword->variances[$i]->varianceRegexable);
83
						}
84
					}
85
				}
86
			}
87
			$knowledges->keywords[$k] = $keyword;
0 ignored issues
show
Bug introduced by
The variable $knowledges does not exist. Did you mean $knowledge?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
88
		}
89
		$knowledges->identity = $identity;
0 ignored issues
show
Bug introduced by
The variable $knowledges does not exist. Did you mean $knowledge?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
90
		$knowledges->synonyms = $synonyms;
0 ignored issues
show
Bug introduced by
The variable $knowledges does not exist. Did you mean $knowledge?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
91
		// Store JSON cache
92
		$this->storeJsonFile($config->getComputedKnowledgePath(), $knowledges, $config->getCharset());
0 ignored issues
show
Bug introduced by
The variable $knowledges does not exist. Did you mean $knowledge?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
93
		return true;
94
	}
95
96
	public function loadJsonFile($filepath, $charset = 'UTF-8')
0 ignored issues
show
Unused Code introduced by
The parameter $charset 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...
97
	{
98
		// Load JSON file
99
		$data = @file_get_contents($filepath);
100
		if (false === $data) {
101
			self::$logger->addWarning('Can\'t load JSON file "' . $filepath . '"');
102
			return NULL;
103
		}
104
		// Encode to UTF-8
105
		if ('UTF-8' != mb_detect_encoding($data, 'UTF-8', true)) {
106
			$data = utf8_encode($data);
107
		}
108
		// Clean
109
		$data = cleanJsonString($data);
110
		
111
		// Parse JSON
112
		try {
113
			$parser = new JsonParser();
114
			$knowledge = $parser->parse($data, JsonParser::ALLOW_DUPLICATE_KEYS);
115
		} catch (ParsingException $e) {
116
			self::$logger->addWarning('Can\'t parse JSON file "' . $filepath . '": ' . $e->getMessage());
117
			return NULL;
118
		}
119
		return $knowledge;
120
	}
121
122
	private function storeJsonFile($filepath, $data, $charset = 'UTF-8')
123
	{
124
		$jsonData = json_encode($data);
125
		if ('UTF-8' != $charset) {
126
			$jsonData = utf8_decode($jsonData);
127
		}
128
		file_put_contents($filepath, $jsonData);
129
	}
130
131
	private function getSynonyms($synonymKey, $synonymList)
132
	{
133
		foreach ($synonymList as $synonym) {
134
			if ($synonym->key == $synonymKey) {
135
				return $synonym->synonyms;
136
			}
137
		}
138
	}
139
}