PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/php-soundcloud/Soundcloud.php

https://gitlab.com/x33n/ampache
PHP | 1004 lines | 423 code | 109 blank | 472 comment | 33 complexity | 8191179f67c688ed7e242d8e0910f2a1 MD5 | raw file
  1. <?php
  2. require_once 'Soundcloud/Exception.php';
  3. require_once 'Soundcloud/Version.php';
  4. /**
  5. * SoundCloud API wrapper with support for authentication using OAuth 2
  6. *
  7. * @category Services
  8. * @package Services_Soundcloud
  9. * @author Anton Lindqvist <anton@qvister.se>
  10. * @copyright 2010 Anton Lindqvist <anton@qvister.se>
  11. * @license http://www.opensource.org/licenses/mit-license.php MIT
  12. * @link http://github.com/mptre/php-soundcloud
  13. */
  14. class Services_Soundcloud
  15. {
  16. /**
  17. * Custom cURL option
  18. *
  19. * @var integer
  20. *
  21. * @access public
  22. */
  23. const CURLOPT_OAUTH_TOKEN = 173;
  24. /**
  25. * Access token returned by the service provider after a successful authentication
  26. *
  27. * @var string
  28. *
  29. * @access private
  30. */
  31. private $_accessToken;
  32. /**
  33. * Version of the API to use
  34. *
  35. * @var integer
  36. *
  37. * @access private
  38. * @static
  39. */
  40. private static $_apiVersion = 1;
  41. /**
  42. * Supported audio MIME types
  43. *
  44. * @var array
  45. *
  46. * @access private
  47. * @static
  48. */
  49. private static $_audioMimeTypes = array(
  50. 'aac' => 'video/mp4',
  51. 'aiff' => 'audio/x-aiff',
  52. 'flac' => 'audio/flac',
  53. 'mp3' => 'audio/mpeg',
  54. 'ogg' => 'audio/ogg',
  55. 'wav' => 'audio/x-wav'
  56. );
  57. /**
  58. * OAuth client id
  59. *
  60. * @var string
  61. *
  62. * @access private
  63. */
  64. private $_clientId;
  65. /**
  66. * OAuth client secret
  67. *
  68. * @var string
  69. *
  70. * @access private
  71. */
  72. private $_clientSecret;
  73. /**
  74. * Default cURL options
  75. *
  76. * @var array
  77. *
  78. * @access private
  79. * @static
  80. */
  81. private static $_curlDefaultOptions = array(
  82. CURLOPT_HEADER => true,
  83. CURLOPT_RETURNTRANSFER => true,
  84. CURLOPT_USERAGENT => '',
  85. CURLOPT_FOLLOWLOCATION => true
  86. );
  87. /**
  88. * cURL options
  89. *
  90. * @var array
  91. *
  92. * @access private
  93. */
  94. private $_curlOptions;
  95. /**
  96. * Development mode
  97. *
  98. * @var boolean
  99. *
  100. * @access private
  101. */
  102. private $_development;
  103. /**
  104. * Available API domains
  105. *
  106. * @var array
  107. *
  108. * @access private
  109. * @static
  110. */
  111. private static $_domains = array(
  112. 'development' => 'sandbox-soundcloud.com',
  113. 'production' => 'soundcloud.com'
  114. );
  115. /**
  116. * HTTP response body from the last request
  117. *
  118. * @var string
  119. *
  120. * @access private
  121. */
  122. private $_lastHttpResponseBody;
  123. /**
  124. * HTTP response code from the last request
  125. *
  126. * @var integer
  127. *
  128. * @access private
  129. */
  130. private $_lastHttpResponseCode;
  131. /**
  132. * HTTP response headers from last request
  133. *
  134. * @var array
  135. *
  136. * @access private
  137. */
  138. private $_lastHttpResponseHeaders;
  139. /**
  140. * OAuth paths
  141. *
  142. * @var array
  143. *
  144. * @access private
  145. * @static
  146. */
  147. private static $_paths = array(
  148. 'authorize' => 'connect',
  149. 'access_token' => 'oauth2/token',
  150. );
  151. /**
  152. * OAuth redirect URI
  153. *
  154. * @var string
  155. *
  156. * @access private
  157. */
  158. private $_redirectUri;
  159. /**
  160. * API response format MIME type
  161. *
  162. * @var string
  163. *
  164. * @access private
  165. */
  166. private $_requestFormat;
  167. /**
  168. * Available response formats
  169. *
  170. * @var array
  171. *
  172. * @access private
  173. * @static
  174. */
  175. private static $_responseFormats = array(
  176. '*' => '*/*',
  177. 'json' => 'application/json',
  178. 'xml' => 'application/xml'
  179. );
  180. /**
  181. * HTTP user agent
  182. *
  183. * @var string
  184. *
  185. * @access private
  186. * @static
  187. */
  188. private static $_userAgent = 'PHP-SoundCloud';
  189. /**
  190. * Class constructor
  191. *
  192. * @param string $clientId OAuth client id
  193. * @param string $clientSecret OAuth client secret
  194. * @param string $redirectUri OAuth redirect URI
  195. * @param boolean $development Sandbox mode
  196. *
  197. * @return void
  198. * @throws Services_Soundcloud_Missing_Client_Id_Exception
  199. *
  200. * @access public
  201. */
  202. function __construct($clientId, $clientSecret, $redirectUri = null, $development = false)
  203. {
  204. if (empty($clientId)) {
  205. throw new Services_Soundcloud_Missing_Client_Id_Exception();
  206. }
  207. $this->_clientId = $clientId;
  208. $this->_clientSecret = $clientSecret;
  209. $this->_redirectUri = $redirectUri;
  210. $this->_development = $development;
  211. $this->_responseFormat = self::$_responseFormats['json'];
  212. $this->_curlOptions = self::$_curlDefaultOptions;
  213. $this->_curlOptions[CURLOPT_USERAGENT] .= $this->_getUserAgent();
  214. }
  215. /**
  216. * Get authorization URL
  217. *
  218. * @param array $params Optional query string parameters
  219. *
  220. * @return string
  221. *
  222. * @access public
  223. * @see Soundcloud::_buildUrl()
  224. */
  225. function getAuthorizeUrl($params = array())
  226. {
  227. $defaultParams = array(
  228. 'client_id' => $this->_clientId,
  229. 'redirect_uri' => $this->_redirectUri,
  230. 'response_type' => 'code'
  231. );
  232. $params = array_merge($defaultParams, $params);
  233. return $this->_buildUrl(self::$_paths['authorize'], $params, false);
  234. }
  235. /**
  236. * Get access token URL
  237. *
  238. * @param array $params Optional query string parameters
  239. *
  240. * @return string
  241. *
  242. * @access public
  243. * @see Soundcloud::_buildUrl()
  244. */
  245. function getAccessTokenUrl($params = array())
  246. {
  247. return $this->_buildUrl(self::$_paths['access_token'], $params, false);
  248. }
  249. /**
  250. * Retrieve access token through credentials flow
  251. *
  252. * @param string $username Username
  253. * @param string $password Password
  254. *
  255. * @return mixed
  256. *
  257. * @access public
  258. */
  259. function credentialsFlow($username, $password)
  260. {
  261. $postData = array(
  262. 'client_id' => $this->_clientId,
  263. 'client_secret' => $this->_clientSecret,
  264. 'username' => $username,
  265. 'password' => $password,
  266. 'grant_type' => 'password'
  267. );
  268. $options = array(CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData);
  269. $response = json_decode(
  270. $this->_request($this->getAccessTokenUrl(), $options),
  271. true
  272. );
  273. if (array_key_exists('access_token', $response)) {
  274. $this->_accessToken = $response['access_token'];
  275. return $response;
  276. } else {
  277. return false;
  278. }
  279. }
  280. /**
  281. * Retrieve access token
  282. *
  283. * @param string $code Optional OAuth code returned from the service provider
  284. * @param array $postData Optional post data
  285. * @param array $curlOptions Optional cURL options
  286. *
  287. * @return mixed
  288. *
  289. * @access public
  290. * @see Soundcloud::_getAccessToken()
  291. */
  292. function accessToken($code = null, $postData = array(), $curlOptions = array())
  293. {
  294. $defaultPostData = array(
  295. 'code' => $code,
  296. 'client_id' => $this->_clientId,
  297. 'client_secret' => $this->_clientSecret,
  298. 'redirect_uri' => $this->_redirectUri,
  299. 'grant_type' => 'authorization_code'
  300. );
  301. $postData = array_filter(array_merge($defaultPostData, $postData));
  302. return $this->_getAccessToken($postData, $curlOptions);
  303. }
  304. /**
  305. * Refresh access token
  306. *
  307. * @param string $refreshToken The token to refresh
  308. * @param array $postData Optional post data
  309. * @param array $curlOptions Optional cURL options
  310. *
  311. * @return mixed
  312. * @see Soundcloud::_getAccessToken()
  313. *
  314. * @access public
  315. */
  316. function accessTokenRefresh($refreshToken, $postData = array(), $curlOptions = array())
  317. {
  318. $defaultPostData = array(
  319. 'refresh_token' => $refreshToken,
  320. 'client_id' => $this->_clientId,
  321. 'client_secret' => $this->_clientSecret,
  322. 'redirect_uri' => $this->_redirectUri,
  323. 'grant_type' => 'refresh_token'
  324. );
  325. $postData = array_merge($defaultPostData, $postData);
  326. return $this->_getAccessToken($postData, $curlOptions);
  327. }
  328. /**
  329. * Get access token
  330. *
  331. * @return mixed
  332. *
  333. * @access public
  334. */
  335. function getAccessToken()
  336. {
  337. return $this->_accessToken;
  338. }
  339. /**
  340. * Get API version
  341. *
  342. * @return integer
  343. *
  344. * @access public
  345. */
  346. function getApiVersion()
  347. {
  348. return self::$_apiVersion;
  349. }
  350. /**
  351. * Get the corresponding MIME type for a given file extension
  352. *
  353. * @param string $extension Given extension
  354. *
  355. * @return string
  356. * @throws Services_Soundcloud_Unsupported_Audio_Format_Exception
  357. *
  358. * @access public
  359. */
  360. function getAudioMimeType($extension)
  361. {
  362. if (array_key_exists($extension, self::$_audioMimeTypes)) {
  363. return self::$_audioMimeTypes[$extension];
  364. } else {
  365. throw new Services_Soundcloud_Unsupported_Audio_Format_Exception();
  366. }
  367. }
  368. /**
  369. * Get cURL options
  370. *
  371. * @param string $key Optional options key
  372. *
  373. * @return mixed
  374. *
  375. * @access public
  376. */
  377. function getCurlOptions($key = null)
  378. {
  379. if ($key) {
  380. return (array_key_exists($key, $this->_curlOptions))
  381. ? $this->_curlOptions[$key]
  382. : false;
  383. } else {
  384. return $this->_curlOptions;
  385. }
  386. }
  387. /**
  388. * Get development mode
  389. *
  390. * @return boolean
  391. *
  392. * @access public
  393. */
  394. function getDevelopment()
  395. {
  396. return $this->_development;
  397. }
  398. /**
  399. * Get HTTP response header
  400. *
  401. * @param string $header Name of the header
  402. *
  403. * @return mixed
  404. *
  405. * @access public
  406. */
  407. function getHttpHeader($header)
  408. {
  409. if (is_array($this->_lastHttpResponseHeaders)
  410. && array_key_exists($header, $this->_lastHttpResponseHeaders)
  411. ) {
  412. return $this->_lastHttpResponseHeaders[$header];
  413. } else {
  414. return false;
  415. }
  416. }
  417. /**
  418. * Get redirect URI
  419. *
  420. * @return string
  421. *
  422. * @access public
  423. */
  424. function getRedirectUri()
  425. {
  426. return $this->_redirectUri;
  427. }
  428. /**
  429. * Get response format
  430. *
  431. * @return string
  432. *
  433. * @access public
  434. */
  435. function getResponseFormat()
  436. {
  437. return $this->_responseFormat;
  438. }
  439. /**
  440. * Set access token
  441. *
  442. * @param string $accessToken Access token
  443. *
  444. * @return object
  445. *
  446. * @access public
  447. */
  448. function setAccessToken($accessToken)
  449. {
  450. $this->_accessToken = $accessToken;
  451. return $this;
  452. }
  453. /**
  454. * Set cURL options
  455. *
  456. * The method accepts arguments in two ways.
  457. *
  458. * You could pass two arguments when adding a single option.
  459. * <code>
  460. * $soundcloud->setCurlOptions(CURLOPT_SSL_VERIFYHOST, 0);
  461. * </code>
  462. *
  463. * You could also pass an associative array when adding multiple options.
  464. * <code>
  465. * $soundcloud->setCurlOptions(array(
  466. * CURLOPT_SSL_VERIFYHOST => 0,
  467. * CURLOPT_SSL_VERIFYPEER => 0
  468. * ));
  469. * </code>
  470. *
  471. * @return object
  472. *
  473. * @access public
  474. */
  475. function setCurlOptions()
  476. {
  477. $args = func_get_args();
  478. $options = (is_array($args[0]))
  479. ? $args[0]
  480. : array($args[0] => $args[1]);
  481. foreach ($options as $key => $val) {
  482. $this->_curlOptions[$key] = $val;
  483. }
  484. return $this;
  485. }
  486. /**
  487. * Set redirect URI
  488. *
  489. * @param string $redirectUri Redirect URI
  490. *
  491. * @return object
  492. *
  493. * @access public
  494. */
  495. function setRedirectUri($redirectUri)
  496. {
  497. $this->_redirectUri = $redirectUri;
  498. return $this;
  499. }
  500. /**
  501. * Set response format
  502. *
  503. * @param string $format Response format, could either be XML or JSON
  504. *
  505. * @return object
  506. * @throws Services_Soundcloud_Unsupported_Response_Format_Exception
  507. *
  508. * @access public
  509. */
  510. function setResponseFormat($format)
  511. {
  512. if (array_key_exists($format, self::$_responseFormats)) {
  513. $this->_responseFormat = self::$_responseFormats[$format];
  514. } else {
  515. throw new Services_Soundcloud_Unsupported_Response_Format_Exception();
  516. }
  517. return $this;
  518. }
  519. /**
  520. * Set development mode
  521. *
  522. * @param boolean $development Development mode
  523. *
  524. * @return object
  525. *
  526. * @access public
  527. */
  528. function setDevelopment($development)
  529. {
  530. $this->_development = $development;
  531. return $this;
  532. }
  533. /**
  534. * Send a GET HTTP request
  535. *
  536. * @param string $path Request path
  537. * @param array $params Optional query string parameters
  538. * @param array $curlOptions Optional cURL options
  539. *
  540. * @return mixed
  541. *
  542. * @access public
  543. * @see Soundcloud::_request()
  544. */
  545. function get($path, $params = array(), $curlOptions = array())
  546. {
  547. $url = $this->_buildUrl($path, $params);
  548. return $this->_request($url, $curlOptions);
  549. }
  550. /**
  551. * Send a POST HTTP request
  552. *
  553. * @param string $path Request path
  554. * @param array $postData Optional post data
  555. * @param array $curlOptions Optional cURL options
  556. *
  557. * @return mixed
  558. *
  559. * @access public
  560. * @see Soundcloud::_request()
  561. */
  562. function post($path, $postData = array(), $curlOptions = array())
  563. {
  564. $url = $this->_buildUrl($path);
  565. $options = array(CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData);
  566. $options += $curlOptions;
  567. return $this->_request($url, $options);
  568. }
  569. /**
  570. * Send a PUT HTTP request
  571. *
  572. * @param string $path Request path
  573. * @param array $postData Optional post data
  574. * @param array $curlOptions Optional cURL options
  575. *
  576. * @return mixed
  577. *
  578. * @access public
  579. * @see Soundcloud::_request()
  580. */
  581. function put($path, $postData, $curlOptions = array())
  582. {
  583. $url = $this->_buildUrl($path);
  584. $options = array(
  585. CURLOPT_CUSTOMREQUEST => 'PUT',
  586. CURLOPT_POSTFIELDS => $postData
  587. );
  588. $options += $curlOptions;
  589. return $this->_request($url, $options);
  590. }
  591. /**
  592. * Send a DELETE HTTP request
  593. *
  594. * @param string $path Request path
  595. * @param array $params Optional query string parameters
  596. * @param array $curlOptions Optional cURL options
  597. *
  598. * @return mixed
  599. *
  600. * @access public
  601. * @see Soundcloud::_request()
  602. */
  603. function delete($path, $params = array(), $curlOptions = array())
  604. {
  605. $url = $this->_buildUrl($path, $params);
  606. $options = array(CURLOPT_CUSTOMREQUEST => 'DELETE');
  607. $options += $curlOptions;
  608. return $this->_request($url, $options);
  609. }
  610. /**
  611. * Download track
  612. *
  613. * @param integer $trackId Track id to download
  614. * @param array $params Optional query string parameters
  615. * @param array $curlOptions Optional cURL options
  616. *
  617. * @return mixed
  618. *
  619. * @access public
  620. * @see Soundcloud::_request()
  621. */
  622. function download($trackId, $params = array(), $curlOptions = array())
  623. {
  624. $lastResponseFormat = array_pop(explode('/', $this->getResponseFormat()));
  625. $defaultParams = array('oauth_token' => $this->getAccessToken());
  626. $defaultCurlOptions = array(
  627. CURLOPT_FOLLOWLOCATION => true,
  628. self::CURLOPT_OAUTH_TOKEN => false
  629. );
  630. $url = $this->_buildUrl(
  631. 'tracks/' . $trackId . '/download',
  632. array_merge($defaultParams, $params)
  633. );
  634. $options = $defaultCurlOptions + $curlOptions;
  635. $this->setResponseFormat('*');
  636. $response = $this->_request($url, $options);
  637. // rollback to the previously defined response format.
  638. $this->setResponseFormat($lastResponseFormat);
  639. return $response;
  640. }
  641. function stream($trackId, $params = array(), $curlOptions = array())
  642. {
  643. $lastResponseFormat = array_pop(explode('/', $this->getResponseFormat()));
  644. $defaultParams = array('oauth_token' => $this->getAccessToken());
  645. $defaultCurlOptions = array(
  646. CURLOPT_FOLLOWLOCATION => false,
  647. self::CURLOPT_OAUTH_TOKEN => false,
  648. );
  649. $url = $this->_buildUrl(
  650. 'tracks/' . $trackId . '/stream',
  651. array_merge($defaultParams, $params),
  652. false
  653. );
  654. $options = $defaultCurlOptions + $curlOptions;
  655. $this->setResponseFormat('*');
  656. $response = $this->_request($url, $options, true);
  657. // rollback to the previously defined response format.
  658. $this->setResponseFormat($lastResponseFormat);
  659. return $this->get_headers_from_curl_response($response);
  660. }
  661. function get_headers_from_curl_response($response)
  662. {
  663. $headers = array();
  664. $header_text = substr($response, 0, strpos($response, "\r\n\r\n"));
  665. foreach (explode("\r\n", $header_text) as $i => $line)
  666. if ($i === 0)
  667. $headers['http_code'] = $line;
  668. else
  669. {
  670. list ($key, $value) = explode(': ', $line);
  671. $headers[$key] = $value;
  672. }
  673. return $headers;
  674. }
  675. /**
  676. * Update a existing playlist
  677. *
  678. * @param integer $playlistId The playlist id
  679. * @param array $trackIds Tracks to add to the playlist
  680. * @param array $optionalPostData Optional playlist fields to update
  681. *
  682. * @return mixed
  683. *
  684. * @access public
  685. * @see Soundcloud::_request()
  686. */
  687. public function updatePlaylist($playlistId, $trackIds, $optionalPostData = null)
  688. {
  689. $url = $this->_buildUrl('playlists/' . $playlistId);
  690. $postData = array();
  691. foreach ($trackIds as $trackId) {
  692. array_push($postData, 'playlist[tracks][][id]=' . $trackId);
  693. }
  694. if (is_array($optionalPostData)) {
  695. foreach ($optionalPostData as $key => $val) {
  696. array_push($postData, 'playlist[' . $key . ']=' . $val);
  697. }
  698. }
  699. $postData = implode('&', $postData);
  700. $curlOptions = array(
  701. CURLOPT_CUSTOMREQUEST => 'PUT',
  702. CURLOPT_HTTPHEADER => array('Content-Length' => strlen($postData)),
  703. CURLOPT_POSTFIELDS => $postData
  704. );
  705. return $this->_request($url, $curlOptions);
  706. }
  707. /**
  708. * Construct default HTTP request headers
  709. *
  710. * @param boolean $includeAccessToken Include access token
  711. *
  712. * @return array $headers
  713. *
  714. * @access protected
  715. */
  716. protected function _buildDefaultHeaders($includeAccessToken = true)
  717. {
  718. $headers = array();
  719. if ($this->_responseFormat) {
  720. array_push($headers, 'Accept: ' . $this->_responseFormat);
  721. }
  722. if ($includeAccessToken && $this->_accessToken) {
  723. array_push($headers, 'Authorization: OAuth ' . $this->_accessToken);
  724. }
  725. return $headers;
  726. }
  727. /**
  728. * Construct a URL
  729. *
  730. * @param string $path Relative or absolute URI
  731. * @param array $params Optional query string parameters
  732. * @param boolean $includeVersion Include API version
  733. *
  734. * @return string $url
  735. *
  736. * @access protected
  737. */
  738. protected function _buildUrl($path, $params = array(), $includeVersion = true)
  739. {
  740. if (!$this->_accessToken) {
  741. $params['consumer_key'] = $this->_clientId;
  742. }
  743. if (preg_match('/^https?\:\/\//', $path)) {
  744. $url = $path;
  745. } else {
  746. $url = 'https://';
  747. $url .= (!preg_match('/connect/', $path)) ? 'api.' : '';
  748. $url .= ($this->_development)
  749. ? self::$_domains['development']
  750. : self::$_domains['production'];
  751. $url .= '/';
  752. $url .= ($includeVersion) ? 'v' . self::$_apiVersion . '/' : '';
  753. $url .= $path;
  754. }
  755. $url .= (count($params)) ? '?' . http_build_query($params) : '';
  756. return $url;
  757. }
  758. /**
  759. * Retrieve access token
  760. *
  761. * @param array $postData Post data
  762. * @param array $curlOptions Optional cURL options
  763. *
  764. * @return mixed
  765. *
  766. * @access protected
  767. */
  768. protected function _getAccessToken($postData, $curlOptions = array())
  769. {
  770. $options = array(CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData);
  771. $options += $curlOptions;
  772. $response = json_decode(
  773. $this->_request($this->getAccessTokenUrl(), $options),
  774. true
  775. );
  776. if (array_key_exists('access_token', $response)) {
  777. $this->_accessToken = $response['access_token'];
  778. return $response;
  779. } else {
  780. return false;
  781. }
  782. }
  783. /**
  784. * Get HTTP user agent
  785. *
  786. * @return string
  787. *
  788. * @access protected
  789. */
  790. protected function _getUserAgent()
  791. {
  792. return self::$_userAgent . '/' . new Services_Soundcloud_Version;
  793. }
  794. /**
  795. * Parse HTTP headers
  796. *
  797. * @param string $headers HTTP headers
  798. *
  799. * @return array $parsedHeaders
  800. *
  801. * @access protected
  802. */
  803. protected function _parseHttpHeaders($headers)
  804. {
  805. $headers = explode("\n", trim($headers));
  806. $parsedHeaders = array();
  807. foreach ($headers as $header) {
  808. if (!preg_match('/\:\s/', $header)) {
  809. continue;
  810. }
  811. list($key, $val) = explode(': ', $header, 2);
  812. $key = str_replace('-', '_', strtolower($key));
  813. $val = trim($val);
  814. $parsedHeaders[$key] = $val;
  815. }
  816. return $parsedHeaders;
  817. }
  818. /**
  819. * Validate HTTP response code
  820. *
  821. * @param integer $code HTTP code
  822. *
  823. * @return boolean
  824. *
  825. * @access protected
  826. */
  827. protected function _validResponseCode($code)
  828. {
  829. return (bool)preg_match('/^20[0-9]{1}$/', $code);
  830. }
  831. /**
  832. * Performs the actual HTTP request using cURL
  833. *
  834. * @param string $url Absolute URL to request
  835. * @param array $curlOptions Optional cURL options
  836. *
  837. * @return mixed
  838. * @throws Services_Soundcloud_Invalid_Http_Response_Code_Exception
  839. *
  840. * @access protected
  841. */
  842. protected function _request($url, $curlOptions = array(), $raw = false)
  843. {
  844. $ch = curl_init($url);
  845. $options = $this->_curlOptions;
  846. foreach ($curlOptions as $key => $value) {
  847. $options[$key] = $value;
  848. }
  849. if (array_key_exists(self::CURLOPT_OAUTH_TOKEN, $options)) {
  850. $includeAccessToken = $options[self::CURLOPT_OAUTH_TOKEN];
  851. unset($options[self::CURLOPT_OAUTH_TOKEN]);
  852. } else {
  853. $includeAccessToken = true;
  854. }
  855. if (array_key_exists(CURLOPT_HTTPHEADER, $options)) {
  856. $options[CURLOPT_HTTPHEADER] = array_merge(
  857. $this->_buildDefaultHeaders(),
  858. $curlOptions[CURLOPT_HTTPHEADER]
  859. );
  860. } else {
  861. $options[CURLOPT_HTTPHEADER] = $this->_buildDefaultHeaders(
  862. $includeAccessToken
  863. );
  864. }
  865. $options[CURLOPT_SSL_VERIFYPEER] = false;
  866. $options[CURLOPT_SSL_VERIFYHOST] = false;
  867. curl_setopt_array($ch, $options);
  868. $data = curl_exec($ch);
  869. $info = curl_getinfo($ch);
  870. curl_close($ch);
  871. if ($raw) {
  872. return $data;
  873. }
  874. if (array_key_exists(CURLOPT_HEADER, $options) && $options[CURLOPT_HEADER]) {
  875. $this->_lastHttpResponseHeaders = $this->_parseHttpHeaders(
  876. substr($data, 0, $info['header_size'])
  877. );
  878. $this->_lastHttpResponseBody = substr($data, $info['header_size']);
  879. } else {
  880. $this->_lastHttpResponseHeaders = array();
  881. $this->_lastHttpResponseBody = $data;
  882. }
  883. $this->_lastHttpResponseCode = $info['http_code'];
  884. if ($this->_validResponseCode($this->_lastHttpResponseCode)) {
  885. return $this->_lastHttpResponseBody;
  886. } else {
  887. throw new Services_Soundcloud_Invalid_Http_Response_Code_Exception(
  888. null,
  889. 0,
  890. $this->_lastHttpResponseBody,
  891. $this->_lastHttpResponseCode
  892. );
  893. }
  894. }
  895. }