diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3ca311b..2068a35 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,6 +29,27 @@ jobs:
- name: Run friendsofphp/php-cs-fixer
run: composer php-cs
+ type-checker:
+ name: Type Checker
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: 8.0
+ coverage: none
+
+ - name: Install composer dependencies
+ uses: ramsey/composer-install@v1
+
+ - name: Run vimeo/psalm
+ run: composer psalm
+
tests:
name: Tests
diff --git a/composer.json b/composer.json
index 7c87bd4..9be5435 100644
--- a/composer.json
+++ b/composer.json
@@ -20,7 +20,8 @@
"php-http/mock-client": "^1.4",
"phpunit/phpunit": "^8.5",
"symfony/http-client": "^5.3",
- "symfony/var-dumper": "^5.3"
+ "symfony/var-dumper": "^5.3",
+ "vimeo/psalm": "^4.8"
},
"config": {
"sort-packages": true
@@ -41,6 +42,7 @@
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
+ "psalm": "@php vendor/bin/psalm --no-progress",
"php-cs": "@php vendor/bin/php-cs-fixer fix --dry-run",
"php-cs-fix": "@php vendor/bin/php-cs-fixer fix",
"test": "@php vendor/bin/phpunit --configuration phpunit.dist.xml",
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000..f6529b3
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Client.php b/src/Client.php
index c977472..9f29fe0 100644
--- a/src/Client.php
+++ b/src/Client.php
@@ -4,12 +4,12 @@
namespace BlueMedia;
+use BlueMedia\Common\ValueObject\HashableInterface;
use BlueMedia\Confirmation\Builder\ConfirmationVOBuilder;
use BlueMedia\HttpClient\HttpClientInterface;
use BlueMedia\Hash\HashChecker;
use BlueMedia\Itn\Builder\ItnVOBuilder;
use BlueMedia\Itn\Decoder\ItnDecoder;
-use BlueMedia\Serializer\SerializableInterface;
use BlueMedia\Transaction\View;
use BlueMedia\Itn\ValueObject\Itn;
use BlueMedia\HttpClient\HttpClient;
@@ -40,7 +40,7 @@ final class Client
private $configuration;
/**
- * @var HttpClientInterface|null
+ * @var HttpClientInterface
*/
private $httpClient;
@@ -126,11 +126,9 @@ public function doItnIn(string $itn): Response
/**
* Returns response for ITN IN request.
*
- * @return Response
- *
* @api
*/
- public function doItnInResponse(Itn $itn, bool $transactionConfirmed = true)
+ public function doItnInResponse(Itn $itn, bool $transactionConfirmed = true): Response
{
return new Response(ItnResponseBuilder::build($itn, $transactionConfirmed, $this->configuration));
}
@@ -196,7 +194,7 @@ public function getRegulationList(string $gatewayUrl): Response
*
* @api
*/
- public function checkHash(SerializableInterface $data): bool
+ public function checkHash(HashableInterface $data): bool
{
return HashChecker::checkHash($data, $this->configuration);
}
diff --git a/src/Common/Builder/ServiceDtoBuilder.php b/src/Common/Builder/ServiceDtoBuilder.php
index 32c02e0..c8da477 100644
--- a/src/Common/Builder/ServiceDtoBuilder.php
+++ b/src/Common/Builder/ServiceDtoBuilder.php
@@ -11,6 +11,12 @@
final class ServiceDtoBuilder
{
+ /**
+ * @template T of AbstractDto
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
public static function build(array $data, string $type, Configuration $configuration): AbstractDto
{
$serializer = new Serializer();
diff --git a/src/Common/Dto/AbstractDto.php b/src/Common/Dto/AbstractDto.php
index f860d0c..6aa1369 100644
--- a/src/Common/Dto/AbstractDto.php
+++ b/src/Common/Dto/AbstractDto.php
@@ -4,8 +4,8 @@
namespace BlueMedia\Common\Dto;
+use BlueMedia\Common\ValueObject\AbstractValueObject;
use BlueMedia\HttpClient\ValueObject\Request;
-use BlueMedia\Serializer\SerializableInterface;
use JMS\Serializer\Annotation\Type;
abstract class AbstractDto
@@ -39,5 +39,5 @@ public function getRequest(): ?Request
return $this->request;
}
- abstract public function getRequestData(): SerializableInterface;
+ abstract public function getRequestData(): AbstractValueObject;
}
diff --git a/src/Common/Parser/ServiceResponseParser.php b/src/Common/Parser/ServiceResponseParser.php
index e9535d9..9d014db 100644
--- a/src/Common/Parser/ServiceResponseParser.php
+++ b/src/Common/Parser/ServiceResponseParser.php
@@ -9,6 +9,12 @@
final class ServiceResponseParser extends ResponseParser
{
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
public function parseListResponse(string $type): SerializableInterface
{
$this->isErrorResponse();
diff --git a/src/Common/ValueObject/HashableInterface.php b/src/Common/ValueObject/HashableInterface.php
new file mode 100644
index 0000000..9cb5cd2
--- /dev/null
+++ b/src/Common/ValueObject/HashableInterface.php
@@ -0,0 +1,10 @@
+toArray(),
diff --git a/src/Itn/Builder/ItnDtoBuilder.php b/src/Itn/Builder/ItnDtoBuilder.php
index 1699114..52bf57e 100644
--- a/src/Itn/Builder/ItnDtoBuilder.php
+++ b/src/Itn/Builder/ItnDtoBuilder.php
@@ -5,18 +5,18 @@
namespace BlueMedia\Itn\Builder;
use BlueMedia\Itn\Dto\ItnDto;
-use BlueMedia\Serializer\SerializableInterface;
use BlueMedia\Serializer\Serializer;
use BlueMedia\Common\Util\XMLParser;
final class ItnDtoBuilder
{
- public static function build(string $itnData): SerializableInterface
+ public static function build(string $itnData): ItnDto
{
$serializer = new Serializer();
$xmlData = XMLParser::parse($itnData);
$xmlTransaction = $xmlData->transactions->transaction->asXML();
+ /** @var ItnDto $itnDto */
$itnDto = $serializer->deserializeXml($xmlTransaction, ItnDto::class);
$itnDto->getItn()->setServiceID((string) $xmlData->serviceID);
diff --git a/src/Itn/Dto/ItnDto.php b/src/Itn/Dto/ItnDto.php
index 8152655..96bbbe0 100644
--- a/src/Itn/Dto/ItnDto.php
+++ b/src/Itn/Dto/ItnDto.php
@@ -5,6 +5,7 @@
namespace BlueMedia\Itn\Dto;
use BlueMedia\Common\Dto\AbstractDto;
+use BlueMedia\Common\ValueObject\AbstractValueObject;
use BlueMedia\Itn\ValueObject\Itn;
use BlueMedia\Serializer\SerializableInterface;
use JMS\Serializer\Annotation\XmlList;
@@ -24,7 +25,7 @@ public function getItn(): Itn
return $this->itn;
}
- public function getRequestData(): SerializableInterface
+ public function getRequestData(): AbstractValueObject
{
return $this->getItn();
}
diff --git a/src/PaywayList/Dto/PaywayListDto.php b/src/PaywayList/Dto/PaywayListDto.php
index 89c9147..4819251 100644
--- a/src/PaywayList/Dto/PaywayListDto.php
+++ b/src/PaywayList/Dto/PaywayListDto.php
@@ -5,8 +5,8 @@
namespace BlueMedia\PaywayList\Dto;
use BlueMedia\Common\Dto\AbstractDto;
+use BlueMedia\Common\ValueObject\AbstractValueObject;
use JMS\Serializer\Annotation\Type;
-use BlueMedia\Serializer\SerializableInterface;
use BlueMedia\PaywayList\ValueObject\PaywayList;
final class PaywayListDto extends AbstractDto
@@ -22,7 +22,7 @@ public function getPaywayList(): PaywayList
return $this->paywayList;
}
- public function getRequestData(): SerializableInterface
+ public function getRequestData(): AbstractValueObject
{
return $this->getPaywayList();
}
diff --git a/src/RegulationList/Dto/RegulationListDto.php b/src/RegulationList/Dto/RegulationListDto.php
index b6e0986..013534f 100644
--- a/src/RegulationList/Dto/RegulationListDto.php
+++ b/src/RegulationList/Dto/RegulationListDto.php
@@ -4,9 +4,9 @@
namespace BlueMedia\RegulationList\Dto;
+use BlueMedia\Common\ValueObject\AbstractValueObject;
use JMS\Serializer\Annotation\Type;
use BlueMedia\Common\Dto\AbstractDto;
-use BlueMedia\Serializer\SerializableInterface;
use BlueMedia\RegulationList\ValueObject\RegulationList;
final class RegulationListDto extends AbstractDto
@@ -22,7 +22,7 @@ public function getRegulationList(): RegulationList
return $this->regulationList;
}
- public function getRequestData(): SerializableInterface
+ public function getRequestData(): AbstractValueObject
{
return $this->getRegulationList();
}
diff --git a/src/Serializer/Serializer.php b/src/Serializer/Serializer.php
index d2d2d2b..e75ea40 100644
--- a/src/Serializer/Serializer.php
+++ b/src/Serializer/Serializer.php
@@ -4,7 +4,6 @@
namespace BlueMedia\Serializer;
-use BlueMedia\Common\Dto\AbstractDto;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
@@ -13,6 +12,9 @@ final class Serializer implements SerializerInterface
{
private const XML_TYPE = 'xml';
+ /**
+ * @var \JMS\Serializer\Serializer
+ */
private $serializer;
public function __construct()
@@ -26,7 +28,13 @@ public function __construct()
->build();
}
- public function serializeDataToDto(array $data, string $type): AbstractDto
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
+ public function serializeDataToDto(array $data, string $type)
{
return $this->serializer->fromArray($data, $type);
}
@@ -36,12 +44,24 @@ public function toArray(object $object): array
return $this->serializer->toArray($object);
}
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
public function fromArray(array $data, string $type)
{
return $this->serializer->fromArray($data, $type);
}
- public function deserializeXml(string $xml, string $type): SerializableInterface
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
+ public function deserializeXml(string $xml, string $type)
{
return $this->serializer->deserialize($xml, $type, self::XML_TYPE);
}
diff --git a/src/Serializer/SerializerInterface.php b/src/Serializer/SerializerInterface.php
index 5807679..2a8fd7f 100644
--- a/src/Serializer/SerializerInterface.php
+++ b/src/Serializer/SerializerInterface.php
@@ -4,17 +4,33 @@
namespace BlueMedia\Serializer;
-use BlueMedia\Common\Dto\AbstractDto;
-
interface SerializerInterface
{
- public function serializeDataToDto(array $data, string $type): AbstractDto;
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
+ public function serializeDataToDto(array $data, string $type);
public function toArray(object $object): array;
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
public function fromArray(array $data, string $type);
- public function deserializeXml(string $xml, string $type): SerializableInterface;
+ /**
+ * @template T
+ * @psalm-param class-string $type
+ *
+ * @return T
+ */
+ public function deserializeXml(string $xml, string $type);
public function toXml($data): string;
}
diff --git a/src/Transaction/Builder/TransactionDtoBuilder.php b/src/Transaction/Builder/TransactionDtoBuilder.php
index 285dc67..85dacaf 100644
--- a/src/Transaction/Builder/TransactionDtoBuilder.php
+++ b/src/Transaction/Builder/TransactionDtoBuilder.php
@@ -4,7 +4,6 @@
namespace BlueMedia\Transaction\Builder;
-use BlueMedia\Common\Dto\AbstractDto;
use BlueMedia\Configuration;
use BlueMedia\Hash\HashGenerator;
use BlueMedia\Serializer\Serializer;
@@ -12,9 +11,10 @@
final class TransactionDtoBuilder
{
- public static function build(array $transactionData, Configuration $configuration): AbstractDto
+ public static function build(array $transactionData, Configuration $configuration): TransactionDto
{
$serializer = new Serializer();
+ /** @var TransactionDto $transactionDto */
$transactionDto = $serializer->serializeDataToDto($transactionData, TransactionDto::class);
$transactionDto->getTransaction()->setServiceId($configuration->getServiceId());
diff --git a/src/Transaction/Dto/TransactionDto.php b/src/Transaction/Dto/TransactionDto.php
index 7cdc88e..3b3397b 100644
--- a/src/Transaction/Dto/TransactionDto.php
+++ b/src/Transaction/Dto/TransactionDto.php
@@ -5,7 +5,7 @@
namespace BlueMedia\Transaction\Dto;
use BlueMedia\Common\Dto\AbstractDto;
-use BlueMedia\Serializer\SerializableInterface;
+use BlueMedia\Common\ValueObject\AbstractValueObject;
use BlueMedia\Transaction\ValueObject\Transaction;
use JMS\Serializer\Annotation\Type;
@@ -44,7 +44,7 @@ public function setHtmlFormLanguage(string $htmlFormLanguage): self
return $this;
}
- public function getRequestData(): SerializableInterface
+ public function getRequestData(): AbstractValueObject
{
return $this->getTransaction();
}
diff --git a/src/Transaction/ValueObject/Transaction.php b/src/Transaction/ValueObject/Transaction.php
index b8956c7..252d796 100644
--- a/src/Transaction/ValueObject/Transaction.php
+++ b/src/Transaction/ValueObject/Transaction.php
@@ -4,6 +4,7 @@
namespace BlueMedia\Transaction\ValueObject;
+use BlueMedia\Common\ValueObject\HashableInterface;
use BlueMedia\Serializer\SerializableInterface;
use BlueMedia\Common\ValueObject\AbstractValueObject;
use JMS\Serializer\Annotation\Type;
@@ -43,7 +44,7 @@
* "hash"
* })
*/
-class Transaction extends AbstractValueObject implements SerializableInterface
+class Transaction extends AbstractValueObject implements SerializableInterface, HashableInterface
{
/**
* Transaction service id.
diff --git a/src/Transaction/View.php b/src/Transaction/View.php
index 555cf2f..4ac5a15 100644
--- a/src/Transaction/View.php
+++ b/src/Transaction/View.php
@@ -4,13 +4,13 @@
namespace BlueMedia\Transaction;
-use BlueMedia\Common\Dto\AbstractDto;
use BlueMedia\Common\Enum\ClientEnum;
use BlueMedia\Common\Util\Translations;
+use BlueMedia\Transaction\Dto\TransactionDto;
final class View
{
- public static function createRedirectHtml(AbstractDto $transactionDto): string
+ public static function createRedirectHtml(TransactionDto $transactionDto): string
{
$translation = (new Translations())->getTranslation(
$transactionDto->getHtmlFormLanguage()