PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Adapter/AbstractAdapter.php

http://github.com/hybridauth/hybridauth
PHP | 372 lines | 173 code | 57 blank | 142 comment | 10 complexity | bb5b28cc28add2ae3e76c72a4f1ea5a3 MD5 | raw file
  1. <?php
  2. /*!
  3. * Hybridauth
  4. * https://hybridauth.github.io | https://github.com/hybridauth/hybridauth
  5. * (c) 2017 Hybridauth authors | https://hybridauth.github.io/license.html
  6. */
  7. namespace Hybridauth\Adapter;
  8. use Hybridauth\Exception\NotImplementedException;
  9. use Hybridauth\Exception\InvalidArgumentException;
  10. use Hybridauth\Exception\HttpClientFailureException;
  11. use Hybridauth\Exception\HttpRequestFailedException;
  12. use Hybridauth\Storage\StorageInterface;
  13. use Hybridauth\Storage\Session;
  14. use Hybridauth\Logger\LoggerInterface;
  15. use Hybridauth\Logger\Logger;
  16. use Hybridauth\HttpClient\HttpClientInterface;
  17. use Hybridauth\HttpClient\Curl as HttpClient;
  18. use Hybridauth\Data;
  19. /**
  20. * Class AbstractAdapter
  21. */
  22. abstract class AbstractAdapter implements AdapterInterface
  23. {
  24. use DataStoreTrait;
  25. /**
  26. * Provider ID (unique name).
  27. *
  28. * @var string
  29. */
  30. protected $providerId = '';
  31. /**
  32. * Specific Provider config.
  33. *
  34. * @var mixed
  35. */
  36. protected $config = [];
  37. /**
  38. * Extra Provider parameters.
  39. *
  40. * @var array
  41. */
  42. protected $params;
  43. /**
  44. * Callback url
  45. *
  46. * @var string
  47. */
  48. protected $callback = '';
  49. /**
  50. * Storage.
  51. *
  52. * @var StorageInterface
  53. */
  54. public $storage;
  55. /**
  56. * HttpClient.
  57. *
  58. * @var HttpClientInterface
  59. */
  60. public $httpClient;
  61. /**
  62. * Logger.
  63. *
  64. * @var LoggerInterface
  65. */
  66. public $logger;
  67. /**
  68. * Whether to validate API status codes of http responses
  69. *
  70. * @var bool
  71. */
  72. protected $validateApiResponseHttpCode = true;
  73. /**
  74. * Common adapters constructor.
  75. *
  76. * @param array $config
  77. * @param HttpClientInterface $httpClient
  78. * @param StorageInterface $storage
  79. * @param LoggerInterface $logger
  80. */
  81. public function __construct(
  82. $config = [],
  83. HttpClientInterface $httpClient = null,
  84. StorageInterface $storage = null,
  85. LoggerInterface $logger = null
  86. ) {
  87. $this->providerId = (new \ReflectionClass($this))->getShortName();
  88. $this->config = new Data\Collection($config);
  89. $this->setHttpClient($httpClient);
  90. $this->setStorage($storage);
  91. $this->setLogger($logger);
  92. $this->configure();
  93. $this->logger->debug(sprintf('Initialize %s, config: ', get_class($this)), $config);
  94. $this->initialize();
  95. }
  96. /**
  97. * Load adapter's configuration
  98. */
  99. abstract protected function configure();
  100. /**
  101. * Adapter initializer
  102. */
  103. abstract protected function initialize();
  104. /**
  105. * {@inheritdoc}
  106. */
  107. abstract public function isConnected();
  108. /**
  109. * {@inheritdoc}
  110. */
  111. public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [], $multipart = false)
  112. {
  113. throw new NotImplementedException('Provider does not support this feature.');
  114. }
  115. /**
  116. * {@inheritdoc}
  117. */
  118. public function maintainToken()
  119. {
  120. // Nothing needed for most providers
  121. }
  122. /**
  123. * {@inheritdoc}
  124. */
  125. public function getUserProfile()
  126. {
  127. throw new NotImplementedException('Provider does not support this feature.');
  128. }
  129. /**
  130. * {@inheritdoc}
  131. */
  132. public function getUserContacts()
  133. {
  134. throw new NotImplementedException('Provider does not support this feature.');
  135. }
  136. /**
  137. * {@inheritdoc}
  138. */
  139. public function getUserPages()
  140. {
  141. throw new NotImplementedException('Provider does not support this feature.');
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function getUserActivity($stream)
  147. {
  148. throw new NotImplementedException('Provider does not support this feature.');
  149. }
  150. /**
  151. * {@inheritdoc}
  152. */
  153. public function setUserStatus($status)
  154. {
  155. throw new NotImplementedException('Provider does not support this feature.');
  156. }
  157. /**
  158. * {@inheritdoc}
  159. */
  160. public function setPageStatus($status, $pageId)
  161. {
  162. throw new NotImplementedException('Provider does not support this feature.');
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function disconnect()
  168. {
  169. $this->clearStoredData();
  170. }
  171. /**
  172. * {@inheritdoc}
  173. */
  174. public function getAccessToken()
  175. {
  176. $tokenNames = [
  177. 'access_token',
  178. 'access_token_secret',
  179. 'token_type',
  180. 'refresh_token',
  181. 'expires_in',
  182. 'expires_at',
  183. ];
  184. $tokens = [];
  185. foreach ($tokenNames as $name) {
  186. if ($this->getStoredData($name)) {
  187. $tokens[$name] = $this->getStoredData($name);
  188. }
  189. }
  190. return $tokens;
  191. }
  192. /**
  193. * {@inheritdoc}
  194. */
  195. public function setAccessToken($tokens = [])
  196. {
  197. $this->clearStoredData();
  198. foreach ($tokens as $token => $value) {
  199. $this->storeData($token, $value);
  200. }
  201. // Re-initialize token parameters.
  202. $this->initialize();
  203. }
  204. /**
  205. * {@inheritdoc}
  206. */
  207. public function setHttpClient(HttpClientInterface $httpClient = null)
  208. {
  209. $this->httpClient = $httpClient ?: new HttpClient();
  210. if ($this->config->exists('curl_options') && method_exists($this->httpClient, 'setCurlOptions')) {
  211. $this->httpClient->setCurlOptions($this->config->get('curl_options'));
  212. }
  213. }
  214. /**
  215. * {@inheritdoc}
  216. */
  217. public function getHttpClient()
  218. {
  219. return $this->httpClient;
  220. }
  221. /**
  222. * {@inheritdoc}
  223. */
  224. public function setStorage(StorageInterface $storage = null)
  225. {
  226. $this->storage = $storage ?: new Session();
  227. }
  228. /**
  229. * {@inheritdoc}
  230. */
  231. public function getStorage()
  232. {
  233. return $this->storage;
  234. }
  235. /**
  236. * {@inheritdoc}
  237. */
  238. public function setLogger(LoggerInterface $logger = null)
  239. {
  240. $this->logger = $logger ?: new Logger(
  241. $this->config->get('debug_mode'),
  242. $this->config->get('debug_file')
  243. );
  244. if (method_exists($this->httpClient, 'setLogger')) {
  245. $this->httpClient->setLogger($this->logger);
  246. }
  247. }
  248. /**
  249. * {@inheritdoc}
  250. */
  251. public function getLogger()
  252. {
  253. return $this->logger;
  254. }
  255. /**
  256. * Set Adapter's API callback url
  257. *
  258. * @param string $callback
  259. *
  260. * @throws InvalidArgumentException
  261. */
  262. protected function setCallback($callback)
  263. {
  264. if (!filter_var($callback, FILTER_VALIDATE_URL)) {
  265. throw new InvalidArgumentException('A valid callback url is required.');
  266. }
  267. $this->callback = $callback;
  268. }
  269. /**
  270. * Overwrite Adapter's API endpoints
  271. *
  272. * @param array|Data\Collection $endpoints
  273. */
  274. protected function setApiEndpoints($endpoints = null)
  275. {
  276. if (empty($endpoints)) {
  277. return;
  278. }
  279. $collection = is_array($endpoints) ? new Data\Collection($endpoints) : $endpoints;
  280. $this->apiBaseUrl = $collection->get('api_base_url') ?: $this->apiBaseUrl;
  281. $this->authorizeUrl = $collection->get('authorize_url') ?: $this->authorizeUrl;
  282. $this->accessTokenUrl = $collection->get('access_token_url') ?: $this->accessTokenUrl;
  283. }
  284. /**
  285. * Validate signed API responses Http status code.
  286. *
  287. * Since the specifics of error responses is beyond the scope of RFC6749 and OAuth Core specifications,
  288. * Hybridauth will consider any HTTP status code that is different than '200 OK' as an ERROR.
  289. *
  290. * @param string $error String to pre append to message thrown in exception
  291. *
  292. * @throws HttpClientFailureException
  293. * @throws HttpRequestFailedException
  294. */
  295. protected function validateApiResponse($error = '')
  296. {
  297. $error .= !empty($error) ? '. ' : '';
  298. if ($this->httpClient->getResponseClientError()) {
  299. throw new HttpClientFailureException(
  300. $error . 'HTTP client error: ' . $this->httpClient->getResponseClientError() . '.'
  301. );
  302. }
  303. // if validateApiResponseHttpCode is set to false, we by pass verification of http status code
  304. if (!$this->validateApiResponseHttpCode) {
  305. return;
  306. }
  307. $status = $this->httpClient->getResponseHttpCode();
  308. if ($status < 200 || $status > 299) {
  309. throw new HttpRequestFailedException(
  310. $error . 'HTTP error ' . $this->httpClient->getResponseHttpCode() .
  311. '. Raw Provider API response: ' . $this->httpClient->getResponseBody() . '.'
  312. );
  313. }
  314. }
  315. }