1: <?php
2:
3: namespace Budabot\Core\Modules;
4:
5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
18: class CommandSearchController {
19:
20:
21: public $chatBot;
22:
23:
24: public $db;
25:
26:
27: public $text;
28:
29:
30: public $accessManager;
31:
32: private $searchWords;
33:
34: 35: 36: 37:
38: public function searchCommand($message, $channel, $sender, $sendto, $arr) {
39: $this->searchWords = explode(" ", $arr[1]);
40:
41:
42: $access = false;
43: if ($this->accessManager->checkAccess($sender, 'mod')) {
44: $access = true;
45: }
46:
47: $sqlquery = "SELECT DISTINCT module, cmd, help, description, admin FROM cmdcfg_<myname> WHERE cmd = ?";
48: if (!$access) {
49: $sqlquery .= " AND status = 1";
50: }
51: $results = $this->db->query($sqlquery, $arr[1]);
52: $results = $this->filterResultsByAccessLevel($sender, $results);
53:
54: $exactMatch = !empty($results);
55:
56: if (!$exactMatch) {
57: $results = $this->findSimilarCommands($this->searchWords, $access);
58: $results = $this->filterResultsByAccessLevel($sender, $results);
59: $results = array_slice($results, 0, 5);
60: }
61:
62: $msg = $this->render($results, $access, $exactMatch);
63:
64: $sendto->reply($msg);
65:
66: return true;
67: }
68:
69: public function filterResultsByAccessLevel($sender, $data) {
70: $results = array();
71: $charAccessLevel = $this->accessManager->getSingleAccessLevel($sender);
72: forEach ($data as $key => $row) {
73: if ($this->accessManager->compareAccessLevels($charAccessLevel, $row->admin) >= 0) {
74: $results []= $row;
75: }
76: }
77: return $results;
78: }
79:
80: public function findSimilarCommands($wordArray, $includeDisabled = false) {
81: $sqlquery = "SELECT DISTINCT module, cmd, help, description, admin FROM cmdcfg_<myname>";
82: if (!$includeDisabled) {
83: $sqlquery .= " WHERE status = 1";
84: }
85: $data = $this->db->query($sqlquery);
86:
87: forEach ($data as $row) {
88: $keywords = explode(' ', $row->description);
89: array_push($keywords, $row->cmd);
90: $keywords = array_unique($keywords);
91: $row->distance = 0;
92: forEach ($wordArray as $searchWord) {
93: $distance = 9999;
94: forEach ($keywords as $keyword) {
95: $distance = min($distance, levenshtein($keyword, $searchWord));
96: }
97: $row->distance += $distance;
98: }
99: }
100: $results = $data;
101: usort($results, array($this, 'sortByDistance'));
102:
103: return $results;
104: }
105:
106: public function sortByDistance($row1, $row2) {
107: $d1 = $row1->distance;
108: $d2 = $row2->distance;
109: if ($d1 == $d2) {
110: return 0;
111: }
112: return ($d1 < $d2) ? -1 : 1;
113: }
114:
115: public function render($results, $hasAccess, $exactMatch) {
116: $blob = '';
117: forEach ($results as $row) {
118: if ($row->help != '') {
119: $helpLink = ' (' . $this->text->makeChatcmd("Help", "/tell <myname> help $row->cmd") . ')';
120: }
121: if ($hasAccess) {
122: $module = $this->text->makeChatcmd($row->module, "/tell <myname> config {$row->module}");
123: } else {
124: $module = "{$row->module}";
125: }
126:
127: $cmd = str_pad($row->cmd . " ", 20, ".");
128: $blob .= "<highlight>{$cmd}<end> {$module} - {$row->description}{$helpLink}\n";
129: }
130:
131: $count = count($results);
132: if ($count == 0) {
133: $msg = "No results found.";
134: } else {
135: if ($exactMatch) {
136: $msg = $this->text->makeBlob("Command Search Results ($count)", $blob);
137: } else {
138: $msg = $this->text->makeBlob("Possible Matches ($count)", $blob);
139: }
140: }
141: return $msg;
142: }
143: }
144: