1
0
mirror of synced 2024-11-21 20:36:03 +03:00

php 7.3 support, better architecture

This commit is contained in:
Pavel 2020-09-28 13:27:19 +03:00
parent f1d0ecaa39
commit 93e6ab06c3
22 changed files with 701 additions and 190 deletions

View File

@ -5,13 +5,14 @@ cache:
- $HOME/.composer/cache - $HOME/.composer/cache
php: php:
- '7.3'
- '7.4' - '7.4'
before_script: before_script:
- flags="-o" - flags="-o"
- composer install $flags - composer install $flags
script: php ./vendor/phpunit/phpunit/phpunit -c phpunit.xml.dist script: composer run-script phpunit
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)

View File

@ -17,13 +17,12 @@
"psr-4": { "RetailCrm\\": "src/" } "psr-4": { "RetailCrm\\": "src/" }
}, },
"require": { "require": {
"php": ">=7.4.0", "php": ">=7.3.0",
"ext-curl": "*", "ext-curl": "*",
"ext-json": "*", "ext-json": "*",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
"symfony/serializer": "^5.1", "symfony/serializer": "^5.1",
"symfony/validator": "^5.1", "symfony/validator": "^5.1",
"devanych/di-container": "^2.1",
"doctrine/annotations": "^1.10", "doctrine/annotations": "^1.10",
"doctrine/cache": "^1.10", "doctrine/cache": "^1.10",
"symfony/property-access": "^5.1" "symfony/property-access": "^5.1"
@ -32,7 +31,15 @@
"phpunit/phpunit": "^9.3", "phpunit/phpunit": "^9.3",
"phpmd/phpmd": "^2.9", "phpmd/phpmd": "^2.9",
"squizlabs/php_codesniffer": "^3.5", "squizlabs/php_codesniffer": "^3.5",
"guzzlehttp/guzzle": "^7.1" "guzzlehttp/guzzle": "^7.1",
"phpcompatibility/php-compatibility": "*",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0"
}, },
"scripts": {
"phpunit": "./vendor/bin/phpunit -c phpunit.xml.dist",
"phpcs": "./vendor/bin/phpcs -p src --runtime-set testVersion 7.3",
"phpcbf": "./vendor/bin/phpcbf -p src"
},
"prefer-stable": true,
"license": "MIT" "license": "MIT"
} }

View File

@ -1,36 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html --> <!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.5/phpunit.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
backupGlobals="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
colors="false" backupGlobals="false"
bootstrap="tests/bootstrap.php" colors="false"
backupStaticAttributes="false" bootstrap="tests/bootstrap.php"
convertErrorsToExceptions="false" backupStaticAttributes="false"
convertNoticesToExceptions="false" convertErrorsToExceptions="false"
convertWarningsToExceptions="false" convertNoticesToExceptions="false"
processIsolation="true" convertWarningsToExceptions="false"
stopOnError="false" processIsolation="true"
stopOnFailure="false" stopOnError="false"
stopOnIncomplete="false" stopOnFailure="false"
stopOnSkipped="false" stopOnIncomplete="false"
stopOnRisky="false" stopOnSkipped="false"
stopOnRisky="false"
> >
<testsuites> <coverage>
<testsuite name="Project Test Suite"> <include>
<directory>tests</directory> <directory>src</directory>
</testsuite> </include>
</testsuites> <report>
<clover outputFile="coverage.xml"/>
<filter> </report>
<whitelist> </coverage>
<directory>src</directory> <testsuites>
</whitelist> <testsuite name="Project Test Suite">
</filter> <directory>tests</directory>
</testsuite>
<logging> </testsuites>
<log type="coverage-clover" target="coverage.xml"/> <logging>
<log type="junit" target="test-report.xml"/> <junit outputFile="test-report.xml"/>
</logging> </logging>
</phpunit> </phpunit>

View File

