Response.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <?php
  2. namespace Qii\Base;
  3. class Response
  4. {
  5. /**
  6. * Default body name
  7. */
  8. const DEFAULT_BODY = 'html';
  9. const FORMAT_JSON = 'json';
  10. const FORMAT_HTML = 'html';
  11. /**
  12. * Body content
  13. * @var array
  14. */
  15. protected $body = array();
  16. /**
  17. * data
  18. * @param array $data
  19. */
  20. protected $data = array();
  21. /**
  22. * Array of headers. Each header is an array with keys 'name' and 'value'
  23. * @var array
  24. */
  25. protected $headers = array();
  26. /**
  27. * Determine to send the headers or not
  28. * @var unknown_type
  29. */
  30. protected $_sendHeader = false;
  31. public function __construct($data = array())
  32. {
  33. $this->format = isset($data['format']) ? isset($data['format']) : self::FORMAT_HTML;
  34. $this->data = $data;
  35. }
  36. /**
  37. * Append content to the body content
  38. *
  39. * @param string $content
  40. * @param string $key
  41. * @return Qii_Response_Abstract
  42. */
  43. public function appendBody($body, $key = NULL)
  44. {
  45. if (!strlen($key)) {
  46. $key = self::DEFAULT_BODY;
  47. }
  48. if (!isset($this->body[$key])) {
  49. $this->body[$key] = '';
  50. }
  51. $this->body[$key] .= (string) $body;
  52. return $this;
  53. }
  54. /**
  55. * Clear the entire body
  56. *
  57. * @param string $key
  58. * @return boolean
  59. */
  60. public function clearBody($key = NULL)
  61. {
  62. if (strlen($key)) {
  63. if (array_key_exists($key, $this->body)) {
  64. unset($this->body[$key]);
  65. }
  66. } else {
  67. $this->body = array();
  68. }
  69. return true;
  70. }
  71. /**
  72. * Clear headers
  73. *
  74. * @return Qii\Response\Abstract
  75. */
  76. public function clearHeaders()
  77. {
  78. $this->headers = array();
  79. return $this;
  80. }
  81. /**
  82. * Return the body content
  83. *
  84. * @param string $key
  85. * @return string
  86. */
  87. public function getBody($key = NULL)
  88. {
  89. if (!strlen($key)) {
  90. $key = self::DEFAULT_BODY;
  91. }
  92. return array_key_exists($key, $this->body) ? $this->body[$key] : null;
  93. }
  94. /**
  95. * Return array of headers; see {@link $headers} for format
  96. *
  97. * @return array
  98. */
  99. public function getHeader()
  100. {
  101. return $this->headers;
  102. }
  103. /**
  104. * Prepend content the body
  105. *
  106. * @param string $body
  107. * @param string $key
  108. * @return Qii_Response_Abstract
  109. */
  110. public function prependBody($body, $key = null)
  111. {
  112. if (!strlen($key)) {
  113. $key = self::DEFAULT_BODY;
  114. }
  115. if (!isset($this->body[$key])) {
  116. $this->body[$key] = '';
  117. }
  118. $this->body[$key] = $body . $this->body[$key];
  119. return $this;
  120. }
  121. /**
  122. * Send the response, including all headers
  123. *
  124. * @return void
  125. */
  126. public function response()
  127. {
  128. if($this->data && isset($this->data['body']))
  129. {
  130. switch($this->data['format'])
  131. {
  132. case self::FORMAT_JSON:
  133. $this->setHeader('Content-Type', 'text/json');
  134. $this->sendHeaders();
  135. echo json_encode($this->data['body'], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
  136. break;
  137. default:
  138. $body = $this->data['body'];
  139. if(is_array($this->data['body'])) {
  140. $body = '';
  141. if(isset($this->data['body']['render']) && $this->data['body']['render'] instanceof \Qii\View\Intf)
  142. {
  143. $tplData = isset($this->data['body']['tplData']) ? $this->data['body']['tplData'] : [];
  144. $this->data['body']['render']->assign($tplData);
  145. $body = $this->data['body']['render']->fetch($this->data['body']['tpl']);
  146. }
  147. }
  148. echo (IS_CLI ? (new \Qii\Response\Cli())->stdout($body) : $body);
  149. break;
  150. }
  151. return;
  152. }
  153. if ($this->_sendHeader == true) {
  154. $this->sendHeaders();
  155. }
  156. foreach ($this->body as $key => $body) {
  157. echo IS_CLI ? new \Qii\Response\Cli($body) : $body;
  158. }
  159. }
  160. public function setAllHeaders()
  161. {
  162. return false;
  163. }
  164. /**
  165. * Set body content
  166. *
  167. * @param string $body
  168. * @param string $key
  169. * @return Qii_Response_Abstract
  170. */
  171. public function setBody($body, $key = NULL)
  172. {
  173. if (!strlen($key)) {
  174. $key = self::DEFAULT_BODY;
  175. }
  176. $this->body[$key] = (string) $body;
  177. return $this;
  178. }
  179. /**
  180. * Set a header
  181. *
  182. * If $replace is true, replaces any headers already defined with that
  183. * $name.
  184. *
  185. * @param string $name
  186. * @param string $value
  187. * @param boolean $replace
  188. * @return Qii_Response_Abstract
  189. */
  190. public function setHeader($name, $value, $replace = false)
  191. {
  192. $name = $this->_normalizeHeader($name);
  193. $value = (string) $value;
  194. if ($replace) {
  195. foreach ($this->headers as $key => $header) {
  196. if ($name == $header['name']) {
  197. unset($this->headers[$key]);
  198. }
  199. }
  200. }
  201. $this->headers[] = array(
  202. 'name' => $name,
  203. 'value' => $value,
  204. 'replace' => $replace
  205. );
  206. return $this;
  207. }
  208. /**
  209. * Set redirect URL
  210. *
  211. * Sets Location header. Forces replacement of any prior redirects.
  212. *
  213. * @param string $url
  214. * @return Qii_Response_Abstract
  215. */
  216. public function setRedirect($url)
  217. {
  218. $this->setHeader('Location', $url, true);
  219. return $this;
  220. }
  221. /**
  222. * Magic __toString functionality
  223. *
  224. * Returns response value as string
  225. * using output buffering.
  226. *
  227. * @return string
  228. */
  229. public function __toString()
  230. {
  231. ob_start();
  232. $this->response();
  233. return ob_get_clean();
  234. }
  235. /**
  236. * Normalize a header name
  237. *
  238. * Normalizes a header name to X-Capitalized-Names
  239. *
  240. * @param string $name
  241. * @return string
  242. */
  243. protected function _normalizeHeader($name)
  244. {
  245. $filtered = str_replace(array('-', '_'), ' ', (string) $name);
  246. $filtered = ucwords(strtolower($filtered));
  247. $filtered = str_replace(' ', '-', $filtered);
  248. return $filtered;
  249. }
  250. /**
  251. * Send all headers
  252. *
  253. * Sends any headers specified.
  254. * If an {@link setHttpResponseCode() HTTP response code}
  255. * has been specified, it is sent with the first header.
  256. *
  257. * @return Qii_Response_Abstract
  258. */
  259. protected function sendHeaders()
  260. {
  261. foreach ($this->headers as $header) {
  262. header(
  263. $header['name'] . ': ' . $header['value'],
  264. $header['replace']
  265. );
  266. }
  267. return $this;
  268. }
  269. }