From 8fb6d0743706d6d6bff8dcae24a18279c5d1c7d7 Mon Sep 17 00:00:00 2001 From: Jim Seconde Date: Mon, 16 Dec 2024 10:49:02 +0000 Subject: [PATCH] Add VonageConfig object --- phpunit.xml.dist | 3 + src/Client.php | 98 +++++----------------------- src/Client/APIResource.php | 63 +++++++++++------- src/Client/VonageConfig.php | 77 ++++++++++++++++++++++ src/Entity/IterableAPICollection.php | 14 +--- test/Account/ClientTest.php | 24 ++----- 6 files changed, 147 insertions(+), 132 deletions(-) create mode 100644 src/Client/VonageConfig.php diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ff6973bd..2124ef16 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,6 +20,9 @@ test + + test/Account + test/Verify diff --git a/src/Client.php b/src/Client.php index 99f858e1..8bd364f5 100644 --- a/src/Client.php +++ b/src/Client.php @@ -5,9 +5,9 @@ namespace Vonage; use Composer\InstalledVersions; +use InvalidArgumentException; use Psr\Container\ContainerInterface; use Psr\Http\Client\ClientInterface; -use Psr\Log\LoggerInterface; use RuntimeException; use Vonage\Account\ClientFactory; use Vonage\Application\ClientFactory as ApplicationClientFactory; @@ -20,6 +20,7 @@ use Vonage\Client\Credentials\SignatureSecret; use Vonage\Client\Factory\FactoryInterface; use Vonage\Client\Factory\MapFactory; +use Vonage\Client\VonageConfig; use Vonage\Conversion\ClientFactory as ConversionClientFactory; use Vonage\Insights\ClientFactory as InsightsClientFactory; use Vonage\Meetings\ClientFactory as MeetingsClientFactory; @@ -66,14 +67,9 @@ * @method Verify2\Client verify2() * @method Voice\Client voice() * @method Vonage\Video\Client video() - * - * @property string restUrl - * @property string apiUrl */ -class Client implements LoggerAwareInterface +class Client { - use LoggerTrait; - protected CredentialsInterface $credentials; protected ClientInterface $client; @@ -81,35 +77,21 @@ class Client implements LoggerAwareInterface protected mixed $debug = false; protected ContainerInterface $factory; + protected VonageConfig $vonageConfig; - /** - * @var LoggerInterface - */ - protected $logger; - - protected array $options = ['show_deprecations' => false, 'debug' => false]; + public const BASE_API = 'https://api.vonage.com/'; /** * Create a new API client using the provided credentials. */ public function __construct( CredentialsInterface $credentials, - ?VonageConfig $options = null, - ?ClientInterface $client = null + ?VonageConfig $vonageConfig = null, ) { - if (is_null($client)) { - // Since the user did not pass a client, try and make a client - // using the Guzzle 6 adapter or Guzzle 7 (depending on availability) - [$guzzleVersion] = explode('@', (string) InstalledVersions::getVersion('guzzlehttp/guzzle'), 1); - $guzzleVersion = (float) $guzzleVersion; - - if ($guzzleVersion >= 6.0 && $guzzleVersion < 7) { - $client = new \Http\Adapter\Guzzle6\Client(); - } - - if ($guzzleVersion >= 7.0 && $guzzleVersion < 8.0) { - $client = new \GuzzleHttp\Client(); - } + if (is_null($vonageConfig)) { + $this->vonageConfig = new VonageConfig(); + } else { + $this->vonageConfig = $vonageConfig; } if ( @@ -124,11 +106,9 @@ public function __construct( $this->credentials = $credentials; - $this->options = array_merge($this->options, $options); - // If they've provided an app name, validate it - if (isset($options['app'])) { - $this->validateAppOptions($options['app']); + if (isset($vonageConfig['app'])) { + $this->validateAppOptions($vonageConfig['app']); } $services = [ @@ -154,7 +134,9 @@ public function __construct( // Additional utility classes APIResource::class => APIResource::class, - Client::class => fn () => $this + Client::class => fn () => $this, + VonageConfig::class => fn () => $this->vonageConfig, + 'credentials' => fn () => $this->credentials, ]; if (class_exists('Vonage\Video\ClientFactory')) { @@ -173,45 +155,15 @@ public function __construct( ); // Disable throwing E_USER_DEPRECATED notices by default, the user can turn it on during development - if (array_key_exists('show_deprecations', $this->options) && ($this->options['show_deprecations'] == true)) { + if ($this->vonageConfig->getShowDeprecations()) { set_error_handler( - static fn (int $errno, string $errstr, string $errfile = null, int $errline = null, array $errorcontext = null) => true, + static fn (int $errno, string $errstr, ?string $errfile = null, ?int $errline = null, ?array + $errorcontext = null) => true, E_USER_DEPRECATED ); } } - public function getRestUrl(): string - { - return $this->restUrl; - } - - public function getApiUrl(): string - { - return $this->apiUrl; - } - - /** - * Set the Http Client to used to make API requests. - * - * This allows the default http client to be swapped out for a HTTPlug compatible - * replacement. - */ - public function setHttpClient(ClientInterface $client): self - { - $this->client = $client; - - return $this; - } - - /** - * Get the Http Client used to make API requests. - */ - public function getHttpClient(): ClientInterface - { - return $this->client; - } - /** * Set the factory used to create API specific clients. */ @@ -271,20 +223,6 @@ public function __get($name) return $this->factory->get($name); } - protected function getVersion(): string - { - return InstalledVersions::getVersion('vonage/client-core'); - } - - public function getLogger(): ?LoggerInterface - { - if (!$this->logger && $this->getFactory()->has(LoggerInterface::class)) { - $this->setLogger($this->getFactory()->get(LoggerInterface::class)); - } - - return $this->logger; - } - public function getCredentials(): CredentialsInterface { return $this->credentials; diff --git a/src/Client/APIResource.php b/src/Client/APIResource.php index 06949e41..7acd36e1 100644 --- a/src/Client/APIResource.php +++ b/src/Client/APIResource.php @@ -11,6 +11,7 @@ use Laminas\Diactoros\Uri; use Psr\Http\Client\ClientInterface; use Psr\Log\LogLevel; +use Vonage\Client\Credentials\CredentialsInterface; use Vonage\Client\Credentials\Handler\BasicHandler; use Vonage\Entity\Filter\EmptyFilter; use Psr\Http\Message\RequestInterface; @@ -65,12 +66,13 @@ class APIResource protected ?ResponseInterface $lastResponse = null; - protected ?ClientInterface $client = null; - protected bool $debug; + protected VonageConfig $vonageConfig; - public function __construct(?ClientInterface $client = null) + protected CredentialsInterface $credentials; + + public function __construct(VonageConfig $vonageConfig) { - if (is_null($client)) { + if (is_null($vonageConfig->getHttpClient())) { // Since the user did not pass a client, try and make a client // using the Guzzle 6 adapter or Guzzle 7 (depending on availability) [$guzzleVersion] = explode('@', (string) InstalledVersions::getVersion('guzzlehttp/guzzle'), 1); @@ -86,18 +88,29 @@ public function __construct(?ClientInterface $client = null) $client = new GuzzleClient(); } - $this->setHttpClient($client); + $vonageConfig->setHttpClient($client); } } - public function getHttpClient(): ?ClientInterface + public function getVonageConfig(): VonageConfig + { + return $this->vonageConfig; + } + + public function setVonageConfig(VonageConfig $vonageConfig): APIResource + { + $this->vonageConfig = $vonageConfig; + return $this; + } + + public function getCredentials(): CredentialsInterface { - return $this->client; + return $this->credentials; } - public function setHttpClient(?ClientInterface $client): APIResource + public function setCredentials(CredentialsInterface $credentials): APIResource { - $this->client = $client; + $this->credentials = $credentials; return $this; } @@ -107,7 +120,7 @@ public function setHttpClient(?ClientInterface $client): APIResource */ public function addAuth(RequestInterface $request): RequestInterface { - $credentials = $this->getClient()->getCredentials(); + $credentials = $this->getCredentials(); if (is_array($this->getAuthHandlers())) { foreach ($this->getAuthHandlers() as $handler) { @@ -167,13 +180,14 @@ public function send(RequestInterface $request): ResponseInterface // Set the header. Build by joining all the parts we have with a space $request = $request->withHeader('User-Agent', implode(' ', $userAgent)); - $response = $this->client->sendRequest($request); + $response = $this->getVonageConfig()->getHttpClient()->sendRequest($request); - if ($this->debug) { + if ($this->getVonageConfig()->isDebugMode()) { $id = uniqid('', true); $request->getBody()->rewind(); $response->getBody()->rewind(); - $this->log( + + $this->vonageConfig->getLogger()->log( LogLevel::DEBUG, 'Request ' . $id, [ @@ -182,7 +196,8 @@ public function send(RequestInterface $request): ResponseInterface 'body' => explode("\n", $request->getBody()->__toString()) ] ); - $this->log( + + $this->vonageConfig->getLogger()->log( LogLevel::DEBUG, 'Response ' . $id, [ @@ -223,7 +238,7 @@ public function create(array $body, string $uri = '', array $headers = []): ?arr $this->lastRequest = $request; - $response = $this->getClient()->send($request); + $response = $this->getVonageConfig()->getHttpClient()->send($request); $status = (int)$response->getStatusCode(); $this->setLastResponse($response); @@ -269,7 +284,7 @@ public function delete(string $id, array $headers = []): ?array $request = $this->addAuth($request); } - $response = $this->getClient()->send($request); + $response = $this->getVonageConfig()->getHttpClient()->send($request); $status = (int)$response->getStatusCode(); $this->lastRequest = $request; @@ -327,7 +342,7 @@ public function get( $request = $this->addAuth($request); } - $response = $this->getClient()->send($request); + $response = $this->getVonageConfig()->getHttpClient()->send($request); $status = (int)$response->getStatusCode(); $this->lastRequest = $request; @@ -347,11 +362,11 @@ public function get( return json_decode($response->getBody()->getContents(), true); } - public function getAuthHandlers() + public function getAuthHandlers(): BasicHandler|array { // If we have not set a handler, default to Basic and issue warning. if (!$this->authHandlers) { - $this->log( + $this->getVonageConfig()->getLogger()->log( LogLevel::WARNING, 'Warning: no authorisation handler set for this Client. Defaulting to Basic which might not be the correct authorisation for this API call' @@ -365,8 +380,8 @@ public function getAuthHandlers() public function getBaseUrl(): ?string { - if (!$this->baseUrl && $this->client) { - $this->baseUrl = $this->client->getApiUrl(); + if ($this->getVonageConfig()->getBaseUrl()) { + return $this->getVonageConfig()->getBaseUrl(); } return $this->baseUrl; @@ -455,7 +470,6 @@ public function search(?FilterInterface $filter = null, string $uri = ''): Itera $collection ->setApiResource($api) ->setFilter($filter); - $collection->setClient($this->client); return $collection; } @@ -621,4 +635,9 @@ public function setErrorsOn200(bool $value): self return $this; } + + protected function getVersion(): string + { + return InstalledVersions::getVersion('vonage/client-core'); + } } diff --git a/src/Client/VonageConfig.php b/src/Client/VonageConfig.php new file mode 100644 index 00000000..b7b99287 --- /dev/null +++ b/src/Client/VonageConfig.php @@ -0,0 +1,77 @@ +logger; + } + + public function setLogger(?LoggerInterface $logger): VonageConfig + { + $this->logger = $logger; + return $this; + } + + public function getShowDeprecations(): bool + { + return $this->showDeprecations; + } + + public function setShowDeprecations(bool $showDeprecations): VonageConfig + { + $this->showDeprecations = $showDeprecations; + return $this; + } + + public function isDebugMode(): bool + { + return $this->debugMode; + } + + public function setDebugMode(bool $debugMode): VonageConfig + { + $this->debugMode = $debugMode; + return $this; + } + + public function getBaseUrl(): ?string + { + return $this->baseUrl; + } + + public function setBaseUrl(?string $baseUrl): VonageConfig + { + $this->baseUrl = $baseUrl; + return $this; + } + public function getHttpClient(): ?ClientInterface + { + return $this->httpClient; + } + + public function setHttpClient(?ClientInterface $httpClient): VonageConfig + { + $this->httpClient = $httpClient; + + return $this; + } +} diff --git a/src/Entity/IterableAPICollection.php b/src/Entity/IterableAPICollection.php index fd2a42a4..39fdf117 100644 --- a/src/Entity/IterableAPICollection.php +++ b/src/Entity/IterableAPICollection.php @@ -15,8 +15,6 @@ use Vonage\Client\ClientAwareInterface; use Vonage\Client\ClientAwareTrait; use Vonage\Client\Exception as ClientException; -use Vonage\Client\Exception\Exception; -use Vonage\Client\Exception\Server; use Vonage\Entity\Filter\EmptyFilter; use Vonage\Entity\Filter\FilterInterface; @@ -32,10 +30,8 @@ /** * Common code for iterating over a collection, and using the collection class to discover the API path. */ -class IterableAPICollection implements ClientAwareInterface, Iterator, Countable +class IterableAPICollection implements Iterator, Countable { - use ClientAwareTrait; - protected APIResource $api; /** @@ -171,11 +167,7 @@ public function setHydrator($hydrator): self return $this; } - /** - * @param $data - * @param $id deprecated - */ - public function hydrateEntity($data, $id = null) + public function hydrateEntity($data) { if ($this->hydrator) { return $this->hydrator->hydrate($data); @@ -540,7 +532,7 @@ protected function fetchPage($absoluteUri): void $request = $this->getApiResource()->addAuth($request); } - $response = $this->client->send($request); + $response = $this->getApiResource()->getVonageConfig()->getHttpClient()->send($request); $this->getApiResource()->setLastRequest($request); $this->response = $response; diff --git a/test/Account/ClientTest.php b/test/Account/ClientTest.php index a8ad5afd..2f8effb1 100644 --- a/test/Account/ClientTest.php +++ b/test/Account/ClientTest.php @@ -24,34 +24,20 @@ class ClientTest extends VonageTestCase use Psr7AssertionTrait; use HTTPTestTrait; - protected $vonageClient; + protected AccountClient $accountClient; - /** - * @var AccountClient - */ - protected $accountClient; - - /** - * APIResource - */ - protected $api; + protected APIResource $api; public function setUp(): void { $this->responsesDirectory = __DIR__ . '/responses'; - $this->vonageClient = $this->prophesize(Client::class); - $this->vonageClient->getRestUrl()->willReturn('https://rest.nexmo.com'); - $this->vonageClient->getApiUrl()->willReturn('https://api.nexmo.com'); - $this->vonageClient->getCredentials()->willReturn( - new Client\Credentials\Container(new Client\Credentials\Basic('abc', 'def')) - ); - - $this->api = new APIResource(); + $this->api = new APIResource(new Client\VonageConfig()); $this->api->setBaseUrl('https://rest.nexmo.com') ->setIsHAL(false) ->setAuthHandlers(new Client\Credentials\Handler\BasicQueryHandler()) - ->setBaseUri('/account'); + ->setBaseUri('/account') + ->setCredentials(new Client\Credentials\Container(new Client\Credentials\Basic('abc', 'def'))); $this->api->setClient($this->vonageClient->reveal()); $this->accountClient = new AccountClient($this->api);