mirror of
https://github.com/SuiteCRM/SuiteCRM-Core.git
synced 2025-09-04 10:14:13 +08:00
Add Csv export bulk action
- Add CsvExportBulkAction process handler to provide the download information - Extract legacy filter handling code to the LegacyFilterMapper.php service - Add ExportBulkAction angular service to download the file using the info provided
This commit is contained in:
parent
8881bc85f9
commit
2a4e209614
9 changed files with 411 additions and 95 deletions
|
@ -15,7 +15,6 @@ parameters:
|
|||
labelKey: LBL_EXPORT
|
||||
params:
|
||||
min: 1
|
||||
max: 5
|
||||
acl:
|
||||
- export
|
||||
merge:
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import {messageServiceMock} from '@services/message/message.service.spec.mock';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {ExportBulkAction} from '@services/process/processes/bulk-action/actions/export/export.bulk-action';
|
||||
import {HttpClientTestingModule} from '@angular/common/http/testing';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientTestingModule
|
||||
],
|
||||
}).compileComponents().then();
|
||||
|
||||
const http = TestBed.get(HttpClient);
|
||||
|
||||
export const exportBulkActionMock = new ExportBulkAction(messageServiceMock, http);
|
|
@ -0,0 +1,68 @@
|
|||
import {BulkActionHandler, BulkActionHandlerData} from '@services/process/processes/bulk-action/bulk-action.model';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {MessageService} from '@services/message/message.service';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ExportBulkAction extends BulkActionHandler {
|
||||
key = 'export';
|
||||
|
||||
constructor(
|
||||
protected message: MessageService,
|
||||
protected http: HttpClient
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
run(data: BulkActionHandlerData): void {
|
||||
|
||||
if (!data || !data.url || !data.formData) {
|
||||
this.message.addDangerMessageByKey('LBL_MISSING_HANDLER_DATA_ROUTE');
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
responseType: 'blob',
|
||||
observe: 'response',
|
||||
} as { [key: string]: any };
|
||||
|
||||
if (data.queryParams) {
|
||||
options.params = data.queryParams;
|
||||
}
|
||||
|
||||
this.download(data.url, data.formData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download file
|
||||
*
|
||||
* NOTE: using a hidden form instead of js for better memory management see:
|
||||
* https://github.com/eligrey/FileSaver.js/wiki/Saving-a-remote-file#using-a-form-element-other-than-get-methods
|
||||
*
|
||||
* @param {string} url for download
|
||||
* @param {object} formData to submit
|
||||
*/
|
||||
protected download(url: string, formData: { [key: string]: string }): void {
|
||||
|
||||
const form = document.createElement('form');
|
||||
form.setAttribute('id', 'export-download');
|
||||
form.setAttribute('method', 'post');
|
||||
form.setAttribute('action', url);
|
||||
form.setAttribute('target', '_self');
|
||||
form.setAttribute('style', 'display: none;');
|
||||
|
||||
|
||||
Object.keys(formData).forEach(key => {
|
||||
const hiddenField = document.createElement('input');
|
||||
hiddenField.setAttribute('name', key);
|
||||
hiddenField.setAttribute('value', formData[key]);
|
||||
form.appendChild(hiddenField);
|
||||
});
|
||||
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
document.body.removeChild(form);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import {appStateStoreMock} from '@store/app-state/app-state.store.spec.mock';
|
|||
import {BulkActionProcess} from '@services/process/processes/bulk-action/bulk-action';
|
||||
import {messageServiceMock} from '@services/message/message.service.spec.mock';
|
||||
import {redirectBulkActionMock} from '@services/process/processes/bulk-action/actions/redirect/redirect.bulk-action.spec.mock';
|
||||
import {exportBulkActionMock} from '@services/process/processes/bulk-action/actions/export/export.bulk-action.spec.mock';
|
||||
|
||||
export const bulkActionMockData = {
|
||||
'bulk-merge': {
|
||||
|
@ -52,5 +53,6 @@ export const bulkActionProcessMock = new BulkActionProcess(
|
|||
processServiceMock,
|
||||
appStateStoreMock,
|
||||
messageServiceMock,
|
||||
redirectBulkActionMock
|
||||
redirectBulkActionMock,
|
||||
exportBulkActionMock
|
||||
);
|
||||
|
|
|
@ -3,15 +3,17 @@ import {Observable} from 'rxjs';
|
|||
import {catchError, take, tap} from 'rxjs/operators';
|
||||
import {Process, ProcessService} from '@services/process/process.service';
|
||||
import {AppStateStore} from '@store/app-state/app-state.store';
|
||||
import {SearchCriteria} from '@store/list-view/list-view.store';
|
||||
import {SearchCriteria, SortingSelection} from '@store/list-view/list-view.store';
|
||||
import {MessageService} from '@services/message/message.service';
|
||||
import {BulkActionHandler} from '@services/process/processes/bulk-action/bulk-action.model';
|
||||
import {RedirectBulkAction} from '@services/process/processes/bulk-action/actions/redirect/redirect.bulk-action';
|
||||
import {ExportBulkAction} from '@services/process/processes/bulk-action/actions/export/export.bulk-action';
|
||||
|
||||
export interface BulkActionProcessInput {
|
||||
action: string;
|
||||
module: string;
|
||||
criteria?: SearchCriteria;
|
||||
sort?: SortingSelection;
|
||||
ids?: string[];
|
||||
}
|
||||
|
||||
|
@ -26,9 +28,11 @@ export class BulkActionProcess {
|
|||
private processService: ProcessService,
|
||||
private appStateStore: AppStateStore,
|
||||
protected message: MessageService,
|
||||
protected redirectActionHandler: RedirectBulkAction
|
||||
protected redirectActionHandler: RedirectBulkAction,
|
||||
protected exportBulkAction: ExportBulkAction
|
||||
) {
|
||||
this.actions[redirectActionHandler.key] = redirectActionHandler;
|
||||
this.actions[exportBulkAction.key] = exportBulkAction;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,9 +10,7 @@ import {
|
|||
SelectionDataSource,
|
||||
SelectionStatus
|
||||
} from '@components/bulk-action-menu/bulk-action-menu.component';
|
||||
import {
|
||||
ChartTypesDataSource
|
||||
} from '@components/chart/chart.component';
|
||||
import {ChartTypesDataSource} from '@components/chart/chart.component';
|
||||
import {ListGQL} from '@store/list-view/api.list.get';
|
||||
import {PageSelection, PaginationCount, PaginationDataSource} from '@components/pagination/pagination.model';
|
||||
import {SystemConfigStore} from '@store/system-config/system-config.store';
|
||||
|
@ -21,7 +19,7 @@ import {AppData, ViewStore} from '@store/view/view.store';
|
|||
import {LanguageStore} from '@store/language/language.store';
|
||||
import {NavigationStore} from '@store/navigation/navigation.store';
|
||||
import {ModuleNavigation} from '@services/navigation/module-navigation/module-navigation.service';
|
||||
import {ChartTypesMap, BulkActionsMap, Metadata, MetadataStore} from '@store/metadata/metadata.store.service';
|
||||
import {BulkActionsMap, Metadata, MetadataStore} from '@store/metadata/metadata.store.service';
|
||||
import {LocalStorageService} from '@services/local-storage/local-storage.service';
|
||||
import {SortDirection} from '@components/sort-button/sort-button.model';
|
||||
import {BulkActionProcess, BulkActionProcessInput} from '@services/process/processes/bulk-action/bulk-action';
|
||||
|
@ -466,16 +464,25 @@ export class ListViewStore extends ViewStore
|
|||
return;
|
||||
}
|
||||
|
||||
const displayedFields = [];
|
||||
|
||||
this.metadata.listView.fields.forEach(value => {
|
||||
displayedFields.push(value.fieldName);
|
||||
});
|
||||
|
||||
const data = {
|
||||
action: actionName,
|
||||
module: this.internalState.module,
|
||||
criteria: null,
|
||||
ids: null
|
||||
sort: null,
|
||||
ids: null,
|
||||
fields: displayedFields
|
||||
} as BulkActionProcessInput;
|
||||
|
||||
|
||||
if (selection.all && selection.count > this.internalState.records.length) {
|
||||
data.criteria = this.internalState.criteria;
|
||||
data.sort = this.internalState.sort;
|
||||
}
|
||||
|
||||
if (selection.all && selection.count <= this.internalState.records.length) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace SuiteCRM\Core\Legacy;
|
||||
|
||||
use App\Entity\ListView;
|
||||
use App\Service\LegacyFilterMapper;
|
||||
use App\Service\ListViewProviderInterface;
|
||||
use App\Service\ModuleNameMapperInterface;
|
||||
use BeanFactory;
|
||||
|
@ -24,10 +25,11 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
* @var ModuleNameMapperInterface
|
||||
*/
|
||||
private $moduleNameMapper;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var LegacyFilterMapper
|
||||
*/
|
||||
private $filterOperatorMap;
|
||||
private $legacyFilterMapper;
|
||||
|
||||
/**
|
||||
* SystemConfigHandler constructor.
|
||||
|
@ -37,7 +39,6 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
* @param string $defaultSessionName
|
||||
* @param LegacyScopeState $legacyScopeState
|
||||
* @param ModuleNameMapperInterface $moduleNameMapper
|
||||
* @param array $filterOperatorMap
|
||||
*/
|
||||
public function __construct(
|
||||
string $projectDir,
|
||||
|
@ -46,11 +47,11 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
string $defaultSessionName,
|
||||
LegacyScopeState $legacyScopeState,
|
||||
ModuleNameMapperInterface $moduleNameMapper,
|
||||
array $filterOperatorMap
|
||||
LegacyFilterMapper $legacyFilterMapper
|
||||
) {
|
||||
parent::__construct($projectDir, $legacyDir, $legacySessionName, $defaultSessionName, $legacyScopeState);
|
||||
$this->moduleNameMapper = $moduleNameMapper;
|
||||
$this->filterOperatorMap = $filterOperatorMap;
|
||||
$this->legacyFilterMapper = $legacyFilterMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,13 +180,13 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
): array {
|
||||
$type = $criteria['type'] ?? 'advanced';
|
||||
|
||||
$mapped = $this->mapFilters($criteria, $type);
|
||||
$mapped = $this->legacyFilterMapper->mapFilters($criteria, $type);
|
||||
|
||||
$baseCriteria = [
|
||||
'searchFormTab' => "${type}_search",
|
||||
'query' => 'true',
|
||||
'orderBy' => $sort['orderBy'] ?? 'date_entered',
|
||||
'sortOrder' => $sort['sortOrder'] ?? 'DESC'
|
||||
'orderBy' => $this->legacyFilterMapper->getOrderBy($sort),
|
||||
'sortOrder' => $this->legacyFilterMapper->getSortOrder($sort)
|
||||
];
|
||||
|
||||
$legacyCriteria = array_merge($baseCriteria, $mapped);
|
||||
|
@ -207,8 +208,7 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
int $limit,
|
||||
array $criteria = [],
|
||||
array $filterFields = []
|
||||
): array
|
||||
{
|
||||
): array {
|
||||
|
||||
$params = $this->getSortingParams($criteria);
|
||||
$legacyListView = $this->getLegacyListView($bean);
|
||||
|
@ -226,82 +226,6 @@ class ListViewHandler extends LegacyHandler implements ListViewProviderInterface
|
|||
return $listViewData->getListViewData($bean, $where, $offset, $limit, $filter_fields, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filters to legacy
|
||||
* @param array $criteria
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function mapFilters(array $criteria, string $type): array
|
||||
{
|
||||
$mapped = [];
|
||||
|
||||
if (empty($criteria['filters'])) {
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
foreach ($criteria['filters'] as $key => $item) {
|
||||
if (empty($item['operator'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($this->filterOperatorMap[$item['operator']])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mapConfig = $this->filterOperatorMap[$item['operator']];
|
||||
|
||||
foreach ($mapConfig as $mappedKey => $mappedValue) {
|
||||
$legacyKey = $this->mapFilterKey($type, $key, $mappedKey);
|
||||
$legacyValue = $this->mapFilterValue($mappedValue, $item);
|
||||
|
||||
$mapped[$legacyKey] = $legacyValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filter key to legacy
|
||||
* @param string $type
|
||||
* @param string $key
|
||||
* @param string $mappedKey
|
||||
* @return string|string[]
|
||||
*/
|
||||
protected function mapFilterKey(string $type, string $key, string $mappedKey): string
|
||||
{
|
||||
return str_replace(array('{field}', '{type}'), array($key, $type), $mappedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filter value to legacy
|
||||
* @param string $mappedValue
|
||||
* @param array $item
|
||||
* @return mixed|string|string[]
|
||||
*/
|
||||
protected function mapFilterValue(string $mappedValue, array $item)
|
||||
{
|
||||
if ($mappedValue === 'values') {
|
||||
|
||||
if (count($item['values']) === 1) {
|
||||
$legacyValue = $item['values'][0];
|
||||
} else {
|
||||
$legacyValue = $item['values'];
|
||||
}
|
||||
|
||||
return $legacyValue;
|
||||
}
|
||||
|
||||
$operator = $item['operator'] ?? '';
|
||||
$start = $item['start'] ?? '';
|
||||
$end = $item['end'] ?? '';
|
||||
|
||||
return str_replace(['{operator}', '{start}', '{end}'], [$operator, $start, $end], $mappedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list view defs
|
||||
* @param ViewList $legacyListView
|
||||
|
|
182
core/src/Service/BulkActions/CsvExportBulkAction.php
Normal file
182
core/src/Service/BulkActions/CsvExportBulkAction.php
Normal file
|
@ -0,0 +1,182 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\BulkActions;
|
||||
|
||||
use ApiPlatform\Core\Exception\InvalidArgumentException;
|
||||
use App\Entity\Process;
|
||||
use App\Service\LegacyFilterMapper;
|
||||
use App\Service\ModuleNameMapperInterface;
|
||||
use App\Service\ProcessHandlerInterface;
|
||||
|
||||
class CsvExportBulkAction implements ProcessHandlerInterface
|
||||
{
|
||||
protected const MSG_OPTIONS_NOT_FOUND = 'Process options is not defined';
|
||||
protected const PROCESS_TYPE = 'bulk-export';
|
||||
|
||||
/**
|
||||
* @var ModuleNameMapperInterface
|
||||
*/
|
||||
private $moduleNameMapper;
|
||||
|
||||
/**
|
||||
* @var LegacyFilterMapper
|
||||
*/
|
||||
private $legacyFilterMapper;
|
||||
|
||||
/**
|
||||
* CsvExportBulkAction constructor.
|
||||
* @param ModuleNameMapperInterface $moduleNameMapper
|
||||
* @param LegacyFilterMapper $legacyFilterMapper
|
||||
*/
|
||||
public function __construct(ModuleNameMapperInterface $moduleNameMapper, LegacyFilterMapper $legacyFilterMapper)
|
||||
{
|
||||
$this->moduleNameMapper = $moduleNameMapper;
|
||||
$this->legacyFilterMapper = $legacyFilterMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getProcessType(): string
|
||||
{
|
||||
return self::PROCESS_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function requiredAuthRole(): string
|
||||
{
|
||||
return 'ROLE_USER';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function configure(Process $process): void
|
||||
{
|
||||
//This process is synchronous
|
||||
//We aren't going to store a record on db
|
||||
//thus we will use process type as the id
|
||||
$process->setId(self::PROCESS_TYPE);
|
||||
$process->setAsync(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function validate(Process $process): void
|
||||
{
|
||||
if (empty($process->getOptions())) {
|
||||
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
|
||||
}
|
||||
|
||||
$options = $process->getOptions();
|
||||
|
||||
if (empty($options['module']) || empty($options['action'])) {
|
||||
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (empty($options['fields'])) {
|
||||
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (empty($options['ids']) && empty($options['criteria'])) {
|
||||
throw new InvalidArgumentException(self::MSG_OPTIONS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function run(Process $process)
|
||||
{
|
||||
$options = $process->getOptions();
|
||||
|
||||
$responseData = $this->getDownloadData($options);
|
||||
|
||||
$process->setStatus('success');
|
||||
$process->setMessages([]);
|
||||
$process->setData($responseData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|null $options
|
||||
* @return array
|
||||
*/
|
||||
protected function getDownloadData(?array $options): array
|
||||
{
|
||||
$responseData = [
|
||||
'handler' => 'export',
|
||||
'params' => [
|
||||
'url' => 'legacy/index.php?entryPoint=export',
|
||||
'formData' => []
|
||||
]
|
||||
];
|
||||
|
||||
if (!empty($options['ids'])) {
|
||||
$responseData = $this->getIdBasedRequestData($options, $responseData);
|
||||
|
||||
return $responseData;
|
||||
}
|
||||
|
||||
if (!empty($options['criteria'])) {
|
||||
$responseData = $this->getCriteriaBasedRequestData($options, $responseData);
|
||||
}
|
||||
|
||||
return $responseData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request data based on a list of ids
|
||||
* @param array|null $options
|
||||
* @param array $responseData
|
||||
* @return array
|
||||
*/
|
||||
protected function getIdBasedRequestData(?array $options, array $responseData): array
|
||||
{
|
||||
$responseData['params']['formData'] = [
|
||||
'uid' => implode(',', $options['ids']),
|
||||
'module' => $this->moduleNameMapper->toLegacy($options['module']),
|
||||
'action' => 'index'
|
||||
];
|
||||
|
||||
return $responseData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Request data based on a search criteria
|
||||
* @param array|null $options
|
||||
* @param array $responseData
|
||||
* @return array
|
||||
*/
|
||||
protected function getCriteriaBasedRequestData(?array $options, array $responseData): array
|
||||
{
|
||||
$responseData['params']['url'] .= '&module=' . $this->moduleNameMapper->toLegacy($options['module']);
|
||||
|
||||
$downloadData = [
|
||||
'module' => $this->moduleNameMapper->toLegacy($options['module']),
|
||||
'action' => 'index',
|
||||
"searchFormTab" => "advanced_search",
|
||||
"query" => "true",
|
||||
"saved_search_name" => "",
|
||||
"search_module" => "",
|
||||
"saved_search_action" => "",
|
||||
"displayColumns" => strtoupper(implode('|', $options['fields'])),
|
||||
"orderBy" => strtoupper($this->legacyFilterMapper->getOrderBy($options['sort'])),
|
||||
"sortOrder" => $this->legacyFilterMapper->getSortOrder($options['sort']),
|
||||
"button" => "Search"
|
||||
];
|
||||
|
||||
$type = $options['criteria']['type'] ?? 'advanced';
|
||||
|
||||
$mapped = $this->legacyFilterMapper->mapFilters($options['criteria'], $type);
|
||||
$downloadData = array_merge($downloadData, $mapped);
|
||||
|
||||
$responseData['params']['formData'] = [
|
||||
'current_post' => json_encode($downloadData)
|
||||
];
|
||||
|
||||
return $responseData;
|
||||
}
|
||||
}
|
114
core/src/Service/LegacyFilterMapper.php
Normal file
114
core/src/Service/LegacyFilterMapper.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
class LegacyFilterMapper
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $filterOperatorMap;
|
||||
|
||||
/**
|
||||
* LegacyFilterMapper constructor.
|
||||
* @param array $filterOperatorMap
|
||||
*/
|
||||
public function __construct(array $filterOperatorMap)
|
||||
{
|
||||
$this->filterOperatorMap = $filterOperatorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filters to legacy
|
||||
* @param array $criteria
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
public function mapFilters(array $criteria, string $type): array
|
||||
{
|
||||
$mapped = [];
|
||||
|
||||
if (empty($criteria['filters'])) {
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
foreach ($criteria['filters'] as $key => $item) {
|
||||
if (empty($item['operator'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($this->filterOperatorMap[$item['operator']])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mapConfig = $this->filterOperatorMap[$item['operator']];
|
||||
|
||||
foreach ($mapConfig as $mappedKey => $mappedValue) {
|
||||
$legacyKey = $this->mapFilterKey($type, $key, $mappedKey);
|
||||
$legacyValue = $this->mapFilterValue($mappedValue, $item);
|
||||
|
||||
$mapped[$legacyKey] = $legacyValue;
|
||||
}
|
||||
}
|
||||
|
||||
return $mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order by
|
||||
* @param array $sort
|
||||
* @return string
|
||||
*/
|
||||
public function getOrderBy(array $sort): string
|
||||
{
|
||||
return $sort['orderBy'] ?? 'date_entered';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sort order
|
||||
* @param array $sort
|
||||
* @return string
|
||||
*/
|
||||
public function getSortOrder(array $sort): string
|
||||
{
|
||||
return $sort['sortOrder'] ?? 'DESC';
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filter key to legacy
|
||||
* @param string $type
|
||||
* @param string $key
|
||||
* @param string $mappedKey
|
||||
* @return string|string[]
|
||||
*/
|
||||
protected function mapFilterKey(string $type, string $key, string $mappedKey): string
|
||||
{
|
||||
return str_replace(array('{field}', '{type}'), array($key, $type), $mappedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Filter value to legacy
|
||||
* @param string $mappedValue
|
||||
* @param array $item
|
||||
* @return mixed|string|string[]
|
||||
*/
|
||||
protected function mapFilterValue(string $mappedValue, array $item)
|
||||
{
|
||||
if ($mappedValue === 'values') {
|
||||
|
||||
if (count($item['values']) === 1) {
|
||||
$legacyValue = $item['values'][0];
|
||||
} else {
|
||||
$legacyValue = $item['values'];
|
||||
}
|
||||
|
||||
return $legacyValue;
|
||||
}
|
||||
|
||||
$operator = $item['operator'] ?? '';
|
||||
$start = $item['start'] ?? '';
|
||||
$end = $item['end'] ?? '';
|
||||
|
||||
return str_replace(['{operator}', '{start}', '{end}'], [$operator, $start, $end], $mappedValue);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue