mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-08-29 11:00:40 +08:00
Add RecordList FilterMappers
- Refactor LegacyFilterMapper to allow adding mappers per type - Add date and date time mappers to convert to proper format -- Api should receive fields in internal format -- Legacy search expects user format -- Convert to user format when calling legacy search - Add multienum to correctly process criteria -- Api search criteria receive an array of values -- For other fields legacy expects just one value not an array -- For multienum legacy expects an array of values -- Add mapper to send array of values to legacy for multienums
This commit is contained in:
parent
805c751a99
commit
af186a7013
13 changed files with 345 additions and 13 deletions
|
@ -58,6 +58,8 @@ services:
|
||||||
tags: [ 'system.config.mapper' ]
|
tags: [ 'system.config.mapper' ]
|
||||||
App\Legacy\Data\PresetListDataHandlerInterface:
|
App\Legacy\Data\PresetListDataHandlerInterface:
|
||||||
tags: [ 'app.data.preset.handler' ]
|
tags: [ 'app.data.preset.handler' ]
|
||||||
|
App\Legacy\Data\FilterMapper\FilterMapperInterface:
|
||||||
|
tags: [ 'app.data.filter.mapper' ]
|
||||||
App\Service\StatisticsProviderInterface:
|
App\Service\StatisticsProviderInterface:
|
||||||
tags: [ 'app.data.statistics.handler' ]
|
tags: [ 'app.data.statistics.handler' ]
|
||||||
|
|
||||||
|
@ -149,3 +151,9 @@ services:
|
||||||
# and use the value of the 'getKey' method to index the services
|
# and use the value of the 'getKey' method to index the services
|
||||||
arguments:
|
arguments:
|
||||||
- !tagged { tag: 'app.data.statistics.handler', default_index_method: 'getKey' }
|
- !tagged { tag: 'app.data.statistics.handler', default_index_method: 'getKey' }
|
||||||
|
|
||||||
|
App\Legacy\Data\FilterMapper\FilterMappers:
|
||||||
|
# inject all services tagged with app.data.filter.mapper as first argument
|
||||||
|
# and use the value of the 'getType' method to index the services
|
||||||
|
arguments:
|
||||||
|
- !tagged { tag: 'app.data.filter.mapper', default_index_method: 'getType' }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Legacy\Data;
|
namespace App\Legacy\Data;
|
||||||
|
|
||||||
use App\Service\LegacyFilterMapper;
|
use App\Legacy\Data\FilterMapper\LegacyFilterMapper;
|
||||||
use BeanFactory;
|
use BeanFactory;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use ListViewDataPort;
|
use ListViewDataPort;
|
||||||
|
|
20
core/legacy/Data/FilterMapper/FilterMapperInterface.php
Normal file
20
core/legacy/Data/FilterMapper/FilterMapperInterface.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper;
|
||||||
|
|
||||||
|
interface FilterMapperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the field type it applies to
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getType(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map value
|
||||||
|
* @param string $mappedValue
|
||||||
|
* @param array $criteriaItem
|
||||||
|
* @return mixed|string|string[]
|
||||||
|
*/
|
||||||
|
public function mapValue(string $mappedValue, array $criteriaItem);
|
||||||
|
}
|
59
core/legacy/Data/FilterMapper/FilterMappers.php
Normal file
59
core/legacy/Data/FilterMapper/FilterMappers.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\Exception\ItemNotFoundException;
|
||||||
|
|
||||||
|
class FilterMappers
|
||||||
|
{
|
||||||
|
protected const MSG_HANDLER_NOT_FOUND = 'Filter mapper is not defined';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FilterMapperInterface[]
|
||||||
|
*/
|
||||||
|
protected $registry = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FilterMappers constructor.
|
||||||
|
* @param iterable $handlers
|
||||||
|
*/
|
||||||
|
public function __construct(iterable $handlers)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var FilterMapperInterface[]
|
||||||
|
*/
|
||||||
|
$handlers = iterator_to_array($handlers);
|
||||||
|
|
||||||
|
foreach ($handlers as $handler) {
|
||||||
|
$type = $handler->getType();
|
||||||
|
$this->registry[$type] = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mapper for field type
|
||||||
|
* @param string $type
|
||||||
|
* @return FilterMapperInterface
|
||||||
|
* @throws ItemNotFoundException
|
||||||
|
*/
|
||||||
|
public function get(string $type): FilterMapperInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
if (empty($this->registry[$type])) {
|
||||||
|
throw new ItemNotFoundException(self::MSG_HANDLER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->registry[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has mapper for the given type
|
||||||
|
* @param string $type
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasMapper(string $type): bool
|
||||||
|
{
|
||||||
|
return !(empty($this->registry[$type]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Service;
|
namespace App\Legacy\Data\FilterMapper;
|
||||||
|
|
||||||
class LegacyFilterMapper
|
class LegacyFilterMapper
|
||||||
{
|
{
|
||||||
|
@ -8,14 +8,20 @@ class LegacyFilterMapper
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $filterOperatorMap;
|
private $filterOperatorMap;
|
||||||
|
/**
|
||||||
|
* @var FilterMappers
|
||||||
|
*/
|
||||||
|
private $mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LegacyFilterMapper constructor.
|
* LegacyFilterMapper constructor.
|
||||||
* @param array $filterOperatorMap
|
* @param array $filterOperatorMap
|
||||||
|
* @param FilterMappers $mappers
|
||||||
*/
|
*/
|
||||||
public function __construct(array $filterOperatorMap)
|
public function __construct(array $filterOperatorMap, FilterMappers $mappers)
|
||||||
{
|
{
|
||||||
$this->filterOperatorMap = $filterOperatorMap;
|
$this->filterOperatorMap = $filterOperatorMap;
|
||||||
|
$this->mappers = $mappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,15 +80,16 @@ class LegacyFilterMapper
|
||||||
*/
|
*/
|
||||||
protected function mapFilterValue(string $mappedValue, array $item)
|
protected function mapFilterValue(string $mappedValue, array $item)
|
||||||
{
|
{
|
||||||
|
$fieldType = $item['fieldType'] ?? '';
|
||||||
|
|
||||||
|
|
||||||
if ($mappedValue === 'values') {
|
if ($mappedValue === 'values') {
|
||||||
|
|
||||||
if (count($item['values']) === 1) {
|
if ($this->mappers->hasMapper($fieldType)) {
|
||||||
$legacyValue = $item['values'][0];
|
return $this->mappers->get($fieldType)->mapValue($mappedValue, $item);
|
||||||
} else {
|
|
||||||
$legacyValue = $item['values'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $legacyValue;
|
return $this->mappers->get('default')->mapValue($mappedValue, $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
$operator = $item['operator'] ?? '';
|
$operator = $item['operator'] ?? '';
|
60
core/legacy/Data/FilterMapper/Mappers/DateFilterMapper.php
Normal file
60
core/legacy/Data/FilterMapper/Mappers/DateFilterMapper.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper\Mappers;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMapperInterface;
|
||||||
|
use App\Legacy\DateTimeHandler;
|
||||||
|
|
||||||
|
class DateFilterMapper implements FilterMapperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var DateTimeHandler
|
||||||
|
*/
|
||||||
|
private $dateTimeHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DateFilterMapper constructor.
|
||||||
|
* @param DateTimeHandler $dateTimeHandler
|
||||||
|
*/
|
||||||
|
public function __construct(DateTimeHandler $dateTimeHandler)
|
||||||
|
{
|
||||||
|
$this->dateTimeHandler = $dateTimeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return 'date';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function mapValue(string $mappedValue, array $criteriaItem)
|
||||||
|
{
|
||||||
|
/** @var array */
|
||||||
|
$values = $criteriaItem['values'] ?? [];
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapped = [];
|
||||||
|
|
||||||
|
foreach ($values as $value) {
|
||||||
|
if (empty($value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$mapped[] = $this->dateTimeHandler->toUserDate($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$legacyValue = $mapped;
|
||||||
|
if (count($mapped) === 1) {
|
||||||
|
$legacyValue = $mapped[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $legacyValue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper\Mappers;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMapperInterface;
|
||||||
|
use App\Legacy\DateTimeHandler;
|
||||||
|
|
||||||
|
class DateTimeFilterMapper implements FilterMapperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var DateTimeHandler
|
||||||
|
*/
|
||||||
|
private $dateTimeHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DateFilterMapper constructor.
|
||||||
|
* @param DateTimeHandler $dateTimeHandler
|
||||||
|
*/
|
||||||
|
public function __construct(DateTimeHandler $dateTimeHandler)
|
||||||
|
{
|
||||||
|
$this->dateTimeHandler = $dateTimeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return 'datetime';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function mapValue(string $mappedValue, array $criteriaItem)
|
||||||
|
{
|
||||||
|
/** @var array */
|
||||||
|
$values = $criteriaItem['values'] ?? [];
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapped = [];
|
||||||
|
|
||||||
|
foreach ($values as $value) {
|
||||||
|
if (empty($value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$mapped[] = $this->dateTimeHandler->toUserDateTime($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$legacyValue = $mapped;
|
||||||
|
if (count($mapped) === 1) {
|
||||||
|
$legacyValue = $mapped[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $legacyValue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper\Mappers;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMapperInterface;
|
||||||
|
|
||||||
|
class DefaultFilterMapper implements FilterMapperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function mapValue(string $mappedValue, array $criteriaItem)
|
||||||
|
{
|
||||||
|
/** @var array */
|
||||||
|
$values = $criteriaItem['values'] ?? [];
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$legacyValue = $values;
|
||||||
|
if (count($values) === 1) {
|
||||||
|
$legacyValue = $values[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $legacyValue;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Legacy\Data\FilterMapper\Mappers;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMapperInterface;
|
||||||
|
|
||||||
|
class MultiEnumFilterMapper implements FilterMapperInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return 'multienum';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function mapValue(string $mappedValue, array $criteriaItem)
|
||||||
|
{
|
||||||
|
/** @var array */
|
||||||
|
$values = $criteriaItem['values'] ?? [];
|
||||||
|
|
||||||
|
if (empty($values)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $criteriaItem['values'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Legacy;
|
namespace App\Legacy;
|
||||||
|
|
||||||
|
use DateFormatService;
|
||||||
|
|
||||||
class DateTimeHandler extends LegacyHandler
|
class DateTimeHandler extends LegacyHandler
|
||||||
{
|
{
|
||||||
public const HANDLER_KEY = 'date-time';
|
public const HANDLER_KEY = 'date-time';
|
||||||
|
@ -10,6 +12,10 @@ class DateTimeHandler extends LegacyHandler
|
||||||
*/
|
*/
|
||||||
private $datetimeFormatMap;
|
private $datetimeFormatMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var DateFormatService
|
||||||
|
*/
|
||||||
|
private $formatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SystemConfigHandler constructor.
|
* SystemConfigHandler constructor.
|
||||||
|
@ -49,4 +55,40 @@ class DateTimeHandler extends LegacyHandler
|
||||||
{
|
{
|
||||||
return strtr($format, $this->datetimeFormatMap);
|
return strtr($format, $this->datetimeFormatMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To user date format
|
||||||
|
* @param string $dateString
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function toUserDate(string $dateString): string
|
||||||
|
{
|
||||||
|
return $this->getFormatter()->toUserDate($dateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To user date format
|
||||||
|
* @param string $dateString
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function toUserDateTime(string $dateString): string
|
||||||
|
{
|
||||||
|
return $this->getFormatter()->toUserDateTime($dateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return DateFormatService
|
||||||
|
*/
|
||||||
|
protected function getFormatter(): DateFormatService
|
||||||
|
{
|
||||||
|
if ($this->formatter !== null) {
|
||||||
|
return $this->formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @noinspection PhpIncludeInspection */
|
||||||
|
require_once 'include/portability/Services/DateTime/DateFormatService.php';
|
||||||
|
$this->formatter = new DateFormatService();
|
||||||
|
|
||||||
|
return $this->formatter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace App\Service\BulkActions;
|
||||||
|
|
||||||
use ApiPlatform\Core\Exception\InvalidArgumentException;
|
use ApiPlatform\Core\Exception\InvalidArgumentException;
|
||||||
use App\Entity\Process;
|
use App\Entity\Process;
|
||||||
use App\Service\LegacyFilterMapper;
|
use App\Legacy\Data\FilterMapper\LegacyFilterMapper;
|
||||||
use App\Service\ModuleNameMapperInterface;
|
use App\Service\ModuleNameMapperInterface;
|
||||||
use App\Service\ProcessHandlerInterface;
|
use App\Service\ProcessHandlerInterface;
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,20 @@
|
||||||
|
|
||||||
namespace App\Tests\unit\core\legacy\Statistics;
|
namespace App\Tests\unit\core\legacy\Statistics;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMappers;
|
||||||
|
use App\Legacy\Data\FilterMapper\LegacyFilterMapper;
|
||||||
use App\Legacy\Data\RecordMapper;
|
use App\Legacy\Data\RecordMapper;
|
||||||
use App\Legacy\ModuleNameMapperHandler;
|
use App\Legacy\ModuleNameMapperHandler;
|
||||||
use App\Service\LegacyFilterMapper;
|
|
||||||
use App\Tests\_mock\Mock\core\legacy\Data\ListDataQueryHandlerMock;
|
use App\Tests\_mock\Mock\core\legacy\Data\ListDataQueryHandlerMock;
|
||||||
use App\Tests\_mock\Mock\core\legacy\Statistics\Series\LeadsByStatusCountMock;
|
use App\Tests\_mock\Mock\core\legacy\Statistics\Series\LeadsByStatusCountMock;
|
||||||
use App\Tests\UnitTester;
|
use App\Tests\UnitTester;
|
||||||
use BeanFactory;
|
use BeanFactory;
|
||||||
use Codeception\Test\Unit;
|
use Codeception\Test\Unit;
|
||||||
|
use EmptyIterator;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LeadByStatusCountTest
|
* Class LeadByStatusCountTest
|
||||||
* @package App\Tests
|
* @package App\Tests
|
||||||
|
@ -124,7 +128,9 @@ class LeadByStatusCountTest extends Unit
|
||||||
$legacyScope
|
$legacyScope
|
||||||
);
|
);
|
||||||
|
|
||||||
$legacyFilterMapper = new LegacyFilterMapper([]);
|
$filterMappers = new FilterMappers(new EmptyIterator());
|
||||||
|
|
||||||
|
$legacyFilterMapper = new LegacyFilterMapper([], $filterMappers);
|
||||||
$recordMapper = new RecordMapper($moduleNameMapper);
|
$recordMapper = new RecordMapper($moduleNameMapper);
|
||||||
|
|
||||||
$queryHandler = new ListDataQueryHandlerMock($legacyFilterMapper, $recordMapper);
|
$queryHandler = new ListDataQueryHandlerMock($legacyFilterMapper, $recordMapper);
|
||||||
|
|
|
@ -2,14 +2,16 @@
|
||||||
|
|
||||||
namespace App\Tests\unit\core\legacy\Statistics;
|
namespace App\Tests\unit\core\legacy\Statistics;
|
||||||
|
|
||||||
|
use App\Legacy\Data\FilterMapper\FilterMappers;
|
||||||
|
use App\Legacy\Data\FilterMapper\LegacyFilterMapper;
|
||||||
use App\Legacy\Data\RecordMapper;
|
use App\Legacy\Data\RecordMapper;
|
||||||
use App\Legacy\ModuleNameMapperHandler;
|
use App\Legacy\ModuleNameMapperHandler;
|
||||||
use App\Service\LegacyFilterMapper;
|
|
||||||
use App\Tests\_mock\Mock\core\legacy\Data\ListDataQueryHandlerMock;
|
use App\Tests\_mock\Mock\core\legacy\Data\ListDataQueryHandlerMock;
|
||||||
use App\Tests\_mock\Mock\core\legacy\Statistics\Series\OpportunitiesBySalesStagePipelineMock;
|
use App\Tests\_mock\Mock\core\legacy\Statistics\Series\OpportunitiesBySalesStagePipelineMock;
|
||||||
use App\Tests\UnitTester;
|
use App\Tests\UnitTester;
|
||||||
use BeanFactory;
|
use BeanFactory;
|
||||||
use Codeception\Test\Unit;
|
use Codeception\Test\Unit;
|
||||||
|
use EmptyIterator;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +50,8 @@ class OpportunitiesBySalesStagePipelineTest extends Unit
|
||||||
$legacyScope
|
$legacyScope
|
||||||
);
|
);
|
||||||
|
|
||||||
$legacyFilterMapper = new LegacyFilterMapper([]);
|
$filterMappers = new FilterMappers(new EmptyIterator());
|
||||||
|
$legacyFilterMapper = new LegacyFilterMapper([], $filterMappers);
|
||||||
$recordMapper = new RecordMapper($moduleNameMapper);
|
$recordMapper = new RecordMapper($moduleNameMapper);
|
||||||
|
|
||||||
$queryHandler = new ListDataQueryHandlerMock($legacyFilterMapper, $recordMapper);
|
$queryHandler = new ListDataQueryHandlerMock($legacyFilterMapper, $recordMapper);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue