From 42fc2a68965a2835a5d9112f9dbbbefe4490bb13 Mon Sep 17 00:00:00 2001 From: Simon Hermann <simon.hermann@civiservice.de> Date: Mon, 26 Jun 2023 11:24:05 +0200 Subject: [PATCH] Added a second output handler, which compares the input string with up to 5 values. If any of these values matches the input, the result is mapped to a the given replacement string. --- Civi/DataProcessor/Factory.php | 3 +- .../ConditionallyMapStrings.php | 156 ++++++++++++++++++ .../FieldOutputHandler/SanitizeString.php | 5 +- .../ConditionallyMapStringsOutputHandler.tpl | 45 +++++ 4 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 Civi/DataProcessor/FieldOutputHandler/ConditionallyMapStrings.php create mode 100644 templates/CRM/Dataprocessor/Form/Field/Configuration/ConditionallyMapStringsOutputHandler.tpl diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php index 611642d2..0a58d8c1 100644 --- a/Civi/DataProcessor/Factory.php +++ b/Civi/DataProcessor/Factory.php @@ -223,7 +223,8 @@ class Factory { $this->addOutputHandler('aggregation_function', new Definition('Civi\DataProcessor\FieldOutputHandler\AggregateFunctionFieldOutputHandler'), E::ts('Aggregation function')); $this->addOutputHandler('image', new Definition('Civi\DataProcessor\FieldOutputHandler\ImageFieldOutputHandler'), E::ts('Image')); $this->addOutputHandler('array', new Definition('Civi\DataProcessor\FieldOutputHandler\ArrayFieldOutputHandler'), E::ts('Multivalue Field as Array')); - $this->addOutputHandler('sanitize_string', new Definition('Civi\DataProcessor\FieldOutputHandler\SanitizeString'), E::ts('Escape special characters in the string and replace newlines by \\n.')); + $this->addOutputHandler('sanitize_string', new Definition('Civi\DataProcessor\FieldOutputHandler\SanitizeString'), E::ts('Replaces special characters by their HTML code and newlines by \\n.')); + $this->addOutputHandler('conditionally_map_strings', new Definition('Civi\DataProcessor\FieldOutputHandler\ConditionallyMapStrings'), E::ts('Compare the input with up to 5 strings and map the output accordingly.')); $this->addFileFormat('csv', new Definition('Civi\DataProcessor\FileFormat\CSVFileFormat'), E::ts('CSV')); } diff --git a/Civi/DataProcessor/FieldOutputHandler/ConditionallyMapStrings.php b/Civi/DataProcessor/FieldOutputHandler/ConditionallyMapStrings.php new file mode 100644 index 00000000..3831e5da --- /dev/null +++ b/Civi/DataProcessor/FieldOutputHandler/ConditionallyMapStrings.php @@ -0,0 +1,156 @@ +<?php + +namespace Civi\DataProcessor\FieldOutputHandler; + +use \Civi\DataProcessor\DataSpecification\FieldSpecification; +use \Civi\DataProcessor\FieldOutputHandler\AbstractSimpleFieldOutputHandler; +use \Civi\DataProcessor\FieldOutputHandler\FieldOutput; +use CRM_Dataprocessor_ExtensionUtil as E; + +class ConditionallyMapStrings extends AbstractSimpleFieldOutputHandler { + + private $conditions; + private $replacements; + private $default; + + private $dataFields = 6; + + /** + * 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); + for ($i = 1; $i < $this->dataFields; ++$i) { + $form->add('text', "condition_{$i}", E::ts("{$i}. input comparison"), FALSE); + $form->add('text', "replacement_{$i}", E::ts("{$i}. input replacement"), FALSE); + } + $form->add('text', "default", E::ts("Default fallback, if no condition matches."), FALSE); + + + // set the default values + if (isset($field['configuration'])) { + $configuration = $field['configuration']; + for ($i = 1; $i < $this->dataFields; ++$i) { + if (isset($configuration["condition_{$i}"])) { + $this->defaults["condition_{$i}"] = $configuration["condition_{$i}"]; + } + if (isset($configuration["replacement_{$i}"])) { + $this->defaults["replacement_{$i}"] = $configuration["replacement_{$i}"]; + } + } + if (isset($configuration['default'])) { + $this->defaults['default'] = $configuration['default']; + } + + $form->setDefaults($this->defaults); + } + } + + /** + * Process the submitted values and create a configuration array + * + * @param $submittedValues + * @return array + */ + public function processConfiguration($submittedValues) { + + $configuration = parent::processConfiguration($submittedValues); + // register the fields to the QuickForm + for ($i = 1; $i < $this->dataFields; ++$i) { + if (isset($submittedValues["condition_{$i}"])) { + $configuration["condition_{$i}"] = $submittedValues["condition_{$i}"]; + } + if (isset($submittedValues["replacement_{$i}"])) { + $configuration["replacement_{$i}"] = $submittedValues["replacement_{$i}"]; + } + } + if (isset($submittedValues['default'])) { + $configuration['default'] = $submittedValues['default']; + } + + return $configuration; + } + + /** + * @return string + */ + protected function getFieldTitle() { + return E::ts('Input field'); + } + + public function getConfigurationTemplateFileName() { + return "CRM/Dataprocessor/Form/Field/Configuration//ConditionallyMapStringsOutputHandler.tpl"; + } + + /** + * 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->outputFieldSpec = new FieldSpecification($alias, 'String', $title, null, $alias); + $this->initializeConfiguration($configuration); + } + + /** + * @param array $configuration + * + * @return void + */ + protected function initializeConfiguration($configuration) { + for ($i = 1; $i < $this->dataFields; ++$i) { + $replacement = "replacement_{$i}"; + $condition = "condition_{$i}"; + if (isset($configuration[$condition])) { + $this->conditions[$condition] = $configuration[$condition]; + } + if (isset($configuration[$replacement])) { + $this->replacements[$replacement] = $configuration[$replacement]; + } + } + if (isset($configuration['default'])) { + $this->default = $configuration['default']; + } + } + + /** + * Returns the formatted value + * + * @param $rawRecord + * @param $formattedRecord + * + * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput + */ + public function formatField($rawRecord, $formattedRecord) { + + $inputField = $rawRecord[$this->inputFieldSpec->alias]; + + // set the default value + if (!empty($this->default)) { + $result = $this->default; + } + else { + $result = $inputField; + } + + // check all conditions and replace with the replacement string, if a match is found + for ($i = 1; $i < $this->dataFields; ++$i) { + $replacement = "replacement_{$i}"; + $condition = "condition_{$i}"; + if (!empty($this->conditions[$condition]) && $this->conditions[$condition] === $inputField) { + $result = $this->replacements[$replacement]; + break 1; + } + } + + return new FieldOutput($result); + } +} \ No newline at end of file diff --git a/Civi/DataProcessor/FieldOutputHandler/SanitizeString.php b/Civi/DataProcessor/FieldOutputHandler/SanitizeString.php index 84b59d7c..48c864e1 100644 --- a/Civi/DataProcessor/FieldOutputHandler/SanitizeString.php +++ b/Civi/DataProcessor/FieldOutputHandler/SanitizeString.php @@ -6,7 +6,7 @@ use \Civi\DataProcessor\FieldOutputHandler\AbstractSimpleFieldOutputHandler; use \Civi\DataProcessor\FieldOutputHandler\FieldOutput; use CRM_Dataprocessor_ExtensionUtil as E; -class SanitizeStringDataprocessor extends AbstractSimpleFieldOutputHandler { +class SanitizeString extends AbstractSimpleFieldOutputHandler { /** * @return string @@ -29,10 +29,9 @@ class SanitizeStringDataprocessor extends AbstractSimpleFieldOutputHandler { * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput */ public function formatField($rawRecord, $formattedRecord) { - $inputField = $rawRecord[$this->inputFieldSpec->alias]; - $result = nl2br(htmlspecialchars($inputField)); + $result = htmlspecialchars(preg_replace("/\R/", '\n', $inputField)); return new FieldOutput($result); } diff --git a/templates/CRM/Dataprocessor/Form/Field/Configuration/ConditionallyMapStringsOutputHandler.tpl b/templates/CRM/Dataprocessor/Form/Field/Configuration/ConditionallyMapStringsOutputHandler.tpl new file mode 100644 index 00000000..6b178983 --- /dev/null +++ b/templates/CRM/Dataprocessor/Form/Field/Configuration/ConditionallyMapStringsOutputHandler.tpl @@ -0,0 +1,45 @@ +{crmScope extensionKey='dataprocessor'} +{include file="CRM/Dataprocessor/Form/Field/Configuration/SimpleFieldOutputHandler.tpl"} + <p class="help">{ts}Compare the input field with up to 5 values. Replace the input value with the replacement of the first value that matches.{/ts}</p> +<div class="crm-section"> + <div class="label">{$form.condition_1.label}</div> + <div class="content">{$form.condition_1.html}</div> + <div class="label">{$form.replacement_1.label}</div> + <div class="content">{$form.replacement_1.html}</div> + <div class="clear"></div> + </div> +<div class="crm-section"> + <div class="label">{$form.condition_2.label}</div> + <div class="content">{$form.condition_2.html}</div> + <div class="label">{$form.replacement_2.label}</div> + <div class="content">{$form.replacement_2.html}</div> + <div class="clear"></div> + </div> +<div class="crm-section"> + <div class="label">{$form.condition_3.label}</div> + <div class="content">{$form.condition_3.html}</div> + <div class="label">{$form.replacement_3.label}</div> + <div class="content">{$form.replacement_3.html}</div> + <div class="clear"></div> + </div> +<div class="crm-section"> + <div class="label">{$form.condition_4.label}</div> + <div class="content">{$form.condition_4.html}</div> + <div class="label">{$form.replacement_4.label}</div> + <div class="content">{$form.replacement_4.html}</div> + <div class="clear"></div> + </div> +<div class="crm-section"> + <div class="label">{$form.condition_5.label}</div> + <div class="content">{$form.condition_5.html}</div> + <div class="label">{$form.replacement_5.label}</div> + <div class="content">{$form.replacement_5.html}</div> + <div class="clear"></div> + </div> +<div class="crm-section"> + <div class="label">{$form.default.label}</div> + <div class="content">{$form.default.html}</div> + <div class="clear"></div> +</div> + <p class="help">{ts}If no default value is provided, the original input is returned, if none of the comparison values matches.{/ts}</p> +{/crmScope} \ No newline at end of file -- GitLab