diff --git a/Civi/DataProcessor/FieldOutputHandler/Calculations/CalculationFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/Calculations/CalculationFieldOutputHandler.php index 5143f5ccfd19cd4d3b25748410ec8eaedfeac52d..d744b16f9f83ae70e09915538791e5b6b43f211c 100644 --- a/Civi/DataProcessor/FieldOutputHandler/Calculations/CalculationFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/Calculations/CalculationFieldOutputHandler.php @@ -224,13 +224,15 @@ abstract class CalculationFieldOutputHandler extends AbstractFieldOutputHandler } $value = $this->doCalculation($values); $formattedValue = $value; - if (is_numeric($this->number_of_decimals)) { + if (is_numeric($this->number_of_decimals) && $value != null) { $formattedValue = number_format($value, $this->number_of_decimals, $this->decimal_sep, $this->thousand_sep); } - $formattedValue = $this->prefix.$formattedValue.$this->suffix; + if ($formattedValue != null) { + $formattedValue = $this->prefix . $formattedValue . $this->suffix; + } $output = new FieldOutput($value); $output->formattedValue = $formattedValue; return $output; } -} \ No newline at end of file +} diff --git a/Civi/DataProcessor/FieldOutputHandler/Calculations/SubtractFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/Calculations/SubtractFieldOutputHandler.php index a7f8141021b9ffa4e469105140f0ed17543564db..aec8d61c134f470273335ca31741e223ba1dfcb8 100644 --- a/Civi/DataProcessor/FieldOutputHandler/Calculations/SubtractFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/Calculations/SubtractFieldOutputHandler.php @@ -6,10 +6,247 @@ namespace Civi\DataProcessor\FieldOutputHandler\Calculations; -use Civi\Api4\Phone; +use Civi\DataProcessor\DataSpecification\FieldSpecification; +use Civi\DataProcessor\Exception\DataSourceNotFoundException; +use Civi\DataProcessor\Exception\FieldNotFoundException; +use Civi\DataProcessor\FieldOutputHandler\AbstractFieldOutputHandler; use Civi\DataProcessor\FieldOutputHandler\FieldOutput; -class SubtractFieldOutputHandler extends CalculationFieldOutputHandler { +use CRM_Dataprocessor_ExtensionUtil as E; + +class SubtractFieldOutputHandler extends AbstractFieldOutputHandler { + + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + protected $outputFieldSpec; + + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification[] + */ + protected $inputFieldSpec1 = array(); + + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification[] + */ + protected $inputFieldSpec2 = array(); + + protected $prefix = ''; + + protected $suffix = ''; + + protected $number_of_decimals = ''; + + protected $decimal_sep = ''; + + protected $thousand_sep = ''; + + /** + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + public function getOutputFieldSpecification() { + return $this->outputFieldSpec; + } + + /** + * Returns the data type of this field + * + * @return String + */ + protected function getType() { + return 'Float'; + } + + /** + * Initialize the processor + * + * @param String $alias + * @param String $title + * @param array $configuration + * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType + */ + public function initialize($alias, $title, $configuration) { + $this->inputFieldSpec1 = $this->initializeField($configuration['field1'], $title); + $this->inputFieldSpec2 = $this->initializeField($configuration['field2'], $title); + + $this->outputFieldSpec = new FieldSpecification($alias, 'Float', $title, null, $alias); + + if (isset($configuration['number_of_decimals'])) { + $this->number_of_decimals = $configuration['number_of_decimals']; + } + if (isset($configuration['decimal_separator'])) { + $this->decimal_sep = $configuration['decimal_separator']; + } + if (isset($configuration['thousand_separator'])) { + $this->thousand_sep = $configuration['thousand_separator']; + } + if (isset($configuration['prefix'])) { + $this->prefix = $configuration['prefix']; + } + if (isset($configuration['suffix'])) { + $this->suffix = $configuration['suffix']; + } + } + + protected function initializeField($field, $title) { + list($datasourceName, $field) = explode('::', $field, 2); + $dataSource = $this->dataProcessor->getDataSourceByName($datasourceName); + if (!$dataSource) { + throw new DataSourceNotFoundException(E::ts("Field %1 requires data source '%2' which could not be found. Did you rename or deleted the data source?", array(1=>$title, 2=>$datasourceName))); + } + $inputFieldSpec = $dataSource->getAvailableFields() + ->getFieldSpecificationByName($field); + if (!$inputFieldSpec) { + throw new FieldNotFoundException(E::ts("Field %1 requires a field with the name '%2' in the data source '%3'. Did you change the data source type?", [ + 1 => $title, + 2 => $field, + 3 => $datasourceName + ])); + } + $dataSource->ensureFieldInSource($inputFieldSpec); + return $inputFieldSpec; + } + + /** + * Returns true when this handler has additional configuration. + * + * @return bool + */ + public function hasConfiguration() { + return true; + } + + /** + * When this handler has additional configuration you can add + * the fields on the form with this function. + * + * @param \CRM_Core_Form $form + * @param array $field + */ + public function buildConfigurationForm(\CRM_Core_Form $form, $field=array()) { + $fieldSelect = $this->getFieldOptions($field['data_processor_id']); + + $form->add('select', 'field1', E::ts('Field 1'), $fieldSelect, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge data-processor-field-for-name', + 'placeholder' => E::ts('- select -'), + 'multiple' => false, + )); + $form->add('select', 'field2', E::ts('Field 2'), $fieldSelect, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge data-processor-field-for-name', + 'placeholder' => E::ts('- select -'), + 'multiple' => false, + )); + $form->add('text', 'number_of_decimals', E::ts('Number of decimals'), false); + $form->add('text', 'decimal_separator', E::ts('Decimal separator'), false); + $form->add('text', 'thousand_separator', E::ts('Thousand separator'), false); + $form->add('text', 'prefix', E::ts('Prefix (e.g. €)'), false); + $form->add('text', 'suffix', E::ts('Suffix (e.g. $)'), false); + if (isset($field['configuration'])) { + $configuration = $field['configuration']; + $defaults = array(); + if (isset($configuration['field1'])) { + $defaults['field1'] = $configuration['field1']; + } + if (isset($configuration['field2'])) { + $defaults['field2'] = $configuration['field2']; + } + if (isset($configuration['number_of_decimals'])) { + $defaults['number_of_decimals'] = $configuration['number_of_decimals']; + } + if (isset($configuration['decimal_separator'])) { + $defaults['decimal_separator'] = $configuration['decimal_separator']; + } + if (isset($configuration['thousand_separator'])) { + $defaults['thousand_separator'] = $configuration['thousand_separator']; + } + if (isset($configuration['prefix'])) { + $defaults['prefix'] = $configuration['prefix']; + } + if (isset($configuration['suffix'])) { + $defaults['suffix'] = $configuration['suffix']; + } + $form->setDefaults($defaults); + } + } + + /** + * When this handler has configuration specify the template file name + * for the configuration form. + * + * @return false|string + */ + public function getConfigurationTemplateFileName() { + return "CRM/Dataprocessor/Form/Field/Configuration/CalculationSubtractFieldOutputHandler.tpl"; + } + + + /** + * Process the submitted values and create a configuration array + * + * @param $submittedValues + * @return array + */ + public function processConfiguration($submittedValues) { + $configuration['field1'] = $submittedValues['field1']; + $configuration['field2'] = $submittedValues['field2']; + $configuration['number_of_decimals'] = $submittedValues['number_of_decimals']; + $configuration['decimal_separator'] = $submittedValues['decimal_separator']; + $configuration['thousand_separator'] = $submittedValues['thousand_separator']; + $configuration['prefix'] = $submittedValues['prefix']; + $configuration['suffix'] = $submittedValues['suffix']; + return $configuration; + } + + /** + * Returns all possible fields + * + * @param $data_processor_id + * + * @return array + * @throws \Exception + */ + protected function getFieldOptions($data_processor_id) { + $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFieldsInDataSources($data_processor_id, array($this, 'isFieldValid')); + return $fieldSelect; + } + + /** + * Callback function for determining whether this field could be handled by this output handler. + * + * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $field + * @return bool + */ + public function isFieldValid(FieldSpecification $field) { + return true; + } + + /** + * Returns the formatted value + * + * @param $rawRecord + * @param $formattedRecord + * + * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput + */ + public function formatField($rawRecord, $formattedRecord) { + $values = array(); + $values[] = $rawRecord[$this->inputFieldSpec1->alias]; + $values[] = $rawRecord[$this->inputFieldSpec2->alias]; + $value = $this->doCalculation($values); + $formattedValue = $value; + if (is_numeric($this->number_of_decimals) && $value != null) { + $formattedValue = number_format($value, $this->number_of_decimals, $this->decimal_sep, $this->thousand_sep); + } + if ($formattedValue != null) { + $formattedValue = $this->prefix . $formattedValue . $this->suffix; + } + $output = new FieldOutput($value); + $output->formattedValue = $formattedValue; + return $output; + } + /** * @param array $values @@ -19,6 +256,9 @@ class SubtractFieldOutputHandler extends CalculationFieldOutputHandler { $value = 0; $i =0; foreach($values as $v) { + if ($v === null) { + return null; + } if ($i == 0) { $value = $v; } else { @@ -29,4 +269,4 @@ class SubtractFieldOutputHandler extends CalculationFieldOutputHandler { return $value; } -} \ No newline at end of file +} diff --git a/templates/CRM/Dataprocessor/Form/Field/Configuration/CalculationSubtractFieldOutputHandler.tpl b/templates/CRM/Dataprocessor/Form/Field/Configuration/CalculationSubtractFieldOutputHandler.tpl new file mode 100644 index 0000000000000000000000000000000000000000..d7e8765e86fa99cd6fa6a27b3a1465be201583e8 --- /dev/null +++ b/templates/CRM/Dataprocessor/Form/Field/Configuration/CalculationSubtractFieldOutputHandler.tpl @@ -0,0 +1,41 @@ +{crmScope extensionKey='dataprocessor'} + <div class="crm-section"> + <div class="label">{$form.field1.label}</div> + <div class="content">{$form.field1.html}</div> + <div class="clear"></div> + </div> + + <div class="crm-section"> + <div class="label">{$form.field2.label}</div> + <div class="content">{$form.field2.html}</div> + <div class="clear"></div> + </div> + + <div class="crm-section"> + <div class="label">{$form.number_of_decimals.label}</div> + <div class="content">{$form.number_of_decimals.html} + <p class="description">{ts}Leave empty for no formatting{/ts}</p> + </div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.decimal_separator.label}</div> + <div class="content">{$form.decimal_separator.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.thousand_separator.label}</div> + <div class="content">{$form.thousand_separator.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.prefix.label}</div> + <div class="content">{$form.prefix.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.suffix.label}</div> + <div class="content">{$form.suffix.html}</div> + <div class="clear"></div> + </div> +{/crmScope}