diff --git a/Civi/DataProcessor/FieldOutputHandler/FallbackFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/FallbackFieldOutputHandler.php index 170c5fbeed3b165d2e69772b853441fb77074d2d..716a284212f7ffbad1a6b8c5ffe5901da5365206 100644 --- a/Civi/DataProcessor/FieldOutputHandler/FallbackFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/FallbackFieldOutputHandler.php @@ -19,6 +19,7 @@ namespace Civi\DataProcessor\FieldOutputHandler; use Civi\DataProcessor\DataSpecification\FieldSpecification; +use Civi\DataProcessor\Source\SourceInterface; use CRM_Dataprocessor_ExtensionUtil as E; class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { @@ -38,6 +39,31 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { */ protected $fallbackField; + /** + * @var string + */ + protected $what; + + /** + * @var SourceInterface + */ + protected $dataSource; + + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + protected $inputFieldSpec; + + /** + * @var SourceInterface + */ + protected $dataSourceFallback; + + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + protected $inputFallbackFieldSpec; + /** * Initialize the processor * @@ -48,8 +74,14 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { */ public function initialize($alias, $title, $configuration) { $this->outputFieldSpec = new FieldSpecification($alias, $this->getType(), $title); - $this->field = $configuration['field']; - $this->fallbackField = $configuration['fallback_field']; + $this->what = $configuration['what']; + if ($this->what == 'fields') { + $this->field = $configuration['field']; + $this->fallbackField = $configuration['fallback_field']; + } elseif ($this->what == 'datasource') { + [$this->dataSource, $this->inputFieldSpec] = $this->initializeField($configuration['datasource_field'], $configuration['datasource'], $alias); + [$this->dataSourceFallback, $this->inputFallbackFieldSpec] = $this->initializeField($configuration['datasource_fallback_field'], $configuration['datasource_fallback'], $alias . '_fallback'); + } } /** @@ -70,7 +102,24 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput */ public function formatField($rawRecord, $formattedRecord) { - return new FieldOutput(); + $rawValue = null; + $formattedValue = null; + if ($this->what == 'datasource') { + $rawValue = $rawRecord[$this->inputFieldSpec->alias] ?? ''; + $formattedValue = $rawRecord[$this->inputFieldSpec->alias] ?? ''; + if ($rawValue == null || $rawValue == '') { + $rawValue = $rawRecord[$this->inputFallbackFieldSpec->alias] ?? ''; + $formattedValue = $rawRecord[$this->inputFallbackFieldSpec->alias] ?? ''; + } + + if (strpos($formattedValue, \CRM_Core_DAO::VALUE_SEPARATOR) !== false) { + $formattedValue = explode(\CRM_Core_DAO::VALUE_SEPARATOR, trim($formattedValue,\CRM_Core_DAO::VALUE_SEPARATOR)); + $formattedValue = implode(",", $formattedValue); + } + } + $output = new FieldOutput($rawValue); + $output->formattedValue = $formattedValue; + return $output; } /** @@ -91,12 +140,14 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput[] */ public function postFormat(array $record): array { - $alias = $this->getOutputFieldSpecification()->alias; - $field = $record[$this->field]; - $fallback = $record[$this->fallbackField]; - $record[$alias] = clone $fallback; - if ($field && !$field->isEmpty()) { - $record[$alias] = clone $field; + if ($this->what == 'fields') { + $alias = $this->getOutputFieldSpecification()->alias; + $field = $record[$this->field]; + $fallback = $record[$this->fallbackField]; + $record[$alias] = clone $fallback; + if ($field && !$field->isEmpty()) { + $record[$alias] = clone $field; + } } return $record; } @@ -118,18 +169,42 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { * @param array $field */ public function buildConfigurationForm(\CRM_Core_Form $form, $field=array()) { + $dataSourceFields = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFieldsInDataSources($field['data_processor_id']); $fieldSelect = $this->getFieldOutputHandlers($field['data_processor_id']); - $form->add('select', 'field', E::ts('Field'), $fieldSelect, true, array( + $whatOptions = [ + 'datasource' => E::ts('Select fields from a data source'), + 'fields' => E::ts('Select fields from field output'), + ]; + + $form->add('select', 'what', E::ts('What'), $whatOptions, true, array( 'style' => 'min-width:250px', - 'class' => 'crm-select2 huge data-processor-field-for-name', + 'class' => 'crm-select2 huge', 'placeholder' => E::ts('- select -'), )); - $form->add('select', 'fallback_field', E::ts('Fallback field'), $fieldSelect, true, array( + + $form->add('select', 'field', E::ts('Field'), $fieldSelect, false, array( 'style' => 'min-width:250px', 'class' => 'crm-select2 huge', 'placeholder' => E::ts('- select -'), )); + $form->add('select', 'fallback_field', E::ts('Fallback field'), $fieldSelect, false, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + + $form->add('select', 'datasource_field', E::ts('Field'), $dataSourceFields, false, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + $form->add('select', 'datasource_fallback_field', E::ts('Fallback field'), $dataSourceFields, false, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + if (isset($field['configuration'])) { $configuration = $field['configuration']; $defaults = array(); @@ -139,8 +214,40 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { if (isset($configuration['fallback_field'])) { $defaults['fallback_field'] = $configuration['fallback_field']; } + if (isset($configuration['what'])) { + $defaults['what'] = $configuration['what']; + } else { + $defaults['what'] = 'fields'; + } + if (isset($configuration['datasource_field']) && isset($configuration['datasource'])) { + $defaults['datasource_field'] = \CRM_Dataprocessor_Utils_DataSourceFields::getSelectedFieldValue($field['data_processor_id'], $configuration['datasource'], $configuration['datasource_field']); + } + if (isset($configuration['datasource_fallback_field']) && isset($configuration['datasource_fallback'])) { + $defaults['datasource_fallback_field'] = \CRM_Dataprocessor_Utils_DataSourceFields::getSelectedFieldValue($field['data_processor_id'], $configuration['datasource_fallback'], $configuration['datasource_fallback_field']); + } $form->setDefaults($defaults); } + $form->addFormRule([FallbackFieldOutputHandler::class, 'validateConfigurationForm']); + } + + public static function validateConfigurationForm(array $values) { + $errors = []; + if ($values['what'] == 'fields') { + if (empty($values['field'])) { + $errors['field'] = E::ts('The field is required.'); + } + if (empty($values['fallback_field'])) { + $errors['fallback_field'] = E::ts('The field is required.'); + } + } elseif ($values['what'] == 'datasource') { + if (empty($values['datasource_field'])) { + $errors['datasource_field'] = E::ts('The field is required.'); + } + if (empty($values['datasource_fallback_field'])) { + $errors['datasource_fallback_field'] = E::ts('The field is required.'); + } + } + return empty($errors) ? TRUE : $errors; } /** @@ -161,8 +268,18 @@ class FallbackFieldOutputHandler extends AbstractFieldOutputHandler { * @return array */ public function processConfiguration($submittedValues) { - $configuration['field'] = $submittedValues['field']; - $configuration['fallback_field'] = $submittedValues['fallback_field']; + $configuration['what'] = $submittedValues['what']; + if ($configuration['what'] == 'fields') { + $configuration['field'] = $submittedValues['field']; + $configuration['fallback_field'] = $submittedValues['fallback_field']; + } elseif ($configuration['what'] == 'datasource') { + [$datasource, $field] = explode('::', $submittedValues['datasource_field'], 2); + $configuration['datasource_field'] = $field; + $configuration['datasource'] = $datasource; + [$datasource_fallback, $fallback_field] = explode('::', $submittedValues['datasource_fallback_field'], 2); + $configuration['datasource_fallback_field'] = $fallback_field; + $configuration['datasource_fallback'] = $datasource_fallback; + } return $configuration; } diff --git a/templates/CRM/Dataprocessor/Form/Field/Configuration/FallbackFieldOutputHandler.tpl b/templates/CRM/Dataprocessor/Form/Field/Configuration/FallbackFieldOutputHandler.tpl index e2c9132b79c4dc155b32b75738f7e9a77e0b9113..c397b68946d39b1705cb7c7dba1fc0f180c941e4 100644 --- a/templates/CRM/Dataprocessor/Form/Field/Configuration/FallbackFieldOutputHandler.tpl +++ b/templates/CRM/Dataprocessor/Form/Field/Configuration/FallbackFieldOutputHandler.tpl @@ -1,12 +1,44 @@ {crmScope extensionKey='dataprocessor'} <div class="crm-section"> - <div class="label">{$form.field.label}</div> + <div class="label">{$form.what.label}</div> + <div class="content">{$form.what.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section fields hiddenElement" > + <div class="label">{$form.field.label} <span class="crm-marker" title="{ts}This field is required{/ts}">*</span></div> <div class="content">{$form.field.html}</div> <div class="clear"></div> </div> - <div class="crm-section"> - <div class="label">{$form.fallback_field.label}</div> + <div class="crm-section fields hiddenElement"> + <div class="label">{$form.fallback_field.label} <span class="crm-marker" title="{ts}This field is required{/ts}">*</span></div> <div class="content">{$form.fallback_field.html}</div> <div class="clear"></div> </div> + <div class="crm-section datasource hiddenElement"> + <div class="label">{$form.datasource_field.label} <span class="crm-marker" title="{ts}This field is required{/ts}">*</span></div> + <div class="content">{$form.datasource_field.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section datasource hiddenElement"> + <div class="label">{$form.datasource_fallback_field.label} <span class="crm-marker" title="{ts}This field is required{/ts}">*</span></div> + <div class="content">{$form.datasource_fallback_field.html}</div> + <div class="clear"></div> + </div> +<script type="text/javascript"> + {literal} + CRM.$(function($) { + $('#what').on('change', function() { + var what = $('#what').val(); + if (what == 'fields') { + $('.crm-section.datasource').addClass('hiddenElement'); + $('.crm-section.fields').removeClass('hiddenElement'); + } else if (what == 'datasource') { + $('.crm-section.datasource').removeClass('hiddenElement'); + $('.crm-section.fields').addClass('hiddenElement'); + } + }); + $('#what').trigger('change'); + }); + {/literal} +</script> {/crmScope}