Response.php 7.3 KB

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