serializer now supports typed arrays and formatted DateTime
This commit is contained in:
parent
102f16cb9e
commit
2828d88069
5 changed files with 266 additions and 2 deletions
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Component\Json\Exception
|
||||
* @author retailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Component\Json\Exception;
|
||||
|
||||
/**
|
||||
* Class InvalidAnnotationException
|
||||
*
|
||||
* @package Intaro\RetailCrm\Component\Json\Exception
|
||||
*/
|
||||
class InvalidAnnotationException extends \Exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy\Deserialize
|
||||
* @author retailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Component\Json\Strategy\Deserialize;
|
||||
|
||||
use Intaro\RetailCrm\Component\Json\Exception\InvalidAnnotationException;
|
||||
use Intaro\RetailCrm\Component\Json\Strategy\StrategyFactory;
|
||||
use Intaro\RetailCrm\Component\Json\Strategy\TypedArrayTrait;
|
||||
|
||||
/**
|
||||
* Class TypedArrayStrategy
|
||||
*
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy\Deserialize
|
||||
*/
|
||||
class TypedArrayStrategy implements DeserializeStrategyInterface
|
||||
{
|
||||
use InnerTypeTrait;
|
||||
use TypedArrayTrait;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function deserialize(string $type, $value)
|
||||
{
|
||||
$keyType = '';
|
||||
$valueType = '';
|
||||
$result = [];
|
||||
|
||||
if (strpos($this->innerType, ',') !== false) {
|
||||
[$keyType, $valueType] = static::getInnerTypes($this->innerType);
|
||||
|
||||
if ('' === $keyType && '' === $valueType) {
|
||||
$valueType = $this->innerType;
|
||||
}
|
||||
} else {
|
||||
$valueType = $this->innerType;
|
||||
}
|
||||
|
||||
$simpleStrategy = new SimpleTypeStrategy();
|
||||
|
||||
foreach (array_keys($value) as $key) {
|
||||
$deserializedKey = $key;
|
||||
|
||||
if ('' !== $keyType) {
|
||||
$deserializedKey = $simpleStrategy->deserialize($keyType, $key);
|
||||
}
|
||||
|
||||
$result[$deserializedKey]
|
||||
= StrategyFactory::deserializeStrategyByType($valueType)->deserialize($valueType, $value[$key]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy\Serialize
|
||||
* @author retailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Component\Json\Strategy\Serialize;
|
||||
|
||||
use Intaro\RetailCrm\Component\Json\Exception\InvalidAnnotationException;
|
||||
use Intaro\RetailCrm\Component\Json\Strategy\StrategyFactory;
|
||||
use Intaro\RetailCrm\Component\Json\Strategy\TypedArrayTrait;
|
||||
|
||||
/**
|
||||
* Class TypedArrayStrategy
|
||||
*
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy\Serialize
|
||||
*/
|
||||
class TypedArrayStrategy implements SerializeStrategyInterface
|
||||
{
|
||||
use InnerTypeTrait;
|
||||
use TypedArrayTrait;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function serialize($value)
|
||||
{
|
||||
$valueType = '';
|
||||
$result = [];
|
||||
|
||||
if (strpos($this->innerType, ',') !== false) {
|
||||
[$keyType, $valueType] = static::getInnerTypes($this->innerType);
|
||||
|
||||
if ('' === $keyType && '' === $valueType) {
|
||||
$valueType = $this->innerType;
|
||||
}
|
||||
} else {
|
||||
$valueType = $this->innerType;
|
||||
}
|
||||
|
||||
$simpleStrategy = new SimpleTypeStrategy();
|
||||
|
||||
foreach (array_keys($value) as $key) {
|
||||
$result[$simpleStrategy->serialize($key)]
|
||||
= StrategyFactory::serializeStrategyByType($valueType)->serialize($value[$key]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,9 @@ use Intaro\RetailCrm\Component\Json\Strategy\Serialize\SerializeStrategyInterfac
|
|||
*/
|
||||
class StrategyFactory
|
||||
{
|
||||
/** @var string */
|
||||
private const TYPED_MATCHER = '/^\\\\?([a-zA-Z0-9_]+)\s*\<(.+)\>$/m';
|
||||
|
||||
/** @var string[] $simpleTypes */
|
||||
private static $simpleTypes = [
|
||||
'bool',
|
||||
|
@ -50,7 +53,17 @@ class StrategyFactory
|
|||
return (new Serialize\DateTimeStrategy())->setInnerType(\DateTime::RFC3339);
|
||||
}
|
||||
|
||||
// TODO: DateTime<format> strategy and array<valueType>, array<keyType, valueType> strategies
|
||||
$arrSubType = static::getArrayInnerTypes($dataType);
|
||||
|
||||
if (!empty($arrSubType)) {
|
||||
return (new Serialize\TypedArrayStrategy())->setInnerType($arrSubType);
|
||||
}
|
||||
|
||||
$dateTimeFormat = static::getDateTimeFormat($dataType);
|
||||
|
||||
if (!empty($dateTimeFormat)) {
|
||||
return (new Serialize\DateTimeStrategy())->setInnerType($dateTimeFormat);
|
||||
}
|
||||
|
||||
return new Serialize\EntityStrategy();
|
||||
}
|
||||
|
@ -70,11 +83,76 @@ class StrategyFactory
|
|||
return (new Deserialize\DateTimeStrategy())->setInnerType(\DateTime::RFC3339);
|
||||
}
|
||||
|
||||
// TODO: DateTime<format> strategy and array<valueType>, array<keyType, valueType> strategies
|
||||
$arrSubType = static::getArrayInnerTypes($dataType);
|
||||
|
||||
if (!empty($arrSubType)) {
|
||||
return (new Deserialize\TypedArrayStrategy())->setInnerType($arrSubType);
|
||||
}
|
||||
|
||||
$dateTimeFormat = static::getDateTimeFormat($dataType);
|
||||
|
||||
if (!empty($dateTimeFormat)) {
|
||||
return (new Deserialize\DateTimeStrategy())->setInnerType($dateTimeFormat);
|
||||
}
|
||||
|
||||
return new Deserialize\EntityStrategy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array inner type for arrays like array<int, \DateTime<Y-m-d\TH:i:sP>>
|
||||
* For this example, "int, \DateTime<Y-m-d\TH:i:sP>" will be returned.
|
||||
*
|
||||
* Also works for arrays like int[].
|
||||
*
|
||||
* @param string $dataType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getArrayInnerTypes(string $dataType): string
|
||||
{
|
||||
$matches = [];
|
||||
|
||||
preg_match_all(static::TYPED_MATCHER, $dataType, $matches, PREG_SET_ORDER, 0);
|
||||
|
||||
if (empty($matches)) {
|
||||
if (strlen($dataType) > 2 && substr($dataType, -2) === '[]') {
|
||||
return substr($dataType, 0, -2);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($matches[0][1] === 'array') {
|
||||
return $matches[0][2];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns DateTime format. Example: \DateTime<Y-m-d\TH:i:sP>>
|
||||
*
|
||||
* @param string $dataType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getDateTimeFormat(string $dataType): string
|
||||
{
|
||||
$matches = [];
|
||||
|
||||
preg_match_all(static::TYPED_MATCHER, $dataType, $matches, PREG_SET_ORDER, 0);
|
||||
|
||||
if (empty($matches)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($matches[0][1] === 'DateTime') {
|
||||
return $matches[0][2];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if provided type is DateTime
|
||||
*
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category Integration
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy
|
||||
* @author retailCRM <integration@retailcrm.ru>
|
||||
* @license MIT
|
||||
* @link http://retailcrm.ru
|
||||
* @see http://retailcrm.ru/docs
|
||||
*/
|
||||
namespace Intaro\RetailCrm\Component\Json\Strategy;
|
||||
|
||||
/**
|
||||
* Class StrategyFactory
|
||||
*
|
||||
* @package Intaro\RetailCrm\Component\Json\Strategy
|
||||
*/
|
||||
trait TypedArrayTrait
|
||||
{
|
||||
private static $innerTypesMatcher = '/^([a-z]+)\s*\,?\s*(.+?\>)/m';
|
||||
|
||||
/**
|
||||
* Returns inner types for array with typed key (example: array<string, DateTime<Y m d H i s>>).
|
||||
*
|
||||
* @param string $innerType
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private static function getInnerTypes(string $innerType)
|
||||
{
|
||||
$matches = [];
|
||||
|
||||
preg_match_all(static::$innerTypesMatcher, $innerType, $matches, PREG_SET_ORDER, 0);
|
||||
|
||||
if (empty($matches)) {
|
||||
return ['', ''];
|
||||
}
|
||||
|
||||
$matches = $matches[0];
|
||||
|
||||
return [trim($matches[1]), trim($matches[2])];
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue