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) { |
|
|
|
|
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; |
|
|
|
|
88
|
|
|
} |
89
|
|
|
$knowledges->identity = $identity; |
|
|
|
|
90
|
|
|
$knowledges->synonyms = $synonyms; |
|
|
|
|
91
|
|
|
// Store JSON cache |
92
|
|
|
$this->storeJsonFile($config->getComputedKnowledgePath(), $knowledges, $config->getCharset()); |
|
|
|
|
93
|
|
|
return true; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
public function loadJsonFile($filepath, $charset = 'UTF-8') |
|
|
|
|
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
|
|
|
} |
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.