Commit 83cb8aec authored by jaapjansma's avatar jaapjansma
Browse files

Formatted Number Field Output Handler

parent e75e2778
......@@ -24,6 +24,7 @@
* Added field to display relationships.
* Added is not empty as a filter operator.
* Added hidden fields option to search outputs, dashboard output and contact summary tab output.
* Added formatted number output field handler
# Version 1.0.7
......
......@@ -142,6 +142,7 @@ class Factory {
$this->addjoinType('simple_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin', E::ts('Select fields to join on'));
$this->addjoinType('simple_non_required_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleNonRequiredJoin', E::ts('Select fields to join on (not required)'));
$this->addOutputHandler('raw', 'Civi\DataProcessor\FieldOutputHandler\RawFieldOutputHandler', E::ts('Raw field value'));
$this->addOutputHandler('number', 'Civi\DataProcessor\FieldOutputHandler\NumberFieldOutputHandler', E::ts('Formatted Number field value'));
$this->addOutputHandler('date', 'Civi\DataProcessor\FieldOutputHandler\DateFieldOutputHandler', E::ts('Date field value'));
$this->addOutputHandler('contact_link', 'Civi\DataProcessor\FieldOutputHandler\ContactLinkFieldOutputHandler', E::ts('Link to view contact'));
$this->addOutputHandler('file_field', 'Civi\DataProcessor\FieldOutputHandler\FileFieldOutputHandler', E::ts('File download link'));
......
......@@ -125,7 +125,7 @@ class AbstractSimpleFieldOutputHandler extends AbstractFieldOutputHandler implem
public function buildConfigurationForm(\CRM_Core_Form $form, $field=array()) {
$fieldSelect = $this->getFieldOptions($field['data_processor_id']);
$form->add('select', 'field', E::ts('Field'), $fieldSelect, true, array(
$form->add('select', 'field', $this->getFieldTitle(), $fieldSelect, true, array(
'style' => 'min-width:250px',
'class' => 'crm-select2 huge data-processor-field-for-name',
'placeholder' => E::ts('- select -'),
......@@ -187,5 +187,16 @@ class AbstractSimpleFieldOutputHandler extends AbstractFieldOutputHandler implem
return true;
}
/**
* Returns the label of the field for selecting a field.
*
* This could be override in a child class.
*
* @return string
*/
protected function getFieldTitle() {
return E::ts('Field');
}
}
......@@ -83,7 +83,7 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler implement
if (!$this->contactIdSource) {
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=>$configuration['datasource'])
2=>$configuration['contact_id_datasource'])
));
}
$this->contactIdField = $this->contactIdSource->getAvailableFields()->getFieldSpecificationByAlias($configuration['contact_id_field']);
......
<?php
/**
* @author Jaap Jansma <jaap.jansma@civicoop.org>
* @license AGPL-3.0
*/
namespace Civi\DataProcessor\FieldOutputHandler;
use Civi\DataProcessor\Exception\DataSourceNotFoundException;
use Civi\DataProcessor\Exception\FieldNotFoundException;
use CRM_Dataprocessor_ExtensionUtil as E;
use Civi\DataProcessor\Source\SourceInterface;
use Civi\DataProcessor\DataSpecification\FieldSpecification;
class NumberFieldOutputHandler extends AbstractSimpleFieldOutputHandler implements OutputHandlerAggregate {
/**
* @var bool
*/
protected $isAggregateField = false;
/**
* Returns the formatted value
*
* @param $rawRecord
* @param $formattedRecord
*
* @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput
*/
public function formatField($rawRecord, $formattedRecord) {
$value = $rawRecord[$this->inputFieldSpec->alias];
$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);
} elseif ($this->inputFieldSpec->type == 'Money') {
$formattedValue = \CRM_Utils_Money::format($value);
}
if ($formattedValue != null) {
$formattedValue = $this->prefix . $formattedValue . $this->suffix;
}
$output = new FieldOutput($rawRecord[$this->aggregateField->alias]);
$output->formattedValue = $formattedValue;
return $output;
}
/**
* Initialize the processor
*
* @param String $alias
* @param String $title
* @param array $configuration
* @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType
*/
public function initialize($alias, $title, $configuration) {
parent::initialize($alias, $title, $configuration);
$this->isAggregateField = isset($configuration['is_aggregate']) ? $configuration['is_aggregate'] : false;
if ($this->isAggregateField) {
$dataFlow = $this->dataSource->ensureField($this->getAggregateFieldSpec());
if ($dataFlow) {
$dataFlow->addAggregateOutputHandler($this);
}
}
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'];
}
}
/**
* 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()) {
parent::buildConfigurationForm($form, $field);
$form->add('checkbox', 'is_aggregate', E::ts('Aggregate on this field'));
$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. &euro;)'), false);
$form->add('text', 'suffix', E::ts('Suffix (e.g. $)'), false);
if (isset($field['configuration'])) {
$configuration = $field['configuration'];
$defaults = array();
if (isset($configuration['is_aggregate'])) {
$defaults['is_aggregate'] = $configuration['is_aggregate'];
}
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/NumberFieldOutputHandler.tpl";
}
/**
* Process the submitted values and create a configuration array
*
* @param $submittedValues
* @return array
*/
public function processConfiguration($submittedValues) {
$configuration = parent::processConfiguration($submittedValues);
$configuration['is_aggregate'] = isset($submittedValues['is_aggregate']) ? $submittedValues['is_aggregate'] : false;
$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;
}
/**
* @return \Civi\DataProcessor\DataSpecification\FieldSpecification
*/
public function getAggregateFieldSpec() {
return $this->inputFieldSpec;
}
/**
* @return bool
*/
public function isAggregateField() {
return $this->isAggregateField;
}
/**
* Returns the value. And if needed a formatting could be applied.
* E.g. when the value is a date field and you want to aggregate on the month
* you can then return the month here.
*
* @param $value
* @return mixed
*/
public function formatAggregationValue($value) {
return $value;
}
/**
* 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) {
switch ($field->type) {
case 'Int':
case 'Float':
case 'Money':
return true;
break;
}
return false;
}
}
......@@ -186,6 +186,10 @@ abstract class AbstractCivicrmEntitySource extends AbstractSource {
} elseif ($this->getAvailableFields()->doesFieldExist($filter_field_alias)) {
$spec = $this->getAvailableFields()->getFieldSpecificationByName($filter_field_alias);
}
if ($spec) {
if ($spec instanceof CustomFieldSpecification) {
$customGroupDataFlow = $this->ensureCustomGroup($spec->customGroupTableName, $spec->customGroupName);
......
......@@ -206,8 +206,11 @@ abstract class AbstractSource implements SourceInterface {
$fields[$alias] = $fieldSpec->title;
}
$form->addElement('select', "{$alias}_op", ts('Operator:'), [
'' => E::ts(' - Select - '),
'=' => E::ts('Is equal to'),
'!=' => E::ts('Is not equal to'),
'IS NOT NULL' => E::ts('Is not empty'),
'IS NULL' => E::ts('Is empty'),
]);
if (!empty($fieldSpec->getOptions())) {
$form->addElement('select', "{$alias}_value", $fieldSpec->title, array('' => E::ts(' - Select - ')) + $fieldSpec->getOptions());
......@@ -221,8 +224,11 @@ abstract class AbstractSource implements SourceInterface {
$fields[$alias] = $fieldSpec->title;
}
$form->addElement('select', "{$alias}_op", ts('Operator:'), [
'' => E::ts(' - Select - '),
'IN' => E::ts('Is one of'),
'NOT IN' => E::ts('Is not one of'),
'IS NOT NULL' => E::ts('Is not empty'),
'IS NULL' => E::ts('Is empty'),
]);
$form->addElement('select', "{$alias}_value", $fieldSpec->title, $fieldSpec->getOptions(), array(
'style' => 'min-width:250px',
......@@ -230,6 +236,17 @@ abstract class AbstractSource implements SourceInterface {
'multiple' => 'multiple',
'placeholder' => E::ts('- select -'),
));
} else {
if ($isRequired) {
$required_fields[$alias] = $fieldSpec->title;
} else {
$fields[$alias] = $fieldSpec->title;
}
$form->addElement('select', "{$alias}_op", ts('Operator:'), [
'' => E::ts(' - Select - '),
'IS NOT NULL' => E::ts('Is not empty'),
'IS NULL' => E::ts('Is empty'),
]);
}
}
}
......@@ -268,10 +285,10 @@ abstract class AbstractSource implements SourceInterface {
$filter_config = array();
foreach($this->getAvailableFilterFields()->getFields() as $fieldSpec) {
$alias = $fieldSpec->name;
if ($this->valueSubmittedAndNotEmpty($alias.'_value', $submittedValues)) {
if (isset($submittedValues[$alias.'_op']) && $submittedValues[$alias.'_op']) {
$filter_config[$alias] = array(
'op' => $submittedValues[$alias.'_op'],
'value' => $submittedValues[$alias.'_value']
'value' => isset($submittedValues[$alias.'_value']) ? $submittedValues[$alias.'_value'] : ''
);
}
}
......@@ -280,25 +297,4 @@ abstract class AbstractSource implements SourceInterface {
return $configuration;
}
/**
* Checks whether a value is submitted and not empty.
*
* @param $field
* @param $values
*
* @return bool
*/
protected function valueSubmittedAndNotEmpty($field, $values) {
if (!isset($values[$field])) {
return false;
}
if (is_array($values[$field]) && count($values[$field]) === 0) {
return false;
}
if (is_string($values[$field]) && strlen($values[$field]) === 0) {
return false;
}
return true;
}
}
......@@ -30,4 +30,20 @@ class MembershipSource extends AbstractCivicrmEntitySource {
return 'civicrm_membership';
}
}
\ No newline at end of file
/**
* Returns the default configuration for this data source
*
* @return array
*/
public function getDefaultConfiguration() {
return array(
'filter' => array(
'is_test' => array (
'op' => '=',
'value' => '0',
)
)
);
}
}
{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>
<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}
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