@@ -52,7 +52,7 @@ discard block |
||
52 | 52 | $i = 0; |
53 | 53 | foreach ($termsForDocumentField as $term) { |
54 | 54 | $frequency = intval($term->count) / $documentField->totalTermCount; |
55 | - $values[] = $quotedDocumentPath . ',' . $quotedField . ', ' . $db->quote($term->term) . ', ' . $db->quote($frequency); |
|
55 | + $values[] = $quotedDocumentPath.','.$quotedField.', '.$db->quote($term->term).', '.$db->quote($frequency); |
|
56 | 56 | $i += 1; |
57 | 57 | if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
58 | 58 | $this->executeStore($sql, $values, $db); |
@@ -101,11 +101,11 @@ discard block |
||
101 | 101 | |
102 | 102 | private function executeStore($sql, $values, $db) |
103 | 103 | { |
104 | - $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
104 | + $sql .= '('.implode('),'.PHP_EOL.'(', $values).');'; |
|
105 | 105 | if (!$db->query($sql)) { |
106 | 106 | $errorInfo = $db->errorInfo(); |
107 | 107 | $errorMsg = $errorInfo[2]; |
108 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
108 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
109 | 109 | } |
110 | 110 | } |
111 | 111 |
@@ -24,92 +24,92 @@ |
||
24 | 24 | */ |
25 | 25 | class TermFrequency |
26 | 26 | { |
27 | - /** |
|
28 | - * @var \PDO |
|
29 | - */ |
|
30 | - protected $dbHandle; |
|
27 | + /** |
|
28 | + * @var \PDO |
|
29 | + */ |
|
30 | + protected $dbHandle; |
|
31 | 31 | |
32 | - /** |
|
33 | - * TermFrequency constructor. |
|
34 | - * |
|
35 | - * @param \PDO $dbHandle |
|
36 | - */ |
|
37 | - public function __construct($dbHandle) |
|
38 | - { |
|
39 | - $this->dbHandle = $dbHandle; |
|
40 | - } |
|
32 | + /** |
|
33 | + * TermFrequency constructor. |
|
34 | + * |
|
35 | + * @param \PDO $dbHandle |
|
36 | + */ |
|
37 | + public function __construct($dbHandle) |
|
38 | + { |
|
39 | + $this->dbHandle = $dbHandle; |
|
40 | + } |
|
41 | 41 | |
42 | - public function execute() |
|
43 | - { |
|
44 | - $db = $this->dbHandle; |
|
45 | - $totalTermCountPerDocument = $this->getTotalTermCountPerDocument($db); |
|
46 | - foreach ($totalTermCountPerDocument as $documentField) { |
|
47 | - $termsForDocumentField = $this->getTermsForDocumentField($documentField->documentPath, $documentField->field); |
|
48 | - $sql = ' |
|
42 | + public function execute() |
|
43 | + { |
|
44 | + $db = $this->dbHandle; |
|
45 | + $totalTermCountPerDocument = $this->getTotalTermCountPerDocument($db); |
|
46 | + foreach ($totalTermCountPerDocument as $documentField) { |
|
47 | + $termsForDocumentField = $this->getTermsForDocumentField($documentField->documentPath, $documentField->field); |
|
48 | + $sql = ' |
|
49 | 49 | INSERT INTO term_frequency (documentPath, field, term, frequency) |
50 | 50 | VALUES |
51 | 51 | '; |
52 | - $quotedDocumentPath = $db->quote($documentField->documentPath); |
|
53 | - $quotedField = $db->quote($documentField->field); |
|
54 | - $values = array(); |
|
55 | - $i = 0; |
|
56 | - foreach ($termsForDocumentField as $term) { |
|
57 | - $frequency = intval($term->count) / $documentField->totalTermCount; |
|
58 | - $values[] = $quotedDocumentPath . ',' . $quotedField . ', ' . $db->quote($term->term) . ', ' . $db->quote($frequency); |
|
59 | - $i += 1; |
|
60 | - if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
61 | - $this->executeStore($sql, $values, $db); |
|
62 | - $i = 0; |
|
63 | - $values = array(); |
|
64 | - } |
|
65 | - } |
|
66 | - if (count($values) != 0) { |
|
67 | - $this->executeStore($sql, $values, $db); |
|
68 | - } |
|
69 | - } |
|
70 | - } |
|
52 | + $quotedDocumentPath = $db->quote($documentField->documentPath); |
|
53 | + $quotedField = $db->quote($documentField->field); |
|
54 | + $values = array(); |
|
55 | + $i = 0; |
|
56 | + foreach ($termsForDocumentField as $term) { |
|
57 | + $frequency = intval($term->count) / $documentField->totalTermCount; |
|
58 | + $values[] = $quotedDocumentPath . ',' . $quotedField . ', ' . $db->quote($term->term) . ', ' . $db->quote($frequency); |
|
59 | + $i += 1; |
|
60 | + if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
61 | + $this->executeStore($sql, $values, $db); |
|
62 | + $i = 0; |
|
63 | + $values = array(); |
|
64 | + } |
|
65 | + } |
|
66 | + if (count($values) != 0) { |
|
67 | + $this->executeStore($sql, $values, $db); |
|
68 | + } |
|
69 | + } |
|
70 | + } |
|
71 | 71 | |
72 | - private function getTermsForDocumentField($documentPath, $field) |
|
73 | - { |
|
74 | - $db = $this->dbHandle; |
|
75 | - $stmt = $db->prepare(' |
|
72 | + private function getTermsForDocumentField($documentPath, $field) |
|
73 | + { |
|
74 | + $db = $this->dbHandle; |
|
75 | + $stmt = $db->prepare(' |
|
76 | 76 | SELECT `term`, `count` |
77 | 77 | FROM `term_count` |
78 | 78 | WHERE `documentPath` = :documentPath |
79 | 79 | AND `field` = :field |
80 | 80 | '); |
81 | - $stmt->bindValue(':documentPath', $documentPath); |
|
82 | - $stmt->bindValue(':field', $field); |
|
83 | - $stmt->execute(); |
|
84 | - return $stmt->fetchAll(\PDO::FETCH_CLASS); |
|
85 | - } |
|
81 | + $stmt->bindValue(':documentPath', $documentPath); |
|
82 | + $stmt->bindValue(':field', $field); |
|
83 | + $stmt->execute(); |
|
84 | + return $stmt->fetchAll(\PDO::FETCH_CLASS); |
|
85 | + } |
|
86 | 86 | |
87 | - /** |
|
88 | - * @param $db |
|
89 | - * |
|
90 | - * @return mixed |
|
91 | - */ |
|
92 | - private function getTotalTermCountPerDocument($db) |
|
93 | - { |
|
94 | - $stmt = $db->prepare(' |
|
87 | + /** |
|
88 | + * @param $db |
|
89 | + * |
|
90 | + * @return mixed |
|
91 | + */ |
|
92 | + private function getTotalTermCountPerDocument($db) |
|
93 | + { |
|
94 | + $stmt = $db->prepare(' |
|
95 | 95 | SELECT documentPath, field, SUM(count) as totalTermCount |
96 | 96 | FROM term_count |
97 | 97 | GROUP BY documentPath, field |
98 | 98 | '); |
99 | - $stmt->execute(); |
|
100 | - $totalTermCountPerDocument = $stmt->fetchAll(\PDO::FETCH_CLASS); |
|
99 | + $stmt->execute(); |
|
100 | + $totalTermCountPerDocument = $stmt->fetchAll(\PDO::FETCH_CLASS); |
|
101 | 101 | |
102 | - return $totalTermCountPerDocument; |
|
103 | - } |
|
102 | + return $totalTermCountPerDocument; |
|
103 | + } |
|
104 | 104 | |
105 | - private function executeStore($sql, $values, $db) |
|
106 | - { |
|
107 | - $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
108 | - if (!$db->query($sql)) { |
|
109 | - $errorInfo = $db->errorInfo(); |
|
110 | - $errorMsg = $errorInfo[2]; |
|
111 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
112 | - } |
|
113 | - } |
|
105 | + private function executeStore($sql, $values, $db) |
|
106 | + { |
|
107 | + $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
108 | + if (!$db->query($sql)) { |
|
109 | + $errorInfo = $db->errorInfo(); |
|
110 | + $errorMsg = $errorInfo[2]; |
|
111 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
112 | + } |
|
113 | + } |
|
114 | 114 | |
115 | 115 | } |
116 | 116 | \ No newline at end of file |
@@ -46,7 +46,7 @@ discard block |
||
46 | 46 | protected function applyFilters($tokens) |
47 | 47 | { |
48 | 48 | foreach ($this->filters as $filterName) { |
49 | - $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
49 | + $filterClassName = '\CloudControl\Cms\search\filters\\'.$filterName; |
|
50 | 50 | $filter = new $filterClassName($tokens); |
51 | 51 | $tokens = $filter->getFilterResults(); |
52 | 52 | } |
@@ -66,7 +66,7 @@ discard block |
||
66 | 66 | foreach ($documentTermCount as $field => $countArray) { |
67 | 67 | $quotedField = $db->quote($field); |
68 | 68 | foreach ($countArray as $term => $count) { |
69 | - $values[] = $quotedDocumentPath . ', ' . $db->quote($term) . ', ' . $db->quote($count) . ', ' . $quotedField; |
|
69 | + $values[] = $quotedDocumentPath.', '.$db->quote($term).', '.$db->quote($count).', '.$quotedField; |
|
70 | 70 | $i += 1; |
71 | 71 | if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
72 | 72 | $this->executeStoreDocumentTermCount($values, $sql, $db); |
@@ -90,12 +90,12 @@ discard block |
||
90 | 90 | */ |
91 | 91 | protected function executeStoreDocumentTermCount($values, $sql, $db) |
92 | 92 | { |
93 | - $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
93 | + $sql .= '('.implode('),'.PHP_EOL.'(', $values).');'; |
|
94 | 94 | $stmt = $db->prepare($sql); |
95 | 95 | if ($stmt === false || !$stmt->execute()) { |
96 | 96 | $errorInfo = $db->errorInfo(); |
97 | 97 | $errorMsg = $errorInfo[2]; |
98 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
98 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
99 | 99 | } |
100 | 100 | } |
101 | 101 |
@@ -14,113 +14,113 @@ |
||
14 | 14 | |
15 | 15 | class TermCount |
16 | 16 | { |
17 | - /** |
|
18 | - * @var \PDO |
|
19 | - */ |
|
20 | - protected $dbHandle; |
|
21 | - protected $documents; |
|
22 | - protected $filters; |
|
23 | - protected $storage; |
|
17 | + /** |
|
18 | + * @var \PDO |
|
19 | + */ |
|
20 | + protected $dbHandle; |
|
21 | + protected $documents; |
|
22 | + protected $filters; |
|
23 | + protected $storage; |
|
24 | 24 | |
25 | - /** |
|
26 | - * TermCount constructor. |
|
27 | - * |
|
28 | - * @param \PDO $dbHandle |
|
29 | - * @param array $documents |
|
30 | - * @param array $filters |
|
31 | - * @param Storage $jsonStorage |
|
32 | - */ |
|
33 | - public function __construct($dbHandle, $documents, $filters, $jsonStorage) |
|
34 | - { |
|
35 | - $this->dbHandle = $dbHandle; |
|
36 | - $this->documents = $documents; |
|
37 | - $this->filters = $filters; |
|
38 | - $this->storage = $jsonStorage; |
|
39 | - } |
|
25 | + /** |
|
26 | + * TermCount constructor. |
|
27 | + * |
|
28 | + * @param \PDO $dbHandle |
|
29 | + * @param array $documents |
|
30 | + * @param array $filters |
|
31 | + * @param Storage $jsonStorage |
|
32 | + */ |
|
33 | + public function __construct($dbHandle, $documents, $filters, $jsonStorage) |
|
34 | + { |
|
35 | + $this->dbHandle = $dbHandle; |
|
36 | + $this->documents = $documents; |
|
37 | + $this->filters = $filters; |
|
38 | + $this->storage = $jsonStorage; |
|
39 | + } |
|
40 | 40 | |
41 | - public function execute() |
|
42 | - { |
|
43 | - $this->iterateDocumentsAndCreateTermCount($this->documents); |
|
44 | - } |
|
41 | + public function execute() |
|
42 | + { |
|
43 | + $this->iterateDocumentsAndCreateTermCount($this->documents); |
|
44 | + } |
|
45 | 45 | |
46 | - protected function applyFilters($tokens) |
|
47 | - { |
|
48 | - foreach ($this->filters as $filterName) { |
|
49 | - $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
50 | - $filter = new $filterClassName($tokens); |
|
51 | - $tokens = $filter->getFilterResults(); |
|
52 | - } |
|
53 | - return $tokens; |
|
54 | - } |
|
46 | + protected function applyFilters($tokens) |
|
47 | + { |
|
48 | + foreach ($this->filters as $filterName) { |
|
49 | + $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
50 | + $filter = new $filterClassName($tokens); |
|
51 | + $tokens = $filter->getFilterResults(); |
|
52 | + } |
|
53 | + return $tokens; |
|
54 | + } |
|
55 | 55 | |
56 | - protected function storeDocumentTermCount($document, $documentTermCount) |
|
57 | - { |
|
58 | - $db = $this->dbHandle; |
|
59 | - $sqlStart = ' |
|
56 | + protected function storeDocumentTermCount($document, $documentTermCount) |
|
57 | + { |
|
58 | + $db = $this->dbHandle; |
|
59 | + $sqlStart = ' |
|
60 | 60 | INSERT INTO `term_count` (`documentPath`, `term`, `count`, `field`) |
61 | 61 | VALUES '; |
62 | - $sql = $sqlStart; |
|
63 | - $values = array(); |
|
64 | - $quotedDocumentPath = $db->quote($document->path); |
|
65 | - $i = 0; |
|
66 | - foreach ($documentTermCount as $field => $countArray) { |
|
67 | - $quotedField = $db->quote($field); |
|
68 | - foreach ($countArray as $term => $count) { |
|
69 | - $values[] = $quotedDocumentPath . ', ' . $db->quote($term) . ', ' . $db->quote($count) . ', ' . $quotedField; |
|
70 | - $i += 1; |
|
71 | - if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
72 | - $this->executeStoreDocumentTermCount($values, $sql, $db); |
|
73 | - $values = array(); |
|
74 | - $sql = $sqlStart; |
|
75 | - $i = 0; |
|
76 | - } |
|
77 | - } |
|
78 | - } |
|
79 | - if (count($values) != 0) { |
|
80 | - $this->executeStoreDocumentTermCount($values, $sql, $db); |
|
81 | - } |
|
82 | - } |
|
62 | + $sql = $sqlStart; |
|
63 | + $values = array(); |
|
64 | + $quotedDocumentPath = $db->quote($document->path); |
|
65 | + $i = 0; |
|
66 | + foreach ($documentTermCount as $field => $countArray) { |
|
67 | + $quotedField = $db->quote($field); |
|
68 | + foreach ($countArray as $term => $count) { |
|
69 | + $values[] = $quotedDocumentPath . ', ' . $db->quote($term) . ', ' . $db->quote($count) . ', ' . $quotedField; |
|
70 | + $i += 1; |
|
71 | + if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
72 | + $this->executeStoreDocumentTermCount($values, $sql, $db); |
|
73 | + $values = array(); |
|
74 | + $sql = $sqlStart; |
|
75 | + $i = 0; |
|
76 | + } |
|
77 | + } |
|
78 | + } |
|
79 | + if (count($values) != 0) { |
|
80 | + $this->executeStoreDocumentTermCount($values, $sql, $db); |
|
81 | + } |
|
82 | + } |
|
83 | 83 | |
84 | - /** |
|
85 | - * @param $values |
|
86 | - * @param $sql |
|
87 | - * @param $db |
|
88 | - * |
|
89 | - * @throws \Exception |
|
90 | - */ |
|
91 | - protected function executeStoreDocumentTermCount($values, $sql, $db) |
|
92 | - { |
|
93 | - $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
94 | - $stmt = $db->prepare($sql); |
|
95 | - if ($stmt === false || !$stmt->execute()) { |
|
96 | - $errorInfo = $db->errorInfo(); |
|
97 | - $errorMsg = $errorInfo[2]; |
|
98 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
99 | - } |
|
100 | - } |
|
84 | + /** |
|
85 | + * @param $values |
|
86 | + * @param $sql |
|
87 | + * @param $db |
|
88 | + * |
|
89 | + * @throws \Exception |
|
90 | + */ |
|
91 | + protected function executeStoreDocumentTermCount($values, $sql, $db) |
|
92 | + { |
|
93 | + $sql .= '(' . implode('),' . PHP_EOL . '(', $values) . ');'; |
|
94 | + $stmt = $db->prepare($sql); |
|
95 | + if ($stmt === false || !$stmt->execute()) { |
|
96 | + $errorInfo = $db->errorInfo(); |
|
97 | + $errorMsg = $errorInfo[2]; |
|
98 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
99 | + } |
|
100 | + } |
|
101 | 101 | |
102 | - /** |
|
103 | - * @param $document |
|
104 | - */ |
|
105 | - private function createTermCountForDocument($document) |
|
106 | - { |
|
107 | - $tokenizer = new DocumentTokenizer($document, $this->storage); |
|
108 | - $tokens = $tokenizer->getTokens(); |
|
109 | - $documentTermCount = $this->applyFilters($tokens); |
|
110 | - $this->storeDocumentTermCount($document, $documentTermCount); |
|
111 | - } |
|
102 | + /** |
|
103 | + * @param $document |
|
104 | + */ |
|
105 | + private function createTermCountForDocument($document) |
|
106 | + { |
|
107 | + $tokenizer = new DocumentTokenizer($document, $this->storage); |
|
108 | + $tokens = $tokenizer->getTokens(); |
|
109 | + $documentTermCount = $this->applyFilters($tokens); |
|
110 | + $this->storeDocumentTermCount($document, $documentTermCount); |
|
111 | + } |
|
112 | 112 | |
113 | - /** |
|
114 | - * @param $documents |
|
115 | - */ |
|
116 | - private function iterateDocumentsAndCreateTermCount($documents) |
|
117 | - { |
|
118 | - foreach ($documents as $document) { |
|
119 | - if ($document->type === 'folder') { |
|
120 | - $this->iterateDocumentsAndCreateTermCount($document->content); |
|
121 | - } else { |
|
122 | - $this->createTermCountForDocument($document); |
|
123 | - } |
|
124 | - } |
|
125 | - } |
|
113 | + /** |
|
114 | + * @param $documents |
|
115 | + */ |
|
116 | + private function iterateDocumentsAndCreateTermCount($documents) |
|
117 | + { |
|
118 | + foreach ($documents as $document) { |
|
119 | + if ($document->type === 'folder') { |
|
120 | + $this->iterateDocumentsAndCreateTermCount($document->content); |
|
121 | + } else { |
|
122 | + $this->createTermCountForDocument($document); |
|
123 | + } |
|
124 | + } |
|
125 | + } |
|
126 | 126 | } |
127 | 127 | \ No newline at end of file |
@@ -45,18 +45,18 @@ discard block |
||
45 | 45 | if ($stmt === false) { |
46 | 46 | $errorInfo = $db->errorInfo(); |
47 | 47 | $errorMsg = $errorInfo[2]; |
48 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
48 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
49 | 49 | } |
50 | 50 | if (($stmt->execute()) === false) { |
51 | 51 | $errorInfo = $db->errorInfo(); |
52 | 52 | $errorMsg = $errorInfo[2]; |
53 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
53 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
54 | 54 | } |
55 | 55 | $uniqueFieldsPerDocument = $stmt->fetchAll(\PDO::FETCH_OBJ); |
56 | 56 | $values = array(); |
57 | 57 | $i = 0; |
58 | 58 | foreach ($uniqueFieldsPerDocument as $fieldRow) { |
59 | - $values[] = 'UPDATE term_frequency SET termNorm = 1/sqrt(' . intval($fieldRow->termCount) . ') WHERE documentPath = ' . $db->quote($fieldRow->documentPath) . ' AND field = ' . $db->quote($fieldRow->field) . ';'; |
|
59 | + $values[] = 'UPDATE term_frequency SET termNorm = 1/sqrt('.intval($fieldRow->termCount).') WHERE documentPath = '.$db->quote($fieldRow->documentPath).' AND field = '.$db->quote($fieldRow->field).';'; |
|
60 | 60 | $i += 1; |
61 | 61 | if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
62 | 62 | $this->executeUpdateTermNorm($values, $db); |
@@ -76,13 +76,13 @@ discard block |
||
76 | 76 | */ |
77 | 77 | private function executeUpdateTermNorm($values, $db) |
78 | 78 | { |
79 | - $sql = 'BEGIN TRANSACTION;' . PHP_EOL; |
|
80 | - $sql .= implode(PHP_EOL, $values) . PHP_EOL; |
|
79 | + $sql = 'BEGIN TRANSACTION;'.PHP_EOL; |
|
80 | + $sql .= implode(PHP_EOL, $values).PHP_EOL; |
|
81 | 81 | $sql .= 'COMMIT;'; |
82 | 82 | if (($db->exec($sql)) === false) { |
83 | 83 | $errorInfo = $db->errorInfo(); |
84 | 84 | $errorMsg = $errorInfo[2]; |
85 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
85 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
86 | 86 | } |
87 | 87 | } |
88 | 88 | } |
89 | 89 | \ No newline at end of file |
@@ -17,72 +17,72 @@ |
||
17 | 17 | */ |
18 | 18 | class TermFieldLengthNorm |
19 | 19 | { |
20 | - /** |
|
21 | - * @var \PDO |
|
22 | - */ |
|
23 | - protected $dbHandle; |
|
20 | + /** |
|
21 | + * @var \PDO |
|
22 | + */ |
|
23 | + protected $dbHandle; |
|
24 | 24 | |
25 | - /** |
|
26 | - * TermFieldLengthNorm constructor. |
|
27 | - * |
|
28 | - * @param \PDO $dbHandle |
|
29 | - */ |
|
30 | - public function __construct($dbHandle) |
|
31 | - { |
|
32 | - $this->dbHandle = $dbHandle; |
|
33 | - } |
|
25 | + /** |
|
26 | + * TermFieldLengthNorm constructor. |
|
27 | + * |
|
28 | + * @param \PDO $dbHandle |
|
29 | + */ |
|
30 | + public function __construct($dbHandle) |
|
31 | + { |
|
32 | + $this->dbHandle = $dbHandle; |
|
33 | + } |
|
34 | 34 | |
35 | - public function execute() |
|
36 | - { |
|
37 | - $db = $this->dbHandle; |
|
38 | - $db->sqliteCreateFunction('sqrt', 'sqrt', 1); |
|
39 | - $sql = ' |
|
35 | + public function execute() |
|
36 | + { |
|
37 | + $db = $this->dbHandle; |
|
38 | + $db->sqliteCreateFunction('sqrt', 'sqrt', 1); |
|
39 | + $sql = ' |
|
40 | 40 | SELECT documentPath, field, COUNT(`count`) as termCount |
41 | 41 | FROM term_count |
42 | 42 | GROUP BY documentPath, field |
43 | 43 | '; |
44 | - $stmt = $db->prepare($sql); |
|
45 | - if ($stmt === false) { |
|
46 | - $errorInfo = $db->errorInfo(); |
|
47 | - $errorMsg = $errorInfo[2]; |
|
48 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
49 | - } |
|
50 | - if (($stmt->execute()) === false) { |
|
51 | - $errorInfo = $db->errorInfo(); |
|
52 | - $errorMsg = $errorInfo[2]; |
|
53 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
54 | - } |
|
55 | - $uniqueFieldsPerDocument = $stmt->fetchAll(\PDO::FETCH_OBJ); |
|
56 | - $values = array(); |
|
57 | - $i = 0; |
|
58 | - foreach ($uniqueFieldsPerDocument as $fieldRow) { |
|
59 | - $values[] = 'UPDATE term_frequency SET termNorm = 1/sqrt(' . intval($fieldRow->termCount) . ') WHERE documentPath = ' . $db->quote($fieldRow->documentPath) . ' AND field = ' . $db->quote($fieldRow->field) . ';'; |
|
60 | - $i += 1; |
|
61 | - if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
62 | - $this->executeUpdateTermNorm($values, $db); |
|
63 | - $values = array(); |
|
64 | - $i = 0; |
|
65 | - } |
|
66 | - } |
|
67 | - if (count($values) != 0) { |
|
68 | - $this->executeUpdateTermNorm($values, $db); |
|
69 | - } |
|
70 | - } |
|
44 | + $stmt = $db->prepare($sql); |
|
45 | + if ($stmt === false) { |
|
46 | + $errorInfo = $db->errorInfo(); |
|
47 | + $errorMsg = $errorInfo[2]; |
|
48 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
49 | + } |
|
50 | + if (($stmt->execute()) === false) { |
|
51 | + $errorInfo = $db->errorInfo(); |
|
52 | + $errorMsg = $errorInfo[2]; |
|
53 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
54 | + } |
|
55 | + $uniqueFieldsPerDocument = $stmt->fetchAll(\PDO::FETCH_OBJ); |
|
56 | + $values = array(); |
|
57 | + $i = 0; |
|
58 | + foreach ($uniqueFieldsPerDocument as $fieldRow) { |
|
59 | + $values[] = 'UPDATE term_frequency SET termNorm = 1/sqrt(' . intval($fieldRow->termCount) . ') WHERE documentPath = ' . $db->quote($fieldRow->documentPath) . ' AND field = ' . $db->quote($fieldRow->field) . ';'; |
|
60 | + $i += 1; |
|
61 | + if ($i >= Indexer::SQLITE_MAX_COMPOUND_SELECT) { |
|
62 | + $this->executeUpdateTermNorm($values, $db); |
|
63 | + $values = array(); |
|
64 | + $i = 0; |
|
65 | + } |
|
66 | + } |
|
67 | + if (count($values) != 0) { |
|
68 | + $this->executeUpdateTermNorm($values, $db); |
|
69 | + } |
|
70 | + } |
|
71 | 71 | |
72 | - /** |
|
73 | - * @param array $values |
|
74 | - * @param \PDO $db |
|
75 | - * @throws \Exception |
|
76 | - */ |
|
77 | - private function executeUpdateTermNorm($values, $db) |
|
78 | - { |
|
79 | - $sql = 'BEGIN TRANSACTION;' . PHP_EOL; |
|
80 | - $sql .= implode(PHP_EOL, $values) . PHP_EOL; |
|
81 | - $sql .= 'COMMIT;'; |
|
82 | - if (($db->exec($sql)) === false) { |
|
83 | - $errorInfo = $db->errorInfo(); |
|
84 | - $errorMsg = $errorInfo[2]; |
|
85 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
86 | - } |
|
87 | - } |
|
72 | + /** |
|
73 | + * @param array $values |
|
74 | + * @param \PDO $db |
|
75 | + * @throws \Exception |
|
76 | + */ |
|
77 | + private function executeUpdateTermNorm($values, $db) |
|
78 | + { |
|
79 | + $sql = 'BEGIN TRANSACTION;' . PHP_EOL; |
|
80 | + $sql .= implode(PHP_EOL, $values) . PHP_EOL; |
|
81 | + $sql .= 'COMMIT;'; |
|
82 | + if (($db->exec($sql)) === false) { |
|
83 | + $errorInfo = $db->errorInfo(); |
|
84 | + $errorMsg = $errorInfo[2]; |
|
85 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
86 | + } |
|
87 | + } |
|
88 | 88 | } |
89 | 89 | \ No newline at end of file |
@@ -47,14 +47,14 @@ |
||
47 | 47 | if (!$stmt = $db->prepare($sql)) { |
48 | 48 | $errorInfo = $db->errorInfo(); |
49 | 49 | $errorMsg = $errorInfo[2]; |
50 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
50 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
51 | 51 | } |
52 | 52 | $stmt->bindValue(':documentCount', $this->documentCount); |
53 | 53 | $result = $stmt->execute(); |
54 | 54 | if ($result === false) { |
55 | 55 | $errorInfo = $db->errorInfo(); |
56 | 56 | $errorMsg = $errorInfo[2]; |
57 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
57 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
58 | 58 | } |
59 | 59 | } |
60 | 60 | } |
61 | 61 | \ No newline at end of file |
@@ -10,51 +10,51 @@ |
||
10 | 10 | |
11 | 11 | class InverseDocumentFrequency |
12 | 12 | { |
13 | - /** |
|
14 | - * @var \PDO |
|
15 | - */ |
|
16 | - protected $dbHandle; |
|
17 | - protected $documentCount; |
|
13 | + /** |
|
14 | + * @var \PDO |
|
15 | + */ |
|
16 | + protected $dbHandle; |
|
17 | + protected $documentCount; |
|
18 | 18 | |
19 | - /** |
|
20 | - * InverseDocumentFrequency constructor. |
|
21 | - * |
|
22 | - * @param \PDO $dbHandle |
|
23 | - * @param int $documentCount |
|
24 | - */ |
|
25 | - public function __construct($dbHandle, $documentCount) |
|
26 | - { |
|
27 | - $this->dbHandle = $dbHandle; |
|
28 | - $this->documentCount = $documentCount; |
|
29 | - } |
|
19 | + /** |
|
20 | + * InverseDocumentFrequency constructor. |
|
21 | + * |
|
22 | + * @param \PDO $dbHandle |
|
23 | + * @param int $documentCount |
|
24 | + */ |
|
25 | + public function __construct($dbHandle, $documentCount) |
|
26 | + { |
|
27 | + $this->dbHandle = $dbHandle; |
|
28 | + $this->documentCount = $documentCount; |
|
29 | + } |
|
30 | 30 | |
31 | - /** |
|
32 | - * Formula to calculate: |
|
33 | - * idf(t) = 1 + log ( totalDocuments / (documentsThatContainTheTerm + 1)) |
|
34 | - * @throws \Exception |
|
35 | - */ |
|
36 | - public function execute() |
|
37 | - { |
|
38 | - $db = $this->dbHandle; |
|
39 | - $db->sqliteCreateFunction('log', 'log', 1); |
|
40 | - $sql = ' |
|
31 | + /** |
|
32 | + * Formula to calculate: |
|
33 | + * idf(t) = 1 + log ( totalDocuments / (documentsThatContainTheTerm + 1)) |
|
34 | + * @throws \Exception |
|
35 | + */ |
|
36 | + public function execute() |
|
37 | + { |
|
38 | + $db = $this->dbHandle; |
|
39 | + $db->sqliteCreateFunction('log', 'log', 1); |
|
40 | + $sql = ' |
|
41 | 41 | INSERT INTO inverse_document_frequency (term, inverseDocumentFrequency) |
42 | 42 | SELECT DISTINCT term, (1+(log(:documentCount / COUNT(documentPath) + 1))) as inverseDocumentFrequency |
43 | 43 | FROM term_count |
44 | 44 | GROUP BY term |
45 | 45 | '; |
46 | 46 | |
47 | - if (!$stmt = $db->prepare($sql)) { |
|
48 | - $errorInfo = $db->errorInfo(); |
|
49 | - $errorMsg = $errorInfo[2]; |
|
50 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
51 | - } |
|
52 | - $stmt->bindValue(':documentCount', $this->documentCount); |
|
53 | - $result = $stmt->execute(); |
|
54 | - if ($result === false) { |
|
55 | - $errorInfo = $db->errorInfo(); |
|
56 | - $errorMsg = $errorInfo[2]; |
|
57 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
58 | - } |
|
59 | - } |
|
47 | + if (!$stmt = $db->prepare($sql)) { |
|
48 | + $errorInfo = $db->errorInfo(); |
|
49 | + $errorMsg = $errorInfo[2]; |
|
50 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
51 | + } |
|
52 | + $stmt->bindValue(':documentCount', $this->documentCount); |
|
53 | + $result = $stmt->execute(); |
|
54 | + if ($result === false) { |
|
55 | + $errorInfo = $db->errorInfo(); |
|
56 | + $errorMsg = $errorInfo[2]; |
|
57 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
58 | + } |
|
59 | + } |
|
60 | 60 | } |
61 | 61 | \ No newline at end of file |
@@ -10,5 +10,5 @@ |
||
10 | 10 | |
11 | 11 | class DutchStopWords extends StopWordsFilter |
12 | 12 | { |
13 | - protected $stopWords = array('aan','af','al','alles','als','altijd','andere','ben','bij','daar','dan','dat','de','der','deze','die','dit','doch','doen','door','doorgaans','dus','een','eens','en','er','ge','geen','geweest','haar','had','heb','hebben','heeft','hem','het','hier','hij','hoe','hun','iemand','iets','ik','in','is','ja','je','kan','kon','kunnen','maar','me','meer','men','met','mij','mijn','moet','na','naar','niet','niets','nog','nu','of','om','omdat','ons','ook','op','over','reeds','te','tegen','toch','toen','tot','u','uit','uw','van','veel','voor','want','waren','was','wat','we','wel','werd','wezen','wie','wij','wil','worden','zal','ze','zei','zelf','zich','zij','zijn','zo','zodat','zonder','zou'); |
|
13 | + protected $stopWords = array('aan', 'af', 'al', 'alles', 'als', 'altijd', 'andere', 'ben', 'bij', 'daar', 'dan', 'dat', 'de', 'der', 'deze', 'die', 'dit', 'doch', 'doen', 'door', 'doorgaans', 'dus', 'een', 'eens', 'en', 'er', 'ge', 'geen', 'geweest', 'haar', 'had', 'heb', 'hebben', 'heeft', 'hem', 'het', 'hier', 'hij', 'hoe', 'hun', 'iemand', 'iets', 'ik', 'in', 'is', 'ja', 'je', 'kan', 'kon', 'kunnen', 'maar', 'me', 'meer', 'men', 'met', 'mij', 'mijn', 'moet', 'na', 'naar', 'niet', 'niets', 'nog', 'nu', 'of', 'om', 'omdat', 'ons', 'ook', 'op', 'over', 'reeds', 'te', 'tegen', 'toch', 'toen', 'tot', 'u', 'uit', 'uw', 'van', 'veel', 'voor', 'want', 'waren', 'was', 'wat', 'we', 'wel', 'werd', 'wezen', 'wie', 'wij', 'wil', 'worden', 'zal', 'ze', 'zei', 'zelf', 'zich', 'zij', 'zijn', 'zo', 'zodat', 'zonder', 'zou'); |
|
14 | 14 | } |
15 | 15 | \ No newline at end of file |
@@ -10,5 +10,5 @@ |
||
10 | 10 | |
11 | 11 | class DutchStopWords extends StopWordsFilter |
12 | 12 | { |
13 | - protected $stopWords = array('aan','af','al','alles','als','altijd','andere','ben','bij','daar','dan','dat','de','der','deze','die','dit','doch','doen','door','doorgaans','dus','een','eens','en','er','ge','geen','geweest','haar','had','heb','hebben','heeft','hem','het','hier','hij','hoe','hun','iemand','iets','ik','in','is','ja','je','kan','kon','kunnen','maar','me','meer','men','met','mij','mijn','moet','na','naar','niet','niets','nog','nu','of','om','omdat','ons','ook','op','over','reeds','te','tegen','toch','toen','tot','u','uit','uw','van','veel','voor','want','waren','was','wat','we','wel','werd','wezen','wie','wij','wil','worden','zal','ze','zei','zelf','zich','zij','zijn','zo','zodat','zonder','zou'); |
|
13 | + protected $stopWords = array('aan','af','al','alles','als','altijd','andere','ben','bij','daar','dan','dat','de','der','deze','die','dit','doch','doen','door','doorgaans','dus','een','eens','en','er','ge','geen','geweest','haar','had','heb','hebben','heeft','hem','het','hier','hij','hoe','hun','iemand','iets','ik','in','is','ja','je','kan','kon','kunnen','maar','me','meer','men','met','mij','mijn','moet','na','naar','niet','niets','nog','nu','of','om','omdat','ons','ook','op','over','reeds','te','tegen','toch','toen','tot','u','uit','uw','van','veel','voor','want','waren','was','wat','we','wel','werd','wezen','wie','wij','wil','worden','zal','ze','zei','zelf','zich','zij','zijn','zo','zodat','zonder','zou'); |
|
14 | 14 | } |
15 | 15 | \ No newline at end of file |
@@ -79,13 +79,13 @@ discard block |
||
79 | 79 | if (!$stmt = $db->query($sql)) { |
80 | 80 | $errorInfo = $db->errorInfo(); |
81 | 81 | $errorMsg = $errorInfo[2]; |
82 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
82 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
83 | 83 | } |
84 | 84 | $result = $stmt->fetch(\PDO::FETCH_COLUMN); |
85 | 85 | if (false === $result) { |
86 | 86 | $errorInfo = $db->errorInfo(); |
87 | 87 | $errorMsg = $errorInfo[2]; |
88 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
88 | + throw new \Exception('SQLite Exception: '.$errorMsg.' in SQL: <br /><pre>'.$sql.'</pre>'); |
|
89 | 89 | } |
90 | 90 | return intval($result); |
91 | 91 | } |
@@ -118,7 +118,7 @@ discard block |
||
118 | 118 | protected function applyFilters($tokens) |
119 | 119 | { |
120 | 120 | foreach ($this->filters as $filterName) { |
121 | - $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
121 | + $filterClassName = '\CloudControl\Cms\search\filters\\'.$filterName; |
|
122 | 122 | $filter = new $filterClassName($tokens); |
123 | 123 | $tokens = $filter->getFilterResults(); |
124 | 124 | } |
@@ -154,13 +154,13 @@ discard block |
||
154 | 154 | GROUP BY term_frequency.documentPath, term_frequency.term |
155 | 155 | ORDER BY score DESC |
156 | 156 | '; |
157 | - if(!$stmt = $db->prepare($sql)) { |
|
158 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
157 | + if (!$stmt = $db->prepare($sql)) { |
|
158 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
159 | 159 | } |
160 | 160 | $stmt->bindValue(':query', $token); |
161 | 161 | $stmt->bindValue(':queryNorm', $queryNorm); |
162 | 162 | if (!$stmt->execute()) { |
163 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
163 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
164 | 164 | } |
165 | 165 | return $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchResult'); |
166 | 166 | } |
@@ -216,13 +216,13 @@ discard block |
||
216 | 216 | $sql = ' |
217 | 217 | SELECT (1 / sqrt(SUM(inverseDocumentFrequency))) as queryNorm |
218 | 218 | FROM inverse_document_frequency |
219 | - WHERE term IN (' . $terms . ') |
|
219 | + WHERE term IN (' . $terms.') |
|
220 | 220 | '; |
221 | - if(!$stmt = $db->prepare($sql)) { |
|
222 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
221 | + if (!$stmt = $db->prepare($sql)) { |
|
222 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
223 | 223 | } |
224 | 224 | if (!$stmt->execute()) { |
225 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
225 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
226 | 226 | } |
227 | 227 | $result = $stmt->fetch(\PDO::FETCH_OBJ); |
228 | 228 | return $result->queryNorm == null ? 1 : $result->queryNorm; |
@@ -272,11 +272,11 @@ discard block |
||
272 | 272 | '; |
273 | 273 | $stmt = $db->prepare($sql); |
274 | 274 | if ($stmt === false) { |
275 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
275 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
276 | 276 | } |
277 | 277 | $stmt->bindValue(':token', $token); |
278 | 278 | if (($stmt === false) | (!$stmt->execute())) { |
279 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
279 | + throw new \Exception('SQLite exception: <pre>'.print_r($db->errorInfo(), true).'</pre> for SQL:<pre>'.$sql.'</pre>'); |
|
280 | 280 | } |
281 | 281 | $result = $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchSuggestion'); |
282 | 282 | $allResults = array_merge($result, $allResults); |
@@ -26,117 +26,117 @@ discard block |
||
26 | 26 | */ |
27 | 27 | class Search extends SearchDbConnected |
28 | 28 | { |
29 | - /** |
|
30 | - * @var Tokenizer |
|
31 | - */ |
|
32 | - protected $tokenizer; |
|
33 | - protected $results = array(); |
|
29 | + /** |
|
30 | + * @var Tokenizer |
|
31 | + */ |
|
32 | + protected $tokenizer; |
|
33 | + protected $results = array(); |
|
34 | 34 | |
35 | - /** |
|
36 | - * An array containing classes implementing \CloudControl\Cms\search\Filters |
|
37 | - * These will be applied to all tokenizers |
|
38 | - * @var array |
|
39 | - */ |
|
40 | - protected $filters = array( |
|
41 | - 'DutchStopWords', |
|
42 | - 'EnglishStopWords' |
|
43 | - ); |
|
35 | + /** |
|
36 | + * An array containing classes implementing \CloudControl\Cms\search\Filters |
|
37 | + * These will be applied to all tokenizers |
|
38 | + * @var array |
|
39 | + */ |
|
40 | + protected $filters = array( |
|
41 | + 'DutchStopWords', |
|
42 | + 'EnglishStopWords' |
|
43 | + ); |
|
44 | 44 | |
45 | - /** |
|
46 | - * Returns an array of SeachResult and / or SearchSuggestion objects, |
|
47 | - * based on the tokens in the Tokenizer |
|
48 | - * @param Tokenizer $tokenizer |
|
49 | - * |
|
50 | - * @return array |
|
51 | - */ |
|
52 | - public function getDocumentsForTokenizer(Tokenizer $tokenizer) |
|
53 | - { |
|
54 | - $this->tokenizer = $tokenizer; |
|
55 | - $resultsPerTokens = $this->queryTokens(); |
|
45 | + /** |
|
46 | + * Returns an array of SeachResult and / or SearchSuggestion objects, |
|
47 | + * based on the tokens in the Tokenizer |
|
48 | + * @param Tokenizer $tokenizer |
|
49 | + * |
|
50 | + * @return array |
|
51 | + */ |
|
52 | + public function getDocumentsForTokenizer(Tokenizer $tokenizer) |
|
53 | + { |
|
54 | + $this->tokenizer = $tokenizer; |
|
55 | + $resultsPerTokens = $this->queryTokens(); |
|
56 | 56 | |
57 | - $flatResults = $this->flattenResults($resultsPerTokens); |
|
58 | - $flatResults = $this->applyQueryCoordination($flatResults); |
|
59 | - usort($flatResults, array($this, "scoreCompare")); |
|
57 | + $flatResults = $this->flattenResults($resultsPerTokens); |
|
58 | + $flatResults = $this->applyQueryCoordination($flatResults); |
|
59 | + usort($flatResults, array($this, "scoreCompare")); |
|
60 | 60 | |
61 | - $flatResults = array_merge($this->getSearchSuggestions(), $flatResults); |
|
61 | + $flatResults = array_merge($this->getSearchSuggestions(), $flatResults); |
|
62 | 62 | |
63 | - return $flatResults; |
|
64 | - } |
|
63 | + return $flatResults; |
|
64 | + } |
|
65 | 65 | |
66 | - /** |
|
67 | - * Returns the amount of distinct documents |
|
68 | - * that are currently in the search index. |
|
69 | - * @return int |
|
70 | - * @throws \Exception |
|
71 | - */ |
|
72 | - public function getIndexedDocuments() |
|
73 | - { |
|
74 | - $db = $this->getSearchDbHandle(); |
|
75 | - $sql = ' |
|
66 | + /** |
|
67 | + * Returns the amount of distinct documents |
|
68 | + * that are currently in the search index. |
|
69 | + * @return int |
|
70 | + * @throws \Exception |
|
71 | + */ |
|
72 | + public function getIndexedDocuments() |
|
73 | + { |
|
74 | + $db = $this->getSearchDbHandle(); |
|
75 | + $sql = ' |
|
76 | 76 | SELECT count(DISTINCT documentPath) as indexedDocuments |
77 | 77 | FROM term_frequency |
78 | 78 | '; |
79 | - if (!$stmt = $db->query($sql)) { |
|
80 | - $errorInfo = $db->errorInfo(); |
|
81 | - $errorMsg = $errorInfo[2]; |
|
82 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
83 | - } |
|
84 | - $result = $stmt->fetch(\PDO::FETCH_COLUMN); |
|
85 | - if (false === $result) { |
|
86 | - $errorInfo = $db->errorInfo(); |
|
87 | - $errorMsg = $errorInfo[2]; |
|
88 | - throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
89 | - } |
|
90 | - return intval($result); |
|
91 | - } |
|
79 | + if (!$stmt = $db->query($sql)) { |
|
80 | + $errorInfo = $db->errorInfo(); |
|
81 | + $errorMsg = $errorInfo[2]; |
|
82 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
83 | + } |
|
84 | + $result = $stmt->fetch(\PDO::FETCH_COLUMN); |
|
85 | + if (false === $result) { |
|
86 | + $errorInfo = $db->errorInfo(); |
|
87 | + $errorMsg = $errorInfo[2]; |
|
88 | + throw new \Exception('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>'); |
|
89 | + } |
|
90 | + return intval($result); |
|
91 | + } |
|
92 | 92 | |
93 | - /** |
|
94 | - * Queries each token present in the Tokenizer |
|
95 | - * and returns SearchResult objects for the found |
|
96 | - * documents |
|
97 | - * @return array |
|
98 | - */ |
|
99 | - private function queryTokens() |
|
100 | - { |
|
101 | - $tokens = $this->getTokens(); |
|
93 | + /** |
|
94 | + * Queries each token present in the Tokenizer |
|
95 | + * and returns SearchResult objects for the found |
|
96 | + * documents |
|
97 | + * @return array |
|
98 | + */ |
|
99 | + private function queryTokens() |
|
100 | + { |
|
101 | + $tokens = $this->getTokens(); |
|
102 | 102 | |
103 | - $queryNorm = $this->getQueryNorm($tokens); |
|
104 | - $results = array(); |
|
105 | - foreach ($tokens as $token) { |
|
106 | - $results[$token] = $this->getResultsForToken($token, $queryNorm); |
|
107 | - } |
|
108 | - return $results; |
|
109 | - } |
|
103 | + $queryNorm = $this->getQueryNorm($tokens); |
|
104 | + $results = array(); |
|
105 | + foreach ($tokens as $token) { |
|
106 | + $results[$token] = $this->getResultsForToken($token, $queryNorm); |
|
107 | + } |
|
108 | + return $results; |
|
109 | + } |
|
110 | 110 | |
111 | - /** |
|
112 | - * Applies the Filter objects in the the filter array to the |
|
113 | - * tokens in the Tokenizer |
|
114 | - * @param $tokens |
|
115 | - * |
|
116 | - * @return mixed |
|
117 | - */ |
|
118 | - protected function applyFilters($tokens) |
|
119 | - { |
|
120 | - foreach ($this->filters as $filterName) { |
|
121 | - $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
122 | - $filter = new $filterClassName($tokens); |
|
123 | - $tokens = $filter->getFilterResults(); |
|
124 | - } |
|
125 | - return $tokens; |
|
126 | - } |
|
111 | + /** |
|
112 | + * Applies the Filter objects in the the filter array to the |
|
113 | + * tokens in the Tokenizer |
|
114 | + * @param $tokens |
|
115 | + * |
|
116 | + * @return mixed |
|
117 | + */ |
|
118 | + protected function applyFilters($tokens) |
|
119 | + { |
|
120 | + foreach ($this->filters as $filterName) { |
|
121 | + $filterClassName = '\CloudControl\Cms\search\filters\\' . $filterName; |
|
122 | + $filter = new $filterClassName($tokens); |
|
123 | + $tokens = $filter->getFilterResults(); |
|
124 | + } |
|
125 | + return $tokens; |
|
126 | + } |
|
127 | 127 | |
128 | - /** |
|
129 | - * Queries the search index for a given token |
|
130 | - * and the query norm. |
|
131 | - * @param $token |
|
132 | - * @param $queryNorm |
|
133 | - * |
|
134 | - * @return array |
|
135 | - * @throws \Exception |
|
136 | - */ |
|
137 | - public function getResultsForToken($token, $queryNorm) { |
|
138 | - $db = $this->getSearchDbHandle(); |
|
139 | - $sql = ' |
|
128 | + /** |
|
129 | + * Queries the search index for a given token |
|
130 | + * and the query norm. |
|
131 | + * @param $token |
|
132 | + * @param $queryNorm |
|
133 | + * |
|
134 | + * @return array |
|
135 | + * @throws \Exception |
|
136 | + */ |
|
137 | + public function getResultsForToken($token, $queryNorm) { |
|
138 | + $db = $this->getSearchDbHandle(); |
|
139 | + $sql = ' |
|
140 | 140 | SELECT (:queryNorm * |
141 | 141 | (SUM(term_frequency.frequency) --TF |
142 | 142 | * inverse_document_frequency.inverseDocumentFrequency -- IDF |
@@ -154,113 +154,113 @@ discard block |
||
154 | 154 | GROUP BY term_frequency.documentPath, term_frequency.term |
155 | 155 | ORDER BY score DESC |
156 | 156 | '; |
157 | - if(!$stmt = $db->prepare($sql)) { |
|
158 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
159 | - } |
|
160 | - $stmt->bindValue(':query', $token); |
|
161 | - $stmt->bindValue(':queryNorm', $queryNorm); |
|
162 | - if (!$stmt->execute()) { |
|
163 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
164 | - } |
|
165 | - return $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchResult'); |
|
166 | - } |
|
157 | + if(!$stmt = $db->prepare($sql)) { |
|
158 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
159 | + } |
|
160 | + $stmt->bindValue(':query', $token); |
|
161 | + $stmt->bindValue(':queryNorm', $queryNorm); |
|
162 | + if (!$stmt->execute()) { |
|
163 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
164 | + } |
|
165 | + return $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchResult'); |
|
166 | + } |
|
167 | 167 | |
168 | - /** |
|
169 | - * @param $resultsPerTokens |
|
170 | - * |
|
171 | - * @return array |
|
172 | - */ |
|
173 | - private function flattenResults($resultsPerTokens) |
|
174 | - { |
|
175 | - $finalResults = array(); |
|
176 | - foreach ($resultsPerTokens as $token => $resultPerToken) { |
|
177 | - foreach ($resultPerToken as $result) { |
|
178 | - if (isset($finalResults[$result->documentPath])) { |
|
179 | - $finalResults[$result->documentPath]->score += $result->score; |
|
180 | - $finalResults[$result->documentPath]->matchingTokens[] = $token; |
|
181 | - } else { |
|
182 | - $resultObj = new SearchResult(); |
|
183 | - $resultObj->documentPath = $result->documentPath; |
|
184 | - $resultObj->matchingTokens = array($token); |
|
185 | - $resultObj->score = floatval($result->score); |
|
186 | - $resultObj->setStorage($this->storage); |
|
187 | - $finalResults[$result->documentPath] = $resultObj; |
|
188 | - } |
|
189 | - } |
|
190 | - } |
|
191 | - return $finalResults; |
|
192 | - } |
|
168 | + /** |
|
169 | + * @param $resultsPerTokens |
|
170 | + * |
|
171 | + * @return array |
|
172 | + */ |
|
173 | + private function flattenResults($resultsPerTokens) |
|
174 | + { |
|
175 | + $finalResults = array(); |
|
176 | + foreach ($resultsPerTokens as $token => $resultPerToken) { |
|
177 | + foreach ($resultPerToken as $result) { |
|
178 | + if (isset($finalResults[$result->documentPath])) { |
|
179 | + $finalResults[$result->documentPath]->score += $result->score; |
|
180 | + $finalResults[$result->documentPath]->matchingTokens[] = $token; |
|
181 | + } else { |
|
182 | + $resultObj = new SearchResult(); |
|
183 | + $resultObj->documentPath = $result->documentPath; |
|
184 | + $resultObj->matchingTokens = array($token); |
|
185 | + $resultObj->score = floatval($result->score); |
|
186 | + $resultObj->setStorage($this->storage); |
|
187 | + $finalResults[$result->documentPath] = $resultObj; |
|
188 | + } |
|
189 | + } |
|
190 | + } |
|
191 | + return $finalResults; |
|
192 | + } |
|
193 | 193 | |
194 | - private function scoreCompare($a, $b) { |
|
195 | - if ($a->score == $b->score) { |
|
196 | - return 0; |
|
197 | - } |
|
198 | - return ($a->score > $b->score) ? -1 : 1; |
|
199 | - } |
|
194 | + private function scoreCompare($a, $b) { |
|
195 | + if ($a->score == $b->score) { |
|
196 | + return 0; |
|
197 | + } |
|
198 | + return ($a->score > $b->score) ? -1 : 1; |
|
199 | + } |
|
200 | 200 | |
201 | - /** |
|
202 | - * Calculates the query norm for all tokens in the Tokenizer |
|
203 | - * @param $tokens |
|
204 | - * |
|
205 | - * @return int |
|
206 | - * @throws \Exception |
|
207 | - */ |
|
208 | - private function getQueryNorm($tokens) |
|
209 | - { |
|
210 | - $db = $this->getSearchDbHandle(); |
|
211 | - $db->sqliteCreateFunction('sqrt', 'sqrt', 1); |
|
212 | - foreach ($tokens as $key => $token) { |
|
213 | - $tokens[$key] = $db->quote($token); |
|
214 | - } |
|
215 | - $terms = implode(',', $tokens); |
|
216 | - $sql = ' |
|
201 | + /** |
|
202 | + * Calculates the query norm for all tokens in the Tokenizer |
|
203 | + * @param $tokens |
|
204 | + * |
|
205 | + * @return int |
|
206 | + * @throws \Exception |
|
207 | + */ |
|
208 | + private function getQueryNorm($tokens) |
|
209 | + { |
|
210 | + $db = $this->getSearchDbHandle(); |
|
211 | + $db->sqliteCreateFunction('sqrt', 'sqrt', 1); |
|
212 | + foreach ($tokens as $key => $token) { |
|
213 | + $tokens[$key] = $db->quote($token); |
|
214 | + } |
|
215 | + $terms = implode(',', $tokens); |
|
216 | + $sql = ' |
|
217 | 217 | SELECT (1 / sqrt(SUM(inverseDocumentFrequency))) as queryNorm |
218 | 218 | FROM inverse_document_frequency |
219 | 219 | WHERE term IN (' . $terms . ') |
220 | 220 | '; |
221 | - if(!$stmt = $db->prepare($sql)) { |
|
222 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
223 | - } |
|
224 | - if (!$stmt->execute()) { |
|
225 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
226 | - } |
|
227 | - $result = $stmt->fetch(\PDO::FETCH_OBJ); |
|
228 | - return $result->queryNorm == null ? 1 : $result->queryNorm; |
|
229 | - } |
|
221 | + if(!$stmt = $db->prepare($sql)) { |
|
222 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
223 | + } |
|
224 | + if (!$stmt->execute()) { |
|
225 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
226 | + } |
|
227 | + $result = $stmt->fetch(\PDO::FETCH_OBJ); |
|
228 | + return $result->queryNorm == null ? 1 : $result->queryNorm; |
|
229 | + } |
|
230 | 230 | |
231 | - /** |
|
232 | - * Applies query coordination to all results |
|
233 | - * @param $flatResults |
|
234 | - * |
|
235 | - * @return mixed |
|
236 | - */ |
|
237 | - private function applyQueryCoordination($flatResults) |
|
238 | - { |
|
239 | - $tokenVector = $this->tokenizer->getTokenVector(); |
|
240 | - $tokens = array_keys($tokenVector); |
|
241 | - $tokenCount = count($tokens); |
|
242 | - foreach ($flatResults as $key => $result) { |
|
243 | - $matchCount = count($result->matchingTokens); |
|
244 | - $result->score = ($matchCount / $tokenCount) * $result->score; |
|
245 | - $flatResults[$key] = $result; |
|
246 | - } |
|
247 | - return $flatResults; |
|
248 | - } |
|
231 | + /** |
|
232 | + * Applies query coordination to all results |
|
233 | + * @param $flatResults |
|
234 | + * |
|
235 | + * @return mixed |
|
236 | + */ |
|
237 | + private function applyQueryCoordination($flatResults) |
|
238 | + { |
|
239 | + $tokenVector = $this->tokenizer->getTokenVector(); |
|
240 | + $tokens = array_keys($tokenVector); |
|
241 | + $tokenCount = count($tokens); |
|
242 | + foreach ($flatResults as $key => $result) { |
|
243 | + $matchCount = count($result->matchingTokens); |
|
244 | + $result->score = ($matchCount / $tokenCount) * $result->score; |
|
245 | + $flatResults[$key] = $result; |
|
246 | + } |
|
247 | + return $flatResults; |
|
248 | + } |
|
249 | 249 | |
250 | - /** |
|
251 | - * Uses the levenshtein algorithm to determine the term that is |
|
252 | - * closest to the token that was input for the search |
|
253 | - * @return array |
|
254 | - * @throws \Exception |
|
255 | - */ |
|
256 | - private function getSearchSuggestions() |
|
257 | - { |
|
258 | - $tokens = $this->getTokens(); |
|
259 | - $allResults = array(); |
|
260 | - foreach ($tokens as $token) { |
|
261 | - $db = $this->getSearchDbHandle(); |
|
262 | - $db->sqliteCreateFunction('levenshtein', 'levenshtein', 2); |
|
263 | - $sql = ' |
|
250 | + /** |
|
251 | + * Uses the levenshtein algorithm to determine the term that is |
|
252 | + * closest to the token that was input for the search |
|
253 | + * @return array |
|
254 | + * @throws \Exception |
|
255 | + */ |
|
256 | + private function getSearchSuggestions() |
|
257 | + { |
|
258 | + $tokens = $this->getTokens(); |
|
259 | + $allResults = array(); |
|
260 | + foreach ($tokens as $token) { |
|
261 | + $db = $this->getSearchDbHandle(); |
|
262 | + $db->sqliteCreateFunction('levenshtein', 'levenshtein', 2); |
|
263 | + $sql = ' |
|
264 | 264 | SELECT * |
265 | 265 | FROM ( |
266 | 266 | SELECT :token as original, term, levenshtein(term, :token) as editDistance |
@@ -270,35 +270,35 @@ discard block |
||
270 | 270 | ) |
271 | 271 | WHERE editDistance > 0 |
272 | 272 | '; |
273 | - $stmt = $db->prepare($sql); |
|
274 | - if ($stmt === false) { |
|
275 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
276 | - } |
|
277 | - $stmt->bindValue(':token', $token); |
|
278 | - if (($stmt === false) | (!$stmt->execute())) { |
|
279 | - throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
280 | - } |
|
281 | - $result = $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchSuggestion'); |
|
282 | - $allResults = array_merge($result, $allResults); |
|
283 | - } |
|
284 | - return $allResults; |
|
285 | - } |
|
273 | + $stmt = $db->prepare($sql); |
|
274 | + if ($stmt === false) { |
|
275 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
276 | + } |
|
277 | + $stmt->bindValue(':token', $token); |
|
278 | + if (($stmt === false) | (!$stmt->execute())) { |
|
279 | + throw new \Exception('SQLite exception: <pre>' . print_r($db->errorInfo(), true) . '</pre> for SQL:<pre>' . $sql . '</pre>'); |
|
280 | + } |
|
281 | + $result = $stmt->fetchAll(\PDO::FETCH_CLASS, '\CloudControl\Cms\search\results\SearchSuggestion'); |
|
282 | + $allResults = array_merge($result, $allResults); |
|
283 | + } |
|
284 | + return $allResults; |
|
285 | + } |
|
286 | 286 | |
287 | - /** |
|
288 | - * Retrieves all tokens from the tokenizer |
|
289 | - * @return array |
|
290 | - */ |
|
291 | - private function getTokens() |
|
292 | - { |
|
293 | - $tokenVector = array( |
|
294 | - 'query' => array(), |
|
295 | - ); |
|
296 | - $tokenVector['query'] = $this->tokenizer->getTokenVector(); |
|
297 | - $tokens = $this->applyFilters($tokenVector); |
|
298 | - if (!empty($tokens)) { |
|
299 | - $tokens = array_keys($tokens['query']); |
|
300 | - } |
|
287 | + /** |
|
288 | + * Retrieves all tokens from the tokenizer |
|
289 | + * @return array |
|
290 | + */ |
|
291 | + private function getTokens() |
|
292 | + { |
|
293 | + $tokenVector = array( |
|
294 | + 'query' => array(), |
|
295 | + ); |
|
296 | + $tokenVector['query'] = $this->tokenizer->getTokenVector(); |
|
297 | + $tokens = $this->applyFilters($tokenVector); |
|
298 | + if (!empty($tokens)) { |
|
299 | + $tokens = array_keys($tokens['query']); |
|
300 | + } |
|
301 | 301 | |
302 | - return $tokens; |
|
303 | - } |
|
302 | + return $tokens; |
|
303 | + } |
|
304 | 304 | } |
305 | 305 | \ No newline at end of file |
@@ -89,11 +89,11 @@ discard block |
||
89 | 89 | |
90 | 90 | private function tokenizeBrick($brick, $brickSlug) |
91 | 91 | { |
92 | - $fields = $brick->fields; |
|
92 | + $fields = $brick->fields; |
|
93 | 93 | $brickDefinition = $this->storage->getBricks()->getBrickBySlug($brick->type); |
94 | 94 | foreach ($fields as $fieldName => $field) { |
95 | 95 | $fieldType = $this->getFieldType($fieldName, $brickDefinition); |
96 | - $this->tokenizeField($field, $brickSlug . '__' . $fieldName, $fieldType); |
|
96 | + $this->tokenizeField($field, $brickSlug.'__'.$fieldName, $fieldType); |
|
97 | 97 | } |
98 | 98 | } |
99 | 99 | |
@@ -101,7 +101,7 @@ discard block |
||
101 | 101 | { |
102 | 102 | $dynamicBricks = $this->document->dynamicBricks; |
103 | 103 | foreach ($dynamicBricks as $key => $brick) { |
104 | - $this->tokenizeBrick($brick, 'dynamicBricks__' . $brick->type . $key); |
|
104 | + $this->tokenizeBrick($brick, 'dynamicBricks__'.$brick->type.$key); |
|
105 | 105 | } |
106 | 106 | } |
107 | 107 | |
@@ -154,6 +154,6 @@ discard block |
||
154 | 154 | } |
155 | 155 | } |
156 | 156 | |
157 | - throw new \Exception('Unknown field type for field' . $fieldName . ' in document ' . $this->document->path); |
|
157 | + throw new \Exception('Unknown field type for field'.$fieldName.' in document '.$this->document->path); |
|
158 | 158 | } |
159 | 159 | } |
160 | 160 | \ No newline at end of file |
@@ -13,149 +13,149 @@ |
||
13 | 13 | |
14 | 14 | class DocumentTokenizer |
15 | 15 | { |
16 | - /** |
|
17 | - * @var Document |
|
18 | - */ |
|
19 | - protected $document; |
|
20 | - |
|
21 | - /** |
|
22 | - * @var array |
|
23 | - */ |
|
24 | - protected $tokenVector = array(); |
|
25 | - protected $storage; |
|
26 | - |
|
27 | - /** |
|
28 | - * Tokenizer constructor. |
|
29 | - * |
|
30 | - * @param \CloudControl\Cms\storage\Document $document |
|
31 | - * @param Storage $storage |
|
32 | - */ |
|
33 | - public function __construct(Document $document, Storage $storage) |
|
34 | - { |
|
35 | - $this->document = $document; |
|
36 | - $this->storage = $storage; |
|
37 | - $this->tokenize(); |
|
38 | - } |
|
39 | - |
|
40 | - /** |
|
41 | - * Execute tokenization of all document fields |
|
42 | - */ |
|
43 | - private function tokenize() |
|
44 | - { |
|
45 | - $this->tokenizeTitle(); |
|
46 | - $this->tokenizeFields(); |
|
47 | - $this->tokenizeBricks(); |
|
48 | - $this->tokenizeDynamicBricks(); |
|
49 | - $this->tokenVector = array_filter($this->tokenVector); |
|
50 | - arsort($this->tokenVector); |
|
51 | - } |
|
52 | - |
|
53 | - private function tokenizeTitle() |
|
54 | - { |
|
55 | - $filteredString = new CharacterFilter($this->document->title); |
|
56 | - $tokenizer = new Tokenizer($filteredString); |
|
57 | - $this->addTokenVectorToVector($tokenizer->getTokenVector(), 'title'); |
|
58 | - } |
|
59 | - |
|
60 | - private function tokenizeFields() |
|
61 | - { |
|
62 | - $fields = $this->document->fields; |
|
63 | - $documentDefinition = $this->storage->getDocumentTypes()->getDocumentTypeBySlug($this->document->documentTypeSlug); |
|
64 | - foreach ($fields as $fieldName => $field) { |
|
65 | - $fieldType = $this->getFieldType($fieldName, $documentDefinition); |
|
66 | - $this->tokenizeField($field, $fieldName, $fieldType); |
|
67 | - } |
|
68 | - } |
|
69 | - |
|
70 | - private function tokenizeField($field, $fieldName, $fieldType) |
|
71 | - { |
|
72 | - foreach ($field as $value) { |
|
73 | - // Only index fields that contain text |
|
74 | - if (in_array($fieldType, array('String', 'Text', 'Rich Text'))) { |
|
75 | - $filteredString = new CharacterFilter($value); |
|
76 | - $tokenizer = new Tokenizer($filteredString); |
|
77 | - $this->addTokenVectorToVector($tokenizer->getTokenVector(), $fieldName); |
|
78 | - } |
|
79 | - } |
|
80 | - } |
|
81 | - |
|
82 | - private function tokenizeBricks() |
|
83 | - { |
|
84 | - $bricks = $this->document->bricks; |
|
85 | - foreach ($bricks as $brickSlug => $bricks) { |
|
86 | - foreach ($bricks as $brick) { |
|
87 | - $this->tokenizeBrick($brick, $brickSlug); |
|
88 | - } |
|
89 | - } |
|
90 | - } |
|
91 | - |
|
92 | - private function tokenizeBrick($brick, $brickSlug) |
|
93 | - { |
|
94 | - $fields = $brick->fields; |
|
95 | - $brickDefinition = $this->storage->getBricks()->getBrickBySlug($brick->type); |
|
96 | - foreach ($fields as $fieldName => $field) { |
|
97 | - $fieldType = $this->getFieldType($fieldName, $brickDefinition); |
|
98 | - $this->tokenizeField($field, $brickSlug . '__' . $fieldName, $fieldType); |
|
99 | - } |
|
100 | - } |
|
101 | - |
|
102 | - private function tokenizeDynamicBricks() |
|
103 | - { |
|
104 | - $dynamicBricks = $this->document->dynamicBricks; |
|
105 | - foreach ($dynamicBricks as $key => $brick) { |
|
106 | - $this->tokenizeBrick($brick, 'dynamicBricks__' . $brick->type . $key); |
|
107 | - } |
|
108 | - } |
|
109 | - |
|
110 | - public function getTokens() |
|
111 | - { |
|
112 | - return $this->tokenVector; |
|
113 | - } |
|
114 | - |
|
115 | - /** |
|
116 | - * Add a token to the existing tokenvector |
|
117 | - * @param $token |
|
118 | - * @param string $field |
|
119 | - * @param int $count |
|
120 | - */ |
|
121 | - private function addTokenToVector($token, $field, $count = 1) |
|
122 | - { |
|
123 | - if (!empty($token)) { |
|
124 | - if (isset($this->tokenVector[$field][$token])) { |
|
125 | - $this->tokenVector[$field][$token] += $count; |
|
126 | - } else { |
|
127 | - $this->tokenVector[$field][$token] = $count; |
|
128 | - } |
|
129 | - } |
|
130 | - } |
|
131 | - |
|
132 | - /** |
|
133 | - * Add a complete token vector to the existing one. |
|
134 | - * @param $tokenVector |
|
135 | - * @param $field |
|
136 | - */ |
|
137 | - private function addTokenVectorToVector($tokenVector, $field) |
|
138 | - { |
|
139 | - foreach ($tokenVector as $token => $count) { |
|
140 | - $this->addTokenToVector($token, $field, $count); |
|
141 | - } |
|
142 | - } |
|
143 | - |
|
144 | - /** |
|
145 | - * Get the type for a field |
|
146 | - * @param $fieldName |
|
147 | - * @param $documentDefinition |
|
148 | - * @return mixed |
|
149 | - * @throws \Exception |
|
150 | - */ |
|
151 | - private function getFieldType($fieldName, $documentDefinition) |
|
152 | - { |
|
153 | - foreach ($documentDefinition->fields as $fieldTypeDefinition) { |
|
154 | - if ($fieldTypeDefinition->slug === $fieldName) { |
|
155 | - return $fieldTypeDefinition->type; |
|
156 | - } |
|
157 | - } |
|
158 | - |
|
159 | - throw new \Exception('Unknown field type for field' . $fieldName . ' in document ' . $this->document->path); |
|
160 | - } |
|
16 | + /** |
|
17 | + * @var Document |
|
18 | + */ |
|
19 | + protected $document; |
|
20 | + |
|
21 | + /** |
|
22 | + * @var array |
|
23 | + */ |
|
24 | + protected $tokenVector = array(); |
|
25 | + protected $storage; |
|
26 | + |
|
27 | + /** |
|
28 | + * Tokenizer constructor. |
|
29 | + * |
|
30 | + * @param \CloudControl\Cms\storage\Document $document |
|
31 | + * @param Storage $storage |
|
32 | + */ |
|
33 | + public function __construct(Document $document, Storage $storage) |
|
34 | + { |
|
35 | + $this->document = $document; |
|
36 | + $this->storage = $storage; |
|
37 | + $this->tokenize(); |
|
38 | + } |
|
39 | + |
|
40 | + /** |
|
41 | + * Execute tokenization of all document fields |
|
42 | + */ |
|
43 | + private function tokenize() |
|
44 | + { |
|
45 | + $this->tokenizeTitle(); |
|
46 | + $this->tokenizeFields(); |
|
47 | + $this->tokenizeBricks(); |
|
48 | + $this->tokenizeDynamicBricks(); |
|
49 | + $this->tokenVector = array_filter($this->tokenVector); |
|
50 | + arsort($this->tokenVector); |
|
51 | + } |
|
52 | + |
|
53 | + private function tokenizeTitle() |
|
54 | + { |
|
55 | + $filteredString = new CharacterFilter($this->document->title); |
|
56 | + $tokenizer = new Tokenizer($filteredString); |
|
57 | + $this->addTokenVectorToVector($tokenizer->getTokenVector(), 'title'); |
|
58 | + } |
|
59 | + |
|
60 | + private function tokenizeFields() |
|
61 | + { |
|
62 | + $fields = $this->document->fields; |
|
63 | + $documentDefinition = $this->storage->getDocumentTypes()->getDocumentTypeBySlug($this->document->documentTypeSlug); |
|
64 | + foreach ($fields as $fieldName => $field) { |
|
65 | + $fieldType = $this->getFieldType($fieldName, $documentDefinition); |
|
66 | + $this->tokenizeField($field, $fieldName, $fieldType); |
|
67 | + } |
|
68 | + } |
|
69 | + |
|
70 | + private function tokenizeField($field, $fieldName, $fieldType) |
|
71 | + { |
|
72 | + foreach ($field as $value) { |
|
73 | + // Only index fields that contain text |
|
74 | + if (in_array($fieldType, array('String', 'Text', 'Rich Text'))) { |
|
75 | + $filteredString = new CharacterFilter($value); |
|
76 | + $tokenizer = new Tokenizer($filteredString); |
|
77 | + $this->addTokenVectorToVector($tokenizer->getTokenVector(), $fieldName); |
|
78 | + } |
|
79 | + } |
|
80 | + } |
|
81 | + |
|
82 | + private function tokenizeBricks() |
|
83 | + { |
|
84 | + $bricks = $this->document->bricks; |
|
85 | + foreach ($bricks as $brickSlug => $bricks) { |
|
86 | + foreach ($bricks as $brick) { |
|
87 | + $this->tokenizeBrick($brick, $brickSlug); |
|
88 | + } |
|
89 | + } |
|
90 | + } |
|
91 | + |
|
92 | + private function tokenizeBrick($brick, $brickSlug) |
|
93 | + { |
|
94 | + $fields = $brick->fields; |
|
95 | + $brickDefinition = $this->storage->getBricks()->getBrickBySlug($brick->type); |
|
96 | + foreach ($fields as $fieldName => $field) { |
|
97 | + $fieldType = $this->getFieldType($fieldName, $brickDefinition); |
|
98 | + $this->tokenizeField($field, $brickSlug . '__' . $fieldName, $fieldType); |
|
99 | + } |
|
100 | + } |
|
101 | + |
|
102 | + private function tokenizeDynamicBricks() |
|
103 | + { |
|
104 | + $dynamicBricks = $this->document->dynamicBricks; |
|
105 | + foreach ($dynamicBricks as $key => $brick) { |
|
106 | + $this->tokenizeBrick($brick, 'dynamicBricks__' . $brick->type . $key); |
|
107 | + } |
|
108 | + } |
|
109 | + |
|
110 | + public function getTokens() |
|
111 | + { |
|
112 | + return $this->tokenVector; |
|
113 | + } |
|
114 | + |
|
115 | + /** |
|
116 | + * Add a token to the existing tokenvector |
|
117 | + * @param $token |
|
118 | + * @param string $field |
|
119 | + * @param int $count |
|
120 | + */ |
|
121 | + private function addTokenToVector($token, $field, $count = 1) |
|
122 | + { |
|
123 | + if (!empty($token)) { |
|
124 | + if (isset($this->tokenVector[$field][$token])) { |
|
125 | + $this->tokenVector[$field][$token] += $count; |
|
126 | + } else { |
|
127 | + $this->tokenVector[$field][$token] = $count; |
|
128 | + } |
|
129 | + } |
|
130 | + } |
|
131 | + |
|
132 | + /** |
|
133 | + * Add a complete token vector to the existing one. |
|
134 | + * @param $tokenVector |
|
135 | + * @param $field |
|
136 | + */ |
|
137 | + private function addTokenVectorToVector($tokenVector, $field) |
|
138 | + { |
|
139 | + foreach ($tokenVector as $token => $count) { |
|
140 | + $this->addTokenToVector($token, $field, $count); |
|
141 | + } |
|
142 | + } |
|
143 | + |
|
144 | + /** |
|
145 | + * Get the type for a field |
|
146 | + * @param $fieldName |
|
147 | + * @param $documentDefinition |
|
148 | + * @return mixed |
|
149 | + * @throws \Exception |
|
150 | + */ |
|
151 | + private function getFieldType($fieldName, $documentDefinition) |
|
152 | + { |
|
153 | + foreach ($documentDefinition->fields as $fieldTypeDefinition) { |
|
154 | + if ($fieldTypeDefinition->slug === $fieldName) { |
|
155 | + return $fieldTypeDefinition->type; |
|
156 | + } |
|
157 | + } |
|
158 | + |
|
159 | + throw new \Exception('Unknown field type for field' . $fieldName . ' in document ' . $this->document->path); |
|
160 | + } |
|
161 | 161 | } |
162 | 162 | \ No newline at end of file |
@@ -53,7 +53,7 @@ discard block |
||
53 | 53 | protected function configureDatabase() |
54 | 54 | { |
55 | 55 | $db = $this->getSearchDbHandle(); |
56 | - $sqlPath = __DIR__ . DIRECTORY_SEPARATOR . '../cc/install/search.sql'; |
|
56 | + $sqlPath = __DIR__.DIRECTORY_SEPARATOR.'../cc/install/search.sql'; |
|
57 | 57 | $searchSql = file_get_contents($sqlPath); |
58 | 58 | $db->exec($searchSql); |
59 | 59 | } |
@@ -69,8 +69,8 @@ discard block |
||
69 | 69 | protected function getSearchDbHandle() |
70 | 70 | { |
71 | 71 | if ($this->searchDbHandle === null) { |
72 | - $path = $this->storageDir . DIRECTORY_SEPARATOR; |
|
73 | - $this->searchDbHandle = new \PDO('sqlite:' . $path . 'search.db'); |
|
72 | + $path = $this->storageDir.DIRECTORY_SEPARATOR; |
|
73 | + $this->searchDbHandle = new \PDO('sqlite:'.$path.'search.db'); |
|
74 | 74 | } |
75 | 75 | return $this->searchDbHandle; |
76 | 76 | } |
@@ -17,61 +17,61 @@ |
||
17 | 17 | */ |
18 | 18 | abstract class SearchDbConnected |
19 | 19 | { |
20 | - /** |
|
21 | - * @var \PDO |
|
22 | - */ |
|
23 | - protected $searchDbHandle; |
|
20 | + /** |
|
21 | + * @var \PDO |
|
22 | + */ |
|
23 | + protected $searchDbHandle; |
|
24 | 24 | |
25 | - /** |
|
26 | - * @var \CloudControl\Cms\storage\Storage |
|
27 | - */ |
|
28 | - protected $storage; |
|
29 | - /** |
|
30 | - * @var string |
|
31 | - */ |
|
32 | - protected $storageDir; |
|
25 | + /** |
|
26 | + * @var \CloudControl\Cms\storage\Storage |
|
27 | + */ |
|
28 | + protected $storage; |
|
29 | + /** |
|
30 | + * @var string |
|
31 | + */ |
|
32 | + protected $storageDir; |
|
33 | 33 | |
34 | - /** |
|
35 | - * Indexer constructor. |
|
36 | - * |
|
37 | - * @param \CloudControl\Cms\storage\Storage $storage |
|
38 | - */ |
|
39 | - public function __construct(Storage $storage) |
|
40 | - { |
|
41 | - $this->storageDir = $storage->getStorageDir(); |
|
42 | - $this->storage = $storage; |
|
43 | - $this->initializeDb(); |
|
44 | - } |
|
34 | + /** |
|
35 | + * Indexer constructor. |
|
36 | + * |
|
37 | + * @param \CloudControl\Cms\storage\Storage $storage |
|
38 | + */ |
|
39 | + public function __construct(Storage $storage) |
|
40 | + { |
|
41 | + $this->storageDir = $storage->getStorageDir(); |
|
42 | + $this->storage = $storage; |
|
43 | + $this->initializeDb(); |
|
44 | + } |
|
45 | 45 | |
46 | - protected function initializeDb() |
|
47 | - { |
|
48 | - if (!$this->isDatabaseConfigured()) { |
|
49 | - $this->configureDatabase(); |
|
50 | - } |
|
51 | - } |
|
46 | + protected function initializeDb() |
|
47 | + { |
|
48 | + if (!$this->isDatabaseConfigured()) { |
|
49 | + $this->configureDatabase(); |
|
50 | + } |
|
51 | + } |
|
52 | 52 | |
53 | - protected function configureDatabase() |
|
54 | - { |
|
55 | - $db = $this->getSearchDbHandle(); |
|
56 | - $sqlPath = __DIR__ . DIRECTORY_SEPARATOR . '../cc/install/search.sql'; |
|
57 | - $searchSql = file_get_contents($sqlPath); |
|
58 | - $db->exec($searchSql); |
|
59 | - } |
|
53 | + protected function configureDatabase() |
|
54 | + { |
|
55 | + $db = $this->getSearchDbHandle(); |
|
56 | + $sqlPath = __DIR__ . DIRECTORY_SEPARATOR . '../cc/install/search.sql'; |
|
57 | + $searchSql = file_get_contents($sqlPath); |
|
58 | + $db->exec($searchSql); |
|
59 | + } |
|
60 | 60 | |
61 | - protected function isDatabaseConfigured() |
|
62 | - { |
|
63 | - $db = $this->getSearchDbHandle(); |
|
64 | - $stmt = $db->query('SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'term_count\';'); |
|
65 | - $result = $stmt->fetchAll(); |
|
66 | - return !empty($result); |
|
67 | - } |
|
61 | + protected function isDatabaseConfigured() |
|
62 | + { |
|
63 | + $db = $this->getSearchDbHandle(); |
|
64 | + $stmt = $db->query('SELECT name FROM sqlite_master WHERE type=\'table\' AND name=\'term_count\';'); |
|
65 | + $result = $stmt->fetchAll(); |
|
66 | + return !empty($result); |
|
67 | + } |
|
68 | 68 | |
69 | - protected function getSearchDbHandle() |
|
70 | - { |
|
71 | - if ($this->searchDbHandle === null) { |
|
72 | - $path = $this->storageDir . DIRECTORY_SEPARATOR; |
|
73 | - $this->searchDbHandle = new \PDO('sqlite:' . $path . 'search.db'); |
|
74 | - } |
|
75 | - return $this->searchDbHandle; |
|
76 | - } |
|
69 | + protected function getSearchDbHandle() |
|
70 | + { |
|
71 | + if ($this->searchDbHandle === null) { |
|
72 | + $path = $this->storageDir . DIRECTORY_SEPARATOR; |
|
73 | + $this->searchDbHandle = new \PDO('sqlite:' . $path . 'search.db'); |
|
74 | + } |
|
75 | + return $this->searchDbHandle; |
|
76 | + } |
|
77 | 77 | } |
78 | 78 | \ No newline at end of file |
@@ -48,7 +48,7 @@ discard block |
||
48 | 48 | $string = strip_tags($string); |
49 | 49 | $string = trim($string); |
50 | 50 | $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string); // Remove special alphanumeric characters |
51 | - $string = str_replace(array('+', '=', '!', ',', '.',';', ':', '?'), ' ', $string); // Replace sentence breaking charaters with spaces |
|
51 | + $string = str_replace(array('+', '=', '!', ',', '.', ';', ':', '?'), ' ', $string); // Replace sentence breaking charaters with spaces |
|
52 | 52 | $string = preg_replace("/[\r\n]+/", " ", $string); // Replace multiple newlines with a single space. |
53 | 53 | $string = preg_replace("/[\t]+/", " ", $string); // Replace multiple tabs with a single space. |
54 | 54 | $string = preg_replace("/[^a-zA-Z0-9 ]/", '', $string); // Filter out everything that is not alphanumeric or a space |
@@ -66,7 +66,7 @@ discard block |
||
66 | 66 | { |
67 | 67 | $encoding = mb_detect_encoding($string, mb_detect_order(), false); |
68 | 68 | |
69 | - if($encoding == "UTF-8") { |
|
69 | + if ($encoding == "UTF-8") { |
|
70 | 70 | $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); |
71 | 71 | } |
72 | 72 |
@@ -9,76 +9,76 @@ |
||
9 | 9 | |
10 | 10 | class CharacterFilter |
11 | 11 | { |
12 | - protected $originalString; |
|
13 | - protected $filteredString = ''; |
|
12 | + protected $originalString; |
|
13 | + protected $filteredString = ''; |
|
14 | 14 | |
15 | - /** |
|
16 | - * CharacterFilter constructor. |
|
17 | - * |
|
18 | - * @param $string |
|
19 | - */ |
|
20 | - public function __construct($string) |
|
21 | - { |
|
22 | - $this->originalString = $string; |
|
23 | - $string = $this->convertToUTF8($string); |
|
24 | - $string = mb_strtolower($string); |
|
25 | - $string = $this->filterSpecialCharacters($string); |
|
26 | - $this->filteredString = $string; |
|
27 | - } |
|
15 | + /** |
|
16 | + * CharacterFilter constructor. |
|
17 | + * |
|
18 | + * @param $string |
|
19 | + */ |
|
20 | + public function __construct($string) |
|
21 | + { |
|
22 | + $this->originalString = $string; |
|
23 | + $string = $this->convertToUTF8($string); |
|
24 | + $string = mb_strtolower($string); |
|
25 | + $string = $this->filterSpecialCharacters($string); |
|
26 | + $this->filteredString = $string; |
|
27 | + } |
|
28 | 28 | |
29 | - /** |
|
30 | - * Returns the filtered string |
|
31 | - * @return string|void |
|
32 | - */ |
|
33 | - public function __toString() |
|
34 | - { |
|
35 | - return $this->filteredString; |
|
36 | - } |
|
29 | + /** |
|
30 | + * Returns the filtered string |
|
31 | + * @return string|void |
|
32 | + */ |
|
33 | + public function __toString() |
|
34 | + { |
|
35 | + return $this->filteredString; |
|
36 | + } |
|
37 | 37 | |
38 | - /** |
|
39 | - * Filter out all special characters, like punctuation and characters with accents |
|
40 | - * |
|
41 | - * @param $string |
|
42 | - * |
|
43 | - * @return mixed|string |
|
44 | - */ |
|
45 | - private function filterSpecialCharacters($string) |
|
46 | - { |
|
47 | - $string = str_replace('<', ' <', $string); // This is need, otherwise this: <h1>something</h1><h2>something</h2> will result in somethingsomething |
|
48 | - $string = strip_tags($string); |
|
49 | - $string = trim($string); |
|
50 | - $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string); // Remove special alphanumeric characters |
|
51 | - $string = str_replace(array('+', '=', '!', ',', '.',';', ':', '?'), ' ', $string); // Replace sentence breaking charaters with spaces |
|
52 | - $string = preg_replace("/[\r\n]+/", " ", $string); // Replace multiple newlines with a single space. |
|
53 | - $string = preg_replace("/[\t]+/", " ", $string); // Replace multiple tabs with a single space. |
|
54 | - $string = preg_replace("/[^a-zA-Z0-9 ]/", '', $string); // Filter out everything that is not alphanumeric or a space |
|
55 | - $string = preg_replace('!\s+!', ' ', $string); // Replace multiple spaces with a single space |
|
56 | - return $string; |
|
57 | - } |
|
38 | + /** |
|
39 | + * Filter out all special characters, like punctuation and characters with accents |
|
40 | + * |
|
41 | + * @param $string |
|
42 | + * |
|
43 | + * @return mixed|string |
|
44 | + */ |
|
45 | + private function filterSpecialCharacters($string) |
|
46 | + { |
|
47 | + $string = str_replace('<', ' <', $string); // This is need, otherwise this: <h1>something</h1><h2>something</h2> will result in somethingsomething |
|
48 | + $string = strip_tags($string); |
|
49 | + $string = trim($string); |
|
50 | + $string = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $string); // Remove special alphanumeric characters |
|
51 | + $string = str_replace(array('+', '=', '!', ',', '.',';', ':', '?'), ' ', $string); // Replace sentence breaking charaters with spaces |
|
52 | + $string = preg_replace("/[\r\n]+/", " ", $string); // Replace multiple newlines with a single space. |
|
53 | + $string = preg_replace("/[\t]+/", " ", $string); // Replace multiple tabs with a single space. |
|
54 | + $string = preg_replace("/[^a-zA-Z0-9 ]/", '', $string); // Filter out everything that is not alphanumeric or a space |
|
55 | + $string = preg_replace('!\s+!', ' ', $string); // Replace multiple spaces with a single space |
|
56 | + return $string; |
|
57 | + } |
|
58 | 58 | |
59 | - /** |
|
60 | - * Convert the string to UTF-8 encoding |
|
61 | - * @param $string |
|
62 | - * |
|
63 | - * @return string |
|
64 | - */ |
|
65 | - private function convertToUTF8($string) |
|
66 | - { |
|
67 | - $encoding = mb_detect_encoding($string, mb_detect_order(), false); |
|
59 | + /** |
|
60 | + * Convert the string to UTF-8 encoding |
|
61 | + * @param $string |
|
62 | + * |
|
63 | + * @return string |
|
64 | + */ |
|
65 | + private function convertToUTF8($string) |
|
66 | + { |
|
67 | + $encoding = mb_detect_encoding($string, mb_detect_order(), false); |
|
68 | 68 | |
69 | - if($encoding == "UTF-8") { |
|
70 | - $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); |
|
71 | - } |
|
69 | + if($encoding == "UTF-8") { |
|
70 | + $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8'); |
|
71 | + } |
|
72 | 72 | |
73 | - $out = iconv(mb_detect_encoding($string, mb_detect_order(), false), "UTF-8//IGNORE", $string); |
|
74 | - return $out; |
|
75 | - } |
|
73 | + $out = iconv(mb_detect_encoding($string, mb_detect_order(), false), "UTF-8//IGNORE", $string); |
|
74 | + return $out; |
|
75 | + } |
|
76 | 76 | |
77 | - /** |
|
78 | - * @return mixed|string |
|
79 | - */ |
|
80 | - public function getFilteredString() |
|
81 | - { |
|
82 | - return $this->filteredString; |
|
83 | - } |
|
77 | + /** |
|
78 | + * @return mixed|string |
|
79 | + */ |
|
80 | + public function getFilteredString() |
|
81 | + { |
|
82 | + return $this->filteredString; |
|
83 | + } |
|
84 | 84 | } |
85 | 85 | \ No newline at end of file |