diff --git a/composer.json b/composer.json index 8a173dd..a680aa9 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ ], "minimum-stability": "stable", "require": { + "ext-json": "*", "symfony/http-client": "^5.0" }, "autoload": { @@ -24,6 +25,10 @@ }, "require-dev": { "phpunit/phpunit": "^9.1", - "squizlabs/php_codesniffer": "^3.5" + "squizlabs/php_codesniffer": "^3.5", + "symfony/var-dumper": "^5.0" + }, + "config": { + "sort-packages": true } } diff --git a/src/Glassboxx/Request/AbstractRequest.php b/src/Glassboxx/Request/AbstractRequest.php index 173f849..1bf70f7 100644 --- a/src/Glassboxx/Request/AbstractRequest.php +++ b/src/Glassboxx/Request/AbstractRequest.php @@ -4,7 +4,29 @@ declare(strict_types=1); namespace Opdavies\Glassboxx\Request; +use Opdavies\Glassboxx\Config; +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Contracts\HttpClient\HttpClientInterface; + abstract class AbstractRequest { public const BASE_URL = 'https://server.glassboxx.co.uk/rest/V1'; + + /** @var HttpClient */ + protected $client; + + /** @var Config */ + protected $config; + + public function __construct(HttpClientInterface $client) + { + $this->client = $client; + } + + public function withConfig(Config $config): AbstractRequest + { + $this->config = $config; + + return $this; + } } diff --git a/src/Glassboxx/Request/AuthTokenRequest.php b/src/Glassboxx/Request/AuthTokenRequest.php index 02afbee..9496508 100644 --- a/src/Glassboxx/Request/AuthTokenRequest.php +++ b/src/Glassboxx/Request/AuthTokenRequest.php @@ -8,41 +8,20 @@ use Opdavies\Glassboxx\Config; use Symfony\Component\HttpClient\HttpClient; use Symfony\Contracts\HttpClient\HttpClientInterface; -final class AuthTokenRequest extends AbstractRequest +final class AuthTokenRequest extends AbstractRequest implements AuthTokenRequestInterface { - public const ENDPOINT = '/integration/admin/token'; - - /** @var Config */ - private $config; - - /** @var HttpClient */ - private $client; - - public function __construct(HttpClientInterface $client) - { - $this->client = $client; - } - - public function withConfig(Config $config): self - { - $this->config = $config; - - return $this; - } - public function getToken(): string { - $response = $this->client - ->request( - 'POST', - self::BASE_URL.self::ENDPOINT, - [ - 'query' => [ - 'password' => $this->config->getPassword(), - 'username' => $this->config->getUsername(), - ], - ] - ); + $response = $this->client->request( + 'POST', + self::BASE_URL.self::ENDPOINT, + [ + 'query' => [ + 'password' => $this->config->getPassword(), + 'username' => $this->config->getUsername(), + ], + ] + ); return json_decode($response->getContent()); } diff --git a/src/Glassboxx/Request/AuthTokenRequestInterface.php b/src/Glassboxx/Request/AuthTokenRequestInterface.php new file mode 100644 index 0000000..fad8996 --- /dev/null +++ b/src/Glassboxx/Request/AuthTokenRequestInterface.php @@ -0,0 +1,12 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\Request; + +interface AuthTokenRequestInterface +{ + public const ENDPOINT = '/integration/admin/token'; + + public function getToken(): string; +} diff --git a/src/Glassboxx/Request/CustomerRequest.php b/src/Glassboxx/Request/CustomerRequest.php new file mode 100644 index 0000000..0e84ed8 --- /dev/null +++ b/src/Glassboxx/Request/CustomerRequest.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\Request; + +use Opdavies\Glassboxx\Config; +use Opdavies\Glassboxx\ValueObject\Customer; +use Opdavies\Glassboxx\ValueObject\CustomerInterface; +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +final class CustomerRequest extends AbstractRequest +{ + public const ENDPOINT = '/glassboxxorder/customCustomer'; + + /** @var string */ + protected $authToken; + + /** @var CustomerInterface */ + protected $customer; + + public function forCustomer(CustomerInterface $customer): self + { + $this->customer = $customer; + + return $this; + } + + public function withAuthToken(string $authToken): self + { + $this->authToken = $authToken; + + return $this; + } + + public function execute(): string + { + $body = [ + 'customer' => [ + 'created_in' => $this->config->getVendorId(), + 'email' => $this->customer->getEmailAddress(), + 'firstname' => $this->customer->getFirstName(), + 'lastname' => $this->customer->getLastName(), + ], + ]; + + $response = $this->client->request( + 'POST', + self::BASE_URL . self::ENDPOINT, + [ + 'auth_bearer' => $this->authToken, + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => json_encode($body), + ] + ); + + return json_decode($response->getContent()); + } +} diff --git a/src/Glassboxx/ValueObject/Customer.php b/src/Glassboxx/ValueObject/Customer.php new file mode 100644 index 0000000..5a5f129 --- /dev/null +++ b/src/Glassboxx/ValueObject/Customer.php @@ -0,0 +1,42 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\ValueObject; + +final class Customer implements CustomerInterface +{ + /** @var string */ + private $firstName; + + /** @var string */ + private $lastName; + + /** @var string */ + private $emailAddress; + + public function __construct( + string $firstName, + string $lastName, + string $emailAddress + ) { + $this->firstName = $firstName; + $this->lastName = $lastName; + $this->emailAddress = $emailAddress; + } + + public function getFirstName(): string + { + return $this->firstName; + } + + public function getLastName(): string + { + return $this->lastName; + } + + public function getEmailAddress(): string + { + return $this->emailAddress; + } +} diff --git a/src/Glassboxx/ValueObject/CustomerInterface.php b/src/Glassboxx/ValueObject/CustomerInterface.php new file mode 100644 index 0000000..4feec6e --- /dev/null +++ b/src/Glassboxx/ValueObject/CustomerInterface.php @@ -0,0 +1,20 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\ValueObject; + +interface CustomerInterface +{ + public function __construct( + string $firstName, + string $lastName, + string $emailAddress + ); + + public function getEmailAddress(): string; + + public function getFirstName(): string; + + public function getLastName(): string; +} diff --git a/tests/Glassboxx/Request/CustomerRequestTest.php b/tests/Glassboxx/Request/CustomerRequestTest.php new file mode 100644 index 0000000..68a1670 --- /dev/null +++ b/tests/Glassboxx/Request/CustomerRequestTest.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\Tests\Glassboxx\Request; + +use Opdavies\Glassboxx\Request\AuthTokenRequestInterface; +use Opdavies\Glassboxx\Request\CustomerRequest; +use Opdavies\Glassboxx\Tests\Glassboxx\TestCase; +use Opdavies\Glassboxx\ValueObject\CustomerInterface; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Contracts\HttpClient\ResponseInterface; + +final class CustomerRequestTest extends TestCase +{ + public function testThatItCreatesACustomer(): void + { + $authTokenRequest = $this->getMockBuilder(AuthTokenRequestInterface::class) + ->getMock(); + $authTokenRequest->expects($this->any()) + ->method('getToken') + ->willReturn('testtoken'); + + $response = $this->getMockBuilder(ResponseInterface::class) + ->getMock(); + $response->method('getContent')->willReturn('"Success"'); + + $client = $this->getMockBuilder(MockHttpClient::class)->getMock(); + $client->expects($this->once()) + ->method('request') + ->with( + 'POST', + CustomerRequest::BASE_URL + .CustomerRequest::ENDPOINT, + [ + 'auth_bearer' => $authTokenRequest->getToken(), + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'body' => json_encode([ + 'customer' => [ + 'created_in' => 123, + 'email' => 'oliver@oliverdavies.uk', + 'firstname' => 'Oliver', + 'lastname' => 'Davies', + ], + ]), + ] + ) + ->willReturn($response); + + $customer = $this->getMockBuilder(CustomerInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $customer->method('getFirstName')->willReturn('Oliver'); + $customer->method('getLastName')->willReturn('Davies'); + $customer->method('getEmailAddress')->willReturn('oliver@oliverdavies.uk'); + + $request = (new CustomerRequest($client)) + ->forCustomer($customer) + ->withAuthToken($authTokenRequest->getToken()) + ->withConfig($this->config); + + $this->assertSame('Success', $request->execute()); + } +} diff --git a/tests/Glassboxx/ValueObject/CustomerTest.php b/tests/Glassboxx/ValueObject/CustomerTest.php new file mode 100644 index 0000000..1f81c2e --- /dev/null +++ b/tests/Glassboxx/ValueObject/CustomerTest.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); + +namespace Opdavies\Glassboxx\Tests\Glassboxx\ValueObject; + +use Opdavies\Glassboxx\Tests\Glassboxx\TestCase; +use Opdavies\Glassboxx\ValueObject\Customer; + +final class CustomerTest extends TestCase +{ + public function testCreatingACustomer(): void + { + $customer = new Customer( + 'Oliver', + 'Davies', + 'oliver@oliverdavies.uk' + ); + + $this->assertSame('Oliver', $customer->getFirstName()); + $this->assertSame('Davies', $customer->getLastName()); + $this->assertSame('oliver@oliverdavies.uk', $customer->getEmailAddress()); + } +}