diff --git a/CHANGELOG.md b/CHANGELOG.md index 98bd10398cc79e40bdb614125723e5ac42c4f4a3..42536fe21455a7f9bb14b725604d77fe1d7591ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Replaced the value separator in the raw field with a comma. * Added filter to search text in multiple fields. * Added filter for searching contacts with a certain tag. +* Added filter for searching contacts with a certain type. # Version 1.0.7 diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php index 1354f4479acbce469c252a53e36afa5d29d3f62c..f6e94af448911cb1ebed1ec316d422c3398d9fd6 100644 --- a/Civi/DataProcessor/Factory.php +++ b/Civi/DataProcessor/Factory.php @@ -133,6 +133,7 @@ class Factory { $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')); $this->addFilter('contact_with_tag_filter', 'Civi\DataProcessor\FilterHandler\ContactWithTagFilter', E::ts('Contact has Tag filter')); + $this->addFilter('contact_type_filter', 'Civi\DataProcessor\FilterHandler\ContactTypeFilter', E::ts('Contact Type filter')); $this->addFilter('case_role_filter', 'Civi\DataProcessor\FilterHandler\CaseRoleFilter', E::ts('Case Role filter')); $this->addFilter('in_api_filter', 'Civi\DataProcessor\FilterHandler\InApiFilter', E::ts('API filter')); $this->addjoinType('simple_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin', E::ts('Select fields to join on')); diff --git a/Civi/DataProcessor/FilterHandler/ContactTypeFilter.php b/Civi/DataProcessor/FilterHandler/ContactTypeFilter.php new file mode 100644 index 0000000000000000000000000000000000000000..af4f990619bdd93ab57b19da75f386a3e0371373 --- /dev/null +++ b/Civi/DataProcessor/FilterHandler/ContactTypeFilter.php @@ -0,0 +1,202 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +namespace Civi\DataProcessor\FilterHandler; + +use Civi\DataProcessor\DataFlow\SqlDataFlow; +use Civi\DataProcessor\Exception\InvalidConfigurationException; +use CRM_Dataprocessor_ExtensionUtil as E; + +class ContactTypeFilter extends AbstractFieldFilterHandler { + + /** + * 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['datasource']) || !isset($this->configuration['field'])) { + throw new InvalidConfigurationException(E::ts("Filter %1 requires a field to filter on. None given.", array(1=>$this->title))); + } + $this->initializeField($this->configuration['datasource'], $this->configuration['field']); + } + + /** + * @param array $filter + * The filter settings + * @return mixed + */ + public function setFilter($filter) { + $this->resetFilter(); + $dataFlow = $this->dataSource->ensureField($this->fieldSpecification->name); + $contactTypeIds = $filter['value']; + if (!is_array($contactTypeIds)) { + $contactTypeIds = explode(",", $contactTypeIds); + } + $contactTableAlias = 'civicrm_contact_'.$this->fieldSpecification->alias; + $contactTypeApiParams['id']['IN'] = $contactTypeIds; + $contactTypeApiParams['options']['limit'] = 0; + $contactTypeApi = civicrm_api3('ContactType', 'get', $contactTypeApiParams); + $contactTypeClauses = array(); + foreach($contactTypeApi['values'] as $contactTypeApiResult) { + if (empty($contactTypeApiResult['parent_id'])) { + $contactTypeClauses[] = new SqlDataFlow\SimpleWhereClause($contactTableAlias, 'contact_type', '=', $contactTypeApiResult['name']); + } else { + $contactTypeSearchName = '%'.\CRM_Core_DAO::VALUE_SEPARATOR.$contactTypeApiResult['name'].\CRM_Core_DAO::VALUE_SEPARATOR.'%'; + $contactTypeClauses[] = new SqlDataFlow\SimpleWhereClause($contactTableAlias, 'contact_sub_type', 'LIKE', $contactTypeSearchName); + } + } + if (count($contactTypeClauses)) { + $contactTypeClause = new SqlDataFlow\OrClause($contactTypeClauses); + if ($dataFlow && $dataFlow instanceof SqlDataFlow) { + $this->whereClause = new SqlDataFlow\InTableWhereClause( + 'id', + 'civicrm_contact', + $contactTableAlias, + array($contactTypeClause), + $dataFlow->getName(), + $this->fieldSpecification->name, + $filter['op'] + ); + + $dataFlow->addWhereClause($this->whereClause); + } + } + } + + /** + * 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']); + $form->add('select', 'contact_id_field', E::ts('Contact ID Field'), $fieldSelect, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge data-processor-field-for-name', + 'placeholder' => E::ts('- select -'), + )); + + if (isset($filter['configuration'])) { + $configuration = $filter['configuration']; + $defaults = array(); + if (isset($configuration['field']) && isset($configuration['datasource'])) { + $defaults['contact_id_field'] = $configuration['datasource'] . '::' . $configuration['field']; + } + $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/ContactTypeFilter.tpl"; + } + + + /** + * Process the submitted values and create a configuration array + * + * @param $submittedValues + * @return array + */ + public function processConfiguration($submittedValues) { + list($datasource, $field) = explode('::', $submittedValues['contact_id_field'], 2); + $configuration['field'] = $field; + $configuration['datasource'] = $datasource; + return $configuration; + } + + /** + * Add the elements to the filter form. + * + * @param \CRM_Core_Form $form + * @param array $defaultFilterValue + * @param string $size + * Possible values: full or compact + * @return array + * Return variables belonging to this filter. + */ + public function addToFilterForm(\CRM_Core_Form $form, $defaultFilterValue, $size='full') { + $fieldSpec = $this->getFieldSpecification(); + $alias = $fieldSpec->alias; + $operations = $this->getOperatorOptions($fieldSpec); + + $title = $fieldSpec->title; + if ($this->isRequired()) { + $title .= ' <span class="crm-marker">*</span>'; + } + + $sizeClass = 'huge'; + $minWidth = 'min-width: 250px;'; + if ($size =='compact') { + $sizeClass = 'medium'; + $minWidth = ''; + } + + $api_params['is_active'] = 1; + $form->add('select', "{$fieldSpec->alias}_op", E::ts('Operator:'), $operations, true, [ + 'style' => $minWidth, + 'class' => 'crm-select2 '.$sizeClass, + 'multiple' => FALSE, + 'placeholder' => E::ts('- select -'), + ]); + $form->addEntityRef( "{$fieldSpec->alias}_value", NULL, array( + 'placeholder' => E::ts('Select a contact type'), + 'entity' => 'ContactType', + 'api' => array('params' => $api_params), + 'create' => false, + 'multiple' => true, + 'select' => ['minimumInputLength' => 0], + )); + + if (isset($defaultFilterValue['op'])) { + $defaults[$alias . '_op'] = $defaultFilterValue['op']; + } else { + $defaults[$alias . '_op'] = key($operations); + } + if (isset($defaultFilterValue['value'])) { + $defaults[$alias.'_value'] = $defaultFilterValue['value']; + } + + if (count($defaults)) { + $form->setDefaults($defaults); + } + + $filter['type'] = $fieldSpec->type; + $filter['alias'] = $fieldSpec->alias; + $filter['title'] = $title; + $filter['size'] = $size; + + return $filter; + } + + protected function getOperatorOptions(\Civi\DataProcessor\DataSpecification\FieldSpecification $fieldSpec) { + return array( + 'IN' => E::ts('Is one of'), + 'NOT IN' => E::ts('Is not one of'), + ); + } + + +} diff --git a/templates/CRM/Dataprocessor/Form/Filter/Configuration/ContactTypeFilter.tpl b/templates/CRM/Dataprocessor/Form/Filter/Configuration/ContactTypeFilter.tpl new file mode 100644 index 0000000000000000000000000000000000000000..1b61295169d7a8a2ce842636ebe29d73cc3e7294 --- /dev/null +++ b/templates/CRM/Dataprocessor/Form/Filter/Configuration/ContactTypeFilter.tpl @@ -0,0 +1,7 @@ +{crmScope extensionKey='dataprocessor'} +<div class="crm-section"> + <div class="label">{$form.contact_id_field.label}</div> + <div class="content">{$form.contact_id_field.html}</div> + <div class="clear"></div> +</div> +{/crmScope}