diff --git a/.travis.yml b/.travis.yml index fed5f4a8..59cc4fbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: php php: - - 5.3.29 - - 5.4 - 5.5 - 5.6 - hhvm diff --git a/Makefile b/Makefile index c17c4302..08c97aee 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ all: .PHONY: install install: - composer install --prefer-source --no-interaction + composer install --prefer-dist --no-interaction .PHONY: coveralls coveralls: diff --git a/README.md b/README.md index b1fcb44f..456b1355 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # Requirements -- PHP 5.3.29+ +- PHP 5.5+ - CURL extension - MCrypt extension @@ -205,7 +205,7 @@ $response = $platform->sendRequest($request); # How to demo? -Clone the repo and create a file `demo/_credentials.php`: +Clone the repo and create a file `demo/_credentials.php` copy the contents from the file 'demo/_credentialsSample.php' as shown below: ```php return array( @@ -217,6 +217,8 @@ return array( 'server' => 'https://platform.devtest.ringcentral.com', // for production - https://platform.ringcentral.com 'smsNumber' => '18882223344', // any of SMS-enabled numbers on your RingCentral account 'mobileNumber' => '16501112233', // your own mobile number to which script will send sms + 'dateFrom' => 'yyyy-mm-dd', + 'dateTo' => 'yyyy-mm-dd' ); ``` diff --git a/composer.json b/composer.json index fb7379bd..280051b1 100755 --- a/composer.json +++ b/composer.json @@ -24,10 +24,11 @@ ], "require": { "ext-curl": "*", - "php": ">=5.3.29", - "ringcentral/psr7": "^1.2.0", - "pubnub/pubnub": "~3.7", - "symfony/event-dispatcher": "^2.7" + "php": ">=5.5.0", + "guzzlehttp/psr7": "^1.2.3", + "pubnub/pubnub": "^3.8.1", + "symfony/event-dispatcher": "^3.0.4", + "guzzlehttp/guzzle": "^6.2" }, "require-dev": { "phpunit/phpunit": "*", diff --git a/demo/_credentialsSample.php b/demo/_credentialsSample.php index 0081c719..2d327914 100644 --- a/demo/_credentialsSample.php +++ b/demo/_credentialsSample.php @@ -1,10 +1,14 @@ + '18881112233', // your RingCentral account phone number - 'extension' => null, // or number + 'username' => '18881112233', // your RingCentral account phone number + 'extension' => null, // or number 'password' => 'yourPassword', 'appKey' => 'yourAppKey', 'appSecret' => 'yourAppSecret', - 'server' => 'https: //platform.devtest.ringcentral.com', // for production - https://platform.ringcentral.com - 'smsNumber' => '18882223344', // any of SMS-enabled numbers on your RingCentral account - 'mobileNumber' => '16501112233', // your own mobile number to which script will send sms + 'server' => 'https://platform.devtest.ringcentral.com', // for production - https://platform.ringcentral.com + 'smsNumber' => '18882223344', // any of SMS-enabled numbers on your RingCentral account + 'mobileNumber' => '16501112233', // your own mobile number to which script will send sms + 'dateFrom' => 'yyyy-mm-dd', // dateFrom + 'dateTo' => 'yyyy-mm-dd' // dateTo ); \ No newline at end of file diff --git a/demo/authData.php b/demo/authData.php index a41c2868..413f48d3 100644 --- a/demo/authData.php +++ b/demo/authData.php @@ -4,7 +4,6 @@ use RingCentral\SDK\SDK; - // Create SDK instance $credentials = require(__DIR__ . '/_credentials.php'); diff --git a/demo/callRecording.php b/demo/callRecording.php index c5791e1e..87b14e06 100644 --- a/demo/callRecording.php +++ b/demo/callRecording.php @@ -5,10 +5,12 @@ use RingCentral\SDK\SDK; + // Create SDK instance $credentials = require(__DIR__ . '/_credentials.php'); + $rcsdk = new SDK($credentials['appKey'], $credentials['appSecret'], $credentials['server'], 'Demo', '1.0.0'); $platform = $rcsdk->platform(); @@ -31,41 +33,34 @@ $status = "Success"; $dir = $credentials['dateFrom']; $fname = "recordings_${dir}.csv"; - $fdir = "/DownloadRecordings/Recordings/${dir}"; - - // check if the directory exists - // mkdir('/AllianceRecordings/Recordings/${dir}', 0700); + $fdir = "/Recordings/${dir}"; if (is_dir($fdir) === false) { mkdir($fdir, 0777, true); - // mkdir("/AllianceRecordings/JSON/${dir}", 0755, true); } $file = fopen($fname,'w'); + $fileHeaders = array("RecordingID","ContentURI","Filename","DownloadStatus"); + fputcsv($file, $fileHeaders); - $fileContents = array(); + $fileContents = array(); - $timePerRecording = 6; - + foreach ($callLogRecords as $i => $callLogRecord) { $id = $callLogRecord->recording->id; - - print "Downloading Call Log Record ${id}" . PHP_EOL; - $uri = $callLogRecord->recording->contentUri; - print "The contentURI is : ${uri}"; + $uri = $callLogRecord->recording->contentUri; - print "Retrieving ${uri}" . PHP_EOL; $apiResponse = $platform->get($callLogRecord->recording->contentUri); - + $ext = ($apiResponse->response()->getHeader('Content-Type')[0] == 'audio/mpeg') ? 'mp3' : 'wav'; @@ -79,12 +74,8 @@ $status = "failure"; } - print "Wrote Recording for Call Log Record ${id}" . PHP_EOL; - file_put_contents("${fdir}/recording_${id}.json", json_encode($callLogRecord)); - print "Wrote Metadata for Call Log Record ${id}" . PHP_EOL; - $end=microtime(true); // Check if the recording completed wihtin 6 seconds. @@ -93,7 +84,6 @@ sleep($timePerRecording-$time); } - $fileContents = array($id, $uri, $filename, $status); fputcsv($file, $fileContents); diff --git a/demo/extensions.php b/demo/extensions.php index 2212320c..2a7fa1de 100644 --- a/demo/extensions.php +++ b/demo/extensions.php @@ -4,7 +4,6 @@ use RingCentral\SDK\SDK; - // Create SDK instance $credentials = require(__DIR__ . '/_credentials.php'); diff --git a/demo/fax.php b/demo/fax.php index 8bf92127..3954051d 100644 --- a/demo/fax.php +++ b/demo/fax.php @@ -4,7 +4,6 @@ use RingCentral\SDK\SDK; - // Create SDK instance $credentials = require(__DIR__ . '/_credentials.php'); diff --git a/demo/subscription.php b/demo/subscription.php index 40db5a30..cb8feadf 100644 --- a/demo/subscription.php +++ b/demo/subscription.php @@ -4,10 +4,12 @@ use RingCentral\SDK\SDK; use RingCentral\SDK\Subscription\Events\NotificationEvent; +use RingCentral\SDK\Subscription\Events\SuccessEvent; use RingCentral\SDK\Subscription\Subscription; -// Create SDK instance +$credentials = require('_credentials.php'); + $credentials = require(__DIR__ . '/_credentials.php'); @@ -24,8 +26,9 @@ $subscription = $rcsdk->createSubscription(); $subscription->addEvents(array( - '/account/~/extension/~/message-store', - '/account/~/extension/~/presence')); + '/account/~/extension/~/message-store', + '/account/~/extension/~/presence' +)); $subscription->setKeepPolling(true); @@ -35,10 +38,14 @@ print 'Subscribing' . PHP_EOL; +$subscription->addListener(Subscription::EVENT_TIMEOUT, function () { + print 'Timeout' . PHP_EOL; +}); + +$subscription->addListener(Subscription::EVENT_RENEW_SUCCESS, function (SuccessEvent $e) { + print 'Renewed' . PHP_EOL; +}); + $subscription->register(); print 'End' . PHP_EOL; - -while (1>0) { - sleep(1); -} diff --git a/src/Core/Utils.php b/src/Core/Utils.php index fa2bf79f..44e0cfb4 100644 --- a/src/Core/Utils.php +++ b/src/Core/Utils.php @@ -18,6 +18,10 @@ static function json_parse($json = '', $assoc = false, $depth = 512) $parsed = \json_decode($json, $assoc, $depth); + //if (JSON_ERROR_NONE !== json_last_error()) { + // throw new \RuntimeException('JSON Error: Unable to parse into JSON: ' . json_last_error()); + //} + $error = json_last_error(); switch ($error) { diff --git a/src/Http/ApiResponse.php b/src/Http/ApiResponse.php index 5876e4f9..6aa75f1e 100644 --- a/src/Http/ApiResponse.php +++ b/src/Http/ApiResponse.php @@ -32,28 +32,16 @@ class ApiResponse /** @var RequestInterface */ protected $_request; - protected $_raw; - /** * TODO Support strams - * @param RequestInterface $request Reqeuest used to get the response - * @param mixed $body Stream body - * @param int $status Status code for the response, if any + * @param RequestInterface $request Reqeuest used to get the response + * @param ResponseInterface $response Response */ - public function __construct(RequestInterface $request = null, $body = null, $status = 200) + public function __construct(RequestInterface $request = null, ResponseInterface $response = null) { $this->_request = $request; - $this->_raw = $body; - - $body = (string)$body; - - // Make the HTTP message complete - if (substr($body, 0, 5) !== 'HTTP/') { - $body = "HTTP/1.1 " . $status . " OK\r\n" . $body; - } - - $this->_response = \RingCentral\Psr7\parse_response($body); + $this->_response = $response; } @@ -168,7 +156,9 @@ public function multipart() // Step 3. Create status info object $statusInfoPart = array_shift($parts); - $statusInfoObj = new self(null, trim($statusInfoPart), $this->response()->getStatusCode()); + $statusInfoObj = new self(null, + self::createResponse(trim($statusInfoPart), $this->response()->getStatusCode()) + ); $statusInfo = $statusInfoObj->json()->response; // Step 4. Parse all parts into Response objects @@ -177,7 +167,7 @@ public function multipart() $partInfo = $statusInfo[$i]; - $this->_multiparts[] = new self(null, trim($part), $partInfo->status); + $this->_multiparts[] = new self(null, self::createResponse(trim($part), $partInfo->status)); } @@ -267,4 +257,18 @@ protected function getContentType() return $this->response()->getHeaderLine('content-type'); } + static function createResponse($body = '', $status = 200) + { + + // Make the HTTP message complete + if (substr($body, 0, 5) !== 'HTTP/') { + $body = "HTTP/1.1 " . $status . " Foo\r\n" . $body; + } + + $response = \GuzzleHttp\Psr7\parse_response((string)$body); + + return $response->withStatus($status); + + } + } \ No newline at end of file diff --git a/src/Http/ApiResponseTest.php b/src/Http/ApiResponseTest.php index b8d0bdf1..f6413e03 100644 --- a/src/Http/ApiResponseTest.php +++ b/src/Http/ApiResponseTest.php @@ -27,7 +27,7 @@ public function testMultipart() "{\"baz\" : \"qux\"}\n" . "--Boundary_1245_945802293_1394135045248--\n"; - $r = new ApiResponse(null, $goodMultipartMixedResponse, 207); + $r = new ApiResponse(null, ApiResponse::createResponse($goodMultipartMixedResponse, 207)); $parts = $r->multipart(); $this->assertEquals(2, count($parts)); @@ -58,7 +58,7 @@ public function testMultipartWithErrorPart() "{\"message\" : \"object not found\"}\n" . "--Boundary_1245_945802293_1394135045248--\n"; - $r = new ApiResponse(null, $multipartMixedResponseWithErrorPart, 207); + $r = new ApiResponse(null, ApiResponse::createResponse($multipartMixedResponseWithErrorPart, 207)); $parts = $r->multipart(); $this->assertEquals(2, count($parts)); @@ -87,7 +87,7 @@ public function testMultipartCorruptedResponse() "{\"foo\" : \"bar\"}\n" . "--Boundary_1245_945802293_1394135045248--\n"; - $r3 = new ApiResponse(null, $badMultipartMixedResponse, 207); + $r3 = new ApiResponse(null, ApiResponse::createResponse($badMultipartMixedResponse, 207)); $r3->multipart(); } @@ -99,7 +99,7 @@ public function testMultipartCorruptedResponse() public function testMultipartOnNotAMultipartResponse() { - $r3 = new ApiResponse(null, "Content-Type: text/plain\n\nWhatever", 207); + $r3 = new ApiResponse(null, ApiResponse::createResponse("Content-Type: text/plain\n\nWhatever", 207)); $r3->multipart(); } @@ -124,7 +124,7 @@ public function testMultipartWitoutBoundary() "{\"foo\" : \"bar\"}\n" . "--Boundary_1245_945802293_1394135045248--\n"; - $r3 = new ApiResponse(null, $response, 207); + $r3 = new ApiResponse(null, ApiResponse::createResponse($response, 207)); $r3->multipart(); } @@ -132,7 +132,7 @@ public function testMultipartWitoutBoundary() public function testGetJson() { - $r = new ApiResponse(null, "content-type: application/json\n\n{\"foo\":\"bar\"}", 200); + $r = new ApiResponse(null, ApiResponse::createResponse("content-type: application/json\n\n{\"foo\":\"bar\"}", 200)); $this->assertEquals('{"foo":"bar"}', $r->text()); $this->assertEquals('bar', $r->json()->foo); @@ -149,7 +149,7 @@ public function testGetJson() public function testGetJsonWithNotJSON() { - $r = new ApiResponse(null, "content-type: application/not-a-json\n\nfoo", 200); + $r = new ApiResponse(null, ApiResponse::createResponse("content-type: application/not-a-json\n\nfoo", 200)); $r->json(); } @@ -161,7 +161,7 @@ public function testGetJsonWithNotJSON() public function testGetJsonWithCorruptedJSON() { - $r = new ApiResponse(null, "content-type: application/json\n\n{\"foo\";\"bar\"}", 200); + $r = new ApiResponse(null, ApiResponse::createResponse("content-type: application/json\n\n{\"foo\";\"bar\"}", 200)); $r->json(); } @@ -173,7 +173,7 @@ public function testGetJsonWithCorruptedJSON() public function testGetJsonWithEmptyJSON() { - $r = new ApiResponse(null, "content-type: application/json\n\nnull", 200); + $r = new ApiResponse(null, ApiResponse::createResponse("content-type: application/json\n\nnull", 200)); $r->json(); } diff --git a/src/Http/Client.php b/src/Http/Client.php index 1b87c82a..e6dcb841 100644 --- a/src/Http/Client.php +++ b/src/Http/Client.php @@ -3,13 +3,22 @@ namespace RingCentral\SDK\Http; use Exception; -use RingCentral\Psr7\Request; +use GuzzleHttp\Client as GuzzleClient; +use GuzzleHttp\Psr7\Request; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamInterface; class Client { + /** @var GuzzleClient */ + private $_guzzle; + + public function __construct() + { + $this->_guzzle = new GuzzleClient(); + } + /** * @param RequestInterface $request * @return $this @@ -18,15 +27,16 @@ class Client public function send(RequestInterface $request) { - $response = null; + /** @var ApiResponse $apiResponse */ + $apiResponse = null; try { - $response = $this->loadResponse($request); + $apiResponse = $this->loadResponse($request); - if ($response->ok()) { + if ($apiResponse->ok()) { - return $response; + return $apiResponse; } else { @@ -37,11 +47,11 @@ public function send(RequestInterface $request) } catch (Exception $e) { // The following means that request failed completely - if (empty($response)) { - $response = new ApiResponse($request); + if (empty($apiResponse)) { + $apiResponse = new ApiResponse($request); } - throw new ApiException($response, $e); + throw new ApiException($apiResponse, $e); } @@ -55,58 +65,19 @@ public function send(RequestInterface $request) protected function loadResponse(RequestInterface $request) { - $ch = null; - - try { - - $ch = curl_init(); - - if (!$ch) { - throw new Exception('Cannot initialize a cURL handle'); - } - - curl_setopt($ch, CURLOPT_URL, $request->getUri()); - - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->getMethod()); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HEADER, true); - - if (($request->getMethod() == 'PUT' || $request->getMethod() == 'POST')) { - - if (stristr($request->getHeaderLine('Content-Type'), 'multipart/form-data')) { - $request = $request->withHeader('Expect', ''); - } - - if ($request->getBody()->isSeekable()) { - $request->getBody()->rewind(); - } - - } - - curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getRequestHeaders($request)); - - if ($request->getMethod() == 'PUT' || $request->getMethod() == 'POST') { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$request->getBody()); //TODO Handle streams - } - - $body = curl_exec($ch); - - $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - curl_close($ch); - - return new ApiResponse($request, $body, $status); - - } catch (Exception $e) { + //TODO Is it needed? + if (stristr($request->getHeaderLine('Content-Type'), 'multipart/form-data')) { + $request = $request->withHeader('Expect', ''); + } - if ($ch) { - curl_close($ch); - } + //TODO Is it needed? + if ($request->getBody()->isSeekable()) { + $request->getBody()->rewind(); + } - throw $e; + $response = $this->_guzzle->send($request); - } + return new ApiResponse($request, $response); } diff --git a/src/Http/MultipartBuilder.php b/src/Http/MultipartBuilder.php index afaaa91f..82001569 100644 --- a/src/Http/MultipartBuilder.php +++ b/src/Http/MultipartBuilder.php @@ -2,8 +2,8 @@ namespace RingCentral\SDK\Http; -use RingCentral\Psr7\MultipartStream; -use RingCentral\Psr7\Request; +use GuzzleHttp\Psr7\MultipartStream; +use GuzzleHttp\Psr7\Request; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamInterface; @@ -109,7 +109,7 @@ public function add($content, $filename = '', array $headers = array(), $name = } elseif ($content instanceof StreamInterface) { - $type = \RingCentral\Psr7\mimetype_from_filename($basename); + $type = \GuzzleHttp\Psr7\mimetype_from_filename($basename); if (!$type) { throw new \InvalidArgumentException('Content-Type header was not provided and cannot be auto-discovered'); diff --git a/src/Http/MultipartBuilderTest.php b/src/Http/MultipartBuilderTest.php index 22d06b2c..62e84476 100644 --- a/src/Http/MultipartBuilderTest.php +++ b/src/Http/MultipartBuilderTest.php @@ -1,6 +1,6 @@ setBody(array('to' => array('phoneNumber' => 'foo'), 'faxResolution' => 'High')) ->setBoundary('boundary') - ->add(\RingCentral\Psr7\stream_for('streamed'), 'streamed.txt') + ->add(\GuzzleHttp\Psr7\stream_for('streamed'), 'streamed.txt') ->add(new Stream(fopen($this->fname, 'r'))); $this->assertEquals($expected, (string)$builder->request('/fax')->getBody()); @@ -125,7 +125,7 @@ public function testStreamWithNoName() $builder->setBody(array('to' => array('phoneNumber' => 'foo'), 'faxResolution' => 'High')) ->setBoundary('boundary') - ->add(\RingCentral\Psr7\stream_for('streamed')); + ->add(\GuzzleHttp\Psr7\stream_for('streamed')); } @@ -140,7 +140,7 @@ public function testStreamWithUnknownExtension() $builder->setBody(array('to' => array('phoneNumber' => 'foo'), 'faxResolution' => 'High')) ->setBoundary('boundary') - ->add(\RingCentral\Psr7\stream_for('streamed'), 'streamed'); + ->add(\GuzzleHttp\Psr7\stream_for('streamed'), 'streamed'); } diff --git a/src/Mocks/Client.php b/src/Mocks/Client.php index b69b7683..56a661bf 100644 --- a/src/Mocks/Client.php +++ b/src/Mocks/Client.php @@ -16,6 +16,7 @@ class Client extends HttpClient public function __construct(Registry $registry) { $this->_registry = $registry; + parent::__construct(); } /** diff --git a/src/Mocks/Mock.php b/src/Mocks/Mock.php index 0fb8e7cc..783425f2 100644 --- a/src/Mocks/Mock.php +++ b/src/Mocks/Mock.php @@ -2,7 +2,9 @@ namespace RingCentral\SDK\Mocks; +use GuzzleHttp\Psr7\Response; use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; class Mock { @@ -23,11 +25,11 @@ public function __construct($method = 'GET', $path = '', array $json = array(), /** * Factory method that creates Response object based on given Request object * @param RequestInterface $request - * @return string + * @return ResponseInterface */ public function response(RequestInterface $request) { - return self::createBody($this->_json, $this->_status); + return new Response($this->_status, array('content-type' => 'application/json'), json_encode($this->_json)); } public function path() @@ -52,31 +54,4 @@ public function test(RequestInterface $request) ); } - /** - * Helper function to generate response headers + body as text - * @param array $body - * @param int $status - * @param array $headers - * @return string - */ - protected static function createBody( - array $body = array(), - $status = 200, - array $headers = array('content-type' => 'application/json') - ) { - - $res = array('HTTP/1.1 ' . $status . ' ReasonPhrase Not Implemented In Mocks'); - - foreach ($headers as $k => $v) { - $res[] = $k . ': ' . $v; - } - - $res[] = ''; - - $res[] = json_encode($body); - - return join("\n", $res); - - } - } \ No newline at end of file diff --git a/src/Platform/Platform.php b/src/Platform/Platform.php index bd838c0a..87812974 100644 --- a/src/Platform/Platform.php +++ b/src/Platform/Platform.php @@ -3,7 +3,7 @@ namespace RingCentral\SDK\Platform; use Exception; -use RingCentral\Psr7\Uri; +use GuzzleHttp\Psr7\Uri; use Psr\Http\Message\RequestInterface; use RingCentral\SDK\Http\ApiException; use RingCentral\SDK\Http\ApiResponse; @@ -17,6 +17,7 @@ class Platform const REFRESH_TOKEN_TTL = 604800; // 1 week const TOKEN_ENDPOINT = '/restapi/oauth/token'; const REVOKE_ENDPOINT = '/restapi/oauth/revoke'; + const AUTHORIZE_ENDPOINT = '/restapi/oauth/authorize'; const API_VERSION = 'v1.0'; const URL_PREFIX = '/restapi'; @@ -94,6 +95,7 @@ public function createUrl($path = '', $options = array()) } + public function loggedIn() { try { @@ -103,6 +105,48 @@ public function loggedIn() } } + /** + * @param string $options['redirectUri'] + * @param string $options['state'] + * @param string $options['brandId'] + * @param string $options['display'] + * @param string $options['prompt'] + * @param array $options + * @throws ApiException + * @return ApiResponse + */ + public function authUrl($options) + { + + return $this->createUrl(self::AUTHORIZE_ENDPOINT . '?' . http_build_query( + array ( + 'response_type' => 'code', + 'redirect_uri' => $options['redirectUri'] ? $options['redirectUri'] : null, + 'client_id' => $this->_appKey, + 'state' => $options['state'] ? $options['state'] : null, + 'brand_id' => $options['brandId'] ? $options['brandId'] : null, + 'display' => $options['display'] ? $options['display'] : null, + 'prompt' => $options['prompt'] ? $options['prompt'] : null + )), array( + 'addServer' => 'true' + )); + } + + /** + * @param string $url + * @throws ApiException + * @return ApiResponse + */ + public function parseAuthRedirectUrl($url) + { + + parse_str($url,$qsArray); + return array( + 'code' => $qsArray['code'] + ); + } + + /** * @param string $username * @param string $extension @@ -110,16 +154,34 @@ public function loggedIn() * @throws ApiException * @return ApiResponse */ - public function login($username = '', $extension = '', $password = '') + public function login($options) { + + if(is_string($options)){ + $options = array( + 'username' => func_get_arg(0), + 'extension' => func_get_arg(1) ? func_get_arg(1) : null, + 'password' => func_get_arg(2) + ); + } + + $response = !empty($options['code']) ? $this->requestToken(self::TOKEN_ENDPOINT, array( + + 'grant_type' => 'authorization_code', + 'code' => $options['code'], + 'redirect_uri' => $options['redirectUri'], + 'access_token_ttl' => self::ACCESS_TOKEN_TTL, + 'refresh_token_ttl' => self::REFRESH_TOKEN_TTL - $response = $this->requestToken(self::TOKEN_ENDPOINT, array( + )) :$this->requestToken(self::TOKEN_ENDPOINT, array( + 'grant_type' => 'password', - 'username' => $username, - 'extension' => $extension ? $extension : null, - 'password' => $password, + 'username' => $options['username'], + 'extension' => $options['extension'] ? $options['extension'] : null, + 'password' => $options["password"], 'access_token_ttl' => self::ACCESS_TOKEN_TTL, 'refresh_token_ttl' => self::REFRESH_TOKEN_TTL + )); $this->_auth->setData($response->jsonArray()); diff --git a/src/Platform/PlatformTest.php b/src/Platform/PlatformTest.php index 085bd2ac..9ca01b1c 100644 --- a/src/Platform/PlatformTest.php +++ b/src/Platform/PlatformTest.php @@ -1,6 +1,6 @@ observer = new EventDispatcher(); + $this->eventDispatcher = new EventDispatcher(); } public function subscribe($channel, $callback, $timeToken = 0, $presence = false, $timeoutHandler = null) { - $this->observer->addListener('message', function (PubnubEvent $e) use ($callback) { + $this->eventDispatcher->addListener('message', function (PubnubEvent $e) use ($callback) { call_user_func($callback, $e->getData()); }); @@ -31,7 +31,7 @@ public function subscribe($channel, $callback, $timeToken = 0, $presence = false public function receiveMessage($message) { - $this->observer->dispatch('message', new PubnubEvent(array( + $this->eventDispatcher->dispatch('message', new PubnubEvent(array( 'message' => $message, 'channel' => null, 'timeToken' => time() diff --git a/src/SDK.php b/src/SDK.php index b9a707b3..7f0cf027 100644 --- a/src/SDK.php +++ b/src/SDK.php @@ -13,7 +13,7 @@ class SDK { - const VERSION = '1.1.1'; + const VERSION = '2.0.0-rc1'; const SERVER_PRODUCTION = 'https://platform.ringcentral.com'; const SERVER_SANDBOX = 'https://platform.devtest.ringcentral.com'; diff --git a/src/SDKTest.php b/src/SDKTest.php index c97c0e0f..bb4dd3bb 100644 --- a/src/SDKTest.php +++ b/src/SDKTest.php @@ -1,6 +1,6 @@ setEvents($options['events']); } - if (!$this->alive()) { - throw new Exception('Subscription is not alive'); + if (!$this->subscribed()) { + throw new Exception('No subscription'); } try { @@ -180,8 +184,8 @@ function renew(array $options = array()) function remove() { - if (!$this->alive()) { - throw new Exception('Subscription is not alive'); + if (!$this->subscribed()) { + throw new Exception('No subscription'); } try { @@ -204,7 +208,7 @@ function remove() } - function alive() + function subscribed() { return (!empty($this->_subscription) && !empty($this->_subscription['deliveryMode']) && @@ -212,6 +216,15 @@ function alive() !empty($this->_subscription['deliveryMode']['address'])); } + function alive() + { + return $this->subscribed() && (time() < $this->expirationTime()); + } + + function expirationTime() + { + return strtotime($this->_subscription['expirationTime']) - self::RENEW_HANDICAP; + } function subscription() { @@ -249,12 +262,31 @@ protected function subscribeAtPubnub() 'subscribe_key' => $this->_subscription['deliveryMode']['subscriberKey'] )); - $this->_pubnub->subscribe($this->_subscription['deliveryMode']['address'], array($this, 'notify')); + $this->_pubnub->setSubscribeTimeout(self::SUBSCRIBE_TIMEOUT); + + $this->_pubnub->subscribe($this->_subscription['deliveryMode']['address'], array($this, 'notify'), 0, false, + array($this, 'pubnubTimeoutHandler') + ); return $this; } + /** + * Attention, this function is NOT PUBLIC!!! The only reason it's public is due to PHP 5.3 limitations + * @protected + */ + public function pubnubTimeoutHandler() + { + + $this->dispatch(self::EVENT_TIMEOUT); + + if ($this->subscribed() && !$this->alive()) { + $this->renew(); + } + + } + /** * Attention, this function is NOT PUBLIC!!! The only reason it's public is due to PHP 5.3 limitations * @protected @@ -265,12 +297,20 @@ protected function subscribeAtPubnub() public function notify($pubnubMessage) { - $message = $pubnubMessage['message']; + if (!empty($pubnubMessage['error'])) { + //'error' => true, + //'service' => 'cURL', + //'status' => -1, + //'message' => 'request timeout', + //'payload' => "Pubnub request timeout. Maximum timeout: " . $this->curlTimeout . " seconds" . + // ". Requested URL: " . $curlResponseURL + return $this->_keepPolling; + } - //TODO Since pubnub blocks everything this is probably the only place where we can intercept the process and do subscription renew - //$this->renew(); + $message = $pubnubMessage['message']; $message = $this->decrypt($message); + //print 'Message received: ' . $message . PHP_EOL; $this->dispatch(self::EVENT_NOTIFICATION, new NotificationEvent($message)); @@ -282,8 +322,8 @@ public function notify($pubnubMessage) protected function decrypt($message) { - if (!$this->alive()) { - throw new Exception('Subscription is not alive'); + if (!$this->subscribed()) { + throw new Exception('No subscription'); } if ($this->_subscription['deliveryMode']['encryption'] && $this->_subscription['deliveryMode']['encryptionKey']) {