Commit 0873fff8 authored by jaapjansma's avatar jaapjansma
Browse files

Added filter for searching text in multiple fields

parent e00a06b9
......@@ -8,6 +8,7 @@
* Added field outputs for simple calculations (substract and total).
* Added escaped output to search screens.
* Replaced the value separator in the raw field with a comma.
* Added filter to search text in multiple fields.
# Version 1.0.7
......
......@@ -128,6 +128,7 @@ class Factory {
$this->addOutput('participant_search', 'CRM_DataprocessorSearch_ParticipantSearch', E::ts('Participant Search'));
$this->addOutput('export_csv', 'CRM_DataprocessorOutputExport_CSV', E::ts('CSV Export'));
$this->addFilter('simple_sql_filter', 'Civi\DataProcessor\FilterHandler\SimpleSqlFilter', E::ts('Field filter'));
$this->addFilter('multiple_field_filter', 'Civi\DataProcessor\FilterHandler\MultipleFieldFilter', E::ts('Text in multiple fields Filter'));
$this->addFilter('activity_filter', 'Civi\DataProcessor\FilterHandler\ActivityFilter', E::ts('Activity filter'));
$this->addFilter('contact_filter', 'Civi\DataProcessor\FilterHandler\ContactFilter', E::ts('Contact filter'));
$this->addFilter('contact_in_group_filter', 'Civi\DataProcessor\FilterHandler\ContactInGroupFilter', E::ts('Contact in Group filter'));
......
......@@ -528,7 +528,7 @@ abstract class AbstractFilterHandler {
if (isset($defaultFilterValue['op']) && $defaultFilterValue['op']) {
$defaults[$alias . '_op'] = $defaultFilterValue['op'];
} else {
$defaults[$alias . '_op'] = key($operations);
$defaults[$alias . '_op'] = 'has'; // Contains
}
if (isset($defaultFilterValue['value'])) {
$defaults[$alias.'_value'] = $defaultFilterValue['value'];
......
<?php
/**
* @author Jaap Jansma <jaap.jansma@civicoop.org>
* @license AGPL-3.0
*/
namespace Civi\DataProcessor\FilterHandler;
use Civi\DataProcessor\DataFlow\SqlDataFlow;
use Civi\DataProcessor\DataSpecification\CustomFieldSpecification;
use Civi\DataProcessor\DataSpecification\FieldSpecification;
use Civi\DataProcessor\Exception\DataSourceNotFoundException;
use Civi\DataProcessor\Exception\FieldNotFoundException;
use Civi\DataProcessor\Exception\InvalidConfigurationException;
use CRM_Dataprocessor_ExtensionUtil as E;
class MultipleFieldFilter extends AbstractFilterHandler {
/**
* @var \Civi\DataProcessor\DataSpecification\FieldSpecification
*/
protected $fieldSpecification;
/**
* @var \Civi\DataProcessor\DataFlow\SqlDataFlow\WhereClauseInterface
*/
protected $whereClause;
/**
* Initialize the filter
*
* @throws \Civi\DataProcessor\Exception\DataSourceNotFoundException
* @throws \Civi\DataProcessor\Exception\InvalidConfigurationException
* @throws \Civi\DataProcessor\Exception\FieldNotFoundException
*/
protected function doInitialization() {
if (!isset($this->configuration['fields']) || !is_array($this->configuration['fields']) || !count($this->configuration['fields'])) {
throw new InvalidConfigurationException(E::ts("Filter %1 requires at least one field to filter on. None given.", array(1=>$this->title)));
}
foreach($this->configuration['fields'] as $fieldAndDataSource) {
list($dataSource, $field) = explode("::", $fieldAndDataSource);
$this->initializeField($dataSource, $field);
}
$this->fieldSpecification = new FieldSpecification($this->alias, 'String', $this->title, null, $this->alias);
}
/**
* @param $datasource_name
* @param $field_name
*
* @throws \Civi\DataProcessor\Exception\DataSourceNotFoundException
* @throws \Civi\DataProcessor\Exception\FieldNotFoundException
*/
protected function initializeField($datasource_name, $field_name) {
$dataSource = $this->data_processor->getDataSourceByName($datasource_name);
if (!$dataSource) {
throw new DataSourceNotFoundException(E::ts("Filter %1 requires data source '%2' which could not be found. Did you rename or deleted the data source?", array(1=>$this->title, 2=>$datasource_name)));
}
if (!$dataSource->getAvailableFilterFields()->getFieldSpecificationByName($field_name)) {
throw new FieldNotFoundException(E::ts("Filter %1 requires a field with the name '%2' in the data source '%3'. Did you change the data source type?", array(
1 => $this->title,
2 => $field_name,
3 => $datasource_name
)));
}
$fieldSpecification = clone $dataSource->getAvailableFilterFields()->getFieldSpecificationByName($field_name);
if (!$fieldSpecification) {
throw new FieldNotFoundException(E::ts("Filter %1 requires a field with the name '%2' in the data source '%3'. Did you change the data source type?", array(
1 => $this->title,
2 => $field_name,
3 => $datasource_name
)));
}
}
/**
* Returns true when this filter has additional configuration
*
* @return bool
*/
public function hasConfiguration() {
return true;
}
/**
* When this filter type has additional configuration you can add
* the fields on the form with this function.
*
* @param \CRM_Core_Form $form
* @param array $filter
*/
public function buildConfigurationForm(\CRM_Core_Form $form, $filter=array()) {
$fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFilterFieldsInDataSources($filter['data_processor_id'], [$this, 'filterFieldsForConfiguration']);
$form->add('select', 'fields', E::ts('Fields'), $fieldSelect, true, array(
'style' => 'min-width:250px',
'class' => 'crm-select2 huge data-processor-field-for-name',
'placeholder' => E::ts('- select -'),
'multiple' => true,
));
if (isset($filter['configuration'])) {
$configuration = $filter['configuration'];
if (isset($configuration['fields'])) {
$defaults['fields'] = $configuration['fields'];
$form->setDefaults($defaults);
}
}
}
/**
* When this filter type has configuration specify the template file name
* for the configuration form.
*
* @return false|string
*/
public function getConfigurationTemplateFileName() {
return "CRM/Dataprocessor/Form/Filter/Configuration/MultipleFieldFilter.tpl";
}
/**
* Process the submitted values and create a configuration array
*
* @param $submittedValues
* @return array
*/
public function processConfiguration($submittedValues) {
$configuration['fields'] = $submittedValues['fields'];
return $configuration;
}
/**
* @param \Civi\DataProcessor\DataSpecification\FieldSpecification $field
* @return bool
*/
public function filterFieldsForConfiguration(FieldSpecification $field) {
switch ($field->type) {
case 'String':
return true;
break;
}
return false;
}
/**
* @return \Civi\DataProcessor\DataSpecification\FieldSpecification
*/
public function getFieldSpecification() {
return $this->fieldSpecification;
}
/**
* Resets the filter
*
* @return void
* @throws \Exception
*/
public function resetFilter() {
if (!$this->isInitialized()) {
return;
}
$dataFlow = $this->data_processor->getDataFlow();
if ($dataFlow && $dataFlow instanceof SqlDataFlow && $this->whereClause) {
$dataFlow->removeWhereClause($this->whereClause);
unset($this->whereClause);
}
}
/**
* @param array $filterParams
* The filter settings
*
* @return mixed
*/
public function setFilter($filterParams) {
$this->resetFilter();
$clauses = array();
foreach($this->configuration['fields'] as $fieldAndDataSource) {
list($datasource_name, $field_name) = explode("::", $fieldAndDataSource);
$dataSource = $this->data_processor->getDataSourceByName($datasource_name);
$dataFlow = $dataSource->ensureField($field_name);
if ($dataFlow && $dataFlow instanceof SqlDataFlow) {
$clauses[] = new SqlDataFlow\SimpleWhereClause($dataFlow->getName(), $field_name, $filterParams['op'], $filterParams['value'], $this->fieldSpecification->type);
}
}
if (count($clauses)) {
switch ($filterParams['op']) {
case 'IS NULL':
case 'NOT LIKE':
case '!=':
$this->whereClause = new SqlDataFlow\AndClause($clauses);
default:
$this->whereClause = new SqlDataFlow\OrClause($clauses);
break;
}
$dataFlow = $this->data_processor->getDataFlow();
if ($dataFlow && $dataFlow instanceof SqlDataFlow) {
$dataFlow->addWhereClause($this->whereClause);
}
}
}
}
{crmScope extensionKey='dataprocessor'}
<div class="crm-section">
<div class="label">{$form.fields.label}</div>
<div class="content">{$form.fields.html}</div>
<div class="clear"></div>
</div>
{/crmScope}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment