Response.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <?php
  2. /**
  3. * Pimf
  4. *
  5. * @copyright Copyright (c) Gjero Krsteski (http://krsteski.de)
  6. * @license http://krsteski.de/new-bsd-license New BSD License
  7. */
  8. namespace Pimf;
  9. use \Pimf\Util\Header, Pimf\Util\Json as UtilJson;
  10. /**
  11. * Provides a simple interface around the HTTP an HTTPCache-friendly response generating.
  12. * Use this class to build and the current HTTP response before it is returned to the client.
  13. *
  14. * @package Pimf
  15. * @author Gjero Krsteski <[email protected]>
  16. */
  17. class Response
  18. {
  19. /**
  20. * The request method send by the client-browser.
  21. *
  22. * @var string
  23. */
  24. protected $method = null;
  25. /**
  26. * If the response attempts to send any cached headers.
  27. *
  28. * @var bool
  29. */
  30. protected static $cached = false;
  31. /**
  32. * Type of the data will be send to the client-browser.
  33. *
  34. * @var string
  35. */
  36. protected static $typed = null;
  37. /**
  38. * @param string $requestMethod
  39. *
  40. * @throws \RuntimeException
  41. */
  42. public function __construct($requestMethod)
  43. {
  44. $this->method = '' . strtoupper($requestMethod);
  45. // it is PIMF framework restriction
  46. if (!in_array($this->method, array('POST', 'GET', null))) {
  47. throw new \RuntimeException('unsupported request-method given');
  48. }
  49. Header::clear();
  50. }
  51. /**
  52. * @return string
  53. */
  54. public function getMethod()
  55. {
  56. return $this->method;
  57. }
  58. public function asJSON()
  59. {
  60. $this->preventMultipleTypes();
  61. self::$typed = __FUNCTION__;
  62. Header::asJSON();
  63. return $this;
  64. }
  65. public function asHTML()
  66. {
  67. $this->preventMultipleTypes();
  68. self::$typed = __FUNCTION__;
  69. Header::asTextHTML();
  70. return $this;
  71. }
  72. public function asPDF()
  73. {
  74. $this->preventMultipleTypes();
  75. self::$typed = __FUNCTION__;
  76. Header::asPDF();
  77. return $this;
  78. }
  79. public function asCSV()
  80. {
  81. $this->preventMultipleTypes();
  82. self::$typed = __FUNCTION__;
  83. Header::asCSV();
  84. return $this;
  85. }
  86. public function asTEXT()
  87. {
  88. $this->preventMultipleTypes();
  89. self::$typed = __FUNCTION__;
  90. Header::asTextPlain();
  91. return $this;
  92. }
  93. public function asZIP()
  94. {
  95. $this->preventMultipleTypes();
  96. self::$typed = __FUNCTION__;
  97. Header::asZIP();
  98. return $this;
  99. }
  100. public function asXZIP()
  101. {
  102. $this->preventMultipleTypes();
  103. self::$typed = __FUNCTION__;
  104. Header::asXZIP();
  105. return $this;
  106. }
  107. public function asMSWord()
  108. {
  109. $this->preventMultipleTypes();
  110. self::$typed = __FUNCTION__;
  111. Header::asMSWord();
  112. return $this;
  113. }
  114. /**
  115. * Sends a download dialog to the browser.
  116. *
  117. * @param string $stream Can be a file-path or a string.
  118. * @param string $name Name of the stream/file should be shown.
  119. * @param boolean $exit Optional for testing
  120. */
  121. public function sendStream($stream, $name, $exit = true)
  122. {
  123. Header::clear();
  124. Header::sendDownloadDialog($stream, $name, $exit);
  125. }
  126. /**
  127. * @param mixed $data
  128. * @param bool $exit
  129. */
  130. public function send($data, $exit = true)
  131. {
  132. $body = $data;
  133. if (self::$typed === 'asJSON') {
  134. $body = UtilJson::encode($data);
  135. } elseif ($data instanceof \Pimf\View) {
  136. $body = $data->render();
  137. }
  138. echo '' . $body;
  139. if ($exit) {
  140. exit(0);
  141. }
  142. }
  143. /**
  144. * If instead you have a page that has personalization on it
  145. * (say, for example, the splash page contains local news as well),
  146. * you can set a copy to be cached only by the browser.
  147. *
  148. * @param int $seconds Interval in seconds
  149. *
  150. * @return $this
  151. */
  152. public function cacheBrowser($seconds)
  153. {
  154. self::preventMultipleCaching();
  155. self::$cached = true;
  156. Header::cacheBrowser($seconds);
  157. return $this;
  158. }
  159. /**
  160. * If you want to try as hard as possible to keep a page from being cached anywhere.
  161. *
  162. * @return $this
  163. */
  164. public function cacheNone()
  165. {
  166. self::preventMultipleCaching();
  167. self::$cached = true;
  168. Header::cacheNone();
  169. return $this;
  170. }
  171. /**
  172. * If you want to allow a page to be cached by shared proxies for one minute.
  173. *
  174. * @param int $seconds Interval in seconds
  175. *
  176. * @return $this
  177. */
  178. public function cacheNoValidate($seconds = 60)
  179. {
  180. self::preventMultipleCaching();
  181. self::$cached = true;
  182. Header::cacheNoValidate($seconds);
  183. return $this;
  184. }
  185. /**
  186. * Handles setting pages that are always to be revalidated for freshness by any cache.
  187. *
  188. * @param int $last_modified Timestamp in seconds
  189. *
  190. * @return $this
  191. */
  192. public function exitIfNotModifiedSince($last_modified)
  193. {
  194. self::preventMultipleCaching();
  195. self::$cached = true;
  196. Header::exitIfNotModifiedSince($last_modified);
  197. return $this;
  198. }
  199. /**
  200. * @throws \RuntimeException
  201. */
  202. private function preventMultipleTypes()
  203. {
  204. if (!is_empty(self::$typed)) {
  205. Header::clear();
  206. throw new \RuntimeException('only one HTTP content-type can be sent!');
  207. }
  208. }
  209. /**
  210. * @throws \RuntimeException
  211. */
  212. private function preventMultipleCaching()
  213. {
  214. if ($this->method != 'GET') {
  215. Header::clear();
  216. throw new \RuntimeException('HTTP cache headers can only take effect if request was sent via GET method!');
  217. }
  218. if (self::$cached === true) {
  219. Header::clear();
  220. throw new \RuntimeException('only one HTTP cache-control can be sent!');
  221. }
  222. }
  223. }