Curl.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\net\socket;
  9. use lithium\net\http\Message;
  10. /**
  11. * A Curl-based socket adapter
  12. *
  13. * This curl adapter provides the required method implementations of the abstract Socket class
  14. * for `open`, `close`, `read`, `write`, `timeout` `eof` and `encoding`.
  15. *
  16. * Your PHP installation must have been compiled with the `--with-curl[=DIR]` directive. If this
  17. * is not the case, you must either recompile PHP with the proper configuration flags to enable
  18. * curl, or you may use the `Stream` adapter that is also included with the Lithium core.
  19. *
  20. * @link http://www.php.net/manual/en/curl.installation.php
  21. * @see lithium\net\socket\Stream
  22. */
  23. class Curl extends \lithium\net\Socket {
  24. /**
  25. * Contains options that will be passed to `curl_setopt_array` before
  26. * `read` and `write` operations. These options should be set by
  27. * using the `set` method.
  28. *
  29. * @link http://www.php.net/manual/en/function.curl-setopt.php PHP Manual: curl_setopt()
  30. * @see lithium\net\socket\Curl::set()
  31. * @var array
  32. */
  33. public $options = array();
  34. /**
  35. * Constructor
  36. *
  37. * @param array $config
  38. */
  39. public function __construct(array $config = array()) {
  40. $defaults = array('ignoreExpect' => true);
  41. parent::__construct($config + $defaults);
  42. }
  43. /**
  44. * Opens a curl connection and initializes the internal resource handle.
  45. *
  46. * @param array $options update the config settings
  47. * if $options['options'] exists, will be passed to $this->set()
  48. * @return mixed Returns `false` if the socket configuration does not contain the
  49. * `'scheme'` or `'host'` settings, or if configuration fails, otherwise returns a
  50. * resource stream.
  51. */
  52. public function open(array $options = array()) {
  53. $this->options = array();
  54. parent::open($options);
  55. $config = $this->_config;
  56. if (empty($config['scheme']) || empty($config['host'])) {
  57. return false;
  58. }
  59. if (!empty($config['options'])) {
  60. $this->set($config['options']);
  61. }
  62. $url = "{$config['scheme']}://{$config['host']}";
  63. $this->_resource = curl_init($url);
  64. $this->set(array(
  65. CURLOPT_PORT => $config['port'],
  66. CURLOPT_HEADER => true,
  67. CURLOPT_RETURNTRANSFER => true
  68. ));
  69. if (!is_resource($this->_resource)) {
  70. return false;
  71. }
  72. $this->_isConnected = true;
  73. $this->timeout($config['timeout']);
  74. if (isset($config['encoding'])) {
  75. $this->encoding($config['encoding']);
  76. }
  77. return $this->_resource;
  78. }
  79. /**
  80. * Closes the curl connection.
  81. *
  82. * @return boolean True on closed connection
  83. */
  84. public function close() {
  85. if (!is_resource($this->_resource)) {
  86. return true;
  87. }
  88. curl_close($this->_resource);
  89. if (is_resource($this->_resource)) {
  90. $this->close();
  91. }
  92. return true;
  93. }
  94. /**
  95. * EOF is unimplemented for this socket adapter.
  96. *
  97. * @return null
  98. */
  99. public function eof() {
  100. return null;
  101. }
  102. /**
  103. * Reads data from the curl connection.
  104. * The `read` method will utilize the curl options that have been set.
  105. *
  106. * @link http://php.net/manual/en/function.curl-exec.php PHP Manual: curl_exec()
  107. * @return mixed Boolean false if the resource handle is unavailable, and the result
  108. * of `curl_exec` otherwise.
  109. */
  110. public function read() {
  111. if (!is_resource($this->_resource)) {
  112. return false;
  113. }
  114. return curl_exec($this->_resource);
  115. }
  116. /**
  117. * Writes data to curl options
  118. *
  119. * @param object $data a `lithium\net\Message` object or array
  120. * @return boolean
  121. */
  122. public function write($data = null) {
  123. if (!is_resource($this->_resource)) {
  124. return false;
  125. }
  126. if (!is_object($data)) {
  127. $data = $this->_instance($this->_classes['request'], (array) $data + $this->_config);
  128. }
  129. $this->set(CURLOPT_URL, $data->to('url'));
  130. if ($data instanceof Message) {
  131. if (!empty($this->_config['ignoreExpect'])) {
  132. $data->headers('Expect', ' ');
  133. }
  134. if (isset($data->headers)) {
  135. $this->set(CURLOPT_HTTPHEADER, $data->headers());
  136. }
  137. if (isset($data->method) && $data->method === 'POST') {
  138. $this->set(array(CURLOPT_POST => true, CURLOPT_POSTFIELDS => $data->body()));
  139. }
  140. if (isset($data->method) && $data->method === 'PUT') {
  141. $this->set(array(
  142. CURLOPT_CUSTOMREQUEST => 'PUT',
  143. CURLOPT_POSTFIELDS => $data->body()
  144. ));
  145. }
  146. }
  147. return (boolean) curl_setopt_array($this->_resource, $this->options);
  148. }
  149. /**
  150. * A convenience method to set the curl `CURLOPT_CONNECTTIMEOUT`
  151. * setting for the current connection. This determines the number
  152. * of seconds to wait while trying to connect.
  153. *
  154. * Note: A value of 0 may be used to specify an indefinite wait time.
  155. *
  156. * @param integer $time The timeout value in seconds
  157. * @return boolean False if the resource handle is unavailable or the
  158. * option could not be set, true otherwise.
  159. */
  160. public function timeout($time) {
  161. if (!is_resource($this->_resource)) {
  162. return false;
  163. }
  164. return curl_setopt($this->_resource, CURLOPT_CONNECTTIMEOUT, $time);
  165. }
  166. /**
  167. * encoding() is currently unimplemented for this socket adapter
  168. *
  169. * @todo implement Curl::encoding($charset)
  170. * @param string $charset
  171. */
  172. public function encoding($charset) {}
  173. /**
  174. * Sets the options to be used in subsequent curl requests.
  175. *
  176. * @link http://www.php.net/manual/en/curl.constants.php PHP Manual: cURL Constants
  177. * @param array $flags If $values is an array, $flags will be used as the
  178. * keys to an associative array of curl options. If $values is not set,
  179. * then $flags will be used as the associative array.
  180. * @param array $value If set, this array becomes the values for the
  181. * associative array of curl options.
  182. * @return void
  183. */
  184. public function set($flags, $value = null) {
  185. if ($value !== null) {
  186. $flags = array($flags => $value);
  187. }
  188. $this->options = $flags + $this->options;
  189. }
  190. }
  191. ?>