Response.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. public function asJSON()
  52. {
  53. $this->preventMultipleTypes();
  54. self::$typed = __FUNCTION__;
  55. Header::contentTypeJson();
  56. return $this;
  57. }
  58. public function asHTML()
  59. {
  60. $this->preventMultipleTypes();
  61. self::$typed = __FUNCTION__;
  62. Header::contentTypeTextHTML();
  63. return $this;
  64. }
  65. public function asPDF()
  66. {
  67. $this->preventMultipleTypes();
  68. self::$typed = __FUNCTION__;
  69. Header::contentTypePdf();
  70. return $this;
  71. }
  72. public function asCSV()
  73. {
  74. $this->preventMultipleTypes();
  75. self::$typed = __FUNCTION__;
  76. Header::contentTypeCsv();
  77. return $this;
  78. }
  79. public function asTEXT()
  80. {
  81. $this->preventMultipleTypes();
  82. self::$typed = __FUNCTION__;
  83. Header::contentTypeTextPlain();
  84. return $this;
  85. }
  86. public function asZIP()
  87. {
  88. $this->preventMultipleTypes();
  89. self::$typed = __FUNCTION__;
  90. Header::contentTypeZip();
  91. return $this;
  92. }
  93. public function asXZIP()
  94. {
  95. $this->preventMultipleTypes();
  96. self::$typed = __FUNCTION__;
  97. Header::contentTypeXZip();
  98. return $this;
  99. }
  100. public function asMSWord()
  101. {
  102. $this->preventMultipleTypes();
  103. self::$typed = __FUNCTION__;
  104. Header::contentTypeMSWord();
  105. return $this;
  106. }
  107. /**
  108. * Sends a download dialog to the browser.
  109. *
  110. * @param string $stream Can be a file-path or a string.
  111. * @param string $name Name of the stream/file should be shown.
  112. */
  113. public function sendStream($stream, $name)
  114. {
  115. Header::clear();
  116. Header::sendDownloadDialog($stream, $name);
  117. }
  118. /**
  119. * @param mixed $data
  120. * @param bool $exit
  121. */
  122. public function send($data, $exit = true)
  123. {
  124. $body = $data;
  125. if (self::$typed === 'asJSON') {
  126. $body = UtilJson::encode($data);
  127. } elseif ($data instanceof \Pimf\View) {
  128. $body = $data->render();
  129. }
  130. echo '' . $body;
  131. if ($exit) {
  132. exit(0);
  133. }
  134. }
  135. /**
  136. * If instead you have a page that has personalization on it
  137. * (say, for example, the splash page contains local news as well),
  138. * you can set a copy to be cached only by the browser.
  139. *
  140. * @param int $seconds Interval in seconds
  141. *
  142. * @return $this
  143. */
  144. public function cacheBrowser($seconds)
  145. {
  146. self::preventMultipleCaching();
  147. self::$cached = true;
  148. Header::cacheBrowser($seconds);
  149. return $this;
  150. }
  151. /**
  152. * If you want to try as hard as possible to keep a page from being cached anywhere.
  153. *
  154. * @return $this
  155. */
  156. public function cacheNone()
  157. {
  158. self::preventMultipleCaching();
  159. self::$cached = true;
  160. Header::cacheNone();
  161. return $this;
  162. }
  163. /**
  164. * If you want to allow a page to be cached by shared proxies for one minute.
  165. *
  166. * @param int $seconds Interval in seconds
  167. *
  168. * @return $this
  169. */
  170. public function cacheNoValidate($seconds = 60)
  171. {
  172. self::preventMultipleCaching();
  173. self::$cached = true;
  174. Header::cacheNoValidate($seconds);
  175. return $this;
  176. }
  177. /**
  178. * Handles setting pages that are always to be revalidated for freshness by any cache.
  179. *
  180. * @param int $last_modified Timestamp in seconds
  181. *
  182. * @return $this
  183. */
  184. public function exitIfNotModifiedSince($last_modified)
  185. {
  186. self::preventMultipleCaching();
  187. self::$cached = true;
  188. Header::exitIfNotModifiedSince($last_modified);
  189. return $this;
  190. }
  191. /**
  192. * @throws \RuntimeException
  193. */
  194. private function preventMultipleTypes()
  195. {
  196. if (!is_empty(self::$typed)) {
  197. Header::clear();
  198. throw new \RuntimeException('only one HTTP content-type can be sent!');
  199. }
  200. }
  201. /**
  202. * @throws \RuntimeException
  203. */
  204. private function preventMultipleCaching()
  205. {
  206. if ($this->method != 'GET') {
  207. Header::clear();
  208. throw new \RuntimeException('HTTP cache headers can only take effect if request was sent via GET method!');
  209. }
  210. if (self::$cached === true) {
  211. Header::clear();
  212. throw new \RuntimeException('only one HTTP cache-control can be sent!');
  213. }
  214. }
  215. }