Skip to content
Snippets Groups Projects
Commit c49926ef authored by jaapjansma's avatar jaapjansma
Browse files

refactor filter

parent a72fe1ad
No related branches found
No related tags found
No related merge requests found
......@@ -115,26 +115,7 @@ abstract class CRM_Dataprocessor_Form_Output_AbstractUIOutputForm extends CRM_Co
$errors = array();
if ($this->dataProcessor->getFilterHandlers()) {
foreach ($this->dataProcessor->getFilterHandlers() as $filter) {
if ($filter->isRequired()) {
$isFilterSet = FALSE;
$filterSpec = $filter->getFieldSpecification();
$filterName = $filterSpec->alias;
if ($filterSpec->type == 'Date') {
$relative = CRM_Utils_Array::value("{$filterName}_relative", $this->_formValues);
$from = CRM_Utils_Array::value("{$filterName}_from", $this->_formValues);
$to = CRM_Utils_Array::value("{$filterName}_to", $this->_formValues);
$fromTime = CRM_Utils_Array::value("{$filterName}_from_time", $this->_formValues);
$toTime = CRM_Utils_Array::value("{$filterName}_to_time", $this->_formValues);
list($from, $to) = CRM_Utils_Date::getFromTo($relative, $from, $to, $fromTime, $toTime);
if (!$from && !$to) {
$errors[$filterName . '_relative'] = E::ts('Field %1 is required', [1 => $filterSpec->title]);
}
}
elseif (!isset($this->_formValues[$filterName . '_op']) || !(isset($this->_formValues[$filterName . '_value']) && $this->_formValues[$filterName . '_value'])) {
$errors[$filterName . '_value'] = E::ts('Field %1 is required', [1 => $filterSpec->title]);
}
}
$errors = array_merge($errors, $filter->validateSubmittedFilterParams($this->_formValues));
}
}
return $errors;
......@@ -148,244 +129,27 @@ abstract class CRM_Dataprocessor_Form_Output_AbstractUIOutputForm extends CRM_Co
public static function applyFilters(\Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessor, $submittedValues) {
if ($dataProcessor->getFilterHandlers()) {
foreach ($dataProcessor->getFilterHandlers() as $filter) {
$isFilterSet = FALSE;
$filterSpec = $filter->getFieldSpecification();
$filterName = $filterSpec->alias;
foreach($submittedValues as $k => $v) {
if (strpos($k, $filterName) === 0) {
$filterParamSet[$k] = $v;
}
}
if ($filterSpec->type == 'Date') {
$isFilterSet = self::applyDateFilter($filter, $submittedValues);
}
elseif (isset($submittedValues[$filterName . '_op'])) {
switch ($submittedValues[$filterName . '_op']) {
case 'IN':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'IN',
'value' => $submittedValues[$filterName . '_value'],
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'NOT IN':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'NOT IN',
'value' => $submittedValues[$filterName . '_value'],
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case '=':
case '!=':
case '>':
case '<':
case '>=':
case '<=':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => $submittedValues[$filterName . '_op'],
'value' => $submittedValues[$filterName . '_value'],
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'has':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'] . '%',
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'nhas':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'NOT LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'] . '%',
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'sw':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => $submittedValues[$filterName . '_value'] . '%',
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'ew':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'],
];
$filter->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
}
}
if ($filter->isRequired() && !$isFilterSet) {
throw new \Exception('Field ' . $filterSpec->title . ' is required');
}
$filter->applyFilterFromSubmittedFilterParams($submittedValues);
}
}
}
/**
* @param \Civi\DataProcessor\FilterHandler\AbstractFilterHandler $filter
* @param array $submittedValues
* @return string|null
*/
protected static function applyDateFilter(\Civi\DataProcessor\FilterHandler\AbstractFilterHandler $filter, $submittedValues) {
$filterName = $filter->getFieldSpecification()->alias;
$type = $filter->getFieldSpecification()->type;
$relative = CRM_Utils_Array::value("{$filterName}_relative", $submittedValues);
$from = CRM_Utils_Array::value("{$filterName}_from", $submittedValues);
$to = CRM_Utils_Array::value("{$filterName}_to", $submittedValues);
$fromTime = CRM_Utils_Array::value("{$filterName}_from_time", $submittedValues);
$toTime = CRM_Utils_Array::value("{$filterName}_to_time", $submittedValues);
list($from, $to) = CRM_Utils_Date::getFromTo($relative, $from, $to, $fromTime, $toTime);
if ($from && $to) {
$from = ($type == "Date") ? substr($from, 0, 8) : $from;
$to = ($type == "Date") ? substr($to, 0, 8) : $to;
$filter->setFilter(array(
'op' => 'BETWEEN',
'value' => array($from, $to),
));
return TRUE;
} elseif ($from) {
$from = ($type == "Date") ? substr($from, 0, 8) : $from;
$filter->setFilter(array(
'op' => '>=',
'value' => $from,
));
return TRUE;
} elseif ($to) {
$to = ($type == "Date") ? substr($to, 0, 8) : $to;
$filter->setFilter(array(
'op' => '<=',
'value' => $to,
));
return TRUE;
}
return FALSE;
}
/**
* Build the criteria form
*/
protected function buildCriteriaForm() {
$count = 1;
$filterElements = array();
$types = \CRM_Utils_Type::getValidTypes();
if ($this->dataProcessor->getFilterHandlers()) {
foreach ($this->dataProcessor->getFilterHandlers() as $filterHandler) {
$fieldSpec = $filterHandler->getFieldSpecification();
$type = \CRM_Utils_Type::T_STRING;
if (isset($types[$fieldSpec->type])) {
$type = $types[$fieldSpec->type];
}
if (!$fieldSpec) {
continue;
}
$filter['title'] = $fieldSpec->title;
if ($filterHandler->isRequired()) {
$filter['title'] .= ' <span class="crm-marker">*</span>';
}
$filter['type'] = $fieldSpec->type;
$operations = $this->getOperatorOptions($fieldSpec);
if ($fieldSpec->getOptions()) {
$element = $this->addElement('select', "{$fieldSpec->alias}_op", E::ts('Operator:'), $operations);
$this->addElement('select', "{$fieldSpec->alias}_value", NULL, $fieldSpec->getOptions(), [
'style' => 'min-width:250px',
'class' => 'crm-select2 huge',
'multiple' => TRUE,
'placeholder' => E::ts('- select -'),
]);
}
else {
switch ($type) {
case \CRM_Utils_Type::T_DATE:
case \CRM_Utils_Type::T_TIMESTAMP:
CRM_Core_Form_Date::buildDateRange($this, $fieldSpec->alias, $count, '_from', '_to', E::ts('From:'), $filterHandler->isRequired(), $operations);
$count++;
break;
case CRM_Report_Form::OP_INT:
case CRM_Report_Form::OP_FLOAT:
// and a min value input box
$this->add('text', "{$fieldSpec->alias}_min", E::ts('Min'));
// and a max value input box
$this->add('text', "{$fieldSpec->alias}_max", E::ts('Max'));
default:
// default type is string
$this->addElement('select', "{$fieldSpec->alias}_op", E::ts('Operator:'), $operations,
['onchange' => "return showHideMaxMinVal( '$fieldSpec->alias', this.value );"]
);
// we need text box for value input
$this->add('text', "{$fieldSpec->alias}_value", NULL, ['class' => 'huge']);
break;
}
}
$filterElements[$fieldSpec->alias] = $filter;
$filterElements[$fieldSpec->alias]['filter'] = $filterHandler->addToFilterForm($this);
$filterElements[$fieldSpec->alias]['template'] = $filterHandler->getTemplateFileName();
}
$this->assign('filters', $filterElements);
}
}
protected function getOperatorOptions(\Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpec) {
if ($fieldSpec->getOptions()) {
return array(
'IN' => E::ts('Is one of'),
'NOT IN' => E::ts('Is not one of'),
);
}
$types = \CRM_Utils_Type::getValidTypes();
$type = \CRM_Utils_Type::T_STRING;
if (isset($types[$fieldSpec->type])) {
$type = $types[$fieldSpec->type];
}
switch ($type) {
case \CRM_Utils_Type::T_DATE:
return array();
break;
case \CRM_Utils_Type::T_INT:
case \CRM_Utils_Type::T_FLOAT:
return array(
'=' => E::ts('Is equal to'),
'<=' => E::ts('Is less than or equal to'),
'>=' => E::ts('Is greater than or equal to'),
'<' => E::ts('Is less than'),
'>' => E::ts('Is greater than'),
'!=' => E::ts('Is not equal to'),
);
break;
}
return array(
'=' => E::ts('Is equal to'),
'!=' => E::ts('Is not equal to'),
'has' => E::ts('Contains'),
'sw' => E::ts('Starts with'),
'ew' => E::ts('Ends with'),
'nhas' => E::ts('Does not contain'),
);
}
}
\ No newline at end of file
......@@ -43,6 +43,38 @@ abstract class AbstractFilterHandler {
*/
abstract public function setFilter($filterParams);
/**
* File name of the template to add this filter to the criteria form.
*
* @return string
*/
abstract public function getTemplateFileName();
/**
* Validate the submitted filter parameters.
*
* @param $submittedValues
* @return array
*/
abstract public function validateSubmittedFilterParams($submittedValues);
/**
* Apply the submitted filter
*
* @param $submittedValues
* @throws \Exception
*/
abstract public function applyFilterFromSubmittedFilterParams($submittedValues);
/**
* Add the elements to the filter form.
*
* @param \CRM_Core_Form $form
* @return array
* Return variables belonging to this filter.
*/
abstract public function addToFilterForm(\CRM_Core_Form $form);
public function __construct() {
}
......
......@@ -112,7 +112,7 @@ class SimpleSqlFilter extends AbstractFilterHandler {
* @return false|string
*/
public function getConfigurationTemplateFileName() {
return "CRM/Dataprocessor/Form/Filter/SimpleSqlFilter.tpl";
return "CRM/Dataprocessor/Form/Filter/Configuration/SimpleSqlFilter.tpl";
}
......@@ -129,4 +129,280 @@ class SimpleSqlFilter extends AbstractFilterHandler {
return $configuration;
}
/**
* File name of the template to add this filter to the criteria form.
*
* @return string
*/
public function getTemplateFileName() {
return "CRM/Dataprocessor/Form/Filter/SimpleSqlFilter.tpl";
}
/**
* Validate the submitted filter parameters.
*
* @param $submittedValues
* @return array
*/
public function validateSubmittedFilterParams($submittedValues) {
$errors = array();
if ($this->isRequired()) {
$filterSpec = $this->getFieldSpecification();
$filterName = $filterSpec->alias;
if ($filterSpec->type == 'Date' || $filterSpec->type == 'Timestamp') {
$relative = \CRM_Utils_Array::value("{$filterName}_relative", $submittedValues);
$from = \CRM_Utils_Array::value("{$filterName}_from", $submittedValues);
$to = \CRM_Utils_Array::value("{$filterName}_to", $submittedValues);
$fromTime = \CRM_Utils_Array::value("{$filterName}_from_time", $submittedValues);
$toTime = \CRM_Utils_Array::value("{$filterName}_to_time", $submittedValues);
list($from, $to) = \CRM_Utils_Date::getFromTo($relative, $from, $to, $fromTime, $toTime);
if (!$from && !$to) {
$errors[$filterName . '_relative'] = E::ts('Field %1 is required', [1 => $filterSpec->title]);
}
}
elseif (!isset($submittedValues[$filterName . '_op']) || !(isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value'])) {
$errors[$filterName . '_value'] = E::ts('Field %1 is required', [1 => $filterSpec->title]);
}
}
return $errors;
}
/**
* Apply the submitted filter
*
* @param $submittedValues
* @throws \Exception
*/
public function applyFilterFromSubmittedFilterParams($submittedValues) {
$isFilterSet = FALSE;
$filterSpec = $this->getFieldSpecification();
$filterName = $filterSpec->alias;
if ($filterSpec->type == 'Date' || $filterSpec->type == 'Timestamp') {
$isFilterSet = $this->applyDateFilter($submittedValues);
}
elseif (isset($submittedValues[$filterName . '_op'])) {
switch ($submittedValues[$filterName . '_op']) {
case 'IN':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'IN',
'value' => $submittedValues[$filterName . '_value'],
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'NOT IN':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'NOT IN',
'value' => $submittedValues[$filterName . '_value'],
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case '=':
case '!=':
case '>':
case '<':
case '>=':
case '<=':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => $submittedValues[$filterName . '_op'],
'value' => $submittedValues[$filterName . '_value'],
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'has':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'] . '%',
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'nhas':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'NOT LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'] . '%',
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'sw':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => $submittedValues[$filterName . '_value'] . '%',
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
case 'ew':
if (isset($submittedValues[$filterName . '_value']) && $submittedValues[$filterName . '_value']) {
$filterParams = [
'op' => 'LIKE',
'value' => '%' . $submittedValues[$filterName . '_value'],
];
$this->setFilter($filterParams);
$isFilterSet = TRUE;
}
break;
}
}
if ($this->isRequired() && !$isFilterSet) {
throw new \Exception('Field ' . $filterSpec->title . ' is required');
}
}
/**
* Add the elements to the filter form.
*
* @param \CRM_Core_Form $form
* @return array
* Return variables belonging to this filter.
*/
public function addToFilterForm(\CRM_Core_Form $form) {
static $count = 1;
$types = \CRM_Utils_Type::getValidTypes();
$fieldSpec = $this->getFieldSpecification();
$operations = $this->getOperatorOptions($fieldSpec);
$type = \CRM_Utils_Type::T_STRING;
$title = $fieldSpec->title;
if ($this->isRequired()) {
$title .= ' <span class="crm-marker">*</span>';
}
if (isset($types[$fieldSpec->type])) {
$type = $types[$fieldSpec->type];
}
if ($fieldSpec->getOptions()) {
$form->addElement('select', "{$fieldSpec->alias}_op", E::ts('Operator:'), $operations);
$form->addElement('select', "{$fieldSpec->alias}_value", NULL, $fieldSpec->getOptions(), [
'style' => 'min-width:250px',
'class' => 'crm-select2 huge',
'multiple' => TRUE,
'placeholder' => E::ts('- select -'),
]);
}
else {
switch ($type) {
case \CRM_Utils_Type::T_DATE:
case \CRM_Utils_Type::T_TIMESTAMP:
\CRM_Core_Form_Date::buildDateRange($form, $fieldSpec->alias, $count, '_from', '_to', E::ts('From:'), $this->isRequired(), $operations);
$count ++;
break;
case \CRM_Utils_Type::T_INT:
case \CRM_Utils_Type::T_FLOAT:
// and a min value input box
$form->add('text', "{$fieldSpec->alias}_min", E::ts('Min'));
// and a max value input box
$form->add('text', "{$fieldSpec->alias}_max", E::ts('Max'));
default:
// default type is string
$form->addElement('select', "{$fieldSpec->alias}_op", E::ts('Operator:'), $operations,
['onchange' => "return showHideMaxMinVal( '$fieldSpec->alias', this.value );"]
);
// we need text box for value input
$form->add('text', "{$fieldSpec->alias}_value", NULL, ['class' => 'huge']);
break;
}
}
$filter['type'] = $fieldSpec->type;
$filter['title'] = $title;
return $filter;
}
protected function getOperatorOptions(\Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpec) {
if ($fieldSpec->getOptions()) {
return array(
'IN' => E::ts('Is one of'),
'NOT IN' => E::ts('Is not one of'),
);
}
$types = \CRM_Utils_Type::getValidTypes();
$type = \CRM_Utils_Type::T_STRING;
if (isset($types[$fieldSpec->type])) {
$type = $types[$fieldSpec->type];
}
switch ($type) {
case \CRM_Utils_Type::T_DATE:
return array();
break;
case \CRM_Utils_Type::T_INT:
case \CRM_Utils_Type::T_FLOAT:
return array(
'=' => E::ts('Is equal to'),
'<=' => E::ts('Is less than or equal to'),
'>=' => E::ts('Is greater than or equal to'),
'<' => E::ts('Is less than'),
'>' => E::ts('Is greater than'),
'!=' => E::ts('Is not equal to'),
);
break;
}
return array(
'=' => E::ts('Is equal to'),
'!=' => E::ts('Is not equal to'),
'has' => E::ts('Contains'),
'sw' => E::ts('Starts with'),
'ew' => E::ts('Ends with'),
'nhas' => E::ts('Does not contain'),
);
}
/**
* @param array $submittedValues
* @return string|null
*/
protected function applyDateFilter($submittedValues) {
$filterName = $this->getFieldSpecification()->alias;
$type = $this->getFieldSpecification()->type;
$relative = \CRM_Utils_Array::value("{$filterName}_relative", $submittedValues);
$from = \CRM_Utils_Array::value("{$filterName}_from", $submittedValues);
$to = \CRM_Utils_Array::value("{$filterName}_to", $submittedValues);
$fromTime = \CRM_Utils_Array::value("{$filterName}_from_time", $submittedValues);
$toTime = \CRM_Utils_Array::value("{$filterName}_to_time", $submittedValues);
list($from, $to) = \CRM_Utils_Date::getFromTo($relative, $from, $to, $fromTime, $toTime);
if ($from && $to) {
$from = ($type == "Date") ? substr($from, 0, 8) : $from;
$to = ($type == "Date") ? substr($to, 0, 8) : $to;
$this->setFilter(array(
'op' => 'BETWEEN',
'value' => array($from, $to),
));
return TRUE;
} elseif ($from) {
$from = ($type == "Date") ? substr($from, 0, 8) : $from;
$this->setFilter(array(
'op' => '>=',
'value' => $from,
));
return TRUE;
} elseif ($to) {
$to = ($type == "Date") ? substr($to, 0, 8) : $to;
$this->setFilter(array(
'op' => '<=',
'value' => $to,
));
return TRUE;
}
return FALSE;
}
}
\ No newline at end of file
......@@ -79,6 +79,8 @@ function civicrm_api3_data_processor_field_get($params) {
foreach($return['values'] as $id => $value) {
if (isset($value['configuration'])) {
$return['values'][$id]['configuration'] = json_decode($value['configuration'], TRUE);
} else {
$return['values'][$id]['configuration'] = array();
}
}
return $return;
......
{crmScope extensionKey='dataprocessor'}
<div class="crm-section">
<div class="label">{$form.field.label}</div>
<div class="content">{$form.field.html}</div>
<div class="clear"></div>
</div>
{/crmScope}
\ No newline at end of file
{crmScope extensionKey='dataprocessor'}
<div class="crm-section">
<div class="label">{$form.field.label}</div>
<div class="content">{$form.field.html}</div>
<div class="clear"></div>
</div>
{/crmScope}
\ No newline at end of file
{assign var=fieldOp value=$filterName|cat:"_op"}
{assign var=filterVal value=$filterName|cat:"_value"}
{assign var=filterMin value=$filterName|cat:"_min"}
{assign var=filterMax value=$filterName|cat:"_max"}
{if $filter.type == 'Date' || $filter.type == 'Timestamp'}
<tr>
<td class="label">{$filter.title}</td>
{include file="CRM/Dataprocessor/Form/Filter/DateRange.tpl" fieldName=$filterName from='_from' to='_to'}
</tr>
{elseif $form.$fieldOp.html}
<tr>
<td class="label">{$filter.title}</td>
<td>{$form.$fieldOp.html}</td>
<td>
<span id="{$filterVal}_cell">{$form.$filterVal.label}&nbsp;{$form.$filterVal.html}</span>
<span id="{$filterMin}_max_cell">{$form.$filterMin.label}&nbsp;{$form.$filterMin.html}&nbsp;&nbsp;{$form.$filterMax.label}&nbsp;{$form.$filterMax.html}</span>
</td>
</tr>
{/if}
\ No newline at end of file
......@@ -13,25 +13,7 @@
<th>{ts}Value{/ts}</th>
</tr>
{foreach from=$filters key=filterName item=filter}
{assign var=fieldOp value=$filterName|cat:"_op"}
{assign var=filterVal value=$filterName|cat:"_value"}
{assign var=filterMin value=$filterName|cat:"_min"}
{assign var=filterMax value=$filterName|cat:"_max"}
{if $filter.type == 'Date' || $filter.type == 'Timestamp'}
<tr>
<td class="label">{$filter.title}</td>
{include file="CRM/Dataprocessor/Form/Output/UIOutput/DateRange.tpl" fieldName=$filterName from='_from' to='_to'}
</tr>
{elseif $form.$fieldOp.html}
<tr>
<td class="label">{$filter.title}</td>
<td>{$form.$fieldOp.html}</td>
<td>
<span id="{$filterVal}_cell">{$form.$filterVal.label}&nbsp;{$form.$filterVal.html}</span>
<span id="{$filterMin}_max_cell">{$form.$filterMin.label}&nbsp;{$form.$filterMin.html}&nbsp;&nbsp;{$form.$filterMax.label}&nbsp;{$form.$filterMax.html}</span>
</td>
</tr>
{/if}
{include file=$filter.template filterName=$filterName filter=$filter.filter}
{/foreach}
</table>
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="botton"}</div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment