PageRenderTime 59ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/chatbot/core/aiml/parse_aiml_as_XML.php

https://gitlab.com/tutaalexandr/bot_local
PHP | 1106 lines | 760 code | 47 blank | 299 comment | 75 complexity | 58508f555dea89e539bceb3d57695861 MD5 | raw file
  1. <?php
  2. /***************************************
  3. * http://www.program-o.com
  4. * PROGRAM O
  5. * Version: 2.4.8
  6. * FILE: parse_aiml_as_xml.php
  7. * AUTHOR: Elizabeth Perreau and Dave Morton
  8. * DATE: FEB 01 2016
  9. * DETAILS: Handles the parsing of AIML code as XML
  10. ***************************************/
  11. /**
  12. * This function starts the process of recursively parsing the AIML template as XML, converting it to text
  13. *
  14. * @param array $convoArr - the existing conversation array
  15. * @return array $convoArr
  16. **/
  17. function parse_aiml_as_XML($convoArr)
  18. {
  19. global $botsay, $error_response;
  20. runDebug(__FILE__, __FUNCTION__, __LINE__, "Parsing the AIML template as XML", 2);
  21. $template = add_text_tags($convoArr['aiml']['template']);
  22. try
  23. {
  24. $aimlTemplate = new SimpleXMLElement($template, LIBXML_NOCDATA);
  25. }
  26. catch (exception $e)
  27. {
  28. trigger_error("There was a problem parsing the template as XML. Template value:\n$template", E_USER_WARNING);
  29. $aimlTemplate = new SimpleXMLElement("<text>$error_response</text>", LIBXML_NOCDATA);
  30. }
  31. $responseArray = parseTemplateRecursive($convoArr, $aimlTemplate);
  32. $botsay = trim(implode_recursive(' ', $responseArray, __FILE__, __FUNCTION__, __LINE__));
  33. $botsay = str_replace(' .', '.', $botsay);
  34. $botsay = str_replace(' ', ' ', $botsay);
  35. $botsay = str_replace(' ?', '?', $botsay);
  36. $botsay = str_replace(' ,', ',', $botsay);
  37. $botsay = str_replace(' s ', 's ', $botsay);
  38. $convoArr['aiml']['parsed_template'] = $botsay;
  39. runDebug(__FILE__, __FUNCTION__, __LINE__, "Completed parsing the template. The bot will say: $botsay", 4);
  40. return $convoArr;
  41. }
  42. /**
  43. * Wraps mixed content XML with <text></text> tags, allowing full use of PHP's SimpleXML functions
  44. *
  45. * @param $input
  46. * @return string
  47. */
  48. function add_text_tags($input)
  49. {
  50. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Adding some TEXT tags into the template, just because I can...', 2);
  51. /*
  52. Since we're going to parse the template's contents as XML, we need to prepare it first
  53. by transforming it into valid XML
  54. First, wrap the template in TEMPLATE tags, to give the XML a "root" element:
  55. */
  56. $template = "<template>$input</template>";
  57. /*
  58. SimpleXML can't deal with "mixed" content, so any "loose" text is wrapped in a <text> tag.
  59. The process will sometimes add extra <text> tags, so part of the process below deals with that.
  60. */
  61. $textTagsToRemove = array('<text></text>' => '', '<text> </text>' => '', '<say>' => '', '</say>' => '',
  62. );
  63. // Remove any spaces immediately between the XML tags
  64. $template = preg_replace('~>\s*?<~', '><', $template);
  65. $textTagSearch = array_keys($textTagsToRemove);
  66. $textTagReplace = array_values($textTagsToRemove);
  67. // Remove CRLF
  68. $template = str_replace("\r\n", '', $template);
  69. // Remove newline
  70. $template = str_replace("\n", '', $template);
  71. // Throw <text> tags around everything that lies between existing tags
  72. $template = preg_replace('~>(.*?)<~', "><text>$1</text><", $template);
  73. // Remove any "extra" <text> tags that may have been generated
  74. $template = str_replace($textTagSearch, $textTagReplace, $template);
  75. runDebug(__FILE__, __FUNCTION__, __LINE__, "Returning template:\n$template", 4);
  76. return $template;
  77. }
  78. /**
  79. * Implodes a nested array into a single string recursively
  80. *
  81. * @param string $glue
  82. * @param array $input
  83. * @param string $file
  84. * @param string $function
  85. * @param string $line
  86. * @return string
  87. */
  88. function implode_recursive($glue, $input, $file = 'unknown', $function = 'unknown', $line = 'unknown')
  89. {
  90. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Imploding an array into a string. (recursively, if necessary)', 2);
  91. #runDebug(__FILE__, __FUNCTION__, __LINE__, "This function was called from $file, function $function at line $line.", 4);
  92. if(empty($input)) return '';
  93. if (!is_array($input) and !is_string($input))
  94. {
  95. $varType = gettype($input);
  96. trigger_error("Input not array! Input is of type $varType. Error originated in $file, function $function, line $line. Input = " . print_r($input, true));
  97. return $input;
  98. }
  99. elseif (is_string($input)) return $input;
  100. runDebug(__FILE__, __FUNCTION__, __LINE__,'The variable $input is of type ' . gettype($input), 4);
  101. foreach ($input as $index => $element)
  102. {
  103. if (empty ($element))
  104. continue;
  105. if (is_array($element))
  106. {
  107. $input[$index] = implode_recursive($glue, $element, __FILE__, __FUNCTION__, __LINE__);
  108. }
  109. }
  110. switch (gettype($input))
  111. {
  112. case 'array':
  113. $out = implode($glue, $input);
  114. break;
  115. case 'string':
  116. $out = $input;
  117. break;
  118. default:
  119. runDebug(__FILE__, __FUNCTION__, __LINE__,'input type: ' . gettype($input), 4);
  120. $out = (string) $input;
  121. }
  122. $out = str_replace(' ', ' ', $out);
  123. if ($function != 'implode_recursive') runDebug(__FILE__, __FUNCTION__, __LINE__, "Imploding complete. Returning '$out'", 4);
  124. return ltrim($out);
  125. }
  126. /**
  127. * Parses a SimpleXMLelement object into a string
  128. *
  129. * @param array $convoArr
  130. * @param SimpleXMLElement $element
  131. * @param int $level
  132. * @return string
  133. */
  134. function parseTemplateRecursive(&$convoArr, SimpleXMLElement $element, $level = 0)
  135. {
  136. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Recursively parsing the AIML template.', 2);
  137. $HTML_tags = array('a', 'abbr', 'acronym', 'address', 'applet', 'area', 'b', 'bdo', 'big', 'blockquote', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl', 'dt', 'em', 'fieldset', 'font', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'iframe', 'img', 'ins', 'kbd', 'label', 'legend', 'ol', 'object', 's', 'script', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'tr', 'tt', 'u', 'ul');
  138. $doNotParseChildren = array('li');
  139. $response = array();
  140. $parentName = strtolower($element->getName());
  141. $elementCount = count($element);
  142. $children = ($elementCount > 0) ? $element->children() : $element;
  143. runDebug(__FILE__, __FUNCTION__, __LINE__, "Processing element $parentName at level $level. element XML = " . $element->asXML(), 4);
  144. $func = 'parse_' . $parentName . '_tag';
  145. if (in_array($parentName, $HTML_tags)) {
  146. $func = 'parse_html_tag';
  147. }
  148. if (function_exists($func))
  149. {
  150. runDebug(__FILE__, __FUNCTION__, __LINE__,"Function $func does exist. Processing now.", 4);
  151. if (!in_array(strtolower($parentName), $doNotParseChildren))
  152. {
  153. runDebug(__FILE__, __FUNCTION__, __LINE__, "Passing element $parentName to the $func function", 4);
  154. $retVal = $func($convoArr, $element, $parentName, $level);
  155. $retVal = (is_array($retVal)) ? $retVal = implode_recursive(' ', $retVal, __FILE__, __FUNCTION__, __LINE__) : $retVal;
  156. runDebug(__FILE__, __FUNCTION__, __LINE__, "Adding '$retVal' to the response array. tag name is $parentName", 4);
  157. $response[] = $retVal;
  158. return $response;
  159. }
  160. }
  161. else
  162. {
  163. runDebug(__FILE__, __FUNCTION__, __LINE__,"function $func does not exist. Parsing tag as text.", 4);
  164. $retVal = $element;
  165. }
  166. $value = trim((string) $retVal);
  167. $tmpResponse = ($level <= 1 and ($parentName != 'think') and (!in_array($parentName, $doNotParseChildren))) ? $value : '';
  168. if (count($children) > 0 and is_object($retVal))
  169. {
  170. foreach ($children as $child)
  171. {
  172. $childName = $child->getName();
  173. if (in_array(strtolower($childName), $doNotParseChildren)) continue;
  174. $tmpResponse = parseTemplateRecursive($convoArr, $child, $level + 1);
  175. $tmpResponse = implode_recursive(' ', $tmpResponse, __FILE__, __FUNCTION__, __LINE__);
  176. $tmpResponse = ($childName == 'think') ? '' : $tmpResponse;
  177. runDebug(__FILE__, __FUNCTION__, __LINE__, "Adding '$tmpResponse' to the response array. tag name is $parentName.", 4);
  178. $response[] = $tmpResponse;
  179. }
  180. }
  181. return $response;
  182. }
  183. /**
  184. * Converts an XML <text> tag into a string
  185. *
  186. * @param array $convoArr
  187. * @param SimpleXMLElement $element
  188. * @param string $parentName
  189. * @param int $level
  190. * @return string
  191. */
  192. function parse_text_tag($convoArr, $element, $parentName, $level)
  193. {
  194. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a TEXT tag.', 2);
  195. return (string) $element;
  196. }
  197. /**
  198. * Parses the AIML <star> tag
  199. *
  200. * @param array $convoArr
  201. * @param SimpleXMLElement $element
  202. * @param string $parentName
  203. * @param int $level
  204. * @return array
  205. */
  206. function parse_star_tag($convoArr, $element, $parentName, $level)
  207. {
  208. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a STAR tag.', 2);
  209. $response = array();
  210. runDebug(__FILE__, __FUNCTION__, __LINE__, "parse_star_tag called from the $parentName tag at level $level. element = " . $element->asXML(), 4);
  211. $attributes = $element->attributes();
  212. if (count($attributes) != 0)
  213. {
  214. $index = $element->attributes()->index;
  215. }
  216. else $index = 1;
  217. runDebug(__FILE__, __FUNCTION__, __LINE__, "star index = $index.", 4);
  218. $star = $convoArr['star'][(int) $index];
  219. runDebug(__FILE__, __FUNCTION__, __LINE__, "Adding '$star' to the response array.", 4);
  220. $response[] = $star;
  221. runDebug(__FILE__, __FUNCTION__, __LINE__, "Index value = $index, star value = $star", 4);
  222. return $response;
  223. }
  224. /**
  225. * Parses the AIML <thatstar> tag
  226. *
  227. * @param array $convoArr
  228. * @param SimpleXMLElement $element
  229. * @param string $parentName
  230. * @param int $level
  231. * @return array
  232. */
  233. function parse_thatstar_tag($convoArr, $element, $parentName, $level)
  234. {
  235. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a THATSTAR tag.', 2);
  236. $response = array();
  237. runDebug(__FILE__, __FUNCTION__, __LINE__, "parse_thatstar_tag called from the $parentName tag at level $level. element = " . $element->asXML(), 4);
  238. $attributes = $element->attributes();
  239. if (count($attributes) != 0)
  240. {
  241. $index = $element->attributes()->index;
  242. }
  243. else $index = 1;
  244. runDebug(__FILE__, __FUNCTION__, __LINE__, "thatstar index = $index.", 4);
  245. $star = $convoArr['that_star'][(int) $index];
  246. runDebug(__FILE__, __FUNCTION__, __LINE__, "Adding '$star' to the response array.", 4);
  247. $response[] = $star;
  248. runDebug(__FILE__, __FUNCTION__, __LINE__, "Index value = $index, thatstar value = $star", 4);
  249. return $response;
  250. }
  251. /**
  252. * Parses the AIML <date> tag
  253. *
  254. * @param array $convoArr
  255. * @param SimpleXMLElement $element
  256. * @param string $parentName
  257. * @param int $level
  258. * @return string
  259. */
  260. function parse_date_tag($convoArr, $element, $parentName, $level)
  261. {
  262. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a DATE tag.', 2);
  263. global $time_zone_locale;
  264. $tz_list = array(
  265. '-12'=>'Pacific/Kwajalein',
  266. '-11'=>'Pacific/Samoa',
  267. '-10'=>'Pacific/Honolulu',
  268. '-9'=>'America/Juneau',
  269. '-8'=>'America/Los_Angeles',
  270. '-7'=>'America/Denver',
  271. '-6'=>'America/Mexico_City',
  272. '-5'=>'America/New_York',
  273. '-4'=>'America/Caracas',
  274. '-3.5'=>'America/St_Johns',
  275. '-3'=>'America/Argentina/Buenos_Aires',
  276. '-2'=>'Atlantic/Azores',
  277. '-1'=>'Atlantic/Azores',
  278. '0'=>'Europe/London',
  279. '1'=>'Europe/Paris',
  280. '2'=>'Europe/Helsinki',
  281. '3'=>'Europe/Moscow',
  282. '3.5'=>'Asia/Tehran',
  283. '4'=>'Asia/Baku',
  284. '4.5'=>'Asia/Kabul',
  285. '5'=>'Asia/Karachi',
  286. '5.5'=>'Asia/Calcutta',
  287. '6'=>'Asia/Colombo',
  288. '7'=>'Asia/Bangkok',
  289. '8'=>'Asia/Singapore',
  290. '9'=>'Asia/Tokyo',
  291. '9.5'=>'Australia/Darwin',
  292. '10'=>'Pacific/Guam',
  293. '11'=>'Asia/Magadan',
  294. '12'=>'Asia/Kamchatka'
  295. );
  296. $cur_timezone = date_default_timezone_get();
  297. $cur_locale = setlocale(LC_ALL, '');
  298. #$cur_locale = setlocale(LC_ALL, 'en_US');
  299. $format = $element->attributes()->format;
  300. $locale = $element->attributes()->locale;
  301. $tz = $element->attributes()->timezone;
  302. $format = (string) $format;
  303. $format = (!empty($format)) ? $format : '%c';
  304. $locale = (string)$locale . '.UTF8';
  305. if (!empty($locale)) setlocale(LC_ALL, $locale);
  306. $tz = (string) $tz;
  307. $tz = (!empty($tz)) ? $tz : $cur_timezone;
  308. $tz = (!is_numeric($tz)) ? $tz : $tz_list[$tz];
  309. date_default_timezone_set($tz);
  310. #$response = "$tz - " . strftime($format);
  311. $response = strftime($format);
  312. #$response = $cur_locale;
  313. date_default_timezone_set($cur_timezone);
  314. runDebug(__FILE__, __FUNCTION__, __LINE__, "Date tag parsed. Returning $response", 4);
  315. return $response;
  316. }
  317. /**
  318. * Parses the AIML <random> tag
  319. *
  320. * @param array $convoArr
  321. * @param SimpleXMLElement $element
  322. * @param string $parentName
  323. * @param int $level
  324. * @return string
  325. */
  326. function parse_random_tag($convoArr, $element, $parentName, $level)
  327. {
  328. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a RANDOM tag, or doing some stargazing, or fomenting chaos, or...', 2);
  329. $liArray = $element->xpath('li');
  330. runDebug(__FILE__, __FUNCTION__, __LINE__,"Pick array:\n" . print_r($liArray, true), 4);
  331. $pick = array_rand($liArray);
  332. runDebug(__FILE__, __FUNCTION__, __LINE__, "Picking option #$pick from random tag.\n", 4);
  333. $response = parseTemplateRecursive($convoArr, $liArray[$pick], $level + 1);
  334. $response = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  335. runDebug(__FILE__, __FUNCTION__, __LINE__, "Chose Random Response of '$response' for output.", 4);
  336. return $response;
  337. }
  338. /**
  339. * Parses the AIML <get> tag, obtaining it's value from the database
  340. *
  341. * @param array $convoArr
  342. * @param SimpleXMLElement $element
  343. * @param string $parentName
  344. * @param int $level
  345. * @return string
  346. */
  347. function parse_get_tag($convoArr, $element, $parentName, $level)
  348. {
  349. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a GET tag. Oh, and getting a sandwich while I\'m at it.', 2);
  350. global $dbConn, $dbn, $remember_up_to;
  351. $response = '';
  352. $bot_id = $convoArr['conversation']['bot_id'];
  353. $user_id = $convoArr['conversation']['user_id'];
  354. $var_name = $element->attributes()->name;
  355. $var_name = ($var_name == '*') ? $convoArr['star'][1] : $var_name;
  356. for ($n = 2; $n <= $remember_up_to; $n++) # index multiple star values
  357. {
  358. $var_name = ($var_name == "*$n") ? $convoArr['star'][$n] : $var_name;
  359. }
  360. if (empty ($var_name))
  361. $response = 'undefined';
  362. if (empty ($response))
  363. {
  364. $sql = "select `value` from `$dbn`.`client_properties` where `user_id` = $user_id and `bot_id` = $bot_id and `name` = '$var_name';";
  365. runDebug(__FILE__, __FUNCTION__, __LINE__, "Checking the DB for $var_name - sql:\n$sql", 3);
  366. $row = db_fetch($sql, null, __FILE__, __FUNCTION__, __LINE__);
  367. if (($row) and (count($row) > 0)) {
  368. $response = $row['value'];
  369. }
  370. else {
  371. $response = 'undefined';
  372. }
  373. }
  374. runDebug(__FILE__, __FUNCTION__, __LINE__, "The value for $var_name is $response.", 4);
  375. return $response;
  376. }
  377. /**
  378. * Parses the AIML <set> tag, storing it's value in the database
  379. *
  380. * @param array $convoArr
  381. * @param SimpleXMLElement $element
  382. * @param string $parentName
  383. * @param int $level
  384. * @return string
  385. */
  386. function parse_set_tag(&$convoArr, $element, $parentName, $level)
  387. {
  388. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing the SET tag.', 2);
  389. global $dbConn, $dbn, $user_name, $remember_up_to;
  390. $var_value = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  391. $bot_id = $convoArr['conversation']['bot_id'];
  392. $user_id = $convoArr['conversation']['user_id'];
  393. $var_name = (string)$element->attributes()->name;
  394. $var_name = ($var_name == '*') ? $convoArr['star'][1] : $var_name;
  395. for ($n = 2; $n <= $remember_up_to; $n++) # index multiple star values
  396. {
  397. $var_name = ($var_name == "*$n") ? $convoArr['star'][$n] : $var_name;
  398. }
  399. $vn_type = gettype($var_name);
  400. runDebug(__FILE__, __FUNCTION__, __LINE__, "var_name = $var_name and is type: $vn_type", 4);
  401. if ($var_name == 'name')
  402. {
  403. $convoArr['client_properties'][$var_name] = $var_value;
  404. $user_name = $var_value;
  405. $escaped_var_value = $var_value;
  406. $sql = "UPDATE `$dbn`.`users` set `user_name` = '$escaped_var_value' where `id` = $user_id;";
  407. runDebug(__FILE__, __FUNCTION__, __LINE__, "Updating user name in the DB. SQL:\n$sql", 3);
  408. $sth = $dbConn->prepare($sql);
  409. $sth->execute();
  410. $numRows = $sth->rowCount();
  411. $sql = "select `user_name` from `$dbn`.`users` where `id` = $user_id limit 1;";
  412. runDebug(__FILE__, __FUNCTION__, __LINE__, "Checking the users table to see if the value has changed. - SQL:\n$sql", 3);
  413. $row = db_fetch($sql, null, __FILE__, __FUNCTION__, __LINE__);
  414. $rowCount = count($row);
  415. if ($rowCount != 0)
  416. {
  417. $tmp_name = $row['user_name'];
  418. runDebug(__FILE__, __FUNCTION__, __LINE__, "The value for the user's name is $tmp_name.", 4);
  419. }
  420. }
  421. else $convoArr['client_properties'][$var_name] = $var_value;
  422. $lc_var_name = (IS_MB_ENABLED) ? mb_strtolower($var_name) : strtolower($var_name);
  423. if ($lc_var_name == 'topic') $convoArr['topic'][1] = $var_value;
  424. $sql = "select `value` from `$dbn`.`client_properties` where `user_id` = $user_id and `bot_id` = $bot_id and `name` = '$var_name';";
  425. runDebug(__FILE__, __FUNCTION__, __LINE__, "Checking the client_properties table for the value of $var_name. - SQL:\n$sql", 3);
  426. $result = db_fetchAll($sql, null, __FILE__, __FUNCTION__, __LINE__);
  427. $rowCount = count($result);
  428. /** @noinspection PhpSillyAssignmentInspection */
  429. $var_name = $var_name;
  430. $var_name = str_replace("'", "\'", $var_name);
  431. /** @noinspection PhpSillyAssignmentInspection */
  432. $var_value = $var_value;
  433. $var_value = str_replace("'", "\'", $var_value);
  434. if ($rowCount == 0)
  435. {
  436. $sql = "insert into `$dbn`.`client_properties` (`id`, `user_id`, `bot_id`, `name`, `value` ,`lastdate`)
  437. values (NULL, $user_id, $bot_id, '$var_name', '$var_value' , NOW());";
  438. runDebug(__FILE__, __FUNCTION__, __LINE__, "No value found for $var_name. Inserting $var_value into the table.", 4);
  439. }
  440. else
  441. {
  442. $sql = "update `$dbn`.`client_properties` set `value` = '$var_value' , `lastdate` = NOW() where `user_id` = $user_id and
  443. `bot_id` = $bot_id and `name` = '$var_name';";
  444. runDebug(__FILE__, __FUNCTION__, __LINE__, "Value found for $var_name. Updating the table to $var_value.", 4);
  445. }
  446. runDebug(__FILE__, __FUNCTION__, __LINE__, "Saving to DB - SQL:\n$sql", 3);
  447. $sth = $dbConn->prepare($sql);
  448. $sth->execute();
  449. $rowCount = $sth->rowCount();
  450. $response = $var_value;
  451. $convoArr['client_properties'][$var_name] = $var_value;
  452. runDebug(__FILE__, __FUNCTION__, __LINE__, "Value for $var_name has ben set. Returning $var_value.", 4);
  453. $convoArr['client_properties']['test']='passed';
  454. return $response;
  455. }
  456. /**
  457. * Parses the AIML <think> tag, suppressing output by returning an empty string
  458. *
  459. * @param array $convoArr
  460. * @param SimpleXMLElement $element
  461. * @param string $parentName
  462. * @param int $level
  463. * @return string
  464. */
  465. function parse_think_tag(&$convoArr, $element, $parentName, $level)
  466. {
  467. runDebug(__FILE__, __FUNCTION__, __LINE__, 'I\'m considering parsing a THINK tag.', 2);
  468. /** @noinspection PhpUnusedLocalVariableInspection */
  469. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  470. return '';
  471. }
  472. /**
  473. * Parses the AIML <bot> tag, obtaining it's value from the database
  474. *
  475. * @param array $convoArr
  476. * @param SimpleXMLElement $element
  477. * @return string
  478. */
  479. function parse_bot_tag($convoArr, $element)
  480. {
  481. global $remember_up_to;
  482. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a BOT tag.', 2);
  483. $attributeName = (string)$element->attributes()->name;
  484. $attributeName = ($attributeName == '*') ? $convoArr['star'][1] : $attributeName;
  485. for ($n = 2; $n <= $remember_up_to; $n++) # index multiple star values
  486. {
  487. $attributeName = ($attributeName == "*$n") ? $convoArr['star'][$n] : $attributeName;
  488. }
  489. $response = (!empty ($convoArr['bot_properties'][$attributeName])) ? $convoArr['bot_properties'][$attributeName] : 'undefined';
  490. runDebug(__FILE__, __FUNCTION__, __LINE__, "Returning bot property $attributeName. Value = $response", 4);
  491. return $response;
  492. }
  493. /**
  494. * Parses the AIML <id> tag, returning the current conversation ID
  495. *
  496. * @param array $convoArr
  497. * @param SimpleXMLElement $element
  498. * @param string $parentName
  499. * @param int $level
  500. * @return string
  501. */
  502. function parse_id_tag($convoArr, $element, $parentName, $level)
  503. {
  504. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing an ID tag.', 2);
  505. return $convoArr['conversation']['convo_id'];
  506. }
  507. /**
  508. * Parses the AIML <version> tag, returning the current version of Program O
  509. *
  510. * @param array $convoArr
  511. * @param SimpleXMLElement $element
  512. * @param string $parentName
  513. * @param int $level
  514. * @return string
  515. */
  516. function parse_version_tag($convoArr, $element, $parentName, $level)
  517. {
  518. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a VERSION tag.', 2);
  519. return 'Program O version ' . VERSION;
  520. }
  521. /**
  522. * Parses the AIML <uppercase> tag
  523. *
  524. * @param array $convoArr
  525. * @param SimpleXMLElement $element
  526. * @param string $parentName
  527. * @param int $level
  528. * @return string
  529. */
  530. function parse_uppercase_tag($convoArr, $element, $parentName, $level)
  531. {
  532. runDebug(__FILE__, __FUNCTION__, __LINE__, 'PARSING AN UPPERCASE TAG.', 2);
  533. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  534. $response_string = (IS_MB_ENABLED) ? mb_strtoupper($response_string) : strtoupper($response_string);
  535. return ltrim($response_string, ' ');
  536. }
  537. /**
  538. * Parses the AIML <lowercase> tag
  539. *
  540. * @param array $convoArr
  541. * @param SimpleXMLElement $element
  542. * @param string $parentName
  543. * @param int $level
  544. * @return string
  545. */
  546. function parse_lowercase_tag($convoArr, $element, $parentName, $level)
  547. {
  548. runDebug(__FILE__, __FUNCTION__, __LINE__, 'parsing a lowercase tag.', 2);
  549. $response = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  550. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  551. return ltrim(strtolower($response_string), ' ');
  552. }
  553. /**
  554. * Parses the AIML <sentence> tag
  555. *
  556. * @param array $convoArr
  557. * @param SimpleXMLElement $element
  558. * @param string $parentName
  559. * @param int $level
  560. * @return string
  561. */
  562. function parse_sentence_tag($convoArr, $element, $parentName, $level)
  563. {
  564. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a SENTENCE tag.', 2);
  565. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  566. if (IS_MB_ENABLED)
  567. {
  568. $response_string = mb_strtolower($response_string);
  569. $response = mb_strtoupper(mb_substr($response_string, 0, 1)) . mb_substr($response_string, 1);
  570. }
  571. else $response = ucfirst(strtolower($response_string));
  572. runDebug(__FILE__, __FUNCTION__, __LINE__, "Response string was: $response_string. Transformed to $response.", 4);
  573. return $response;
  574. }
  575. /**
  576. * Parses the AIML <formal> tag
  577. *
  578. * @param array $convoArr
  579. * @param SimpleXMLElement $element
  580. * @param string $parentName
  581. * @param int $level
  582. * @return string
  583. */
  584. function parse_formal_tag($convoArr, $element, $parentName, $level)
  585. {
  586. global $charset;
  587. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing A Formal Tag.', 2);
  588. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  589. $response = (IS_MB_ENABLED) ? mb_convert_case($response_string, MB_CASE_TITLE, $charset) : ucwords(strtolower($response_string));
  590. runDebug(__FILE__, __FUNCTION__, __LINE__, "Response string was: $response_string. Transformed to $response.", 4);
  591. return $response;
  592. }
  593. /**
  594. * Parses the AIML <srai> tag
  595. *
  596. * @param array $convoArr
  597. * @param SimpleXMLElement $element
  598. * @param string $parentName
  599. * @param int $level
  600. * @return string
  601. */
  602. function parse_srai_tag($convoArr, $element, $parentName, $level)
  603. {
  604. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing an SRAI tag.', 2);
  605. $srai = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  606. $response = run_srai($convoArr, $srai);
  607. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Finished parsing SRAI tag', 4);
  608. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  609. return $response_string;
  610. }
  611. /**
  612. * Parses the AIML <sr> tag
  613. *
  614. * @param array $convoArr
  615. * @param SimpleXMLElement $element
  616. * @param string $parentName
  617. * @param int $level
  618. * @return string
  619. */
  620. function parse_sr_tag($convoArr, $element, $parentName, $level)
  621. {
  622. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing an SR tag.', 4);
  623. $response = run_srai($convoArr, $convoArr['star'][1]);
  624. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Finished parsing SR tag', 4);
  625. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  626. return $response_string;
  627. }
  628. /**
  629. * Parses the AIML <condition> tag
  630. *
  631. * @param array $convoArr
  632. * @param SimpleXMLElement $element
  633. * @param string $parentName
  634. * @param int $level
  635. * @return array|string
  636. */
  637. function parse_condition_tag($convoArr, $element, $parentName, $level)
  638. {
  639. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a CONDITION tag.', 2);
  640. global $error_response;
  641. $response = array();
  642. $attributes = (array)$element->attributes();
  643. $attributesArray = (isset($attributes['@attributes'])) ? $attributes['@attributes'] : array();
  644. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Element attributes:' . print_r($attributesArray, true), 4);
  645. $attribute_count = count($attributesArray);
  646. runDebug(__FILE__, __FUNCTION__, __LINE__, "Element attribute count = $attribute_count", 4);
  647. if ($attribute_count == 0) // Bare condition tag
  648. {
  649. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a CONDITION tag with no attributes. XML = ' . $element->asXML(), 4);
  650. $liNamePath = 'li[@name]';
  651. $condition_xPath = '';
  652. $exclude = array();
  653. $choices = $element->xpath($liNamePath);
  654. foreach ($choices as $choice)
  655. {
  656. $choice_name = (string)$choice['name'];
  657. if (in_array($choice_name, $exclude)) continue;
  658. $exclude[] = $choice_name;
  659. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Client properties = ' . print_r($convoArr['client_properties'], true), 4);
  660. $choice_value = trim(get_client_property($convoArr, $choice_name));
  661. $condition_xPath .= "li[@name=\"$choice_name\"][@value=\"$choice_value\"]|";
  662. }
  663. $condition_xPath .= 'li[not(@*)]';
  664. runDebug(__FILE__, __FUNCTION__, __LINE__, "xpath search = $condition_xPath", 4);
  665. $pick_search = $element->xpath($condition_xPath);
  666. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Pick array = ' . print_r($pick_search, true), 4);
  667. $pick_count = count($pick_search);
  668. runDebug(__FILE__, __FUNCTION__, __LINE__, "Pick count = $pick_count.", 4);
  669. $pick = $pick_search[0];
  670. }
  671. elseif (array_key_exists('value', $attributesArray) or array_key_exists('contains', $attributesArray) or array_key_exists('exists', $attributesArray)) // condition tag with either VALUE, CONTAINS or EXISTS attributes
  672. {
  673. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a CONDITION tag with 2 attributes.', 4);
  674. $condition_name = (string)$element['name'];
  675. $test_value = trim(get_client_property($convoArr, $condition_name));
  676. switch (true)
  677. {
  678. case (isset($element['value'])):
  679. $condition_value = (string)$element['value'];
  680. break;
  681. case (isset($element['contains'])):
  682. $condition_value = (string)$element['contains'];
  683. break;
  684. case (isset($element['exists'])):
  685. $condition_value = (string)$element['exists'];
  686. break;
  687. default:
  688. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Something went wrong with parsing the CONDITION tag. Returning the error response.', 1);
  689. return $error_response;
  690. }
  691. $pick = ($condition_value == $test_value) ? $element : '';
  692. }
  693. elseif (array_key_exists('name', $attributesArray)) // this ~SHOULD~ just trigger if the NAME value is present, and ~NOT~ NAME and (VALUE|CONTAINS|EXISTS)
  694. {
  695. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a CONDITION tag with only the NAME attribute', 4);
  696. $condition_name = (string)$element['name'];
  697. $test_value = trim(get_client_property($convoArr, $condition_name));
  698. runDebug(__FILE__, __FUNCTION__, __LINE__, "Looking for test value '$test_value'", 4);
  699. $path = "li[@value]|li[not(@*)]";
  700. runDebug(__FILE__, __FUNCTION__, __LINE__, "search string = $path", 4);
  701. $choice = $element->xpath($path);
  702. runDebug(__FILE__, __FUNCTION__, __LINE__,'element = ' . print_r($element, true), 4);
  703. runDebug(__FILE__, __FUNCTION__, __LINE__,'Choices = ' . print_r($choice, true), 4);
  704. if (count($choice) != 0)
  705. {
  706. $test_value = rtrim($test_value);
  707. runDebug(__FILE__, __FUNCTION__, __LINE__,'parent XML = ' . $element->asXML(), 4);
  708. foreach ($choice as $pick)
  709. {
  710. runDebug(__FILE__, __FUNCTION__, __LINE__,'Current pick = ' . print_r($pick, true), 4);
  711. $attr = $pick->attributes();
  712. runDebug(__FILE__, __FUNCTION__, __LINE__,'Current pick attributes = ' . print_r($attr, true), 4);
  713. $testVarValue = (isset($attr['value'])) ? (string)$attr['value'] : '';
  714. runDebug(__FILE__, __FUNCTION__, __LINE__,"Pick Value = '$testVarValue'", 4);
  715. runDebug(__FILE__, __FUNCTION__, __LINE__,"Checking to see if $testVarValue (condition value) is equal to $test_value (Client Property).", 4);
  716. if (strtolower($testVarValue) == strtolower($test_value))
  717. {
  718. runDebug(__FILE__, __FUNCTION__, __LINE__,'Pick XML = ' . $pick->asXML(), 4);
  719. break;
  720. }
  721. }
  722. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Found a match. Pick = ' . print_r($pick, true), 4);
  723. }
  724. else
  725. {
  726. $path = "li[@value=\"$test_value\"]|li[not(@*)]";
  727. runDebug(__FILE__, __FUNCTION__, __LINE__, "search string = $path", 4);
  728. $choice = $element->xpath($path);
  729. $pick = $choice[0];
  730. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Found a match. Pick = ' . print_r($pick, true), 4);
  731. }
  732. }
  733. else // nothing matches
  734. {
  735. runDebug(__FILE__, __FUNCTION__, __LINE__, 'No matches found. Returning default error response. this is probably because of poorly written AIML code.', 1);
  736. return $error_response;
  737. }
  738. $children = (is_object($pick)) ? $pick->children() : null;
  739. if (!empty ($children))
  740. {
  741. foreach ($children as $child)
  742. {
  743. $response[] = parseTemplateRecursive($convoArr, $child, $level + 1);
  744. }
  745. runDebug(__FILE__, __FUNCTION__, __LINE__, "Response = " . print_r($response, true), 4);
  746. }
  747. else
  748. {
  749. $response[] = (string) $pick;
  750. }
  751. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  752. return $response_string;
  753. }
  754. /**
  755. * Parses the AIML <person> tag
  756. *
  757. * @param array $convoArr
  758. * @param SimpleXMLElement $element
  759. * @param string $parentName
  760. * @param int $level
  761. * @return string
  762. */
  763. function parse_person_tag($convoArr, $element, $parentName, $level)
  764. {
  765. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a PERSON tag.', 2);
  766. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'star');
  767. $response = swapPerson($convoArr, 3, $response_string);
  768. return $response;
  769. }
  770. /**
  771. * Parses the AIML <person2> tag
  772. *
  773. * @param array $convoArr
  774. * @param SimpleXMLElement $element
  775. * @param string $parentName
  776. * @param int $level
  777. * @return string
  778. */
  779. function parse_person2_tag($convoArr, $element, $parentName, $level)
  780. {
  781. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a PERSON2 tag.', 2);
  782. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'star');
  783. $response = swapPerson($convoArr, 2, $response_string);
  784. return $response;
  785. }
  786. /**
  787. * Parses any HTML tags that are not also AIML tags
  788. *
  789. * @param array $convoArr
  790. * @param SimpleXMLElement $element
  791. * @param string $parentName
  792. * @param int $level
  793. * @return string
  794. */
  795. function parse_html_tag($convoArr, $element, $parentName, $level)
  796. {
  797. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a generic HTML tag.', 2);
  798. $response_string = $element->asXML();
  799. $response_string = str_replace('<text>', '', $response_string);
  800. $response_string = str_replace('</text>', '', $response_string);
  801. $star = (isset($convoArr['star'][1])) ? $convoArr['star'][1] : '';
  802. if ($star != '') $response_string = str_replace('<star/>', $star, $response_string);
  803. return $response_string;
  804. }
  805. /**
  806. * Parses the AIML <gender> tag
  807. *
  808. * @param array $convoArr
  809. * @param SimpleXMLElement $element
  810. * @param string $parentName
  811. * @param int $level
  812. * @return string
  813. */
  814. function parse_gender_tag($convoArr, $element, $parentName, $level)
  815. {
  816. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Giving part of the response a sex change!', 2);
  817. $response_string = ' ' . tag_to_string($convoArr, $element, $parentName, $level, 'star');
  818. runDebug(__FILE__, __FUNCTION__, __LINE__, "Original response string = '$response_string'", 4);
  819. $nounList = $convoArr['nounList'];
  820. foreach ($nounList as $noun)
  821. {
  822. // This fixes (most) possessives
  823. $response_string = str_replace(" his $noun ", " x_her $noun ", $response_string);
  824. }
  825. $male2tmp = array('he ' => ' x_she ', ' his ' => ' x_hers ', ' him ' => ' x_her ', ' He ' => ' x_She ', ' His ' => ' x_Hers ', ' Him ' => ' x_Her ', 'he!' => ' x_she!', ' his!' => ' x_hers!', ' him!' => ' x_her!', ' He!' => ' x_She!', ' His!' => ' x_Hers!', ' Him!' => ' x_Her!', 'he,' => ' x_she,', ' his,' => ' x_hers,', ' him,' => ' x_her,', ' He,' => ' x_She,', ' His,' => ' x_Hers,', ' Him,' => ' x_Her,', 'he?' => ' x_she?', ' his?' => ' x_hers?', ' him?' => ' x_her?', ' He?' => ' x_She?', ' His?' => ' x_Hers?', ' Him?' => ' x_Her?',);
  826. $female2male = array(' she ' => ' he ', ' hers ' => ' his ', ' her ' => ' him ', ' She ' => ' He ', ' Hers ' => ' His ', ' Her ' => ' Him ', ' she.' => 'he.', ' hers.' => ' his.', ' her.' => ' him.', ' She.' => ' He.', ' Hers.' => ' His.', ' Her.' => ' Him.', ' she,' => 'he,', ' hers,' => ' his,', ' her,' => ' him,', ' She,' => ' He,', ' Hers,' => ' His,', ' Her,' => ' Him,', ' she!' => 'he!', ' hers!' => ' his!', ' her!' => ' him!', ' She!' => ' He!', ' Hers!' => ' His!', ' Her!' => ' Him!', ' she?' => 'he?', ' hers?' => ' his?', ' her?' => ' him?', ' She?' => ' He?', ' Hers?' => ' His?', ' Her?' => ' Him?',);
  827. $tmp2male = array(' x_he' => ' he', ' x_she' => ' she', ' x_He' => ' He', ' x_She' => ' She',);
  828. $m2tSearch = array_keys($male2tmp);
  829. $m2tReplace = array_values($male2tmp);
  830. $response_string = str_replace($m2tSearch, $m2tReplace, $response_string);
  831. $f2mSearch = array_keys($female2male);
  832. $f2mReplace = array_values($female2male);
  833. $response_string = str_replace($f2mSearch, $f2mReplace, $response_string);
  834. $t2mSearch = array_keys($tmp2male);
  835. $t2mReplace = array_values($tmp2male);
  836. $response_string = str_replace($t2mSearch, $t2mReplace, $response_string);
  837. runDebug(__FILE__, __FUNCTION__, __LINE__, "Transformed response string = '$response_string'", 4);
  838. return $response_string;
  839. }
  840. /**
  841. * Parses the AIML <that> tag
  842. *
  843. * @param array $convoArr
  844. * @param SimpleXMLElement $element
  845. * @param string $parentName
  846. * @param int $level
  847. * @return string
  848. */
  849. function parse_that_tag($convoArr, $element, $parentName, $level)
  850. {
  851. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a THAT tag. How awesome is that?', 2);
  852. if(!empty($element))
  853. {
  854. $attributes = $element->attributes();
  855. runDebug(__FILE__, __FUNCTION__, __LINE__, 'element attributes = ' . print_r($attributes, true), 2);
  856. $index = $attributes['index'];
  857. runDebug(__FILE__, __FUNCTION__, __LINE__, 'element attribute index = ' . $index, 2);
  858. $index = (!empty ($index)) ? $index : 1;
  859. if ($index == intval($index))
  860. {
  861. $response = $convoArr['that'][(int)$index];
  862. //$index .= ',1';
  863. }
  864. if (strstr($index, ',') !== false)
  865. {
  866. list($index1, $index2) = explode(',', $index, 2);
  867. $index1 = intval($index1);
  868. $index2 = intval($index2);
  869. $thatArray = $convoArr['that'];
  870. runDebug(__FILE__, __FUNCTION__, __LINE__,'THAT array = ' . print_r($thatArray, true), 2);
  871. runDebug(__FILE__, __FUNCTION__, __LINE__, 'index1 = ' . $index1, 2);
  872. if (!empty($convoArr['that'][$index1][$index2])) $response = $convoArr['that'][$index1][$index2];
  873. else $response = '';
  874. }
  875. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  876. }
  877. else $response_string = implode_recursive(' ', $convoArr['that'][1], __FILE__, __FUNCTION__, __LINE__);
  878. return $response_string;
  879. }
  880. /**
  881. * Parses the AIML <input> tag
  882. *
  883. * @param array $convoArr
  884. * @param SimpleXMLElement $element
  885. * @param string $parentName
  886. * @param int $level
  887. * @return string
  888. */
  889. function parse_input_tag($convoArr, $element, $parentName, $level)
  890. {
  891. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing an INPUT tag.', 2);
  892. //$element = $element->input;
  893. $input_index = (string)$element['index'];
  894. $input_index = (!empty ($input_index)) ? $input_index : 1;
  895. runDebug(__FILE__, __FUNCTION__, __LINE__, "Parsing the INPUT tag. Index = $input_index.", 4);
  896. $response_string = $convoArr['input'][$input_index];
  897. return $response_string;
  898. }
  899. /**
  900. * Parses the AIML <system> tag, Executing system calls and returning the results
  901. *
  902. * @param array $convoArr
  903. * @param SimpleXMLElement $element
  904. * @param string $parentName
  905. * @param int $level
  906. * @return string
  907. */
  908. function parse_system_tag($convoArr, $element, $parentName, $level)
  909. {
  910. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a SYSTEM tag (May God have mercy on us all).', 2);
  911. $system_call = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  912. $response_string = shell_exec($system_call);
  913. return $response_string;
  914. }
  915. /**
  916. * Parses the 'extended' AIML <learn> tag
  917. *
  918. * @param array $convoArr
  919. * @param SimpleXMLElement $element
  920. * @param string $parentName
  921. * @param int $level
  922. * @return string
  923. */
  924. function parse_learn_tag($convoArr, $element, $parentName, $level)
  925. {
  926. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing a LEARN tag.', 2);
  927. global $dbn, $dbConn;
  928. $bot_id = $convoArr['conversation']['bot_id'];
  929. $user_id = $convoArr['conversation']['user_id'];
  930. $sqlTemplate = "insert into `$dbn`.`aiml_userdefined` (`id`, `bot_id`, `aiml`, `pattern`, `thatpattern`, `template`, `user_id`)
  931. values (NULL, $bot_id, '[aiml]', '[pattern]', '[that]', '[template]', '$user_id');";
  932. $sql = '';
  933. $failure = false;
  934. $remove = array('<text>', '</text>');
  935. $fileName = (string) $element['filename'];
  936. if (empty($fileName)) // enclosed text is the category to add to the DB
  937. {
  938. $category = $element->category;
  939. $pattern = parseTemplateRecursive($convoArr, $category->pattern, $level + 1);
  940. $pattern = implode_recursive(' ', $pattern, __FILE__, __FUNCTION__, __LINE__);
  941. $pattern = (IS_MB_ENABLED) ? mb_strtoupper($pattern) : strtoupper($pattern);
  942. $thatpattern = (string)$category->that;
  943. $parsed_template = parseTemplateRecursive($convoArr, $category->template, $level + 1);
  944. $parsed_template = implode_recursive(' ', $parsed_template, __FILE__, __FUNCTION__, __LINE__);
  945. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsed LEARN template: ' . $parsed_template, 2);
  946. $catXML = new SimpleXMLElement('<category/>');
  947. $catXML->addChild('pattern', $pattern);
  948. if (!empty($thatpattern))
  949. $catXML->addChild('that', $thatpattern);
  950. $catXML->addChild('template', $parsed_template);
  951. $category = $catXML->asXML();
  952. $category = trim(str_replace('<?xml version="1.0"?>', '', $category));
  953. $sqlAdd = str_replace('[aiml]', $category, $sqlTemplate);
  954. $sqlAdd = str_replace('[pattern]', $pattern, $sqlAdd);
  955. $sqlAdd = str_replace('[that]', $thatpattern, $sqlAdd);
  956. $sqlAdd = str_replace('[template]', $parsed_template, $sqlAdd);
  957. $sql .= $sqlAdd;
  958. $sth = $dbConn->prepare($sql);
  959. $sth->execute();
  960. }
  961. else
  962. {
  963. $uploaded_file = _UPLOAD_PATH_ . $fileName;
  964. if (!file_exists($uploaded_file)) $failure = "File $fileName does not exist in the upload path!";
  965. else
  966. {
  967. $aiml = simplexml_load_file($uploaded_file);
  968. if (!$aiml) $failure = "Could not parse file $uploaded_file as XML!";
  969. else
  970. {
  971. foreach ($aiml->topic as $topic)
  972. {
  973. $topicName = (string)$topic['name'];
  974. foreach ($topic as $category)
  975. {
  976. $catXML = $category->asXML();
  977. $pattern = $category->pattern->asXML();
  978. $thatpattern = $category->that->asXML();
  979. $template = $category->template->asXML();
  980. $sqlAdd = str_replace('[aiml]', $catXML, $sqlTemplate);
  981. $sqlAdd = str_replace('[pattern]', $pattern, $sqlAdd);
  982. $sqlAdd = str_replace('[that]', $thatpattern, $sqlAdd);
  983. $sqlAdd = str_replace('[template]', $template, $sqlAdd);
  984. $sqlAdd = str_replace('[topic]', $topicName, $sqlAdd);
  985. $sqlAdd = str_replace('[fileName]', $fileName, $sqlAdd);
  986. $sql .= $sqlAdd;
  987. }
  988. }
  989. }
  990. }
  991. }
  992. if ($failure) {
  993. trigger_error($failure);
  994. }
  995. else {
  996. $sql = str_replace($remove, '', $sql);
  997. runDebug(__FILE__, __FUNCTION__, __LINE__, "Adding AIML to the DB. SQL:\n$sql", 3);
  998. }
  999. return '';
  1000. }
  1001. /**
  1002. * Parses the 'extended' AIML <eval> tag
  1003. *
  1004. * @param array $convoArr
  1005. * @param SimpleXMLElement $element
  1006. * @param string $parentName
  1007. * @param int $level
  1008. * @return array|string
  1009. */
  1010. function parse_eval_tag($convoArr, $element, $parentName, $level)
  1011. {
  1012. runDebug(__FILE__, __FUNCTION__, __LINE__, 'Parsing an EVAL tag.', 2);
  1013. $response_string = tag_to_string($convoArr, $element, $parentName, $level, 'element');
  1014. // do something here
  1015. return $response_string;
  1016. }
  1017. /**
  1018. * Converts the contents of the AIML tag to a string.
  1019. *
  1020. * @param array $convoArr
  1021. * @param SimpleXMLElement $element
  1022. * @param string $parentName
  1023. * @param int $level
  1024. * @param string $type
  1025. * @return string
  1026. */
  1027. function tag_to_string(&$convoArr, $element, $parentName, $level, $type = 'element')
  1028. {
  1029. runDebug(__FILE__, __FUNCTION__, __LINE__, "converting the $parentName tag into text.", 2);
  1030. $response = array();
  1031. $children = $element->children();
  1032. if (!empty ($children))
  1033. {
  1034. foreach ($children as $child)
  1035. {
  1036. $response[] = parseTemplateRecursive($convoArr, $child, $level + 1);
  1037. }
  1038. }
  1039. else
  1040. {
  1041. switch ($type)
  1042. {
  1043. case 'element':
  1044. $response[] = (string) $element;
  1045. break;
  1046. default:
  1047. $response[] = $convoArr['star'][1];
  1048. }
  1049. }
  1050. $response_string = implode_recursive(' ', $response, __FILE__, __FUNCTION__, __LINE__);
  1051. // do something here
  1052. return $response_string;
  1053. }