Viewing file: Client.php (17.19 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/** * Vonage Client Library for PHP * * @copyright Copyright (c) 2016-2020 Vonage, Inc. (http://vonage.com) * @license https://github.com/Vonage/vonage-php-sdk-core/blob/master/LICENSE.txt Apache License 2.0 */
declare(strict_types=1);
namespace Vonage\Message;
use InvalidArgumentException; use Psr\Http\Client\ClientExceptionInterface; use Psr\Http\Message\ResponseInterface; use ReflectionClass; use ReflectionException; use RuntimeException; use Vonage\Client\APIResource; use Vonage\Client\ClientAwareInterface; use Vonage\Client\ClientAwareTrait; use Vonage\Client\Exception as ClientException; use Vonage\Client\Exception\ThrottleException; use Vonage\Entity\Filter\FilterInterface; use Vonage\Entity\Filter\KeyValueFilter;
use function class_exists; use function count; use function get_class; use function is_array; use function is_null; use function is_string; use function json_decode; use function preg_match; use function sleep; use function sprintf; use function strpos; use function strtolower; use function substr; use function trigger_error; use function ucfirst;
/** * Class Client * * @deprecated Use \Vonage\SMS\Client instead * * @method Text sendText(string $to, string $from, string $text, array $additional = []) Send a Test Message */ class Client implements ClientAwareInterface { /** * @deprecated This service will no longer be directly ClientAware */ use ClientAwareTrait;
/** * @var APIResource */ protected $api;
public function __construct(APIResource $api = null) { $this->api = $api; }
/** * Shim to handle older instantiations of this class * * @deprecated Will remove in v3 */ protected function getApiResource(): APIResource { if (is_null($this->api)) { $api = new APIResource(); $api->setClient($this->getClient()) ->setBaseUrl($this->getClient()->getRestUrl()) ->setIsHAL(false) ->setErrorsOn200(true); $api->setExceptionErrorHandler( function (ResponseInterface $response) { //check for valid data, as well as an error response from the API if ((int)$response->getStatusCode() === 429) { throw new ClientException\Request('too many concurrent requests', $response->getStatusCode()); }
$data = json_decode($response->getBody()->getContents(), true);
if (!isset($data['messages'])) { if (isset($data['error-code'], $data['error-code-label'])) { $e = new ClientException\Request($data['error-code-label'], (int)$data['error-code']); } else { $e = new ClientException\Request('unexpected response from API'); }
$e->setEntity($data); throw $e; }
//normalize errors (client vrs server) foreach ($data['messages'] as $part) { switch ($part['status']) { case '0': break; //all okay case '1': $e = new ThrottleException($part['error-text']); $e->setTimeout(1); $e->setEntity($data);
if (preg_match('#Throughput Rate Exceeded - please wait \[\s+(\d+)\s+] and retry#', $part['error-text'], $match)) { $seconds = max((int)$match[1] / 1000, 1); $e->setTimeout($seconds); }
throw $e; case '5': $e = new ClientException\Server($part['error-text'], (int)$part['status']); $e->setEntity($data); throw $e; default: $e = new ClientException\Request($part['error-text'], (int)$part['status']); $e->setEntity($data); throw $e; } } } );
$this->api = $api; }
return clone $this->api; }
/** * @param Message|array $message * * @throws ClientException\Exception * @throws ClientException\Request * @throws ClientException\Server * @throws ClientExceptionInterface */ public function send($message): Message { if (!($message instanceof MessageInterface)) { trigger_error( 'Passing an array to Vonage\Messages\Client::send() is deprecated, ' . 'please pass a MessageInterface object instead', E_USER_DEPRECATED );
$message = $this->createMessageFromArray($message); }
$params = @$message->getRequestData(false);
try { $api = $this->getApiResource(); $api->setBaseUri('/sms/json'); $api->create($params);
@$message->setRequest($api->getLastRequest()); @$message->setResponse($api->getLastResponse()); } catch (ThrottleException $e) { sleep($e->getTimeout());
$this->send($message); } catch (ClientException\Request $e) { $e->setEntity($message);
throw $e; }
return $message; }
/** * @throws ClientExceptionInterface * @throws ClientException\Exception * @throws ClientException\Request */ public function sendShortcode($message): array { if (!($message instanceof Shortcode)) { $message = Shortcode::createMessageFromArray($message); }
$params = $message->getRequestData();
try { $api = $this->getApiResource(); $api->setBaseUri('/sc/us/' . $message->getType() . '/json');
$body = $api->create($params); } catch (ClientException\Request $e) { $e->setEntity($message); throw $e; }
foreach ($body['messages'] as $m) { if ((int)$m['status'] !== 0) { $e = new ClientException\Request($m['error-text'], $m['status']); $e->setEntity($message); throw $e; } }
return $body; }
/** * @todo Fix all this error detection so it's standard * * @throws ClientExceptionInterface * @throws ClientException\Exception * @throws ClientException\Request * * @deprecated Please use the Reports API instead */ public function get($query): array { if ($query instanceof Query) { $params = $query->getParams(); } elseif ($query instanceof FilterInterface) { $params = $query->getQuery(); } elseif ($query instanceof MessageInterface) { $params = ['ids' => [$query->getMessageId()]]; } elseif (is_string($query)) { $params = ['ids' => [$query]]; } elseif (is_array($query)) { $params = ['ids' => $query]; } else { throw new InvalidArgumentException( 'query must be an instance of Query, ' . 'MessageInterface, string ID, or array of IDs.' ); }
$api = $this->getApiResource();
try { $data = $api->get('/search/messages', (new KeyValueFilter($params))->getQuery()); } catch (ClientException\Request $e) { $response = $api->getLastResponse();
if (null !== $response) { $response->getBody()->rewind();
if (null !== $api->getLastResponse()) { $body = $api->getLastResponse()->getBody()->getContents(); } }
if (empty($body)) { $e = new ClientException\Request('error status from API', $e->getCode()); $response->getBody()->rewind(); $e->setEntity($response);
throw $e; }
throw $e; }
if (!isset($data['items'])) { // Check if we just got a single result instead of a list if (isset($data['message-id'])) { $newData = []; $newData['items'][] = $data; $data = $newData; } else { // Otherwise we got an unexpected response from the API $e = new ClientException\Request('unexpected response from API'); $e->setEntity($data); throw $e; } }
if (count($data['items']) === 0) { return []; }
$collection = [];
foreach ($data['items'] as $index => $item) { switch ($item['type']) { case 'MT': $new = new Message($item['message-id']); break; case 'MO': $new = new InboundMessage($item['message-id']); break; default: $e = new ClientException\Request('unexpected response from API'); $e->setEntity($data); throw $e; }
@$new->setResponse($api->getLastResponse()); $new->setIndex($index); $collection[] = $new; }
return $collection; }
/** * @todo Fix all this error detection so it's standard * * @param string|MessageInterface $idOrMessage * * @throws ClientExceptionInterface * @throws ClientException\Exception * @throws ClientException\Request * * @return InboundMessage|Message|MessageInterface|null * * @deprecated Please use the Reports API instead */ public function search($idOrMessage) { if ($idOrMessage instanceof MessageInterface) { $id = $idOrMessage->getMessageId(); $message = $idOrMessage; } else { $id = $idOrMessage; }
$api = $this->getApiResource();
try { $data = $api->get('/search/messages', (new KeyValueFilter(['id' => $id]))->getQuery()); } catch (ClientException\Request $e) { if ($e->getCode() !== 200) { // This method had a different error, so switch to the expected error message if ($e->getMessage() === 'unexpected response from API') { $entity = $e->getEntity(); $e = new ClientException\Request('error status from API', $e->getCode()); $e->setEntity($entity); throw $e; }
throw $e; } }
$response = $api->getLastResponse();
if (null !== $response) { $status = (int)$response->getStatusCode();
if ($status !== 200 && isset($data['error-code'])) { throw new ClientException\Request($data['error-code-label'], $data['error-code']); }
if ($status === 429) { throw new ClientException\Request('too many concurrent requests', $status); }
if ($status !== 200) { $e = new ClientException\Request('error status from API', $status); $response->getBody()->rewind(); $e->setEntity($response);
throw $e; }
if (empty($data)) { $e = new ClientException\Request('no message found for `' . $id . '`'); $response->getBody()->rewind(); $e->setEntity($response);
throw $e; }
switch ($data['type']) { case 'MT': $new = new Message($data['message-id']); break; case 'MO': $new = new InboundMessage($data['message-id']); break; default: $e = new ClientException\Request('unexpected response from API'); $e->setEntity($data); throw $e; }
if (isset($message) && !($message instanceof $new)) { throw new ClientException\Exception( sprintf( 'searched for message with type `%s` but message of type `%s`', get_class($message), get_class($new) ) ); }
if (!isset($message)) { $message = $new; }
@$message->setResponse($response);
return $message; }
return null; }
/** * @todo Fix all this error detection so it's standard * * @throws ClientExceptionInterface * @throws ClientException\Exception * @throws ClientException\Request * * @deprecated Please use the Reports API instead */ public function searchRejections(Query $query): array { $params = $query->getParams(); $api = $this->getApiResource();
try { $data = $api->get('/search/rejections', (new KeyValueFilter($params))->getQuery()); } catch (ClientException\Request $e) { if ($e->getMessage() === 'unexpected response from API') { $entity = $e->getEntity(); $e = new ClientException\Request('error status from API', $e->getCode()); $e->setEntity($entity); throw $e; }
throw $e; }
$response = $api->getLastResponse();
if (null !== $response) { $status = $response->getStatusCode();
if ($status !== 200 && isset($data['error-code'])) { throw new ClientException\Request($data['error-code-label'], $data['error-code']); }
if ($status !== 200) { $e = new ClientException\Request('error status from API', $status); $response->getBody()->rewind(); $e->setEntity($response);
throw $e; }
if (!isset($data['items'])) { $e = new ClientException\Request('unexpected response from API'); $e->setEntity($data);
throw $e; }
if (count($data['items']) === 0) { return []; }
$collection = [];
foreach ($data['items'] as $index => $item) { switch ($item['type']) { case 'MT': $new = new Message($item['message-id']); break; case 'MO': $new = new InboundMessage($item['message-id']); break; default: $e = new ClientException\Request('unexpected response from API'); $e->setEntity($data); throw $e; }
@$new->setResponse($response); $new->setIndex($index);
$collection[] = $new; }
return $collection; }
return []; }
/** * @param MessageInterface|array $message */ protected function createMessageFromArray($message): Message { if (!is_array($message)) { throw new RuntimeException('message must implement `' . MessageInterface::class . '` or be an array`'); }
foreach (['to', 'from'] as $param) { if (!isset($message[$param])) { throw new InvalidArgumentException('missing expected key `' . $param . '`'); } }
$to = $message['to']; $from = $message['from'];
unset($message['to'], $message['from']);
return new Message($to, $from, $message); }
/** * Convenience feature allowing messages to be sent without creating a message object first. * * @throws ClientExceptionInterface * @throws ClientException\Exception * @throws ClientException\Request * @throws ClientException\Server * @throws ReflectionException * * @return array|Message|MessageInterface */ public function __call(string $name, $arguments) { if (strpos($name, "send") !== 0) { throw new RuntimeException( sprintf( '`%s` is not a valid method on `%s`', $name, get_class($this) ) ); }
$class = substr($name, 4); $class = 'Vonage\\Message\\' . ucfirst(strtolower($class));
if (!class_exists($class)) { throw new RuntimeException( sprintf( '`%s` is not a valid method on `%s`', $name, get_class($this) ) ); }
$reflection = new ReflectionClass($class); /** @var Message $message */ $message = $reflection->newInstanceArgs($arguments);
return $this->send($message); } }
|