@ -0,0 +1,280 @@
<?php
/**
* PHP version 7.3
*
* @category Container
* @package RetailCrm\Component\DependencyInjection
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Component\DependencyInjection;
use Closure;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use ReflectionClass;
use ReflectionException;
use RetailCrm\Component\DependencyInjection\Exception\ContainerException;
use RetailCrm\Component\DependencyInjection\Exception\NotFoundException;
use Throwable;
/**
* Class Container
* This implementation took an inspiration from devanych/di-container. It's almost the same, but for PHP 7.3.
*
* @category Container
* @package RetailCrm\Component\DependencyInjection
* @author Evgeniy Zyubin <mail@devanych.ru>
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
class Container implements ContainerInterface
{
/**
* @var array $instances
*/
public $instances = [];
/**
* @var array $definitions
*/
public $definitions = [];
/**
* Container constructor.
*
* @param array $definitions
*/
public function __construct(array $definitions = [])
{
$this->setGroup($definitions);
}
/**
* Sets definition to the container.
*
* @param string $id
* @param mixed $definition
*/
public function set(string $id, $definition): void
{
if ($this->instantiated($id)) {
unset($this->instances[$id]);
}
$this->definitions[$id] = $definition;
}
/**
* Sets group of definitions at once.
*
* @param array<string, mixed> $definitions
*/
public function setGroup(array $definitions): void
{
foreach ($definitions as $id => $definition) {
self::isString($id);
$this->set($id, $definition);
}
}
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @return mixed Entry.
* @throws ContainerExceptionInterface Error while retrieving the entry.
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
*/
public function get($id)
{
self::isString($id);
if ($this->instantiated($id)) {
return $this->instances[$id];
}
$this->instances[$id] = $this->createInstance($id);
return $this->instances[$id];
}
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
*
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has($id): bool
{
return (is_string($id) && array_key_exists($id, $this->definitions));
}
/**
* Create instance by definition from the container by ID.
*
* @param string $id
* @return mixed
* @throws NotFoundException
* @throws ContainerException
*/
private function createInstance(string $id)
{
if (!$this->has($id)) {
if (self::isClassName($id)) {
return $this->createObject($id);
}
throw new NotFoundException(sprintf('`%s` is not set in container and is not a class name.', $id));
}
if (self::isClassName($this->definitions[$id])) {
return $this->createObject($this->definitions[$id]);
}
if ($this->definitions[$id] instanceof Closure) {
return $this->definitions[$id]($this);
}
return $this->definitions[$id];
}
/**
* Create object by class name.
*
* @param string $className
* @return object
* @throws ContainerException If unable to create object.
*/
private function createObject(string $className): object
{
try {
$reflection = new ReflectionClass($className);
} catch (ReflectionException $e) {
throw new ContainerException(sprintf('Unable to create object `%s`.', $className), 0, $e);
}
if (in_array(FactoryInterface::class, $reflection->getInterfaceNames(), true)) {
try {
/*** @var FactoryInterface $factory */
$factory = $this->getObjectFromReflection($reflection);
return $factory->create($this);
} catch (ContainerException $e) {
throw $e;
} catch (Throwable $e) {
throw new ContainerException(sprintf('Unable to create object `%s`.', $className), 0, $e);
}
}
return $this->getObjectFromReflection($reflection);
}
/**
* Create object from reflection.
*
* If the object has dependencies in the constructor, it tries to create them too.
*
* @param ReflectionClass $reflection
* @return object
* @throws ContainerException If unable to create object.
*/
private function getObjectFromReflection(ReflectionClass $reflection): object
{
if (($constructor = $reflection->getConstructor()) === null) {
return $reflection->newInstance();
}
$arguments = [];
foreach ($constructor->getParameters() as $parameter) {
if ($type = $parameter->getType()) {
$typeName = $type->getName();
if (!$type->isBuiltin() && ($this->has($typeName) || self::isClassName($typeName))) {
$arguments[] = $this->get($typeName);
continue;
}
if ($typeName === 'array' && $type->isBuiltin() && !$parameter->isDefaultValueAvailable()) {
$arguments[] = [];
continue;
}
}
if ($parameter->isDefaultValueAvailable()) {
try {
$arguments[] = $parameter->getDefaultValue();
continue;
} catch (ReflectionException $e) {
throw new ContainerException(
sprintf(
'Unable to create object `%s`. Unable to get default value of constructor parameter: `%s`.',
$reflection->getName(),
$parameter->getName()
)
);
}
}
throw new ContainerException(
sprintf(
'Unable to create object `%s`. Unable to process a constructor parameter: `%s`.',
$reflection->getName(),
$parameter->getName()
)
);
}
return $reflection->newInstanceArgs($arguments);
}
/**
* Returns true if definition was instantiated, false otherwise.
*
* @param string $id
*
* @return bool
*/
private function instantiated(string $id): bool
{
return array_key_exists($id, $this->instances);
}
/**
* Returns true if provided parameter is class name, false otherwise.
*
* @param mixed $className
*
* @return bool
*/
private static function isClassName($className): bool
{
return (is_string($className) && class_exists($className));
}
/**
* Validate provided ID
*
* @param mixed $id
* @throws NotFoundException
*/
private static function isString($id): void
{
if (!is_string($id)) {
throw new NotFoundException(sprintf('Invalid id. Expects string, `%s` provided.', gettype($id)));
}
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* PHP version 7.3
*
* @category ContainerException
* @package RetailCrm\Component\DependencyInjection\Exception
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Component\DependencyInjection\Exception;
use Psr\Container\ContainerExceptionInterface;
use LogicException;
/**
* Class ContainerException
*
* @category ContainerException
* @package RetailCrm\Component\DependencyInjection\Exception
* @author Evgeniy Zyubin <mail@devanych.ru>
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
class ContainerException extends LogicException implements ContainerExceptionInterface
{
}

View File

@ -0,0 +1,31 @@
<?php
/**
* PHP version 7.3
*
* @category NotFoundException
* @package RetailCrm\Component\DependencyInjection\Exception
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Component\DependencyInjection\Exception;
use Psr\Container\NotFoundExceptionInterface;
use InvalidArgumentException;
/**
* Class NotFoundException
*
* @category NotFoundException
* @package RetailCrm\Component\DependencyInjection\Exception
* @author Evgeniy Zyubin <mail@devanych.ru>
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
class NotFoundException extends InvalidArgumentException implements NotFoundExceptionInterface
{
}

View File

@ -0,0 +1,36 @@
<?php
/**
* PHP version 7.3
*
* @category FactoryInterface
* @package RetailCrm\Component\DependencyInjection
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Component\DependencyInjection;
use Psr\Container\ContainerInterface;
/**
* Interface FactoryInterface
*
* @category FactoryInterface
* @package RetailCrm\Component\DependencyInjection
* @author Evgeniy Zyubin <mail@devanych.ru>
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
interface FactoryInterface
{
/**
* @param \Psr\Container\ContainerInterface $container
*
* @return object
*/
public function create(ContainerInterface $container): object;
}

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category Environment * @category Environment
* @package RetailCrm\Component * @package RetailCrm\Component
@ -12,10 +12,6 @@
*/ */
namespace RetailCrm\Component; namespace RetailCrm\Component;
use Psr\Container\ContainerInterface;
use RetailCrm\Factory\ClientFactory;
use RetailCrm\TopClient\Client;
/** /**
* Class Environment * Class Environment
* *
@ -31,36 +27,4 @@ class Environment
public const PROD = 'PROD'; public const PROD = 'PROD';
public const DEV = 'DEV'; public const DEV = 'DEV';
public const TEST = 'TEST'; public const TEST = 'TEST';
private ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @return \Psr\Container\ContainerInterface
*/
public function getContainer(): ContainerInterface
{
return $this->container;
}
/**
* @param string $serviceUrl
*
* @return \RetailCrm\TopClient\Client
* @throws \RetailCrm\Component\Exception\ValidationException
*/
public function createClient(string $serviceUrl): Client
{
$factory = $this->container->get(ClientFactory::class);
if (!($factory instanceof ClientFactory)) {
throw new \RuntimeException('Invalid factory definition in the provided container');
}
return $factory->create($serviceUrl);
}
} }

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category ValidationException * @category ValidationException
* @package RetailCrm\Component\Exception * @package RetailCrm\Component\Exception
@ -27,7 +27,10 @@ use Throwable;
*/ */
class ValidationException extends \Exception class ValidationException extends \Exception
{ {
private ?ConstraintViolationListInterface $violations; /**
* @var \Symfony\Component\Validator\ConstraintViolationListInterface|null
*/
private $violations;
/** /**
* ValidationException constructor. * ValidationException constructor.

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category ClientFactory * @category ClientFactory
* @package RetailCrm\Factory * @package RetailCrm\Factory
@ -12,13 +12,11 @@
*/ */
namespace RetailCrm\Factory; namespace RetailCrm\Factory;
use RetailCrm\Interfaces\HttpClientAwareInterface; use Psr\Container\ContainerInterface;
use RetailCrm\Interfaces\ValidatorAwareInterface; use RetailCrm\Interfaces\ContainerAwareInterface;
use RetailCrm\Interfaces\FactoryInterface;
use RetailCrm\TopClient\Client; use RetailCrm\TopClient\Client;
use RetailCrm\Traits\HttpClientAwareTrait; use RetailCrm\Traits\ContainerAwareTrait;
use RetailCrm\Traits\ValidatorAwareTrait;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;
/** /**
* Class ClientFactory * Class ClientFactory
@ -30,24 +28,47 @@ use Symfony\Component\Serializer\SerializerAwareTrait;
* @link http://retailcrm.ru * @link http://retailcrm.ru
* @see https://help.retailcrm.ru * @see https://help.retailcrm.ru
*/ */
class ClientFactory implements HttpClientAwareInterface, SerializerAwareInterface, ValidatorAwareInterface class ClientFactory implements ContainerAwareInterface, FactoryInterface
{ {
use HttpClientAwareTrait; use ContainerAwareTrait;
use SerializerAwareTrait;
use ValidatorAwareTrait; /** @var string $serviceUrl */
private $serviceUrl;
/**
* @param \Psr\Container\ContainerInterface $container
*
* @return \RetailCrm\Factory\ClientFactory
*/
public static function withContainer(ContainerInterface $container): ClientFactory
{
$factory = new self();
$factory->setContainer($container);
return $factory;
}
/** /**
* @param string $serviceUrl * @param string $serviceUrl
* *
* @return $this
*/
public function setServiceUrl(string $serviceUrl): ClientFactory
{
$this->serviceUrl = $serviceUrl;
return $this;
}
/**
* @return \RetailCrm\TopClient\Client * @return \RetailCrm\TopClient\Client
* @throws \RetailCrm\Component\Exception\ValidationException * @throws \RetailCrm\Component\Exception\ValidationException
*/ */
public function create(string $serviceUrl): Client public function create(): Client
{ {
$client = new Client($serviceUrl); $client = new Client($this->serviceUrl);
$client->setHttpClient($this->httpClient); $client->setHttpClient($this->container->get('httpClient'));
$client->setSerializer($this->serializer); $client->setSerializer($this->container->get('serializer'));
$client->setValidator($this->validator); $client->setValidator($this->container->get('validator'));
$client->validateSelf(); $client->validateSelf();
return $client; return $client;

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category EnvironmentFactory * @category EnvironmentFactory
* @package RetailCrm\Factory * @package RetailCrm\Factory
@ -12,17 +12,16 @@
*/ */
namespace RetailCrm\Factory; namespace RetailCrm\Factory;
use Devanych\Di\Container;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;
use Psr\Http\Client\ClientInterface; use Psr\Http\Client\ClientInterface;
use RetailCrm\TopClient\Client; use RetailCrm\Component\DependencyInjection\Container;
use RetailCrm\Component\Environment;
use RetailCrm\Interfaces\FactoryInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerAwareTrait;
use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validation;
use RetailCrm\Component\Environment;
use Symfony\Component\Validator\Validator\TraceableValidator; use Symfony\Component\Validator\Validator\TraceableValidator;
use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface;
@ -36,17 +35,24 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
* @link http://retailcrm.ru * @link http://retailcrm.ru
* @see https://help.retailcrm.ru * @see https://help.retailcrm.ru
*/ */
class EnvironmentFactory implements EnvironmentAwareFactoryInterface class ContainerFactory implements FactoryInterface
{ {
public string $env; /**
public ClientInterface $httpClient; * @var string $env
*/
public $env;
/**
* @var \Psr\Http\Client\ClientInterface $httpClient
*/
public $httpClient;
/** /**
* @param string $environmentType * @param string $environmentType
* *
* @return \RetailCrm\Factory\EnvironmentAwareFactoryInterface * @return ContainerFactory
*/ */
public static function withEnv(string $environmentType = Environment::DEV): EnvironmentAwareFactoryInterface public static function withEnv(string $environmentType = Environment::DEV): ContainerFactory
{ {
$factory = new self(); $factory = new self();
$factory->env = $environmentType; $factory->env = $environmentType;
@ -57,28 +63,35 @@ class EnvironmentFactory implements EnvironmentAwareFactoryInterface
/** /**
* @param \Psr\Http\Client\ClientInterface $httpClient * @param \Psr\Http\Client\ClientInterface $httpClient
* *
* @return \RetailCrm\Component\Environment * @return \RetailCrm\Factory\ContainerFactory
*/ */
public function create(ClientInterface $httpClient): Environment public function withClient(ClientInterface $httpClient): ContainerFactory
{ {
$this->httpClient = $httpClient; $this->httpClient = $httpClient;
return $this;
}
/**
* @return \Psr\Container\ContainerInterface
*/
public function create(): ContainerInterface
{
$container = new Container(); $container = new Container();
switch ($this->env) { switch ($this->env) {
case Environment::PROD: case Environment::PROD:
$this->setProdServices($container); $this->setProdServices($container);
break; break;
case Environment::DEV: case Environment::DEV:
case Environment::TEST: case Environment::TEST:
$this->setProdServices($container); $this->setProdServices($container);
$this->setDevServices($container); $this->setDevServices($container);
break; break;
default: default:
throw new \RuntimeException(sprintf('Invalid environment type: %s', $this->env)); throw new \RuntimeException(sprintf('Invalid environment type: %s', $this->env));
} }
return new Environment($container); return $container;
} }
/** /**
@ -88,18 +101,12 @@ class EnvironmentFactory implements EnvironmentAwareFactoryInterface
{ {
$container->set('httpClient', $this->httpClient); $container->set('httpClient', $this->httpClient);
$container->set('validator', Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator()); $container->set('validator', Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator());
$container->set('serializer', new Serializer( $container->set(
[new ObjectNormalizer()], 'serializer', new Serializer(
[new XmlEncoder(), new JsonEncoder()] [new ObjectNormalizer()],
)); [new XmlEncoder(), new JsonEncoder()]
$container->set(ClientFactory::class, function (ContainerInterface $container): ClientFactory { )
$factory = new ClientFactory(); );
$factory->setHttpClient($container->get('httpClient'));
$factory->setSerializer($container->get('serializer'));
$factory->setValidator($container->get('validator'));
return $factory;
});
} }
/** /**

View File

@ -1,42 +0,0 @@
<?php
/**
* PHP version 7.4
*
* @category EnvironmentAwareFactoryInterface
* @package RetailCrm\Factory
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Factory;
use Psr\Http\Client\ClientInterface;
use RetailCrm\Component\Environment;
/**
* Interface EnvironmentAwareFactoryInterface
*
* @category EnvironmentAwareFactoryInterface
* @package RetailCrm\Factory
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
interface EnvironmentAwareFactoryInterface
{
/**
* @param string $environmentType
*
* @return \RetailCrm\Factory\EnvironmentAwareFactoryInterface
*/
public static function withEnv(string $environmentType = Environment::DEV): EnvironmentAwareFactoryInterface;
/**
* @return \RetailCrm\Component\Environment
*/
public function create(ClientInterface $httpClient): Environment;
}

View File

@ -0,0 +1,41 @@
<?php
/**
* PHP version 7.3
*
* @category ContainerAwareInterface
* @package RetailCrm\Interfaces
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Interfaces;
use Psr\Container\ContainerInterface;
/**
* Interface ContainerAwareInterface
*
* @category ContainerAwareInterface
* @package RetailCrm\Interfaces
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
interface ContainerAwareInterface
{
/**
* @param \Psr\Container\ContainerInterface $container
*
* @return mixed
*/
public function setContainer(ContainerInterface $container): void;
/**
* @return \Psr\Container\ContainerInterface
*/
public function getContainer(): ContainerInterface;
}

View File

@ -0,0 +1,32 @@
<?php
/**
* PHP version 7.3
*
* @category FactoryInterface
* @package RetailCrm\Interfaces
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Interfaces;
/**
* Interface FactoryInterface
*
* @category FactoryInterface
* @package RetailCrm\Interfaces
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
interface FactoryInterface
{
/**
* @return object
*/
public function create();
}

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category ClientAwareInterface * @category ClientAwareInterface
* @package RetailCrm\Interfaces * @package RetailCrm\Interfaces

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category ValidatorAwareInterface * @category ValidatorAwareInterface
* @package RetailCrm\Interfaces * @package RetailCrm\Interfaces

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category Client * @category Client
* @package RetailCrm\TopClient * @package RetailCrm\TopClient
@ -16,9 +16,9 @@ use RetailCrm\Component\Exception\ValidationException;
use RetailCrm\Interfaces\HttpClientAwareInterface; use RetailCrm\Interfaces\HttpClientAwareInterface;
use RetailCrm\Interfaces\ValidatorAwareInterface; use RetailCrm\Interfaces\ValidatorAwareInterface;
use RetailCrm\Traits\HttpClientAwareTrait; use RetailCrm\Traits\HttpClientAwareTrait;
use RetailCrm\Traits\SerializerAwareTrait;
use RetailCrm\Traits\ValidatorAwareTrait; use RetailCrm\Traits\ValidatorAwareTrait;
use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;
use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Constraints as Assert;
/** /**
@ -42,10 +42,11 @@ class Client implements SerializerAwareInterface, HttpClientAwareInterface, Vali
public const AVAILABLE_ENDPOINTS = [self::OVERSEAS_ENDPOINT, self::CHINESE_ENDPOINT]; public const AVAILABLE_ENDPOINTS = [self::OVERSEAS_ENDPOINT, self::CHINESE_ENDPOINT];
/** /**
* @var string $serviceUrl
* @Assert\Url() * @Assert\Url()
* @Assert\Choice(choices=Client::AVAILABLE_ENDPOINTS, message="Choose a valid endpoint.") * @Assert\Choice(choices=Client::AVAILABLE_ENDPOINTS, message="Choose a valid endpoint.")
*/ */
protected string $serviceUrl; protected $serviceUrl;
/** /**
* Client constructor. * Client constructor.
@ -62,11 +63,7 @@ class Client implements SerializerAwareInterface, HttpClientAwareInterface, Vali
*/ */
public function validateSelf(): void public function validateSelf(): void
{ {
$violations = $this->validator->validate($this); $this->validate($this);
if ($violations->count()) {
throw new ValidationException("Invalid client data", $violations);
}
} }
/** /**
@ -79,7 +76,7 @@ class Client implements SerializerAwareInterface, HttpClientAwareInterface, Vali
$violations = $this->validator->validate($item); $violations = $this->validator->validate($item);
if ($violations->count()) { if ($violations->count()) {
throw new ValidationException("Invalid data", $item); throw new ValidationException("Invalid data", $violations);
} }
} }
} }

View File

@ -0,0 +1,52 @@
<?php
/**
* PHP version 7.3
*
* @category ContainerAwareTrait
* @package RetailCrm\Traits
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Traits;
use Psr\Container\ContainerInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Trait ContainerAwareTrait
*
* @category ContainerAwareTrait
* @package RetailCrm\Traits
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
trait ContainerAwareTrait
{
/**
* @var ContainerInterface $container
* @Assert\NotNull(message="Container should be provided")
*/
protected $container;
/**
* @param \Psr\Container\ContainerInterface $container
*/
public function setContainer(ContainerInterface $container): void
{
$this->container = $container;
}
/**
* @return \Psr\Container\ContainerInterface
*/
public function getContainer(): ContainerInterface
{
return $this->container;
}
}

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category HttpClientAwareTrait * @category HttpClientAwareTrait
* @package RetailCrm\Traits * @package RetailCrm\Traits
@ -29,9 +29,10 @@ use Symfony\Component\Validator\Constraints as Assert;
trait HttpClientAwareTrait trait HttpClientAwareTrait
{ {
/** /**
* @var ClientInterface $httpClient
* @Assert\NotNull(message="HTTP client should be provided") * @Assert\NotNull(message="HTTP client should be provided")
*/ */
protected ClientInterface $httpClient; protected $httpClient;
/** /**
* @param \Psr\Http\Client\ClientInterface $httpClient * @param \Psr\Http\Client\ClientInterface $httpClient

View File

@ -0,0 +1,45 @@
<?php
/**
* PHP version 7.3
*
* @category SerializerAwareTrait
* @package RetailCrm\Traits
* @author RetailCRM <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see http://help.retailcrm.ru
*/
namespace RetailCrm\Traits;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Trait SerializerAwareTrait
*
* @category SerializerAwareTrait
* @package RetailCrm\Traits
* @author Joel Wurtz <joel.wurtz@gmail.com>
* @author RetailDriver LLC <integration@retailcrm.ru>
* @license MIT
* @link http://retailcrm.ru
* @see https://help.retailcrm.ru
*/
trait SerializerAwareTrait
{
/**
* @var SerializerInterface $serializer
* @Assert\NotNull(message="Serializer should be provided")
*/
protected $serializer;
/**
* @param \Symfony\Component\Serializer\SerializerInterface $serializer
*/
public function setSerializer(SerializerInterface $serializer): void
{
$this->serializer = $serializer;
}
}

View File

@ -1,7 +1,7 @@
<?php <?php
/** /**
* PHP version 7.4 * PHP version 7.3
* *
* @category ValidatorAwareTrait * @category ValidatorAwareTrait
* @package RetailCrm\Traits * @package RetailCrm\Traits
@ -29,9 +29,10 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
trait ValidatorAwareTrait trait ValidatorAwareTrait
{ {
/** /**
* @var ValidatorInterface $validator
* @Assert\NotNull(message="Validator should be provided") * @Assert\NotNull(message="Validator should be provided")
*/ */
protected ValidatorInterface $validator; protected $validator;
/** /**
* @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator

View File

@ -12,9 +12,10 @@
*/ */
namespace Component; namespace Component;
use GuzzleHttp\Client as HttpClient;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use RetailCrm\Factory\EnvironmentFactory; use RetailCrm\Component\Environment;
use RetailCrm\Factory\ClientFactory;
use RetailCrm\Factory\ContainerFactory;
use RetailCrm\TopClient\Client; use RetailCrm\TopClient\Client;
/** /**
@ -31,9 +32,11 @@ class EnvironmentTest extends TestCase
{ {
public function testCreateClient() public function testCreateClient()
{ {
$client = EnvironmentFactory::withEnv() $client = ClientFactory::withContainer(
->create(new HttpClient()) ContainerFactory::withEnv(Environment::DEV)
->createClient(Client::OVERSEAS_ENDPOINT); ->withClient(new \GuzzleHttp\Client())
->create()
)->setServiceUrl(Client::OVERSEAS_ENDPOINT)->create();
self::assertInstanceOf(Client::class, $client); self::assertInstanceOf(Client::class, $client);
} }