PageRenderTime 61ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ManaPHP/Http/Response.php

https://gitlab.com/szlongshu/manaphp
PHP | 425 lines | 163 code | 53 blank | 209 comment | 18 complexity | a4ad8f4b8f71bd4caf06a7c0d97fad1b MD5 | raw file
  1. <?php
  2. namespace ManaPHP\Http {
  3. use ManaPHP\Component;
  4. use ManaPHP\Di;
  5. use ManaPHP\Http\Response\Exception;
  6. use ManaPHP\Http\Response\Headers;
  7. /**
  8. * ManaPHP\Http\Response
  9. *
  10. * Part of the HTTP cycle is return responses to the clients.
  11. * ManaPHP\HTTP\Response is the ManaPHP component responsible to achieve this task.
  12. * HTTP responses are usually composed by headers and body.
  13. *
  14. *<code>
  15. * $response = new ManaPHP\Http\Response();
  16. * $response->setStatusCode(200, "OK");
  17. * $response->setContent("<html><body>Hello</body></html>");
  18. * $response->send();
  19. *</code>
  20. */
  21. class Response extends Component implements ResponseInterface
  22. {
  23. /**
  24. * @var boolean
  25. */
  26. protected $_sent = false;
  27. /**
  28. * @var string
  29. */
  30. protected $_content;
  31. /**
  32. * @var \ManaPHP\Http\Response\HeadersInterface
  33. */
  34. protected $_headers;
  35. /**
  36. * @var \ManaPHP\Http\Response\CookiesInterface
  37. */
  38. protected $_cookies;
  39. protected $_file;
  40. public function __construct()
  41. {
  42. $this->_headers = new Headers();
  43. }
  44. /**
  45. * Sets the HTTP response code
  46. *
  47. *<code>
  48. * $response->setStatusCode(404, "Not Found");
  49. *</code>
  50. *
  51. * @param int $code
  52. * @param string $message
  53. *
  54. * @return static
  55. * @throws
  56. */
  57. public function setStatusCode($code, $message)
  58. {
  59. $this->setHeader('Status', $code . ' ' . $message);
  60. return $this;
  61. }
  62. /**
  63. * Sets a cookies bag for the response externally
  64. *
  65. * @param \ManaPHP\Http\Response\CookiesInterface $cookies
  66. *
  67. * @return static
  68. */
  69. public function setCookies($cookies)
  70. {
  71. $this->_cookies = $cookies;
  72. return $this;
  73. }
  74. /**
  75. * Returns cookies set by the user
  76. *
  77. * @return \ManaPHP\Http\Response\CookiesInterface
  78. */
  79. public function getCookies()
  80. {
  81. return $this->_cookies;
  82. }
  83. /**
  84. * Overwrites a header in the response
  85. *
  86. *<code>
  87. * $response->setHeader("Content-Type", "text/plain");
  88. *</code>
  89. *
  90. * @param string $name
  91. * @param string $value
  92. *
  93. * @return static
  94. */
  95. public function setHeader($name, $value)
  96. {
  97. $this->_headers->set($name, $value);
  98. return $this;
  99. }
  100. /**
  101. * Send a raw header to the response
  102. *
  103. *<code>
  104. * $response->setRawHeader("HTTP/1.1 404 Not Found");
  105. *</code>
  106. *
  107. * @param string $header
  108. *
  109. * @return static
  110. */
  111. public function setRawHeader($header)
  112. {
  113. $this->_headers->setRaw($header);
  114. return $this;
  115. }
  116. /**
  117. * Sets a Expires header to use HTTP cache
  118. *
  119. *<code>
  120. * $this->response->setExpires(new DateTime());
  121. *</code>
  122. *
  123. * @param int|\DateTime $datetime
  124. *
  125. * @return static
  126. */
  127. public function setExpires($datetime)
  128. {
  129. if (is_int($datetime)) {
  130. $date = new \DateTime('now', new \DateTimeZone('UTC'));
  131. $date->setTimestamp($datetime);
  132. } else {
  133. $date = clone $datetime;
  134. }
  135. $date->setTimezone(new \DateTimeZone('UTC'));
  136. $this->setHeader('Expires', $date->format('D, d M Y H:i:s') . ' GMT');
  137. return $this;
  138. }
  139. /**
  140. * Sets a Not-Modified response
  141. *
  142. * @return static
  143. */
  144. public function setNotModified()
  145. {
  146. $this->setStatusCode(304, 'Not modified');
  147. return $this;
  148. }
  149. /**
  150. * Sets the response content-type mime, optionally the charset
  151. *
  152. *<code>
  153. * $response->setContentType('application/pdf');
  154. * $response->setContentType('text/plain', 'UTF-8');
  155. *</code>
  156. *
  157. * @param string $contentType
  158. * @param string $charset
  159. *
  160. * @return static
  161. */
  162. public function setContentType($contentType, $charset = null)
  163. {
  164. if ($charset === null) {
  165. $this->_headers->set('Content-Type', $contentType);
  166. } else {
  167. $this->_headers->set('Content-Type', $contentType . '; charset=' . $charset);
  168. }
  169. return $this;
  170. }
  171. /**
  172. * Set a custom ETag
  173. *
  174. *<code>
  175. * $response->setEtag(md5(time()));
  176. *</code>
  177. *
  178. * @param string $etag
  179. *
  180. * @return static
  181. */
  182. public function setEtag($etag)
  183. {
  184. $this->_headers->set('Etag', $etag);
  185. return $this;
  186. }
  187. /**
  188. * Redirect by HTTP to another action or URL
  189. *
  190. *<code>
  191. * //Using a string redirect (internal/external)
  192. * $response->redirect("posts/index");
  193. * $response->redirect("http://www.google.com", true);
  194. * $response->redirect("http://www.example.com/new-location", true, 301);
  195. *
  196. * //Making a redirection based on a named route
  197. * $response->redirect(array(
  198. * "for" => "index-lang",
  199. * "lang" => "jp",
  200. * "controller" => "index"
  201. * ));
  202. *</code>
  203. *
  204. * @param string|array $location
  205. * @param boolean $externalRedirect
  206. * @param int|string $statusCode
  207. *
  208. * @return static
  209. * @throws \ManaPHP\Http\Response\Exception
  210. */
  211. public function redirect($location, $externalRedirect = false, $statusCode = 302)
  212. {
  213. if (is_string($statusCode)) {
  214. $statusCode = (int)$statusCode;
  215. }
  216. /**
  217. * The HTTP status is 302 by default, a temporary redirection
  218. */
  219. if ($statusCode === 301) {
  220. $message = 'Permanently Moved';
  221. } elseif ($statusCode === 302) {
  222. $message = 'Temporarily Moved';
  223. } else {
  224. throw new Exception('invalid status code: ' . $statusCode);
  225. }
  226. $this->setStatusCode($statusCode, $message);
  227. /**
  228. * Change the current location using 'Location'
  229. */
  230. $this->setHeader('Location', $location);
  231. return $this;
  232. }
  233. /**
  234. * Sets HTTP response body
  235. *
  236. *<code>
  237. * $response->setContent("<h1>Hello!</h1>");
  238. *</code>
  239. *
  240. * @param string $content
  241. *
  242. * @return static
  243. */
  244. public function setContent($content)
  245. {
  246. $this->_content = $content;
  247. return $this;
  248. }
  249. /**
  250. * Sets HTTP response body. The parameter is automatically converted to JSON
  251. *
  252. *<code>
  253. * $response->setJsonContent(array("status" => "OK"));
  254. * $response->setJsonContent(array("status" => "OK"), JSON_NUMERIC_CHECK);
  255. *</code>
  256. *
  257. * @param string $content
  258. * @param int $jsonOptions consisting on http://www.php.net/manual/en/json.constants.php
  259. *
  260. * @return static
  261. */
  262. public function setJsonContent($content, $jsonOptions = null)
  263. {
  264. if ($jsonOptions === null) {
  265. $jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
  266. }
  267. $this->_content = json_encode($content, $jsonOptions, 512);
  268. return $this;
  269. }
  270. /**
  271. * Appends a string to the HTTP response body
  272. *
  273. * @param string $content
  274. *
  275. * @return static
  276. */
  277. public function appendContent($content)
  278. {
  279. $this->_content .= $content;
  280. return $this;
  281. }
  282. /**
  283. * Gets the HTTP response body
  284. *
  285. * @return string
  286. */
  287. public function getContent()
  288. {
  289. return $this->_content;
  290. }
  291. /**
  292. * Check if the response is already sent
  293. *
  294. * @return boolean
  295. */
  296. public function isSent()
  297. {
  298. return $this->_sent;
  299. }
  300. /**
  301. * Sends headers to the client
  302. *
  303. * @return static
  304. */
  305. public function sendHeaders()
  306. {
  307. if (is_object($this->_headers)) {
  308. $this->_headers->send();
  309. }
  310. return $this;
  311. }
  312. /**
  313. * Sends cookies to the client
  314. *
  315. * @return static
  316. */
  317. public function sendCookies()
  318. {
  319. if (is_object($this->_cookies)) {
  320. $this->_cookies->send();
  321. }
  322. return $this;
  323. }
  324. /**
  325. * Prints out HTTP response to the client
  326. *
  327. * @return static
  328. * @throws \ManaPHP\Http\Response\Exception
  329. */
  330. public function send()
  331. {
  332. if ($this->_sent === true) {
  333. throw new Exception('Response was already sent');
  334. }
  335. if (is_object($this->_headers)) {
  336. $this->_headers->send();
  337. }
  338. if (is_object($this->_cookies)) {
  339. $this->_cookies->send();
  340. }
  341. if ($this->_content !== null) {
  342. echo $this->_content;
  343. } else {
  344. if (is_string($this->_file) && $this->_file !== '') {
  345. readfile($this->_file);
  346. }
  347. }
  348. $this->_sent = true;
  349. return $this;
  350. }
  351. /**
  352. * Sets an attached file to be sent at the end of the request
  353. *
  354. * @param string $filePath
  355. * @param string $attachmentName
  356. *
  357. * @return static
  358. */
  359. public function setFileToSend($filePath, $attachmentName = null)
  360. {
  361. if ($attachmentName === null) {
  362. $attachmentName = basename($filePath);
  363. }
  364. $this->_headers->setRaw('Content-Description: File Transfer');
  365. $this->_headers->setRaw('Content-Type: application/octet-stream');
  366. $this->_headers->setRaw('Content-Disposition: attachment; filename=' . $attachmentName);
  367. $this->_headers->setRaw('Content-Transfer-Encoding: binary');
  368. $this->_file = $filePath;
  369. return $this;
  370. }
  371. }
  372. }