xajaxResponse.inc.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. <?php
  2. /**
  3. * xajaxResponse.inc.php :: xajax XML response class
  4. *
  5. * xajax version 0.2.4
  6. * copyright (c) 2005 by Jared White & J. Max Wilson
  7. * http://www.xajaxproject.org
  8. *
  9. * xajax is an open source PHP class library for easily creating powerful
  10. * PHP-driven, web-based Ajax Applications. Using xajax, you can asynchronously
  11. * call PHP functions and update the content of your your webpage without
  12. * reloading the page.
  13. *
  14. * xajax is released under the terms of the LGPL license
  15. * http://www.gnu.org/copyleft/lesser.html#SEC3
  16. *
  17. * This library is free software; you can redistribute it and/or
  18. * modify it under the terms of the GNU Lesser General Public
  19. * License as published by the Free Software Foundation; either
  20. * version 2.1 of the License, or (at your option) any later version.
  21. *
  22. * This library is distributed in the hope that it will be useful,
  23. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  25. * Lesser General Public License for more details.
  26. *
  27. * You should have received a copy of the GNU Lesser General Public
  28. * License along with this library; if not, write to the Free Software
  29. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  30. *
  31. * @package xajax
  32. * @version $Id: xajaxResponse.inc.php,v 1.1 2006/07/21 15:29:46 elixir_inter Exp $
  33. * @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson
  34. * @license http://www.gnu.org/copyleft/lesser.html#SEC3 LGPL License
  35. */
  36. /*
  37. ----------------------------------------------------------------------------
  38. | Online documentation for this class is available on the xajax wiki at: |
  39. | http://wiki.xajaxproject.org/Documentation:xajaxResponse.inc.php |
  40. ----------------------------------------------------------------------------
  41. */
  42. /**
  43. * The xajaxResponse class is used to create responses to be sent back to your
  44. * Web page. A response contains one or more command messages for updating
  45. * your page.
  46. * Currently xajax supports 21 kinds of command messages, including some common
  47. * ones such as:
  48. * <ul>
  49. * <li>Assign - sets the specified attribute of an element in your page</li>
  50. * <li>Append - appends data to the end of the specified attribute of an
  51. * element in your page</li>
  52. * <li>Prepend - prepends data to the beginning of the specified attribute of
  53. * an element in your page</li>
  54. * <li>Replace - searches for and replaces data in the specified attribute of
  55. * an element in your page</li>
  56. * <li>Script - runs the supplied JavaScript code</li>
  57. * <li>Alert - shows an alert box with the supplied message text</li>
  58. * </ul>
  59. *
  60. * <i>Note:</i> elements are identified by their HTML id, so if you don't see
  61. * your browser HTML display changing from the request, make sure you're using
  62. * the right id names in your response.
  63. *
  64. * @package xajax
  65. */
  66. class xajaxResponse
  67. {
  68. /**#@+
  69. * @access protected
  70. */
  71. /**
  72. * @var string internal XML storage
  73. */
  74. var $xml;
  75. /**
  76. * @var string the encoding type to use
  77. */
  78. var $sEncoding;
  79. /**
  80. * @var boolean if special characters in the XML should be converted to
  81. * entities
  82. */
  83. var $bOutputEntities;
  84. /**#@-*/
  85. /**
  86. * The constructor's main job is to set the character encoding for the
  87. * response.
  88. *
  89. * <i>Note:</i> to change the character encoding for all of the
  90. * responses, set the XAJAX_DEFAULT_ENCODING constant before you
  91. * instantiate xajax.
  92. *
  93. * @param string contains the character encoding string to use
  94. * @param boolean lets you set if you want special characters in the output
  95. * converted to HTML entities
  96. *
  97. */
  98. function xajaxResponse($sEncoding=XAJAX_DEFAULT_CHAR_ENCODING, $bOutputEntities=false)
  99. {
  100. $this->setCharEncoding($sEncoding);
  101. $this->bOutputEntities = $bOutputEntities;
  102. }
  103. /**
  104. * Sets the character encoding for the response based on $sEncoding, which
  105. * is a string containing the character encoding to use. You don't need to
  106. * use this method normally, since the character encoding for the response
  107. * gets set automatically based on the XAJAX_DEFAULT_CHAR_ENCODING
  108. * constant.
  109. *
  110. * @param string
  111. */
  112. function setCharEncoding($sEncoding)
  113. {
  114. $this->sEncoding = $sEncoding;
  115. }
  116. /**
  117. * Tells the response object to convert special characters to HTML entities
  118. * automatically (only works if the mb_string extension is available).
  119. */
  120. function outputEntitiesOn()
  121. {
  122. $this->bOutputEntities = true;
  123. }
  124. /**
  125. * Tells the response object to output special characters intact. (default
  126. * behavior)
  127. */
  128. function outputEntitiesOff()
  129. {
  130. $this->bOutputEntities = false;
  131. }
  132. /**
  133. * Adds a confirm commands command message to the XML response.
  134. *
  135. * <i>Usage:</i> <kbd>$objResponse->addConfirmCommands(1, "Do you want to preview the new data?");</kbd>
  136. *
  137. * @param integer the number of commands to skip if the user presses
  138. * Cancel in the browsers's confirm dialog
  139. * @param string the message to show in the browser's confirm dialog
  140. */
  141. function addConfirmCommands($iCmdNumber, $sMessage)
  142. {
  143. $this->xml .= $this->_cmdXML(array("n"=>"cc","t"=>$iCmdNumber),$sMessage);
  144. }
  145. /**
  146. * Adds an assign command message to the XML response.
  147. *
  148. * <i>Usage:</i> <kbd>$objResponse->addAssign("contentDiv", "innerHTML", "Some Text");</kbd>
  149. *
  150. * @param string contains the id of an HTML element
  151. * @param string the part of the element you wish to modify ("innerHTML",
  152. * "value", etc.)
  153. * @param string the data you want to set the attribute to
  154. */
  155. function addAssign($sTarget,$sAttribute,$sData)
  156. {
  157. $this->xml .= $this->_cmdXML(array("n"=>"as","t"=>$sTarget,"p"=>$sAttribute),$sData);
  158. }
  159. /**
  160. * Adds an append command message to the XML response.
  161. *
  162. * <i>Usage:</i> <kbd>$objResponse->addAppend("contentDiv", "innerHTML", "Some New Text");</kbd>
  163. *
  164. * @param string contains the id of an HTML element
  165. * @param string the part of the element you wish to modify ("innerHTML",
  166. * "value", etc.)
  167. * @param string the data you want to append to the end of the attribute
  168. */
  169. function addAppend($sTarget,$sAttribute,$sData)
  170. {
  171. $this->xml .= $this->_cmdXML(array("n"=>"ap","t"=>$sTarget,"p"=>$sAttribute),$sData);
  172. }
  173. /**
  174. * Adds an prepend command message to the XML response.
  175. *
  176. * <i>Usage:</i> <kbd>$objResponse->addPrepend("contentDiv", "innerHTML", "Some Starting Text");</kbd>
  177. *
  178. * @param string contains the id of an HTML element
  179. * @param string the part of the element you wish to modify ("innerHTML",
  180. * "value", etc.)
  181. * @param string the data you want to prepend to the beginning of the
  182. * attribute
  183. */
  184. function addPrepend($sTarget,$sAttribute,$sData)
  185. {
  186. $this->xml .= $this->_cmdXML(array("n"=>"pp","t"=>$sTarget,"p"=>$sAttribute),$sData);
  187. }
  188. /**
  189. * Adds a replace command message to the XML response.
  190. *
  191. * <i>Usage:</i> <kbd>$objResponse->addReplace("contentDiv", "innerHTML", "text", "<b>text</b>");</kbd>
  192. *
  193. * @param string contains the id of an HTML element
  194. * @param string the part of the element you wish to modify ("innerHTML",
  195. * "value", etc.)
  196. * @param string the string to search for
  197. * @param string the string to replace the search string when found in the
  198. * attribute
  199. */
  200. function addReplace($sTarget,$sAttribute,$sSearch,$sData)
  201. {
  202. $sDta = "<s><![CDATA[$sSearch]]></s><r><![CDATA[$sData]]></r>";
  203. $this->xml .= $this->_cmdXML(array("n"=>"rp","t"=>$sTarget,"p"=>$sAttribute),$sDta);
  204. }
  205. /**
  206. * Adds a clear command message to the XML response.
  207. *
  208. * <i>Usage:</i> <kbd>$objResponse->addClear("contentDiv", "innerHTML");</kbd>
  209. *
  210. * @param string contains the id of an HTML element
  211. * @param string the part of the element you wish to clear ("innerHTML",
  212. * "value", etc.)
  213. */
  214. function addClear($sTarget,$sAttribute)
  215. {
  216. $this->addAssign($sTarget,$sAttribute,'');
  217. }
  218. /**
  219. * Adds an alert command message to the XML response.
  220. *
  221. * <i>Usage:</i> <kbd>$objResponse->addAlert("This is important information");</kbd>
  222. *
  223. * @param string the text to be displayed in the Javascript alert box
  224. */
  225. function addAlert($sMsg)
  226. {
  227. $this->xml .= $this->_cmdXML(array("n"=>"al"),$sMsg);
  228. }
  229. /**
  230. * Uses the addScript() method to add a Javascript redirect to another URL.
  231. *
  232. * <i>Usage:</i> <kbd>$objResponse->addRedirect("http://www.xajaxproject.org");</kbd>
  233. *
  234. * @param string the URL to redirect the client browser to
  235. */
  236. function addRedirect($sURL)
  237. {
  238. //we need to parse the query part so that the values are rawurlencode()'ed
  239. //can't just use parse_url() cos we could be dealing with a relative URL which
  240. // parse_url() can't deal with.
  241. $queryStart = strpos($sURL, '?', strrpos($sURL, '/'));
  242. if ($queryStart !== FALSE)
  243. {
  244. $queryStart++;
  245. $queryEnd = strpos($sURL, '#', $queryStart);
  246. if ($queryEnd === FALSE)
  247. $queryEnd = strlen($sURL);
  248. $queryPart = substr($sURL, $queryStart, $queryEnd-$queryStart);
  249. parse_str($queryPart, $queryParts);
  250. $newQueryPart = "";
  251. foreach($queryParts as $key => $value)
  252. {
  253. $newQueryPart .= rawurlencode($key).'='.rawurlencode($value).ini_get('arg_separator.output');
  254. }
  255. $sURL = str_replace($queryPart, $newQueryPart, $sURL);
  256. }
  257. $this->addScript('window.location = "'.$sURL.'";');
  258. }
  259. /**
  260. * Adds a Javascript command message to the XML response.
  261. *
  262. * <i>Usage:</i> <kbd>$objResponse->addScript("var x = prompt('get some text');");</kbd>
  263. *
  264. * @param string contains Javascript code to be executed
  265. */
  266. function addScript($sJS)
  267. {
  268. $this->xml .= $this->_cmdXML(array("n"=>"js"),$sJS);
  269. }
  270. /**
  271. * Adds a Javascript function call command message to the XML response.
  272. *
  273. * <i>Usage:</i> <kbd>$objResponse->addScriptCall("myJSFunction", "arg 1", "arg 2", 12345);</kbd>
  274. *
  275. * @param string $sFunc the name of a Javascript function
  276. * @param mixed $args,... optional arguments to pass to the Javascript function
  277. */
  278. function addScriptCall() {
  279. $arguments = func_get_args();
  280. $sFunc = array_shift($arguments);
  281. $sData = $this->_buildObjXml($arguments);
  282. $this->xml .= $this->_cmdXML(array("n"=>"jc","t"=>$sFunc),$sData);
  283. }
  284. /**
  285. * Adds a remove element command message to the XML response.
  286. *
  287. * <i>Usage:</i> <kbd>$objResponse->addRemove("Div2");</kbd>
  288. *
  289. * @param string contains the id of an HTML element to be removed
  290. */
  291. function addRemove($sTarget)
  292. {
  293. $this->xml .= $this->_cmdXML(array("n"=>"rm","t"=>$sTarget),'');
  294. }
  295. /**
  296. * Adds a create element command message to the XML response.
  297. *
  298. * <i>Usage:</i> <kbd>$objResponse->addCreate("parentDiv", "h3", "myid");</kbd>
  299. *
  300. * @param string contains the id of an HTML element to to which the new
  301. * element will be appended.
  302. * @param string the tag to be added
  303. * @param string the id to be assigned to the new element
  304. * @param string deprecated, use the addCreateInput() method instead
  305. */
  306. function addCreate($sParent, $sTag, $sId, $sType="")
  307. {
  308. if ($sType)
  309. {
  310. trigger_error("The \$sType parameter of addCreate has been deprecated. Use the addCreateInput() method instead.", E_USER_WARNING);
  311. return;
  312. }
  313. $this->xml .= $this->_cmdXML(array("n"=>"ce","t"=>$sParent,"p"=>$sId),$sTag);
  314. }
  315. /**
  316. * Adds a insert element command message to the XML response.
  317. *
  318. * <i>Usage:</i> <kbd>$objResponse->addInsert("childDiv", "h3", "myid");</kbd>
  319. *
  320. * @param string contains the id of the child before which the new element
  321. * will be inserted
  322. * @param string the tag to be added
  323. * @param string the id to be assigned to the new element
  324. */
  325. function addInsert($sBefore, $sTag, $sId)
  326. {
  327. $this->xml .= $this->_cmdXML(array("n"=>"ie","t"=>$sBefore,"p"=>$sId),$sTag);
  328. }
  329. /**
  330. * Adds a insert element command message to the XML response.
  331. *
  332. * <i>Usage:</i> <kbd>$objResponse->addInsertAfter("childDiv", "h3", "myid");</kbd>
  333. *
  334. * @param string contains the id of the child after which the new element
  335. * will be inserted
  336. * @param string the tag to be added
  337. * @param string the id to be assigned to the new element
  338. */
  339. function addInsertAfter($sAfter, $sTag, $sId)
  340. {
  341. $this->xml .= $this->_cmdXML(array("n"=>"ia","t"=>$sAfter,"p"=>$sId),$sTag);
  342. }
  343. /**
  344. * Adds a create input command message to the XML response.
  345. *
  346. * <i>Usage:</i> <kbd>$objResponse->addCreateInput("form1", "text", "username", "input1");</kbd>
  347. *
  348. * @param string contains the id of an HTML element to which the new input
  349. * will be appended
  350. * @param string the type of input to be created (text, radio, checkbox,
  351. * etc.)
  352. * @param string the name to be assigned to the new input and the variable
  353. * name when it is submitted
  354. * @param string the id to be assigned to the new input
  355. */
  356. function addCreateInput($sParent, $sType, $sName, $sId)
  357. {
  358. $this->xml .= $this->_cmdXML(array("n"=>"ci","t"=>$sParent,"p"=>$sId,"c"=>$sType),$sName);
  359. }
  360. /**
  361. * Adds an insert input command message to the XML response.
  362. *
  363. * <i>Usage:</i> <kbd>$objResponse->addInsertInput("input5", "text", "username", "input1");</kbd>
  364. *
  365. * @param string contains the id of the child before which the new element
  366. * will be inserted
  367. * @param string the type of input to be created (text, radio, checkbox,
  368. * etc.)
  369. * @param string the name to be assigned to the new input and the variable
  370. * name when it is submitted
  371. * @param string the id to be assigned to the new input
  372. */
  373. function addInsertInput($sBefore, $sType, $sName, $sId)
  374. {
  375. $this->xml .= $this->_cmdXML(array("n"=>"ii","t"=>$sBefore,"p"=>$sId,"c"=>$sType),$sName);
  376. }
  377. /**
  378. * Adds an insert input command message to the XML response.
  379. *
  380. * <i>Usage:</i> <kbd>$objResponse->addInsertInputAfter("input7", "text", "email", "input2");</kbd>
  381. *
  382. * @param string contains the id of the child after which the new element
  383. * will be inserted
  384. * @param string the type of input to be created (text, radio, checkbox,
  385. * etc.)
  386. * @param string the name to be assigned to the new input and the variable
  387. * name when it is submitted
  388. * @param string the id to be assigned to the new input
  389. */
  390. function addInsertInputAfter($sAfter, $sType, $sName, $sId)
  391. {
  392. $this->xml .= $this->_cmdXML(array("n"=>"iia","t"=>$sAfter,"p"=>$sId,"c"=>$sType),$sName);
  393. }
  394. /**
  395. * Adds an event command message to the XML response.
  396. *
  397. * <i>Usage:</i> <kbd>$objResponse->addEvent("contentDiv", "onclick", "alert(\'Hello World\');");</kbd>
  398. *
  399. * @param string contains the id of an HTML element
  400. * @param string the event you wish to set ("onclick", "onmouseover", etc.)
  401. * @param string the Javascript string you want the event to invoke
  402. */
  403. function addEvent($sTarget,$sEvent,$sScript)
  404. {
  405. $this->xml .= $this->_cmdXML(array("n"=>"ev","t"=>$sTarget,"p"=>$sEvent),$sScript);
  406. }
  407. /**
  408. * Adds a handler command message to the XML response.
  409. *
  410. * <i>Usage:</i> <kbd>$objResponse->addHandler("contentDiv", "onclick", "content_click");</kbd>
  411. *
  412. * @param string contains the id of an HTML element
  413. * @param string the event you wish to set ("onclick", "onmouseover", etc.)
  414. * @param string the name of a Javascript function that will handle the
  415. * event. Multiple handlers can be added for the same event
  416. */
  417. function addHandler($sTarget,$sEvent,$sHandler)
  418. {
  419. $this->xml .= $this->_cmdXML(array("n"=>"ah","t"=>$sTarget,"p"=>$sEvent),$sHandler);
  420. }
  421. /**
  422. * Adds a remove handler command message to the XML response.
  423. *
  424. * <i>Usage:</i> <kbd>$objResponse->addRemoveHandler("contentDiv", "onclick", "content_click");</kbd>
  425. *
  426. * @param string contains the id of an HTML element
  427. * @param string the event you wish to remove ("onclick", "onmouseover",
  428. * etc.)
  429. * @param string the name of a Javascript handler function that you want to
  430. * remove
  431. */
  432. function addRemoveHandler($sTarget,$sEvent,$sHandler)
  433. {
  434. $this->xml .= $this->_cmdXML(array("n"=>"rh","t"=>$sTarget,"p"=>$sEvent),$sHandler);
  435. }
  436. /**
  437. * Adds an include script command message to the XML response.
  438. *
  439. * <i>Usage:</i> <kbd>$objResponse->addIncludeScript("functions.js");</kbd>
  440. *
  441. * @param string URL of the Javascript file to include
  442. */
  443. function addIncludeScript($sFileName)
  444. {
  445. $this->xml .= $this->_cmdXML(array("n"=>"in"),$sFileName);
  446. }
  447. /**
  448. * Returns the XML to be returned from your function to the xajax processor
  449. * on your page. Since xajax 0.2, you can also return an xajaxResponse
  450. * object from your function directly, and xajax will automatically request
  451. * the XML using this method call.
  452. *
  453. * <i>Usage:</i> <kbd>return $objResponse->getXML();</kbd>
  454. *
  455. * @return string response XML data
  456. */
  457. function getXML()
  458. {
  459. $sXML = "<?xml version=\"1.0\"";
  460. if ($this->sEncoding && strlen(trim($this->sEncoding)) > 0)
  461. $sXML .= " encoding=\"".$this->sEncoding."\"";
  462. $sXML .= " ?"."><xjx>" . $this->xml . "</xjx>";
  463. return $sXML;
  464. }
  465. /**
  466. * Adds the commands of the provided response XML output to this response
  467. * object
  468. *
  469. * <i>Usage:</i>
  470. * <code>$r1 = $objResponse1->getXML();
  471. * $objResponse2->loadXML($r1);
  472. * return $objResponse2->getXML();</code>
  473. *
  474. * @param string the response XML (returned from a getXML() method) to add
  475. * to the end of this response object
  476. */
  477. function loadXML($mXML)
  478. {
  479. if (is_a($mXML, "xajaxResponse")) {
  480. $mXML = $mXML->getXML();
  481. }
  482. $sNewXML = "";
  483. $iStartPos = strpos($mXML, "<xjx>") + 5;
  484. $sNewXML = substr($mXML, $iStartPos);
  485. $iEndPos = strpos($sNewXML, "</xjx>");
  486. $sNewXML = substr($sNewXML, 0, $iEndPos);
  487. $this->xml .= $sNewXML;
  488. }
  489. /**
  490. * Generates XML from command data
  491. *
  492. * @access private
  493. * @param array associative array of attributes
  494. * @param string data
  495. * @return string XML command
  496. */
  497. function _cmdXML($aAttributes, $sData)
  498. {
  499. if ($this->bOutputEntities) {
  500. // An adaptation for the Dokeos LMS, 22-AUG-2009.
  501. if (function_exists('api_convert_encoding')) {
  502. $sData = call_user_func_array('api_convert_encoding', array(&$sData, 'HTML-ENTITIES', $this->sEncoding));
  503. }
  504. //if (function_exists('mb_convert_encoding')) {
  505. elseif (function_exists('mb_convert_encoding')) {
  506. //
  507. $sData = call_user_func_array('mb_convert_encoding', array(&$sData, 'HTML-ENTITIES', $this->sEncoding));
  508. }
  509. else {
  510. trigger_error("The xajax XML response output could not be converted to HTML entities because the mb_convert_encoding function is not available", E_USER_NOTICE);
  511. }
  512. }
  513. $xml = "<cmd";
  514. foreach($aAttributes as $sAttribute => $sValue)
  515. $xml .= " $sAttribute=\"$sValue\"";
  516. if ($sData !== null && !stristr($sData,'<![CDATA['))
  517. $xml .= "><![CDATA[$sData]]></cmd>";
  518. else if ($sData !== null)
  519. $xml .= ">$sData</cmd>";
  520. else
  521. $xml .= "></cmd>";
  522. return $xml;
  523. }
  524. /**
  525. * Recursively serializes a data structure in XML so it can be sent to
  526. * the client. It could be thought of as the opposite of
  527. * {@link xajax::_parseObjXml()}.
  528. *
  529. * @access private
  530. * @param mixed data structure to serialize to XML
  531. * @return string serialized XML
  532. */
  533. function _buildObjXml($var) {
  534. if (gettype($var) == "object") $var = get_object_vars($var);
  535. if (!is_array($var)) {
  536. return "<![CDATA[$var]]>";
  537. }
  538. else {
  539. $data = "<xjxobj>";
  540. foreach ($var as $key => $value) {
  541. $data .= "<e>";
  542. $data .= "<k>" . htmlspecialchars($key) . "</k>";
  543. $data .= "<v>" . $this->_buildObjXml($value) . "</v>";
  544. $data .= "</e>";
  545. }
  546. $data .= "</xjxobj>";
  547. return $data;
  548. }
  549. }
  550. }// end class xajaxResponse
  551. ?>