PageRenderTime 28ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/core/Ajax/AjaxResponse.class.php

https://bitbucket.org/multimedium/bob361
PHP | 495 lines | 149 code | 40 blank | 306 comment | 14 complexity | 450d04891f830bb43f519cedea23918b MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /**
  3. * M_AjaxResponse
  4. *
  5. * @package Core
  6. */
  7. class M_AjaxResponse extends M_Object {
  8. /* -- CONSTANTS -- */
  9. /**
  10. * Response Format: XML
  11. *
  12. * This constant can be used to describe the format in which the AJAX response
  13. * needs to be outputted. With this particular constant, you describe the
  14. * format XML.
  15. *
  16. * @access public
  17. * @var string
  18. */
  19. const FORMAT_XML = 'xml';
  20. /**
  21. * Response Format: JSON
  22. *
  23. * This constant can be used to describe the format in which the AJAX response
  24. * needs to be outputted. With this particular constant, you describe the
  25. * format JSON.
  26. *
  27. * @access public
  28. * @var string
  29. */
  30. const FORMAT_JSON = 'json';
  31. /* -- PROPERTIES -- */
  32. /**
  33. * Outcome flag
  34. *
  35. * This property stores a boolean that describes the outcome of the AJAX
  36. * request: TRUE if the response needs to describe success, FALSE if failure
  37. * is the answer to the request.
  38. *
  39. * @see M_AjaxResponse::setOutcomeFlag()
  40. * @access private
  41. * @var bool
  42. */
  43. private $_outcome;
  44. /**
  45. * Error Message
  46. *
  47. * This property stores a string, containing the error message to be included
  48. * in the response. Typically, this error message is set only if the outcome
  49. * is set to FALSE.
  50. *
  51. * @see M_AjaxResponse::setOutcomeFlag()
  52. * @see M_AjaxResponse::setErrorMessage()
  53. * @access private
  54. * @var string
  55. */
  56. private $_errorMessage;
  57. /**
  58. * Error Code
  59. *
  60. * This property stores a string, containing the error code to be included
  61. * in the response. Typically, this error code is set only if the outcome
  62. * is set to FALSE.
  63. *
  64. * @see M_AjaxResponse::setOutcomeFlag()
  65. * @see M_AjaxResponse::setErrorCode()
  66. * @access private
  67. * @var string
  68. */
  69. private $_errorCode;
  70. /**
  71. * Format
  72. *
  73. * This property stores an integer that describes the format in which the
  74. * AJAX response needs to be outputted.
  75. *
  76. * @see M_AjaxResponse::setOutputFormat()
  77. * @access private
  78. * @var bool
  79. */
  80. private $_format;
  81. /* -- SETTERS -- */
  82. /**
  83. * Set outcome flag
  84. *
  85. * This method allows to describe the outcome of the AJAX request. If you
  86. * want to use this view to describe a successful outcome of the AJAX response,
  87. * then you should provide (boolean) TRUE to this method. If a failure needs
  88. * to be outputted, you should provide (boolean) FALSE instead.
  89. *
  90. * @access public
  91. * @param bool $flag
  92. * @return M_AjaxResponse $response
  93. * Returns itself, for a fluent programming interface
  94. */
  95. public function setOutcomeFlag($flag) {
  96. $this->_outcome = (bool) $flag;
  97. return $this;
  98. }
  99. /**
  100. * Error Message
  101. *
  102. * This method allows to set a string, representing the error message to be
  103. * included in the AJAX response. Typically, this error message is set only
  104. * if the outcome is set to FALSE.
  105. *
  106. * @see M_AjaxResponse::setOutcomeFlag()
  107. * @access public
  108. * @param string $message
  109. * @return M_AjaxResponse $response
  110. * Returns itself, for a fluent programming interface
  111. */
  112. public function setErrorMessage($message) {
  113. $this->_errorMessage = $message ? (string) $message : NULL;
  114. return $this;
  115. }
  116. /**
  117. * Error Code
  118. *
  119. * This method allows to set a string, representing the error code to be
  120. * included in the AJAX response. Typically, this error code is set only
  121. * if the outcome is set to FALSE.
  122. *
  123. * @see M_AjaxResponse::setOutcomeFlag()
  124. * @access public
  125. * @param string $code
  126. * @return M_AjaxResponse $response
  127. * Returns itself, for a fluent programming interface
  128. */
  129. public function setErrorCode($code) {
  130. $this->_errorCode = $code ? (string) $code : NULL;
  131. return $this;
  132. }
  133. /**
  134. * Set format
  135. *
  136. * This class is used to send a response to an AJAX request. Typically, these
  137. * responses are formatted in either XML or JSON. With this method, you can
  138. * specify the format in which to output the AJAX response.
  139. *
  140. * @see M_AjaxResponse::FORMAT_XML
  141. * @see M_AjaxResponse::FORMAT_JSON
  142. * @access public
  143. * @param integer $format
  144. * @return M_AjaxResponse $response
  145. * Returns itself, for a fluent programming interface
  146. */
  147. public function setFormat($format) {
  148. // Cast to lowercase string:
  149. $format = strtolower((string) $format);
  150. // Make sure the provided format is recognized:
  151. if(! in_array($format, array(self::FORMAT_JSON, self::FORMAT_XML))) {
  152. // If not, we throw an exception:
  153. throw new M_AjaxException(sprintf(
  154. 'Cannot set format of AJAX Response to "%s"; Unrecognized format. ' .
  155. 'The format should be either "%s" or "%s"',
  156. $format,
  157. self::FORMAT_JSON,
  158. self::FORMAT_XML
  159. ));
  160. }
  161. // Set the format:
  162. $this->_format = $format;
  163. // Return myself:
  164. return $this;
  165. }
  166. /* -- GETTERS -- */
  167. /**
  168. * Get outcome flag
  169. *
  170. * @see M_AjaxResponse::setOutcomeFlag()
  171. * @access public
  172. * @return bool
  173. */
  174. public function getOutcomeFlag() {
  175. return $this->_outcome;
  176. }
  177. /**
  178. * Get error message
  179. *
  180. * @see M_AjaxResponse::setErrorMessage()
  181. * @access public
  182. * @return string
  183. */
  184. public function getErrorMessage() {
  185. return $this->_errorMessage;
  186. }
  187. /**
  188. * Get error code
  189. *
  190. * @see M_AjaxResponse::setErrorCode()
  191. * @access public
  192. * @return string
  193. */
  194. public function getErrorCode() {
  195. return $this->_errorCode;
  196. }
  197. /**
  198. * Get format
  199. *
  200. * This method will return the format in which the AJAX Response is being
  201. * rendered. This format can be set with {@link M_AjaxResponse::setFormat()}.
  202. *
  203. * If no format has been defined earlier, this method will try to look up
  204. * the desired format by looking at the page request variable with name
  205. * "format". The value of this variable must be either "xml" or "json".
  206. *
  207. * If still no format can be determined with the page request variable, then
  208. * this method will default the format to "json".
  209. *
  210. * @access public
  211. * @return integer
  212. */
  213. public function getFormat() {
  214. // If no format has been set
  215. if(! $this->_format) {
  216. // Then, we define it now, by checking whether or not a request
  217. // variable has been provided to set the format. Note that we default
  218. // to JSON:
  219. $this->setFormat(M_Request::getVariable('format', self::FORMAT_JSON, M_Request::TYPE_STRING_SANITIZED, M_Request::GET));
  220. }
  221. // Return the view mode:
  222. return $this->_format;
  223. }
  224. /**
  225. * Is format XML?
  226. *
  227. * @access public
  228. * @return bool $flag
  229. * Returns TRUE if the format of the response is XML, FALSE if not
  230. */
  231. public function isFormatXml() {
  232. return ($this->getFormat() == self::FORMAT_XML);
  233. }
  234. /**
  235. * Is format JSON?
  236. *
  237. * @access public
  238. * @return bool $flag
  239. * Returns TRUE if the format of the response is JSON, FALSE if not
  240. */
  241. public function isFormatJson() {
  242. return ($this->getFormat() == self::FORMAT_JSON);
  243. }
  244. /**
  245. * Send...
  246. *
  247. * This method will send the AJAX response back to the client that initiated
  248. * the request.
  249. *
  250. * @access public
  251. * @uses M_View::_render()
  252. * @see M_View::fetch()
  253. * @return void
  254. */
  255. public function send() {
  256. // If the response is JSON
  257. if($this->isFormatJson()) {
  258. // Output the encoded string:
  259. echo $this->fetch();
  260. }
  261. // If the response is XML
  262. elseif($this->isFormatXml()) {
  263. // Then, first, we send the XML headers:
  264. M_Header::send(M_Header::CONTENT_TYPE_XML);
  265. // And, finally, we send the XML string:
  266. echo $this->fetch();
  267. }
  268. // If the response format is not known:
  269. else {
  270. // Then, we throw an exception to inform about the error:
  271. throw new M_AjaxException(sprintf(
  272. 'Cannot send AJAX Response. The output format has not been ' .
  273. 'specified!'
  274. ));
  275. }
  276. }
  277. /**
  278. * Render the output
  279. *
  280. * This method will render the contents of the AJAX Response. Typically, this
  281. * method will be overwritten by subclasses, in order to include the specifics
  282. * of the response.
  283. *
  284. * @uses M_AjaxResponse::_getFromArray()
  285. * @access public
  286. * @return string
  287. */
  288. public function fetch() {
  289. // Parse an array with the parameters in the view:
  290. return $this->_getFromArray(array(
  291. 'outcome' => $this->getOutcomeFlag(),
  292. 'errorMessage' => $this->getErrorMessage(),
  293. 'errorCode' => $this->getErrorCode()
  294. ));
  295. }
  296. /* -- PRIVATE/PROTECTED -- */
  297. /**
  298. * Get JSON string from associative array
  299. *
  300. * This method will render the output string that serves as the AJAX response.
  301. * The result of this method will depend on the format that has been specified
  302. * for the AJAX response.
  303. *
  304. * @access protected
  305. * @param array $array
  306. * @return string
  307. */
  308. protected function _getFromArray(array $array) {
  309. // If the response is JSON:
  310. if($this->isFormatJson()) {
  311. // Then, we output the array as JSON:
  312. return $this->_getJsonFromArray($array);
  313. }
  314. // If the response is XML
  315. elseif($this->isFormatXml()) {
  316. // Then, we output the array as XML
  317. $out = '<?xml version="1.0" encoding="UTF-8"?>';
  318. $out .= '<response>';
  319. $out .= $this->_getXmlFromArray($array);
  320. $out .= '</response>';
  321. return $out;
  322. }
  323. // If the response format is not known:
  324. else {
  325. // Then, we throw an exception to inform about the error:
  326. throw new M_AjaxException(sprintf(
  327. 'Cannot output AJAX Response Values (Array). The output ' .
  328. 'format has not been specified!'
  329. ));
  330. }
  331. }
  332. /**
  333. * Get JSON string from associative array
  334. *
  335. * This method will render the output string that serves as the AJAX response.
  336. * The result of this method will be in JSON format.
  337. *
  338. * @access protected
  339. * @param array $array
  340. * @return string
  341. */
  342. protected function _getJsonFromArray(array $array) {
  343. return M_Helper::jsonEncode($array);
  344. }
  345. /**
  346. * Get XML string from associative array
  347. *
  348. * This method will render the output string that serves as the AJAX response.
  349. * The result of this method will be in XML format.
  350. *
  351. * @access protected
  352. * @param array $array
  353. * @return M_XmlElement
  354. */
  355. protected function _getXmlFromArray(array $array) {
  356. // The output string
  357. $out = '';
  358. // For each of the elements in the array:
  359. foreach($array as $name => $value) {
  360. // We add a node to the XML output string:
  361. $out .= '<' . $name;
  362. // If a value is not available:
  363. if(! $value) {
  364. // Then, we create a self-closing tag:
  365. $out .= ' />';
  366. }
  367. // If a value is available:
  368. else {
  369. // Then, we close the opening tag:
  370. $out .= '>';
  371. // We add the value to the output string:
  372. $out .= $this->_getXmlValue($value);
  373. // And we close the tag:
  374. $out .= '</' . $name . '>';
  375. }
  376. }
  377. // Return the XML Output String
  378. return $out;
  379. }
  380. /**
  381. * Get XML value
  382. *
  383. * This method will convert the provided value into a string that may be
  384. * used as a value of an XML tag.
  385. *
  386. * @access protected
  387. * @param mixed $value
  388. * @return string
  389. */
  390. protected function _getXmlValue($value) {
  391. // If the provided value is numeric:
  392. if(is_numeric($value)) {
  393. // Then, we return the value unaffected:
  394. return $value;
  395. }
  396. // If the provided value is a string:
  397. elseif(is_string($value)) {
  398. // Then, first, we check if the value contains characters that need
  399. // to be wrapped by a CDATA block:
  400. if(M_Helper::containsCharactersForXmlCdata($value)) {
  401. // If so, we wrap the value and return:
  402. return '<![CDATA[' . $value . ']]>';
  403. }
  404. // If not to be wrapped:
  405. else {
  406. // Then, return the value as-is:
  407. return $value;
  408. }
  409. }
  410. // If the provided value is an array
  411. elseif(is_array($value)) {
  412. // Then, we convert the array to XML
  413. return $this->_getXmlFromArray($value);
  414. }
  415. // If the provided value is NULL
  416. elseif(is_null($value)) {
  417. // Then, we return an empty value:
  418. return '';
  419. }
  420. // If the provided value is a boolean flag:
  421. elseif(is_bool($value)) {
  422. // Then, we return either 0 or 1
  423. return ($value ? 1 : 0);
  424. }
  425. // Any other value cannot be translated into XML for now:
  426. else {
  427. // We throw an exception if we cannot translate the value:
  428. throw new M_AjaxException(sprintf(
  429. 'Cannot output AJAX Response Value to XML: %s',
  430. var_export($value, TRUE)
  431. ));
  432. }
  433. }
  434. /**
  435. * Get HTML Output from view
  436. *
  437. * This method will accept a view as argument, and will render the HTML source
  438. * code that is to be outputted as part of the AJAX response. Among others,
  439. * this method will remove new lines and tabs from the source code.
  440. *
  441. * @access protected
  442. * @param M_ViewHtml $view
  443. * @return string
  444. */
  445. protected function _getHtml(M_ViewHtml $view) {
  446. // Render the HTML:
  447. $html = $view->fetch();
  448. // Remove new lines and tabs
  449. $html = str_replace("\r", '', $html);
  450. $html = str_replace("\n", '', $html);
  451. $html = str_replace("\t", '', $html);
  452. // Return the HTML:
  453. return $html;
  454. }
  455. }