xajaxResponse.inc.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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 chamilo.include.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 chamilo.include.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. public function __construct($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. public 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. public 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. public 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. public 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. public 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. public 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. public 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. public 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. public 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. public 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. $queryStart++;
  244. $queryEnd = strpos($sURL, '#', $queryStart);
  245. if ($queryEnd === false) {
  246. $queryEnd = strlen($sURL);
  247. }
  248. $queryPart = substr($sURL, $queryStart, $queryEnd - $queryStart);
  249. $queryParts = array();
  250. parse_str($queryPart, $queryParts);
  251. $newQueryPart = "";
  252. foreach ($queryParts as $key => $value) {
  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. public 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. public function addScriptCall()
  279. {
  280. $arguments = func_get_args();
  281. $sFunc = array_shift($arguments);
  282. $sData = $this->_buildObjXml($arguments);
  283. $this->xml .= $this->_cmdXML(array("n" => "jc", "t" => $sFunc), $sData);
  284. }
  285. /**
  286. * Adds a remove element command message to the XML response.
  287. *
  288. * <i>Usage:</i> <kbd>$objResponse->addRemove("Div2");</kbd>
  289. *
  290. * @param string contains the id of an HTML element to be removed
  291. */
  292. public function addRemove($sTarget)
  293. {
  294. $this->xml .= $this->_cmdXML(array("n" => "rm", "t" => $sTarget), '');
  295. }
  296. /**
  297. * Adds a create element command message to the XML response.
  298. *
  299. * <i>Usage:</i> <kbd>$objResponse->addCreate("parentDiv", "h3", "myid");</kbd>
  300. *
  301. * @param string contains the id of an HTML element to to which the new
  302. * element will be appended.
  303. * @param string the tag to be added
  304. * @param string the id to be assigned to the new element
  305. * @param string deprecated, use the addCreateInput() method instead
  306. */
  307. public function addCreate($sParent, $sTag, $sId, $sType = "")
  308. {
  309. if ($sType) {
  310. trigger_error(
  311. "The \$sType parameter of addCreate has been deprecated. Use the addCreateInput() method instead.",
  312. E_USER_WARNING
  313. );
  314. return;
  315. }
  316. $this->xml .= $this->_cmdXML(array("n" => "ce", "t" => $sParent, "p" => $sId), $sTag);
  317. }
  318. /**
  319. * Adds a insert element command message to the XML response.
  320. *
  321. * <i>Usage:</i> <kbd>$objResponse->addInsert("childDiv", "h3", "myid");</kbd>
  322. *
  323. * @param string contains the id of the child before which the new element
  324. * will be inserted
  325. * @param string the tag to be added
  326. * @param string the id to be assigned to the new element
  327. */
  328. public function addInsert($sBefore, $sTag, $sId)
  329. {
  330. $this->xml .= $this->_cmdXML(array("n" => "ie", "t" => $sBefore, "p" => $sId), $sTag);
  331. }
  332. /**
  333. * Adds a insert element command message to the XML response.
  334. *
  335. * <i>Usage:</i> <kbd>$objResponse->addInsertAfter("childDiv", "h3", "myid");</kbd>
  336. *
  337. * @param string contains the id of the child after which the new element
  338. * will be inserted
  339. * @param string the tag to be added
  340. * @param string the id to be assigned to the new element
  341. */
  342. public function addInsertAfter($sAfter, $sTag, $sId)
  343. {
  344. $this->xml .= $this->_cmdXML(array("n" => "ia", "t" => $sAfter, "p" => $sId), $sTag);
  345. }
  346. /**
  347. * Adds a create input command message to the XML response.
  348. *
  349. * <i>Usage:</i> <kbd>$objResponse->addCreateInput("form1", "text", "username", "input1");</kbd>
  350. *
  351. * @param string contains the id of an HTML element to which the new input
  352. * will be appended
  353. * @param string the type of input to be created (text, radio, checkbox,
  354. * etc.)
  355. * @param string the name to be assigned to the new input and the variable
  356. * name when it is submitted
  357. * @param string the id to be assigned to the new input
  358. */
  359. public function addCreateInput($sParent, $sType, $sName, $sId)
  360. {
  361. $this->xml .= $this->_cmdXML(array("n" => "ci", "t" => $sParent, "p" => $sId, "c" => $sType), $sName);
  362. }
  363. /**
  364. * Adds an insert input command message to the XML response.
  365. *
  366. * <i>Usage:</i> <kbd>$objResponse->addInsertInput("input5", "text", "username", "input1");</kbd>
  367. *
  368. * @param string contains the id of the child before which the new element
  369. * will be inserted
  370. * @param string the type of input to be created (text, radio, checkbox,
  371. * etc.)
  372. * @param string the name to be assigned to the new input and the variable
  373. * name when it is submitted
  374. * @param string the id to be assigned to the new input
  375. */
  376. public function addInsertInput($sBefore, $sType, $sName, $sId)
  377. {
  378. $this->xml .= $this->_cmdXML(array("n" => "ii", "t" => $sBefore, "p" => $sId, "c" => $sType), $sName);
  379. }
  380. /**
  381. * Adds an insert input command message to the XML response.
  382. *
  383. * <i>Usage:</i> <kbd>$objResponse->addInsertInputAfter("input7", "text", "email", "input2");</kbd>
  384. *
  385. * @param string contains the id of the child after which the new element
  386. * will be inserted
  387. * @param string the type of input to be created (text, radio, checkbox,
  388. * etc.)
  389. * @param string the name to be assigned to the new input and the variable
  390. * name when it is submitted
  391. * @param string the id to be assigned to the new input
  392. */
  393. public function addInsertInputAfter($sAfter, $sType, $sName, $sId)
  394. {
  395. $this->xml .= $this->_cmdXML(array("n" => "iia", "t" => $sAfter, "p" => $sId, "c" => $sType), $sName);
  396. }
  397. /**
  398. * Adds an event command message to the XML response.
  399. *
  400. * <i>Usage:</i> <kbd>$objResponse->addEvent("contentDiv", "onclick", "alert(\'Hello World\');");</kbd>
  401. *
  402. * @param string contains the id of an HTML element
  403. * @param string the event you wish to set ("onclick", "onmouseover", etc.)
  404. * @param string the Javascript string you want the event to invoke
  405. */
  406. public function addEvent($sTarget, $sEvent, $sScript)
  407. {
  408. $this->xml .= $this->_cmdXML(array("n" => "ev", "t" => $sTarget, "p" => $sEvent), $sScript);
  409. }
  410. /**
  411. * Adds a handler command message to the XML response.
  412. *
  413. * <i>Usage:</i> <kbd>$objResponse->addHandler("contentDiv", "onclick", "content_click");</kbd>
  414. *
  415. * @param string contains the id of an HTML element
  416. * @param string the event you wish to set ("onclick", "onmouseover", etc.)
  417. * @param string the name of a Javascript function that will handle the
  418. * event. Multiple handlers can be added for the same event
  419. */
  420. public function addHandler($sTarget, $sEvent, $sHandler)
  421. {
  422. $this->xml .= $this->_cmdXML(array("n" => "ah", "t" => $sTarget, "p" => $sEvent), $sHandler);
  423. }
  424. /**
  425. * Adds a remove handler command message to the XML response.
  426. *
  427. * <i>Usage:</i> <kbd>$objResponse->addRemoveHandler("contentDiv", "onclick", "content_click");</kbd>
  428. *
  429. * @param string contains the id of an HTML element
  430. * @param string the event you wish to remove ("onclick", "onmouseover",
  431. * etc.)
  432. * @param string the name of a Javascript handler function that you want to
  433. * remove
  434. */
  435. public function addRemoveHandler($sTarget, $sEvent, $sHandler)
  436. {
  437. $this->xml .= $this->_cmdXML(array("n" => "rh", "t" => $sTarget, "p" => $sEvent), $sHandler);
  438. }
  439. /**
  440. * Adds an include script command message to the XML response.
  441. *
  442. * <i>Usage:</i> <kbd>$objResponse->addIncludeScript("functions.js");</kbd>
  443. *
  444. * @param string URL of the Javascript file to include
  445. */
  446. public function addIncludeScript($sFileName)
  447. {
  448. $this->xml .= $this->_cmdXML(array("n" => "in"), $sFileName);
  449. }
  450. /**
  451. * Returns the XML to be returned from your function to the xajax processor
  452. * on your page. Since xajax 0.2, you can also return an xajaxResponse
  453. * object from your function directly, and xajax will automatically request
  454. * the XML using this method call.
  455. *
  456. * <i>Usage:</i> <kbd>return $objResponse->getXML();</kbd>
  457. *
  458. * @return string response XML data
  459. */
  460. public function getXML()
  461. {
  462. $sXML = "<?xml version=\"1.0\"";
  463. if ($this->sEncoding && strlen(trim($this->sEncoding)) > 0) {
  464. $sXML .= " encoding=\"".$this->sEncoding."\"";
  465. }
  466. $sXML .= " ?"."><xjx>".$this->xml."</xjx>";
  467. return $sXML;
  468. }
  469. /**
  470. * Adds the commands of the provided response XML output to this response
  471. * object
  472. *
  473. * <i>Usage:</i>
  474. * <code>$r1 = $objResponse1->getXML();
  475. * $objResponse2->loadXML($r1);
  476. * return $objResponse2->getXML();</code>
  477. *
  478. * @param string the response XML (returned from a getXML() method) to add
  479. * to the end of this response object
  480. */
  481. public function loadXML($mXML)
  482. {
  483. if (is_a($mXML, "xajaxResponse")) {
  484. $mXML = $mXML->getXML();
  485. }
  486. $sNewXML = "";
  487. $iStartPos = strpos($mXML, "<xjx>") + 5;
  488. $sNewXML = substr($mXML, $iStartPos);
  489. $iEndPos = strpos($sNewXML, "</xjx>");
  490. $sNewXML = substr($sNewXML, 0, $iEndPos);
  491. $this->xml .= $sNewXML;
  492. }
  493. /**
  494. * Generates XML from command data
  495. *
  496. * @access private
  497. * @param array associative array of attributes
  498. * @param string data
  499. * @return string XML command
  500. */
  501. public function _cmdXML($aAttributes, $sData)
  502. {
  503. if ($this->bOutputEntities) {
  504. // An adaptation for the Dokeos LMS, 22-AUG-2009.
  505. if (function_exists('api_convert_encoding')) {
  506. $sData = call_user_func_array(
  507. 'api_convert_encoding',
  508. array(&$sData, 'HTML-ENTITIES', $this->sEncoding)
  509. );
  510. } //if (function_exists('mb_convert_encoding')) {
  511. elseif (function_exists('mb_convert_encoding')) {
  512. //
  513. $sData = call_user_func_array('mb_convert_encoding', array(&$sData, 'HTML-ENTITIES', $this->sEncoding));
  514. } else {
  515. trigger_error(
  516. "The xajax XML response output could not be converted to HTML entities because the mb_convert_encoding function is not available",
  517. E_USER_NOTICE
  518. );
  519. }
  520. }
  521. $xml = "<cmd";
  522. foreach ($aAttributes as $sAttribute => $sValue) {
  523. $xml .= " $sAttribute=\"$sValue\"";
  524. }
  525. if ($sData !== null && !stristr($sData, '<![CDATA[')) {
  526. $xml .= "><![CDATA[$sData]]></cmd>";
  527. } else {
  528. if ($sData !== null) {
  529. $xml .= ">$sData</cmd>";
  530. } else {
  531. $xml .= "></cmd>";
  532. }
  533. }
  534. return $xml;
  535. }
  536. /**
  537. * Recursively serializes a data structure in XML so it can be sent to
  538. * the client. It could be thought of as the opposite of
  539. * {@link xajax::_parseObjXml()}.
  540. *
  541. * @access private
  542. * @param mixed data structure to serialize to XML
  543. * @return string serialized XML
  544. */
  545. public function _buildObjXml($var)
  546. {
  547. if (gettype($var) == "object") {
  548. $var = get_object_vars($var);
  549. }
  550. if (!is_array($var)) {
  551. return "<![CDATA[$var]]>";
  552. } else {
  553. $data = "<xjxobj>";
  554. foreach ($var as $key => $value) {
  555. $data .= "<e>";
  556. $data .= "<k>".htmlspecialchars($key)."</k>";
  557. $data .= "<v>".$this->_buildObjXml($value)."</v>";
  558. $data .= "</e>";
  559. }
  560. $data .= "</xjxobj>";
  561. return $data;
  562. }
  563. }
  564. }