PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/classes/request/driver.php

http://github.com/fuel/core
PHP | 424 lines | 194 code | 50 blank | 180 comment | 13 complexity | 60efca3b07f5f48a66a915ca0463b369 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP 5.4+ framework.
  4. *
  5. * @package Fuel
  6. * @version 1.9-dev
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2019 Fuel Development Team
  10. * @link https://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. class RequestException extends \HttpNotFoundException {}
  14. class RequestStatusException extends \RequestException {}
  15. /**
  16. * Request_Driver Class
  17. *
  18. * base class for request classes
  19. *
  20. * @package Fuel\Core
  21. *
  22. */
  23. abstract class Request_Driver
  24. {
  25. /**
  26. * Forge
  27. *
  28. * @param string $resource
  29. * @param array $options
  30. * @param mixed $method
  31. * @return Request_Driver
  32. */
  33. public static function forge($resource, array $options = array(), $method = null)
  34. {
  35. return new static($resource, $options, $method);
  36. }
  37. /**
  38. * @var string URL resource to perform requests upon
  39. */
  40. protected $resource = '';
  41. /**
  42. * @var array parameters to pass
  43. */
  44. protected $params = array();
  45. /**
  46. * @var array params set during object creation are handled as the defaults
  47. */
  48. protected $default_params = array();
  49. /**
  50. * @var array driver specific options
  51. */
  52. protected $options = array();
  53. /**
  54. * @var array options set during object creation are handled as the defaults
  55. */
  56. protected $default_options = array();
  57. /**
  58. * @var array http headers set for the request
  59. */
  60. protected $headers = array();
  61. /**
  62. * @var Response the response object after execute
  63. */
  64. protected $response;
  65. /**
  66. * @var array info about the response
  67. */
  68. protected $response_info = array();
  69. /**
  70. * @var bool whether to attempt auto-formatting the response
  71. */
  72. protected $auto_format = false;
  73. /**
  74. * @var string $method request method
  75. */
  76. protected $method = null;
  77. /**
  78. * @var array supported response formats
  79. */
  80. protected static $supported_formats = array(
  81. 'xml' => 'application/xml',
  82. 'json' => 'application/json',
  83. 'serialize' => 'application/vnd.php.serialized',
  84. 'php' => 'text/plain',
  85. 'csv' => 'text/csv',
  86. );
  87. /**
  88. * @var array mimetype format autodetection
  89. */
  90. protected static $auto_detect_formats = array(
  91. 'application/xml' => 'xml',
  92. 'application/soap+xml' => 'xml',
  93. 'text/xml' => 'xml',
  94. 'application/json' => 'json',
  95. 'text/json' => 'json',
  96. 'text/csv' => 'csv',
  97. 'application/csv' => 'csv',
  98. 'application/vnd.php.serialized' => 'serialize',
  99. );
  100. public function __construct($resource, array $options, $method = null)
  101. {
  102. $this->resource = $resource;
  103. $method and $this->set_method($method);
  104. foreach ($options as $key => $value)
  105. {
  106. if (method_exists($this, 'set_'.$key))
  107. {
  108. $this->{'set_'.$key}($value);
  109. }
  110. }
  111. $this->default_options = $this->options;
  112. $this->default_params = $this->params;
  113. }
  114. /**
  115. * Sets the request method.
  116. *
  117. * @param string $method request method
  118. * @return object current instance
  119. */
  120. public function set_method($method)
  121. {
  122. $this->method = strtoupper($method);
  123. return $this;
  124. }
  125. /**
  126. * Returns the request method.
  127. *
  128. * @return string request method
  129. */
  130. public function get_method()
  131. {
  132. return $this->method;
  133. }
  134. /**
  135. * Set the parameters to pass with the request
  136. *
  137. * @param array $params
  138. * @return Request_Driver
  139. */
  140. public function set_params($params)
  141. {
  142. $this->params = $params;
  143. return $this;
  144. }
  145. /**
  146. * Sets options on the driver
  147. *
  148. * @param array $options
  149. * @return Request_Driver
  150. */
  151. public function set_options(array $options)
  152. {
  153. foreach ($options as $key => $val)
  154. {
  155. $this->options[$key] = $val;
  156. }
  157. return $this;
  158. }
  159. /**
  160. * Sets a single option/value
  161. *
  162. * @param int|string $option
  163. * @param mixed $value
  164. * @return Request_Driver
  165. */
  166. public function set_option($option, $value)
  167. {
  168. return $this->set_options(array($option => $value));
  169. }
  170. /**
  171. * Add a single parameter/value or an array of parameters
  172. *
  173. * @param string|array $param
  174. * @param mixed $value
  175. * @return Request_Driver
  176. */
  177. public function add_param($param, $value = null)
  178. {
  179. if ( ! is_array($param))
  180. {
  181. $param = array($param => $value);
  182. }
  183. foreach ($param as $key => $val)
  184. {
  185. \Arr::set($this->params, $key, $val);
  186. }
  187. return $this;
  188. }
  189. /**
  190. * set a request http header
  191. *
  192. * @param string $header
  193. * @param string $content
  194. * @return Request_Driver
  195. */
  196. public function set_header($header, $content = null)
  197. {
  198. if (is_null($content))
  199. {
  200. $this->headers[] = $header;
  201. }
  202. else
  203. {
  204. $this->headers[$header] = $content;
  205. }
  206. return $this;
  207. }
  208. /**
  209. * Collect all headers and parse into consistent string
  210. *
  211. * @return array
  212. */
  213. public function get_headers()
  214. {
  215. $headers = array();
  216. foreach ($this->headers as $key => $value)
  217. {
  218. $headers[] = is_int($key) ? $value : $key.': '.$value;
  219. }
  220. return $headers;
  221. }
  222. /**
  223. * Set mime-type accept header
  224. *
  225. * @param string $mime
  226. * @return string Request_Driver
  227. */
  228. public function set_mime_type($mime)
  229. {
  230. if (array_key_exists($mime, static::$supported_formats))
  231. {
  232. $mime = static::$supported_formats[$mime];
  233. }
  234. $this->set_header('Accept', $mime);
  235. return $this;
  236. }
  237. /**
  238. * Switch auto formatting on or off
  239. *
  240. * @param bool $auto_format
  241. * @return Request_Driver
  242. */
  243. public function set_auto_format($auto_format)
  244. {
  245. $this->auto_format = (bool) $auto_format;
  246. return $this;
  247. }
  248. /**
  249. * Executes the request upon the URL
  250. *
  251. * @param array $additional_params
  252. * @return Response
  253. */
  254. abstract public function execute(array $additional_params = array());
  255. /**
  256. * Reset before doing another request
  257. *
  258. * @return Request_Driver
  259. */
  260. protected function set_defaults()
  261. {
  262. $this->options = $this->default_options;
  263. $this->params = $this->default_params;
  264. return $this;
  265. }
  266. /**
  267. * Validate if a given mime type is accepted according to an accept header
  268. *
  269. * @param string $mime
  270. * @param string $accept_header
  271. * @return bool
  272. */
  273. protected function mime_in_header($mime, $accept_header)
  274. {
  275. // make sure we have input
  276. if (empty($mime) or empty($accept_header))
  277. {
  278. // no header or no mime to check
  279. return true;
  280. }
  281. // process the accept header and get a list of accepted mimes
  282. $accept_mimes = array();
  283. $accept_header = explode(',', $accept_header);
  284. foreach ($accept_header as $accept_def)
  285. {
  286. $accept_def = explode(';', $accept_def);
  287. $accept_def = trim($accept_def[0]);
  288. if ( ! in_array($accept_def, $accept_mimes))
  289. {
  290. $accept_mimes[] = $accept_def;
  291. }
  292. }
  293. // match on generic mime type
  294. if (in_array('*/*', $accept_mimes))
  295. {
  296. return true;
  297. }
  298. // match on full mime type
  299. if (in_array($mime, $accept_mimes))
  300. {
  301. return true;
  302. }
  303. // match on generic mime type
  304. $mime = substr($mime, 0, strpos($mime, '/')).'/*';
  305. if (in_array($mime, $accept_mimes))
  306. {
  307. return true;
  308. }
  309. // no match
  310. return false;
  311. }
  312. /**
  313. * Creates the Response and optionally attempts to auto-format the output
  314. *
  315. * @param string $body
  316. * @param int $status
  317. * @param string $mime
  318. * @param array $headers
  319. * @param string $accept_header
  320. * @return Response
  321. *
  322. * @throws \OutOfRangeException if an accept header was specified, but the mime type isn't in it
  323. */
  324. public function set_response($body, $status, $mime = null, $headers = array(), $accept_header = null)
  325. {
  326. // Strip attribs from mime type to avoid over-specific matching
  327. $mime = strstr($mime, ';', true) ?: $mime;
  328. // did we use an accept header? If so, validate the returned mimetype
  329. if ( ! $this->mime_in_header($mime, $accept_header))
  330. {
  331. throw new \OutOfRangeException('The mimetype "'.$mime.'" of the returned response is not acceptable according to the accept header sent.');
  332. }
  333. // do we have auto formatting enabled and can we format this mime type?
  334. if ($this->auto_format and array_key_exists($mime, static::$auto_detect_formats))
  335. {
  336. $body = \Format::forge($body, static::$auto_detect_formats[$mime])->to_array();
  337. }
  338. $this->response = \Response::forge($body, $status, $headers);
  339. return $this->response;
  340. }
  341. /**
  342. * Fetch the response
  343. *
  344. * @return Response
  345. */
  346. public function response()
  347. {
  348. return $this->response;
  349. }
  350. /**
  351. * Fetch the response info or a key from it
  352. *
  353. * @param string $key
  354. * @param string $default
  355. * @return mixed
  356. */
  357. public function response_info($key = null, $default = null)
  358. {
  359. if (func_num_args() == 0)
  360. {
  361. return $this->response_info;
  362. }
  363. return \Arr::get($this->response_info, $key, $default);
  364. }
  365. /**
  366. * Returns the body as a string.
  367. *
  368. * @return string
  369. */
  370. public function __toString()
  371. {
  372. return (string) $this->response();
  373. }
  374. }