Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customers name and surname can not be empty strings and e-mail must be valid e-mail address #71

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
"require": {
"php": "~7.4|~8.0",
"ext-json": "*",
"egulias/email-validator": "^3.2",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0|^2.0"
19 changes: 10 additions & 9 deletions src/Model/CreatePaymentCustomer.php
Original file line number Diff line number Diff line change
@@ -3,16 +3,17 @@
namespace ThePay\ApiClient\Model;

use InvalidArgumentException;
use ThePay\ApiClient\ValueObject\EmailAddress;
use ThePay\ApiClient\ValueObject\NonEmptyString;
use ThePay\ApiClient\ValueObject\PhoneNumber;
use ThePay\ApiClient\ValueObject\StringValue;

final class CreatePaymentCustomer
{
private string $name;
private string $surname;
/** @var StringValue|null */
/** @var string|null */
private $email;
/** @var PhoneNumber|null */
/** @var string|null */
private $phone;
/** @var Address|null */
private $billingAddress;
@@ -31,10 +32,10 @@ public function __construct(string $name, string $surname, $email, $phone, Addre
throw new InvalidArgumentException('At least one of $email and $phone is required.');
}

$this->name = $name;
$this->surname = $surname;
$this->email = $email === null ? null : new StringValue($email);
$this->phone = $phone === null ? null : new PhoneNumber($phone);
$this->name = (new NonEmptyString($name))->getValue();
$this->surname = (new NonEmptyString($surname))->getValue();
$this->email = $email === null ? null : (new EmailAddress($email))->getValue();
$this->phone = $phone === null ? null : (new PhoneNumber($phone))->getValue();
$this->billingAddress = $billingAddress;
$this->shippingAddress = $shippingAddress;
}
@@ -54,15 +55,15 @@ public function getSurname(): string
*/
public function getEmail()
{
return $this->email === null ? null : $this->email->getValue();
return $this->email;
}

/**
* @return string|null
*/
public function getPhone()
{
return $this->phone === null ? null : $this->phone->getValue();
return $this->phone;
}

/**
6 changes: 3 additions & 3 deletions src/ValueObject/Amount.php
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<int>
*/
final class Amount extends BaseValueObject
{
/** @var int */
private $value;

/**
* Amount constructor.
*
54 changes: 50 additions & 4 deletions src/ValueObject/BaseValueObject.php
Original file line number Diff line number Diff line change
@@ -2,17 +2,34 @@

namespace ThePay\ApiClient\ValueObject;

use InvalidArgumentException;

/**
* @template TValue of mixed
*/
abstract class BaseValueObject implements ValueObject
{
/**
* BaseValueObject constructor.
* @param mixed $value
* @var TValue
*/
abstract public function __construct($value);
protected $value;

/**
* @param TValue|mixed $value
*
* @throws InvalidArgumentException
*/
public function __construct($value)
{
$this->value = static::filter($value);
}

/**
* @param mixed $value
* @param TValue|mixed $value
*
* @return static
*
* @throws InvalidArgumentException
*/
public static function create($value)
{
@@ -30,4 +47,33 @@ public function equals(ValueObject $object)

return $this->getValue() === $object->getValue();
}

/**
* @return TValue
*/
public function getValue()
{
return $this->value;
}

/**
* @note should be abstract
*
* @param TValue|mixed $value
*
* @return TValue
*
* @throws InvalidArgumentException
*/
protected static function filter($value)
{
throw self::invalidValue('expected');
}

protected static function invalidValue(string $expected, ?string $actual = null): InvalidArgumentException
{
return new InvalidArgumentException(
'Value ' . ($actual === null ? '' : '"' . $actual . '" ') . 'is not ' . $expected,
);
}
}
6 changes: 3 additions & 3 deletions src/ValueObject/CountryCode.php
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@

namespace ThePay\ApiClient\ValueObject;

/**
* @extends BaseValueObject<string>
*/
final class CountryCode extends BaseValueObject
{
/** @var string */
private $value;

/**
* @param string $value
*/
6 changes: 3 additions & 3 deletions src/ValueObject/CurrencyCode.php
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<string>
*/
final class CurrencyCode extends BaseValueObject
{
/** @var string */
private $value;

/**
* CurrencyCode constructor.
*
20 changes: 20 additions & 0 deletions src/ValueObject/EmailAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

petrknap marked this conversation as resolved.
Show resolved Hide resolved
namespace ThePay\ApiClient\ValueObject;

use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\RFCValidation;

class EmailAddress extends NonEmptyString
{
public static function filter($value)
{
$nonEmptyString = parent::filter($value);

if ((new EmailValidator())->isValid($nonEmptyString, new RFCValidation()) === false) {
petrknap marked this conversation as resolved.
Show resolved Hide resolved
throw self::invalidValue('e-mail address', $nonEmptyString);
}

return $nonEmptyString;
}
}
6 changes: 3 additions & 3 deletions src/ValueObject/EnumValueObject.php
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@

namespace ThePay\ApiClient\ValueObject;

/**
* @extends BaseValueObject<string>
*/
abstract class EnumValueObject extends BaseValueObject
{
/** @var string */
protected $value;

/**
* @param string $value
*/
6 changes: 3 additions & 3 deletions src/ValueObject/Identifier.php
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<string>
*/
final class Identifier extends BaseValueObject
{
/** @var string */
private $value;

/**
* Uid constructor.
*
6 changes: 3 additions & 3 deletions src/ValueObject/LanguageCode.php
Original file line number Diff line number Diff line change
@@ -4,11 +4,11 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<string>
*/
final class LanguageCode extends BaseValueObject
{
/** @var string */
private $value;

/**
* CurrencyCode constructor.
*
17 changes: 17 additions & 0 deletions src/ValueObject/NonEmptyString.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace ThePay\ApiClient\ValueObject;

class NonEmptyString extends StringValue
{
protected static function filter($value)
{
$string = parent::filter($value);

if (trim($string) === '') {
petrknap marked this conversation as resolved.
Show resolved Hide resolved
throw self::invalidValue('non-empty string', $string);
}

return $string;
}
}
3 changes: 3 additions & 0 deletions src/ValueObject/PhoneNumber.php
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<string>
*/
final class PhoneNumber extends BaseValueObject
{
/** @var string */
3 changes: 3 additions & 0 deletions src/ValueObject/SecureUrl.php
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@

namespace ThePay\ApiClient\ValueObject;

/**
* @extends BaseValueObject<string>
*/
final class SecureUrl extends BaseValueObject
{
/** @var string */
31 changes: 10 additions & 21 deletions src/ValueObject/StringValue.php
Original file line number Diff line number Diff line change
@@ -2,33 +2,22 @@

namespace ThePay\ApiClient\ValueObject;

final class StringValue extends BaseValueObject
/**
* @extends BaseValueObject<string>
*/
class StringValue extends BaseValueObject
{
/** @var string */
private $value;

public function __construct($value)
{
if ( ! is_string($value)) {
throw new \InvalidArgumentException('type of value: ' . (string) $value . ' is not string');
}

$this->value = $value;
}

/**
* @return string
*/
public function __toString()
{
return $this->value;
}

/**
* @return string
*/
public function getValue()
protected static function filter($value)
{
return $this->value;
if ( ! is_string($value)) {
throw self::invalidValue('string');
}

return $value;
}
}
3 changes: 3 additions & 0 deletions src/ValueObject/Url.php
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@

use InvalidArgumentException;

/**
* @extends BaseValueObject<string>
*/
final class Url extends BaseValueObject
{
/** @var string */
58 changes: 58 additions & 0 deletions tests/ValueObject/BaseValueObjectTestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace ThePay\ApiClient\Tests\ValueObject;

use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
use ThePay\ApiClient\ValueObject\BaseValueObject;

abstract class BaseValueObjectTestCase extends TestCase
{
/**
* @dataProvider validValuesAndStringRepresentationsDataProvider
*
* @param mixed $value
*/
public function testCreatesWorkingInstanceWithValidValue($value, string $stringRepresentation): void
{
$className = static::getClassName();
$a = $className::create($value);
$b = new $className($value);

self::assertTrue($a->equals($b));
self::assertTrue($b->equals($a));
self::assertSame($value, $a->getValue());
self::assertSame($stringRepresentation, (string) $a);
}

/**
* @dataProvider invalidValuesAndExceptionMessagesDataProvider
*
* @param mixed $value
*/
public function testThrowsWithInvalidValue($value, string $exceptionMessage): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage($exceptionMessage);

$className = static::getClassName();
$className::create($value);
}

/**
* @return class-string<BaseValueObject<mixed>>
*/
abstract protected static function getClassName(): string;

/**
* @return array<array<mixed|string>>|array<string, array<mixed|string>>
*/
abstract public static function validValuesAndStringRepresentationsDataProvider(): array;

/**
* @return array<array<mixed|string>>|array<string, array<mixed|string>>
*/
abstract public static function invalidValuesAndExceptionMessagesDataProvider(): array;
}
Loading
Loading