PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 1.9.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v1.9.4
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / modules / chatbot.php
ai-engine / classes / modules Last commit date
assistants.php 3 years ago chatbot.php 2 years ago chatbot_legacy.php 2 years ago discussions.php 2 years ago security.php 3 years ago
chatbot.php
489 lines
1 <?php
2
3 // Params for the chatbot (front and server)
4
5 define( 'MWAI_CHATBOT_FRONT_PARAMS', [ 'aiName', 'userName', 'guestName', 'textSend', 'textClear',
6 'textInputPlaceholder', 'textInputMaxLength', 'textCompliance', 'startSentence', 'localMemory',
7 'themeId', 'window', 'icon', 'iconText', 'iconAlt', 'iconPosition', 'fullscreen', 'copyButton'
8 ] );
9 define( 'MWAI_CHATBOT_SERVER_PARAMS', [ 'id', 'env', 'mode', 'contentAware', 'embeddingsIndex', 'context',
10 'casuallyFineTuned', 'promptEnding', 'completionEnding', 'model', 'temperature', 'maxTokens',
11 'maxResults', 'apiKey', 'service'
12 ] );
13
14 // Params for the discussions (front and server)
15
16 define( 'MWAI_DISCUSSIONS_FRONT_PARAMS', [ 'themeId', 'textNewChat' ] );
17 define( 'MWAI_DISCUSSIONS_SERVER_PARAMS', [] );
18
19 class Meow_MWAI_Modules_Chatbot {
20 private $core = null;
21 private $namespace = 'mwai-ui/v1';
22 private $siteWideChatId = null;
23
24 public function __construct() {
25 global $mwai_core;
26 $this->core = $mwai_core;
27 add_shortcode( 'mwai_chatbot_v2', array( $this, 'chat_shortcode' ) );
28 add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
29 $this->siteWideChatId = $this->core->get_option( 'botId' );
30 add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
31
32 if ( $this->core->get_option( 'shortcode_chat_discussions' ) ) {
33 add_shortcode( 'mwai_discussions', [ $this, 'shortcode_chat_discussions' ] );
34 }
35 }
36
37 public function register_scripts() {
38 wp_register_script( 'mwai_highlight', MWAI_URL . 'vendor/highlightjs/highlight.min.js', [], '11.7', false );
39 $physical_file = trailingslashit( MWAI_PATH ) . 'app/chatbot.js';
40 $cache_buster = file_exists( $physical_file ) ? filemtime( $physical_file ) : MWAI_VERSION;
41 wp_register_script( 'mwai_chatbot', trailingslashit( MWAI_URL ) . 'app/chatbot.js',
42 [ 'wp-element' ], $cache_buster, false );
43 if ( !empty( $this->siteWideChatId ) && $this->siteWideChatId !== 'none' ) {
44 $this->enqueue_scripts();
45 add_action( 'wp_footer', array( $this, 'inject_chat' ) );
46 }
47 }
48
49 public function enqueue_scripts() {
50 wp_enqueue_script( "mwai_chatbot" );
51 if ( $this->core->get_option( 'shortcode_chat_syntax_highlighting' ) ) {
52 wp_enqueue_script( "mwai_highlight" );
53 }
54 }
55
56 public function rest_api_init() {
57 register_rest_route( $this->namespace, '/chats/submit', array(
58 'methods' => 'POST',
59 'callback' => array( $this, 'rest_chat' ),
60 'permission_callback' => '__return_true'
61 ) );
62
63 }
64
65 public function basics_security_check( $id, $botId, $newMessage ) {
66 if ( empty( $newMessage ) ) {
67 error_log("AI Engine: The query was rejected - message was empty.");
68 return false;
69 }
70 if ( !$botId && !$id ) {
71 error_log("AI Engine: The query was rejected - no botId nor id was specified.");
72 return false;
73 }
74
75 $length = strlen( $newMessage );
76 if ( $length < 1 || $length > ( 4096 * 16 ) ) {
77 error_log("AI Engine: The query was rejected - message was too short or too long.");
78 return false;
79 }
80 return true;
81 }
82
83 public function rest_chat( $request ) {
84 $params = $request->get_json_params();
85 $id = $params['id'] ?? null;
86 $botId = $params['botId'] ?? null;
87 $stream = $params['stream'] ?? false;
88 $newMessage = trim( $params['newMessage'] ?? '' );
89
90 if ( !$this->basics_security_check( $id, $botId, $newMessage )) {
91 return new WP_REST_Response( [
92 'success' => false,
93 'message' => apply_filters( 'mwai_ai_exception', 'Sorry, your query has been rejected.' )
94 ], 403 );
95 }
96
97 try {
98 $data = $this->chat_submit( $botId, $newMessage, $params, $stream );
99 return new WP_REST_Response( [
100 'success' => true,
101 'reply' => $data['reply'],
102 'images' => $data['images'],
103 'usage' => $data['usage']
104 ], 200 );
105 }
106 catch ( Exception $e ) {
107 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
108 return new WP_REST_Response( [
109 'success' => false,
110 'message' => $message
111 ], 500 );
112 }
113 }
114
115 public function chat_submit( $botId, $newMessage, $params = [], $stream = false ) {
116 try {
117 $chatbot = null;
118 $id = $params['id'] ?? null;
119
120 // Custom Chatbot
121 if ( $id ) {
122 $chatbot = get_transient( 'mwai_custom_chatbot_' . $id );
123 }
124 // Registered Chatbot
125 if ( !$chatbot && $botId ) {
126 $chatbot = $this->core->getChatbot( $botId );
127 }
128
129 if ( !$chatbot ) {
130 error_log("AI Engine: No chatbot was found for this query.");
131 throw new Exception( 'Sorry, your query has been rejected.' );
132 }
133
134 // Create QueryText
135 $context = null;
136 $mode = $chatbot['mode'] ?? 'chat';
137
138 if ( $mode === 'images' ) {
139 $query = new Meow_MWAI_Query_Image( $newMessage );
140
141 // Handle Params
142 $newParams = [];
143 foreach ( $chatbot as $key => $value ) {
144 $newParams[$key] = $value;
145 }
146 foreach ( $params as $key => $value ) {
147 $newParams[$key] = $value;
148 }
149 $params = apply_filters( 'mwai_chatbot_params', $newParams );
150 $params['env'] = empty( $params['env'] ) ? 'chatbot' : $params['env'];
151 $query->injectParams( $params );
152 }
153 else {
154 $query = new Meow_MWAI_Query_Text( $newMessage, 1024 );
155 $streamCallback = null;
156
157 // Handle Params
158 $newParams = [];
159 foreach ( $chatbot as $key => $value ) {
160 $newParams[$key] = $value;
161 }
162 foreach ( $params as $key => $value ) {
163 $newParams[$key] = $value;
164 }
165 $params = apply_filters( 'mwai_chatbot_params', $newParams );
166 $params['env'] = empty( $params['env'] ) ? 'chatbot' : $params['env'];
167 $query->injectParams( $params );
168
169 // Takeover
170 $takeoverAnswer = apply_filters( 'mwai_chatbot_takeover', null, $query, $params );
171 if ( !empty( $takeoverAnswer ) ) {
172 return [
173 'reply' => $takeoverAnswer,
174 'images' => null,
175 'usage' => null
176 ];
177 }
178
179 // Moderation
180 if ( $this->core->get_option( 'shortcode_chat_moderation' ) ) {
181 global $mwai;
182 $isFlagged = $mwai->moderationCheck( $query->prompt );
183 if ( $isFlagged ) {
184 throw new Exception( 'Sorry, your message has been rejected by moderation.' );
185 }
186 }
187
188 // Awareness & Embeddings
189 // TODO: This is same in Chatbot Legacy and Forms, maybe we should move it to the core?
190 $embeddingsIndex = $params['embeddingsIndex'] ?? null;
191 $embeddingsNamespace = $params['embeddingsNamespace'] ?? null;
192 if ( $query->mode === 'chat' ) {
193 $context = apply_filters( 'mwai_context_search', $context, $query, [
194 'embeddingsIndex' => $embeddingsIndex,
195 'embeddingsNamespace' => $embeddingsNamespace
196 ] );
197 if ( !empty( $context ) ) {
198 if ( isset( $context['content'] ) ) {
199 $content = $this->core->cleanSentences( $context['content'] );
200 $query->injectContext( $content );
201 }
202 else {
203 error_log( "AI Engine: A context without content was returned." );
204 }
205 }
206 }
207 }
208
209 // Process Query
210 if ( $stream ) {
211 $streamCallback = function( $reply ) {
212 //$raw = _wp_specialchars( $reply, ENT_NOQUOTES, 'UTF-8', true );
213 $raw = $reply;
214 $this->stream_push( [ 'type' => 'live', 'data' => $raw ] );
215 if ( ob_get_level() > 0 ) {
216 ob_flush();
217 }
218 flush();
219 };
220 header( 'Cache-Control: no-cache' );
221 header( 'Content-Type: text/event-stream' );
222 header( 'X-Accel-Buffering: no' ); // This is useful to disable buffering in nginx through headers.
223 ob_implicit_flush( true );
224 ob_end_flush();
225 }
226
227 $reply = $this->core->ai->run( $query, $streamCallback );
228 $rawText = $reply->result;
229 $extra = [];
230 if ( $context ) {
231 $extra = [ 'embeddings' => $context['embeddings'] ];
232 }
233
234 $rawText = apply_filters( 'mwai_chatbot_reply', $rawText, $query, $params, $extra );
235 // TODO: There is no need for the shortcode_chat_formatting sice Markdown is handled on the client side.
236 // if ( $this->core->get_option( 'shortcode_chat_formatting' ) ) {
237 // $html = $this->core->markdown_to_html( $rawText );
238 // }
239
240 $restRes = [
241 'reply' => $rawText,
242 'images' => $reply->getType() === 'images' ? $reply->results : null,
243 'usage' => $reply->usage
244 ];
245
246 // Process Reply
247 if ( $stream ) {
248 $this->stream_push( [
249 'type' => 'end',
250 'data' => json_encode([
251 'success' => true,
252 'reply' => $restRes['reply'],
253 'images' => $restRes['images'],
254 'usage' => $restRes['usage']
255 ])
256 ] );
257 die();
258 }
259 else {
260 return $restRes;
261 }
262
263 }
264 catch ( Exception $e ) {
265 $message = apply_filters( 'mwai_ai_exception', $e->getMessage() );
266 if ( $stream ) {
267 $this->stream_push( [ 'type' => 'error', 'data' => $message ] );
268 }
269 else {
270 throw $e;
271 }
272 }
273 }
274
275 public function stream_push( $data ) {
276 $out = "data: " . json_encode( $data );
277 echo $out;
278 echo "\n\n";
279 if (ob_get_level() > 0) {
280 ob_end_flush();
281 }
282 flush();
283 }
284
285 public function inject_chat() {
286 $params = $this->core->getChatbot( $this->siteWideChatId );
287 $cleanParams = [];
288 if ( !empty( $params ) ) {
289 $cleanParams['window'] = true;
290 $cleanParams['id'] = $this->siteWideChatId;
291 echo $this->chat_shortcode( $cleanParams );
292 }
293 return null;
294 }
295
296 public function build_front_params( $id, $botId ) {
297 $frontSystem = [
298 'id' => $id,
299 'botId' => $botId,
300 'userData' => $this->core->getUserData(),
301 'sessionId' => $this->core->get_session_id(),
302 'restNonce' => $this->core->get_nonce(),
303 'contextId' => get_the_ID(),
304 'pluginUrl' => MWAI_URL,
305 'restUrl' => untrailingslashit( rest_url() ),
306 'debugMode' => $this->core->get_option( 'debug_mode' ),
307 'typewriter' => $this->core->get_option( 'shortcode_chat_typewriter' ),
308 'speech_recognition' => $this->core->get_option( 'speech_recognition' ),
309 'speech_synthesis' => $this->core->get_option( 'speech_synthesis' ),
310 'stream' => $this->core->get_option( 'shortcode_chat_stream' ),
311 ];
312 return $frontSystem;
313 }
314
315 public function chat_shortcode( $atts ) {
316 $atts = empty($atts) ? [] : $atts;
317
318 // Properly handle the id, botId, and chatbot
319 // We have the same in discussions.php
320 $chatbot = null;
321 $botId = $atts['chat_id'] ?? null;
322 $id = $atts['id'] ?? null;
323 unset( $atts['chat_id'], $atts['id'] );
324 if ( $botId ) {
325 $chatbot = $this->core->getChatbot( $botId );
326 if ( !$chatbot ) {
327 return "AI Engine: Chatbot not found.";
328 }
329 }
330 if ( $id && !$chatbot ) {
331 $chatbot = $this->core->getChatbot( $id );
332 $botId = $chatbot ? $id : 'default';
333 }
334 $chatbot = $chatbot ?: $this->core->getChatbot( 'default' );
335 $botId = $botId ?: 'default';
336 $isCustom = $botId == 'default' && isset( $atts['id'] );
337
338 $atts = apply_filters( 'mwai_chatbot_params', $atts, $chatbot, $isCustom );
339
340 // Rename the keys of the atts into camelCase to match the internal params system.
341 $atts = array_map( function( $key, $value ) {
342 $key = str_replace( '_', ' ', $key );
343 $key = ucwords( $key );
344 $key = str_replace( ' ', '', $key );
345 $key = lcfirst( $key );
346 return [ $key => $value ];
347 }, array_keys( $atts ), $atts );
348 $atts = array_merge( ...$atts );
349
350 $frontParams = [];
351 foreach ( MWAI_CHATBOT_FRONT_PARAMS as $param ) {
352 if ( isset( $atts[$param] ) ) {
353 if ( $param === 'localMemory' ) {
354 $frontParams[$param] = $atts[$param] === 'true';
355 }
356 else {
357 $frontParams[$param] = $atts[$param];
358 }
359 }
360 else if ( isset( $chatbot[$param] ) ) {
361 $frontParams[$param] = $chatbot[$param];
362 }
363 }
364
365 // Server Params
366 $serverParams = [];
367 foreach ( MWAI_CHATBOT_SERVER_PARAMS as $param ) {
368 if ( isset( $atts[$param] ) ) {
369 $serverParams[$param] = $atts[$param];
370 }
371 }
372
373 // Front Params
374 $frontSystem = $this->build_front_params( $id, $botId );
375
376 // Clean Params
377 $frontParams = $this->cleanParams( $frontParams );
378 $frontSystem = $this->cleanParams( $frontSystem );
379 $serverParams = $this->cleanParams( $serverParams );
380
381 // Server-side: Keep the System Params
382 if ( count( $serverParams ) > 0 ) {
383 if ( !$isCustom ) {
384 $id = md5( json_encode( $serverParams ) );
385 $botId = null;
386 $frontSystem['id'] = $id;
387 $frontSystem['botId'] = $botId;
388 }
389 set_transient( 'mwai_custom_chatbot_' . $id, $serverParams, 60 * 60 * 24 );
390 }
391
392 // Client-side: Prepare JSON for Front Params and System Params
393 $theme = isset( $frontParams['themeId'] ) ? $this->core->getTheme( $frontParams['themeId'] ) : null;
394 $jsonFrontParams = htmlspecialchars( json_encode( $frontParams ), ENT_QUOTES, 'UTF-8' );
395 $jsonFrontSystem = htmlspecialchars( json_encode( $frontSystem ), ENT_QUOTES, 'UTF-8' );
396 $jsonFrontTheme = htmlspecialchars( json_encode( $theme ), ENT_QUOTES, 'UTF-8' );
397 //$jsonAttributes = htmlspecialchars(json_encode($atts), ENT_QUOTES, 'UTF-8');
398
399 $this->enqueue_scripts();
400 return "<div class='mwai-chatbot-container' data-params='{$jsonFrontParams}' data-system='{$jsonFrontSystem}' data-theme='{$jsonFrontTheme}'></div>";
401 }
402
403 function shortcode_chat_discussions( $atts ) {
404 $atts = empty($atts) ? [] : $atts;
405
406 // Properly handle the id, botId, and chatbot
407 // We have the same in chatbot.php
408 $chatbot = null;
409 $botId = $atts['chat_id'] ?? null;
410 $id = $atts['id'] ?? null;
411 unset( $atts['chat_id'], $atts['id'] );
412 if ( $botId ) {
413 $chatbot = $this->core->getChatbot( $botId );
414 if ( !$chatbot ) {
415 return "AI Engine: Chatbot not found.";
416 }
417 }
418 if ( $id && !$chatbot ) {
419 $chatbot = $this->core->getChatbot( $id );
420 $botId = $chatbot ? $id : 'default';
421 }
422 $chatbot = $chatbot ?: $this->core->getChatbot( 'default' );
423 $botId = $botId ?: 'default';
424 $isCustom = $botId == 'default' && isset( $atts['id'] );
425
426 // Rename the keys of the atts into camelCase to match the internal params system.
427 $atts = array_map( function( $key, $value ) {
428 $key = str_replace( '_', ' ', $key );
429 $key = ucwords( $key );
430 $key = str_replace( ' ', '', $key );
431 $key = lcfirst( $key );
432 return [ $key => $value ];
433 }, array_keys( $atts ), $atts );
434 $atts = array_merge( ...$atts );
435
436 // Front Params
437 $frontParams = [];
438 foreach ( MWAI_DISCUSSIONS_FRONT_PARAMS as $param ) {
439 if ( isset( $atts[$param] ) ) {
440 $frontParams[$param] = $atts[$param];
441 }
442 else if ( isset( $chatbot[$param] ) ) {
443 $frontParams[$param] = $chatbot[$param];
444 }
445 }
446
447 // Server Params
448 $serverParams = [];
449 foreach ( MWAI_DISCUSSIONS_SERVER_PARAMS as $param ) {
450 if ( isset( $atts[$param] ) ) {
451 $serverParams[$param] = $atts[$param];
452 }
453 }
454
455
456 // Front System
457 $frontSystem = $this->build_front_params( $id, $botId );
458
459 // Clean Params
460 $frontParams = $this->cleanParams( $frontParams );
461 $frontSystem = $this->cleanParams( $frontSystem );
462 $serverParams = $this->cleanParams( $serverParams );
463
464 $theme = isset( $frontParams['themeId'] ) ? $this->core->getTheme( $frontParams['themeId'] ) : null;
465 $jsonFrontParams = htmlspecialchars( json_encode( $frontParams ), ENT_QUOTES, 'UTF-8' );
466 $jsonFrontSystem = htmlspecialchars( json_encode( $frontSystem ), ENT_QUOTES, 'UTF-8' );
467 $jsonFrontTheme = htmlspecialchars( json_encode( $theme ), ENT_QUOTES, 'UTF-8' );
468
469 return "<div class='mwai-discussions-container' data-params='{$jsonFrontParams}' data-system='{$jsonFrontSystem}' data-theme='{$jsonFrontTheme}'></div>";
470 }
471
472 function cleanParams( &$params ) {
473 foreach ( $params as $param => $value ) {
474 if ( empty( $value ) || is_array( $value ) ) {
475 continue;
476 }
477 $lowerCaseValue = strtolower( $value );
478 if ( $lowerCaseValue === 'true' || $lowerCaseValue === 'false' || is_bool( $value ) ) {
479 $params[$param] = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
480 }
481 else if ( is_numeric( $value ) ) {
482 $params[$param] = filter_var( $value, FILTER_VALIDATE_FLOAT );
483 }
484 }
485 return $params;
486 }
487
488 }
489