Skip to content

Commit

Permalink
GP-44069 Allow multiple values for input parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
mflandorfer committed Nov 14, 2024
1 parent a81e815 commit 038be6a
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 46 deletions.
10 changes: 8 additions & 2 deletions CRM/Sqltasks/Action.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,14 @@ protected function resolveGlobalTokens($value) {
if (empty($token_prop)) {
$ctx_val = $this->context[$token_name];
$token_value = is_array($ctx_val) ? json_encode($ctx_val) : $ctx_val;
} else {
$token_value = $this->context[$token_name][$token_prop];
break;
}

$token_value = $this->context[$token_name][$token_prop];

if (is_array($token_value)) {
Civi::log()->warning('Accessing global token property with multiple values');
$token_value = json_encode($token_value);
}

break;
Expand Down
7 changes: 4 additions & 3 deletions CRM/Sqltasks/BAO/SqlTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -794,9 +794,10 @@ private static function validateInputSpec($input_spec) {
}

$normalized = [
'default' => $param_spec['default'] ?? NULL,
'name' => $param_spec['name'],
'type' => $param_spec['type'] ?? 'String',
'default' => $param_spec['default'] ?? NULL,
'multiple' => $param_spec['multiple'] ?? FALSE,
'name' => $param_spec['name'],
'type' => $param_spec['type'] ?? 'String',
];

if (is_null($normalized['default']) || $normalized['default'] === '') {
Expand Down
54 changes: 29 additions & 25 deletions Civi/Sqltasks/Actions/RunSQLTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ public function getParameterSpecification() {
foreach ($input_spec as $input_param) {
$name = $input_param['name'];
$type = $input_param['type'];
$default = $input_param['default'] ?? NULL;
$multiple = (bool) ($input_param['multiple'] ?? FALSE);
$default = $multiple ? [] : ($input_param['default'] ?? NULL);

$specs[] = new Specification(
$name,
Expand All @@ -133,7 +134,7 @@ public function getParameterSpecification() {
$default,
NULL,
NULL,
FALSE
$multiple
);
}

Expand Down Expand Up @@ -212,38 +213,41 @@ private function getInputValues($parameters) {
if (empty($input_values)) return NULL;

return count($input_values) > 1 ? json_encode($input_values) : $input_values[0];
} else {
$exec_params = [];
}

foreach ($input_spec as $input_param) {
$name = $input_param['name'];
$type = $input_param['type'] ?? 'String';
$value = $parameters->getParameter($name);
$exec_params = [];

foreach ($input_spec as $input_param) {
$name = $input_param['name'];
$type = $input_param['type'] ?? 'String';
$value = $parameters->getParameter($name);

if (is_null($value) || $value === '') continue;
if (is_null($value) || $value === '') continue;

switch ($type) {
case 'String':
$exec_params[$name] = (string) $value;
break;
if (is_array($value)) {
$exec_params[$name] = $value;
continue;
}

case 'Float':
$exec_params[$name] = (float) $value;
break;
switch ($type) {
case 'String':
$exec_params[$name] = (string) $value;
break;

case 'Boolean':
$exec_params[$name] = (bool) $value;
break;
case 'Float':
$exec_params[$name] = (float) $value;
break;

default:
$exec_params[$name] = $value;
}
}
case 'Boolean':
$exec_params[$name] = (bool) $value;
break;

return json_encode($exec_params);
default:
$exec_params[$name] = $value;
}
}

return NULL;
return json_encode($exec_params);
}

}
1 change: 1 addition & 0 deletions ang/sqlTaskConfigurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@
$scope.taskOptions.input_spec.push({
name: "",
type: "String",
multiple: false,
value_string: "",
value_float: 0,
value_boolean: false,
Expand Down
15 changes: 14 additions & 1 deletion ang/sqlTaskConfigurator/sqlTaskConfigurator.html
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@ <h3>{{ts('Input')}}:</h3>
class="crm-form-select"
id="param-{{$index}}-type"
name="type"
ng-change="resetInputDefault($index)"
ng-model="taskOptions.input_spec[$index].type"
required
>
Expand All @@ -412,6 +411,20 @@ <h3>{{ts('Input')}}:</h3>
</td>

<td>
<label for="param-{{$index}}-multiple">{{ts('Multiple')}}</label>

<input
class="crm-form-checkbox"
id="param-{{$index}}-multiple"
name="multiple"
ng-model="taskOptions.input_spec[$index].multiple"
type="checkbox"
/>
</td>

<td ng-if="taskOptions.input_spec[$index].multiple"></td>

<td ng-if="!taskOptions.input_spec[$index].multiple">
<label for="param-{{$index}}-default">{{ts('Default')}}:</label>

<input
Expand Down
26 changes: 18 additions & 8 deletions ang/taskRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,27 @@
if ($scope.inputRequired && $scope.inputValue.length < 1 && $scope.inputParams.length < 1) {
$scope.state = "error";
$scope.errors.push(new Error("Input value is required"));
// $scope.$apply();
return;
}

$scope.inputValue = $scope.inputParams.length < 1
? $scope.inputValue
: JSON.stringify($scope.inputParams.reduce(
(result, param) =>
Object.assign(result, { [param.name]: param[`value_${param.type.toLowerCase()}`] }),
{}
));
try {
$scope.inputValue = $scope.inputParams.length < 1
? $scope.inputValue
: JSON.stringify($scope.inputParams.reduce(
(result, param) => {
if (param.multiple) {
return Object.assign(result, { [param.name]: JSON.parse(param[`value_multiple`]) });
} else {
return Object.assign(result, { [param.name]: param[`value_${param.type.toLowerCase()}`] });
}
},
{}
));
} catch (error) {
$scope.state = "error";
$scope.errors.push(new Error("Failed to parse input parameters"));
return;
}

const taskExecResult = await $scope.api3("Sqltask", "execute", {
async: $scope.backgroundQueueEnabled,
Expand Down
14 changes: 11 additions & 3 deletions ang/taskRunner/taskRunner.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,33 @@ <h1 crm-page-title>{{ts('Run SQL task:')}} {{task.name}}</h1>
class="crm-form-text"
id="param-{{param.name}}-string"
ng-model="inputParams[$index].value_string"
ng-show="param.type === 'String'"
ng-show="!param.multiple && param.type === 'String'"
type="text"
/>

<input
class="crm-form-text"
id="param-{{param.name}}-number"
ng-model="inputParams[$index].value_float"
ng-show="param.type === 'Float'"
ng-show="!param.multiple && param.type === 'Float'"
type="number"
/>

<input
class="crm-form-checkbox"
id="param-{{param.name}}-boolean"
ng-model="inputParams[$index].value_boolean"
ng-show="param.type === 'Boolean'"
ng-show="!param.multiple && param.type === 'Boolean'"
type="checkbox"
/>

<input
class="crm-form-text"
id="param-{{param.name}}-multiple"
ng-model="inputParams[$index].value_multiple"
ng-show="param.multiple"
type="text"
/>
</div>
</div>
</div>
Expand Down
10 changes: 6 additions & 4 deletions js/inputSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ function parseInputSpec (inputSpec) {
const defaultValue = param.default;
delete param.default;

param.value_string = param.type === "String" ? String(defaultValue ?? "") : "";
param.value_float = param.type === "Float" ? Number(defaultValue ?? 0) : 0;
param.value_boolean = param.type === "Boolean" ? Boolean(defaultValue) : false;
param.value_string = !param.multiple && param.type === "String" ? String(defaultValue ?? "") : "";
param.value_float = !param.multiple && param.type === "Float" ? Number(defaultValue ?? 0) : 0;
param.value_boolean = !param.multiple && param.type === "Boolean" ? Boolean(defaultValue) : false;
param.value_multiple = "[]";
}

return params;
Expand All @@ -24,10 +25,11 @@ function serializeInputSpec (inputSpec) {
const params = structuredClone(inputSpec);

for (const param of params) {
param.default = param[`value_${param.type.toLowerCase()}`];
param.default = param.multiple ? [] : param[`value_${param.type.toLowerCase()}`];
delete param.value_string;
delete param.value_float;
delete param.value_boolean;
delete param.value_multiple;
}

return JSON.stringify(params);
Expand Down

0 comments on commit 038be6a

Please sign in to comment.