Skip to content

Commit

Permalink
Customers name and surname can not be empty strings and e-mail must b…
Browse files Browse the repository at this point in the history
…e valid e-mail address
  • Loading branch information
petrknap committed Aug 23, 2024
1 parent 38a5dc8 commit 28fa964
Show file tree
Hide file tree
Showing 19 changed files with 284 additions and 51 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"require": {
"php": "~7.4|~8.0",
"ext-json": "*",
"egulias/email-validator": "^4.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0|^2.0"
Expand Down
19 changes: 10 additions & 9 deletions src/Model/CreatePaymentCustomer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}

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

use InvalidArgumentException;

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

/**
* Amount constructor.
*
Expand Down
49 changes: 46 additions & 3 deletions src/ValueObject/BaseValueObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,27 @@

namespace ThePay\ApiClient\ValueObject;

use InvalidArgumentException;

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

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

/**
* @param mixed $value
Expand All @@ -30,4 +44,33 @@ public function equals(ValueObject $object)

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

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

/**
* @internal 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
Expand Up @@ -2,11 +2,11 @@

namespace ThePay\ApiClient\ValueObject;

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

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

use InvalidArgumentException;

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

/**
* CurrencyCode constructor.
*
Expand Down
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

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) {
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
Expand Up @@ -2,11 +2,11 @@

namespace ThePay\ApiClient\ValueObject;

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

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

use InvalidArgumentException;

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

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

use InvalidArgumentException;

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

/**
* CurrencyCode constructor.
*
Expand Down
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) === '') {
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
Expand Up @@ -4,6 +4,9 @@

use InvalidArgumentException;

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

namespace ThePay\ApiClient\ValueObject;

/**
* @extends BaseValueObject<string>
*/
final class SecureUrl extends BaseValueObject
{
/** @var string */
Expand Down
31 changes: 10 additions & 21 deletions src/ValueObject/StringValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -4,6 +4,9 @@

use InvalidArgumentException;

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

declare(strict_types=1);

namespace ThePay\ApiClient\Tests\ValueObject;

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

abstract class BaseValueObjectTestCase extends TestCase
{
/**
* @dataProvider validValuesDataProvider
*
* @param mixed $value
*/
public function testCreatesWorkingInstanceWithValidValue($value): 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((string) $value, (string) $a);
}

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

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

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

Check failure on line 46 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.1

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::getClassName() return type with generic class ThePay\ApiClient\ValueObject\BaseValueObject does not specify its types: TValue

Check failure on line 46 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 2.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::getClassName() return type with generic class ThePay\ApiClient\ValueObject\BaseValueObject does not specify its types: TValue

Check failure on line 46 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 1.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::getClassName() return type with generic class ThePay\ApiClient\ValueObject\BaseValueObject does not specify its types: TValue

Check failure on line 46 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.3

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::getClassName() return type with generic class ThePay\ApiClient\ValueObject\BaseValueObject does not specify its types: TValue

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

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.1

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::validValuesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.1

PHPDoc tag @return has invalid value (array<array<mixed>>|array<string, array<mixed>): Unexpected token "*/", expected '>' at offset 71

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 2.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::validValuesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 2.0

PHPDoc tag @return has invalid value (array<array<mixed>>|array<string, array<mixed>): Unexpected token "*/", expected '>' at offset 71

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 1.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::validValuesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 1.0

PHPDoc tag @return has invalid value (array<array<mixed>>|array<string, array<mixed>): Unexpected token "*/", expected '>' at offset 71

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.3

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::validValuesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 51 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.3

PHPDoc tag @return has invalid value (array<array<mixed>>|array<string, array<mixed>): Unexpected token "*/", expected '>' at offset 71

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

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.1

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::invalidValuesAndMessagesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.1

PHPDoc tag @return has invalid value (array<array<mixed|string>>|array<string, array<mixed|string>): Unexpected token "*/", expected '>' at offset 85

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 2.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::invalidValuesAndMessagesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 2.0

PHPDoc tag @return has invalid value (array<array<mixed|string>>|array<string, array<mixed|string>): Unexpected token "*/", expected '>' at offset 85

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 1.0

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::invalidValuesAndMessagesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.2 psr/http-message 1.0

PHPDoc tag @return has invalid value (array<array<mixed|string>>|array<string, array<mixed|string>): Unexpected token "*/", expected '>' at offset 85

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.3

Method ThePay\ApiClient\Tests\ValueObject\BaseValueObjectTestCase::invalidValuesAndMessagesDataProvider() return type has no value type specified in iterable type array.

Check failure on line 56 in tests/ValueObject/BaseValueObjectTestCase.php

View workflow job for this annotation

GitHub Actions / php 8.3

PHPDoc tag @return has invalid value (array<array<mixed|string>>|array<string, array<mixed|string>): Unexpected token "*/", expected '>' at offset 85
}
Loading

0 comments on commit 28fa964

Please sign in to comment.