Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ui/include/classes/api/services/CScript.php')
-rw-r--r--ui/include/classes/api/services/CScript.php528
1 files changed, 276 insertions, 252 deletions
diff --git a/ui/include/classes/api/services/CScript.php b/ui/include/classes/api/services/CScript.php
index 4df3da2d23b..6dc9e6621b2 100644
--- a/ui/include/classes/api/services/CScript.php
+++ b/ui/include/classes/api/services/CScript.php
@@ -114,15 +114,16 @@ class CScript extends CApiService {
'editable' => ['type' => API_BOOLEAN, 'default' => false],
'preservekeys' => ['type' => API_BOOLEAN, 'default' => false]
]];
+
if (!CApiInputValidator::validate($api_input_rules, $options, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
$sql_parts = [
- 'select' => ['scripts' => 's.scriptid'],
- 'from' => ['scripts' => 'scripts s'],
- 'where' => [],
- 'order' => []
+ 'select' => ['scripts' => 's.scriptid'],
+ 'from' => ['scripts' => 'scripts s'],
+ 'where' => [],
+ 'order' => []
];
// editable + permission check
@@ -234,27 +235,24 @@ class CScript extends CApiService {
* @return array
*/
public function create(array $scripts) {
+ if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
+ self::exception(ZBX_API_ERROR_PERMISSIONS,
+ _s('No permissions to call "%1$s.%2$s".', 'script', __FUNCTION__)
+ );
+ }
+
$this->validateCreate($scripts);
$scriptids = DB::insert('scripts', $scripts);
- $scripts_params = [];
foreach ($scripts as $index => &$script) {
$script['scriptid'] = $scriptids[$index];
-
- if ($script['type'] == ZBX_SCRIPT_TYPE_WEBHOOK && array_key_exists('parameters', $script)) {
- foreach ($script['parameters'] as $param) {
- $scripts_params[] = ['scriptid' => $script['scriptid']] + $param;
- }
- }
}
unset($script);
- if ($scripts_params) {
- DB::insertBatch('script_param', $scripts_params);
- }
+ self::updateParams($scripts, __FUNCTION__);
- $this->addAuditBulk(CAudit::ACTION_ADD, CAudit::RESOURCE_SCRIPT, $scripts);
+ self::addAuditLog(CAudit::ACTION_ADD, CAudit::RESOURCE_SCRIPT, $scripts);
return ['scriptids' => $scriptids];
}
@@ -265,13 +263,9 @@ class CScript extends CApiService {
* @throws APIException if the input is invalid
*/
protected function validateCreate(array &$scripts) {
- if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
- self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.'));
- }
-
/*
* Get general validation rules and firstly validate name uniqueness and all the possible fields, so that there
- * are no invalid fields for any of the script types. Unfortunaly there is also a drawback, since field types
+ * are no invalid fields for any of the script types. Unfortunately there is also a drawback, since field types
* validated before we know what rules belong to each script type.
*/
$api_input_rules = $this->getValidationRules('create', $common_fields);
@@ -284,18 +278,13 @@ class CScript extends CApiService {
* Then validate each script separately. Depending on script type, each script may have different set of allowed
* fields. Then in case the type is SSH and authtype is set, validate parameters again.
*/
- $i = 0;
- $check_names = [];
-
- foreach ($scripts as $script) {
- $path = '/'.++$i;
-
+ foreach ($scripts as $index => $script) {
$type_rules = $this->getTypeValidationRules($script['type'], 'create', $type_fields);
$this->getScopeValidationRules($script['scope'], $scope_fields);
$type_rules['fields'] += $common_fields + $scope_fields;
- if (!CApiInputValidator::validate($type_rules, $script, $path, $error)) {
+ if (!CApiInputValidator::validate($type_rules, $script, '/'.($index + 1), $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
@@ -303,22 +292,13 @@ class CScript extends CApiService {
$ssh_rules = $this->getAuthTypeValidationRules($script['authtype'], 'create');
$ssh_rules['fields'] += $common_fields + $type_fields + $scope_fields;
- if (!CApiInputValidator::validate($ssh_rules, $script, $path, $error)) {
+ if (!CApiInputValidator::validate($ssh_rules, $script, '/'.($index + 1), $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
}
-
- $check_names[$script['name']] = true;
}
- $db_script_names = API::getApiService()->select('scripts', [
- 'output' => ['scriptid'],
- 'filter' => ['name' => array_keys($check_names)]
- ]);
-
- if ($db_script_names) {
- self::exception(ZBX_API_ERROR_PARAMETERS, _s('Script "%1$s" already exists.', $script['name']));
- }
+ self::checkDuplicates($scripts);
// Finally check User and Host IDs.
$this->checkUserGroups($scripts);
@@ -331,115 +311,23 @@ class CScript extends CApiService {
* @return array
*/
public function update(array $scripts) {
+ if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
+ self::exception(ZBX_API_ERROR_PERMISSIONS,
+ _s('No permissions to call "%1$s.%2$s".', 'script', __FUNCTION__)
+ );
+ }
+
$this->validateUpdate($scripts, $db_scripts);
$upd_scripts = [];
- $scripts_params = [];
foreach ($scripts as $script) {
- $scriptid = $script['scriptid'];
- $db_script = $db_scripts[$scriptid];
- $db_type = $db_script['type'];
- $db_authtype = $db_script['authtype'];
- $db_scope = $db_script['scope'];
- $type = array_key_exists('type', $script) ? $script['type'] : $db_type;
- $authtype = array_key_exists('authtype', $script) ? $script['authtype'] : $db_authtype;
- $scope = array_key_exists('scope', $script) ? $script['scope'] : $db_scope;
-
- $upd_script = [];
-
- // strings
- foreach (['name', 'command', 'description', 'confirmation', 'timeout', 'menu_path', 'username', 'publickey',
- 'privatekey', 'password'] as $field_name) {
- if (array_key_exists($field_name, $script) && $script[$field_name] !== $db_script[$field_name]) {
- $upd_script[$field_name] = $script[$field_name];
- }
- }
-
- // integers
- foreach (['type', 'execute_on', 'usrgrpid', 'groupid', 'host_access', 'scope', 'port', 'authtype']
- as $field_name) {
- if (array_key_exists($field_name, $script) && $script[$field_name] != $db_script[$field_name]) {
- $upd_script[$field_name] = $script[$field_name];
- }
- }
-
- // No mattter what the old type was, clear and reset all unnecessary fields from any other types.
- if ($type != $db_type) {
- switch ($type) {
- case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT:
- $upd_script['port'] = '';
- $upd_script['authtype'] = DB::getDefault('scripts', 'authtype');
- $upd_script['username'] = '';
- $upd_script['password'] = '';
- $upd_script['publickey'] = '';
- $upd_script['privatekey'] = '';
- break;
-
- case ZBX_SCRIPT_TYPE_IPMI:
- $upd_script['port'] = '';
- $upd_script['authtype'] = DB::getDefault('scripts', 'authtype');
- $upd_script['username'] = '';
- $upd_script['password'] = '';
- $upd_script['publickey'] = '';
- $upd_script['privatekey'] = '';
- $upd_script['execute_on'] = DB::getDefault('scripts', 'execute_on');
- break;
-
- case ZBX_SCRIPT_TYPE_SSH:
- $upd_script['execute_on'] = DB::getDefault('scripts', 'execute_on');
- break;
-
- case ZBX_SCRIPT_TYPE_TELNET:
- $upd_script['authtype'] = DB::getDefault('scripts', 'authtype');
- $upd_script['publickey'] = '';
- $upd_script['privatekey'] = '';
- $upd_script['execute_on'] = DB::getDefault('scripts', 'execute_on');
- break;
-
- case ZBX_SCRIPT_TYPE_WEBHOOK:
- $upd_script['port'] = '';
- $upd_script['authtype'] = DB::getDefault('scripts', 'authtype');
- $upd_script['username'] = '';
- $upd_script['password'] = '';
- $upd_script['publickey'] = '';
- $upd_script['privatekey'] = '';
- $upd_script['execute_on'] = DB::getDefault('scripts', 'execute_on');
- break;
- }
- }
- elseif ($type == ZBX_SCRIPT_TYPE_SSH && $authtype != $db_authtype && $authtype == ITEM_AUTHTYPE_PASSWORD) {
- $upd_script['publickey'] = '';
- $upd_script['privatekey'] = '';
- }
-
- if ($scope != $db_scope && $scope == ZBX_SCRIPT_SCOPE_ACTION) {
- $upd_script['menu_path'] = '';
- $upd_script['usrgrpid'] = 0;
- $upd_script['host_access'] = DB::getDefault('scripts', 'host_access');;
- $upd_script['confirmation'] = '';
- }
-
- if ($type == ZBX_SCRIPT_TYPE_WEBHOOK && array_key_exists('parameters', $script)) {
- $params = [];
-
- foreach ($script['parameters'] as $param) {
- $params[$param['name']] = $param['value'];
- }
-
- $scripts_params[$scriptid] = $params;
- unset($script['parameters']);
- }
-
- if ($type != $db_type && $db_type == ZBX_SCRIPT_TYPE_WEBHOOK) {
- $upd_script['timeout'] = DB::getDefault('scripts', 'timeout');
- $scripts_params[$scriptid] = [];
- }
+ $upd_script = DB::getUpdatedValues('scripts', $script, $db_scripts[$script['scriptid']]);
if ($upd_script) {
$upd_scripts[] = [
'values' => $upd_script,
- 'where' => ['scriptid' => $scriptid]
+ 'where' => ['scriptid' => $script['scriptid']]
];
}
}
@@ -448,57 +336,11 @@ class CScript extends CApiService {
DB::update('scripts', $upd_scripts);
}
- if ($scripts_params) {
- $insert_script_param = [];
- $delete_script_param = [];
- $update_script_param = [];
- $db_scripts_params = DB::select('script_param', [
- 'output' => ['script_paramid', 'scriptid', 'name', 'value'],
- 'filter' => ['scriptid' => array_keys($scripts_params)]
- ]);
-
- foreach ($db_scripts_params as $param) {
- $scriptid = $param['scriptid'];
-
- if (!array_key_exists($param['name'], $scripts_params[$scriptid])) {
- $delete_script_param[] = $param['script_paramid'];
- }
- elseif ($scripts_params[$scriptid][$param['name']] !== $param['value']) {
- $update_script_param[] = [
- 'values' => ['value' => $scripts_params[$scriptid][$param['name']]],
- 'where' => ['script_paramid' => $param['script_paramid']]
- ];
- unset($scripts_params[$scriptid][$param['name']]);
- }
- else {
- unset($scripts_params[$scriptid][$param['name']]);
- }
- }
-
- $scripts_params = array_filter($scripts_params);
+ self::updateParams($scripts, __FUNCTION__, $db_scripts);
- foreach ($scripts_params as $scriptid => $params) {
- foreach ($params as $name => $value) {
- $insert_script_param[] = compact('scriptid', 'name', 'value');
- }
- }
+ self::addAuditLog(CAudit::ACTION_UPDATE, CAudit::RESOURCE_SCRIPT, $scripts, $db_scripts);
- if ($delete_script_param) {
- DB::delete('script_param', ['script_paramid' => array_keys(array_flip($delete_script_param))]);
- }
-
- if ($update_script_param) {
- DB::update('script_param', $update_script_param);
- }
-
- if ($insert_script_param) {
- DB::insert('script_param', $insert_script_param);
- }
- }
-
- $this->addAuditBulk(CAudit::ACTION_UPDATE, CAudit::RESOURCE_SCRIPT, $scripts, $db_scripts);
-
- return ['scriptids' => zbx_objectValues($scripts, 'scriptid')];
+ return ['scriptids' => array_column($scripts, 'scriptid')];
}
/**
@@ -508,13 +350,9 @@ class CScript extends CApiService {
* @throws APIException if the input is invalid
*/
protected function validateUpdate(array &$scripts, array &$db_scripts = null) {
- if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
- self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.'));
- }
-
/*
* Get general validation rules and firstly validate name uniqueness and all the possible fields, so that there
- * are no invalid fields for any of the script types. Unfortunaly there is also a drawback, since field types
+ * are no invalid fields for any of the script types. Unfortunately there is also a drawback, since field types
* validated before we know what rules belong to each script type.
*/
$api_input_rules = $this->getValidationRules('update', $common_fields);
@@ -529,40 +367,17 @@ class CScript extends CApiService {
'confirmation', 'type', 'execute_on', 'timeout', 'scope', 'port', 'authtype', 'username', 'password',
'publickey', 'privatekey', 'menu_path'
],
- 'scriptids' => zbx_objectValues($scripts, 'scriptid'),
+ 'scriptids' => array_column($scripts, 'scriptid'),
'preservekeys' => true
]);
- $check_names = [];
- foreach ($scripts as $script) {
- if (!array_key_exists($script['scriptid'], $db_scripts)) {
- self::exception(ZBX_API_ERROR_PERMISSIONS,
- _('No permissions to referred object or it does not exist!')
- );
- }
-
- if (array_key_exists('name', $script)) {
- $check_names[$script['name']] = true;
- }
+ if (count($db_scripts) != count($scripts)) {
+ self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
}
- if ($check_names) {
- $db_script_names = API::getApiService()->select('scripts', [
- 'output' => ['scriptid', 'name'],
- 'filter' => ['name' => array_keys($check_names)]
- ]);
- $db_script_names = zbx_toHash($db_script_names, 'name');
-
- foreach ($scripts as $script) {
- if (array_key_exists('name', $script)
- && array_key_exists($script['name'], $db_script_names)
- && !idcmp($db_script_names[$script['name']]['scriptid'], $script['scriptid'])) {
- self::exception(ZBX_API_ERROR_PARAMETERS,
- _s('Script "%1$s" already exists.', $script['name'])
- );
- }
- }
- }
+ self::checkDuplicates($scripts, $db_scripts);
+
+ self::addAffectedObjects($scripts, $db_scripts);
// Validate if scripts belong to actions and scope can be changed.
$action_scriptids = [];
@@ -639,12 +454,9 @@ class CScript extends CApiService {
}
// Populate common and mandatory fields.
- $scripts = zbx_toHash($scripts, 'scriptid');
- $scripts = $this->extendFromObjects($scripts, $db_scripts, ['name', 'type', 'command', 'scope']);
+ $scripts = $this->extendObjectsByKey($scripts, $db_scripts, 'scriptid', ['name', 'type', 'command', 'scope']);
- $i = 0;
- foreach ($scripts as &$script) {
- $path = '/'.++$i;
+ foreach ($scripts as $index => &$script) {
$db_script = $db_scripts[$script['scriptid']];
$method = 'update';
@@ -666,7 +478,7 @@ class CScript extends CApiService {
$type_rules['fields'] += $common_fields + $scope_fields;
- if (!CApiInputValidator::validate($type_rules, $script, $path, $error)) {
+ if (!CApiInputValidator::validate($type_rules, $script, '/'.($index + 1), $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
@@ -677,18 +489,81 @@ class CScript extends CApiService {
$method = 'create';
}
- $script = $this->extendFromObjects([$script], [$db_script], ['authtype'])[0];
+ $script += ['authtype' => $db_script['authtype']];
$ssh_rules = $this->getAuthTypeValidationRules($script['authtype'], $method);
$ssh_rules['fields'] += $common_fields + $type_fields + $scope_fields;
- if (!CApiInputValidator::validate($ssh_rules, $script, $path, $error)) {
+ if (!CApiInputValidator::validate($ssh_rules, $script, '/'.($index + 1), $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
}
}
unset($script);
+ // Clear and reset all unnecessary fields.
+ foreach ($scripts as &$script) {
+ $db_script = $db_scripts[$script['scriptid']];
+
+ if ($script['type'] != $db_script['type']) {
+ switch ($script['type']) {
+ case ZBX_SCRIPT_TYPE_IPMI:
+ $script['execute_on'] = DB::getDefault('scripts', 'execute_on');
+ // break; is not missing here
+
+ case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT:
+ $script['port'] = '';
+ $script['authtype'] = DB::getDefault('scripts', 'authtype');
+ $script['username'] = '';
+ $script['password'] = '';
+ $script['publickey'] = '';
+ $script['privatekey'] = '';
+ $script['parameters'] = [];
+ $script['timeout'] = DB::getDefault('scripts', 'timeout');
+ break;
+
+ case ZBX_SCRIPT_TYPE_SSH:
+ $script['execute_on'] = DB::getDefault('scripts', 'execute_on');
+ $script['parameters'] = [];
+ $script['timeout'] = DB::getDefault('scripts', 'timeout');
+ break;
+
+ case ZBX_SCRIPT_TYPE_TELNET:
+ $script['authtype'] = DB::getDefault('scripts', 'authtype');
+ $script['publickey'] = '';
+ $script['privatekey'] = '';
+ $script['execute_on'] = DB::getDefault('scripts', 'execute_on');
+ $script['parameters'] = [];
+ $script['timeout'] = DB::getDefault('scripts', 'timeout');
+ break;
+
+ case ZBX_SCRIPT_TYPE_WEBHOOK:
+ $script['port'] = '';
+ $script['authtype'] = DB::getDefault('scripts', 'authtype');
+ $script['username'] = '';
+ $script['password'] = '';
+ $script['publickey'] = '';
+ $script['privatekey'] = '';
+ $script['execute_on'] = DB::getDefault('scripts', 'execute_on');
+ break;
+ }
+ }
+ elseif ($script['type'] == ZBX_SCRIPT_TYPE_SSH && $script['authtype'] != $db_script['authtype']
+ && $script['authtype'] == ITEM_AUTHTYPE_PASSWORD) {
+ $script['publickey'] = '';
+ $script['privatekey'] = '';
+ }
+
+ if ($script['scope'] != $db_script['scope'] && $script['scope'] == ZBX_SCRIPT_SCOPE_ACTION) {
+ $script['menu_path'] = '';
+ $script['usrgrpid'] = 0;
+ $script['host_access'] = DB::getDefault('scripts', 'host_access');;
+ $script['confirmation'] = '';
+ }
+
+ }
+ unset($script);
+
$this->checkUserGroups($scripts);
$this->checkHostGroups($scripts);
}
@@ -721,7 +596,7 @@ class CScript extends CApiService {
$common_fields['command']['flags'] |= API_REQUIRED;
}
else {
- $api_input_rules['uniq'] = [['scriptid'], ['name']];
+ $api_input_rules['uniq'] = [['scriptid'], ['name']];
$common_fields += ['scriptid' => ['type' => API_ID, 'flags' => API_REQUIRED]];
}
@@ -945,27 +820,32 @@ class CScript extends CApiService {
* @return array
*/
public function delete(array $scriptids) {
- $this->validateDelete($scriptids, $db_scripts);
+ if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
+ self::exception(ZBX_API_ERROR_PERMISSIONS,
+ _s('No permissions to call "%1$s.%2$s".', 'script', __FUNCTION__)
+ );
+ }
+
+ self::validateDelete($scriptids, $db_scripts);
DB::delete('scripts', ['scriptid' => $scriptids]);
- $this->addAuditBulk(CAudit::ACTION_DELETE, CAudit::RESOURCE_SCRIPT, $db_scripts);
+ self::addAuditLog(CAudit::ACTION_DELETE, CAudit::RESOURCE_SCRIPT, $db_scripts);
return ['scriptids' => $scriptids];
}
/**
- * @param array $scriptids
- * @param array $db_scripts
+ * @static
+ *
+ * @param array $scriptids
+ * @param array|null $db_scripts
*
* @throws APIException if the input is invalid
*/
- protected function validateDelete(array &$scriptids, array &$db_scripts = null) {
- if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
- self::exception(ZBX_API_ERROR_PERMISSIONS, _('You do not have permission to perform this operation.'));
- }
-
+ private static function validateDelete(array &$scriptids, array &$db_scripts = null) {
$api_input_rules = ['type' => API_IDS, 'flags' => API_NOT_EMPTY, 'uniq' => true];
+
if (!CApiInputValidator::validate($api_input_rules, $scriptids, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
@@ -976,12 +856,8 @@ class CScript extends CApiService {
'preservekeys' => true
]);
- foreach ($scriptids as $scriptid) {
- if (!array_key_exists($scriptid, $db_scripts)) {
- self::exception(ZBX_API_ERROR_PERMISSIONS,
- _('No permissions to referred object or it does not exist!')
- );
- }
+ if (count($db_scripts) != count($scriptids)) {
+ self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
}
// Check if deleted scripts used in actions.
@@ -1016,6 +892,7 @@ class CScript extends CApiService {
'hostid' => ['type' => API_ID],
'eventid' => ['type' => API_ID]
]];
+
if (!CApiInputValidator::validate($api_input_rules, $data, '/', $error)) {
self::exception(ZBX_API_ERROR_PARAMETERS, $error);
}
@@ -1067,6 +944,7 @@ class CScript extends CApiService {
'hostids' => $hostids,
'scriptids' => $data['scriptid']
]);
+
if (!$db_scripts) {
self::exception(ZBX_API_ERROR_PERMISSIONS, _('No permissions to referred object or it does not exist!'));
}
@@ -1267,15 +1145,16 @@ class CScript extends CApiService {
$result[$scriptid]['parameters'] = [];
}
- $parameters = DB::select('script_param', [
- 'output' => ['scriptid', 'name', 'value'],
+ $param_options = [
+ 'output' => ['script_paramid', 'scriptid', 'name', 'value'],
'filter' => ['scriptid' => array_keys($result)]
- ]);
+ ];
+ $db_parameters = DBselect(DB::makeSql('script_param', $param_options));
- foreach ($parameters as $parameter) {
- $result[$parameter['scriptid']]['parameters'][] = [
- 'name' => $parameter['name'],
- 'value' => $parameter['value']
+ while ($db_param = DBfetch($db_parameters)) {
+ $result[$db_param['scriptid']]['parameters'][] = [
+ 'name' => $db_param['name'],
+ 'value' => $db_param['value']
];
}
}
@@ -1429,4 +1308,149 @@ class CScript extends CApiService {
return $result;
}
+
+ /**
+ * Check for unique script names.
+ *
+ * @static
+ *
+ * @param array $scripts
+ * @param array|null $db_scripts
+ *
+ * @throws APIException if script names are not unique.
+ */
+ private static function checkDuplicates(array $scripts, array $db_scripts = null): void {
+ $names = [];
+
+ foreach ($scripts as $script) {
+ if (!array_key_exists('name', $script)) {
+ continue;
+ }
+
+ if ($db_scripts === null || $script['name'] !== $db_scripts[$script['scriptid']]['name']) {
+ $names[] = $script['name'];
+ }
+ }
+
+ if (!$names) {
+ return;
+ }
+
+ $duplicates = DB::select('scripts', [
+ 'output' => ['name'],
+ 'filter' => ['name' => $names],
+ 'limit' => 1
+ ]);
+
+ if ($duplicates) {
+ self::exception(ZBX_API_ERROR_PARAMETERS, _s('Script "%1$s" already exists.', $duplicates[0]['name']));
+ }
+ }
+
+ /**
+ * Update "script_param" table and populate script.parameters by "script_paramid" property.
+ *
+ * @static
+ *
+ * @param array $scripts
+ * @param string $method
+ * @param array|null $db_scripts
+ */
+ private static function updateParams(array &$scripts, string $method, array $db_scripts = null): void {
+ $ins_params = [];
+ $upd_params = [];
+ $del_paramids = [];
+
+ foreach ($scripts as &$script) {
+ if (!array_key_exists('parameters', $script)) {
+ continue;
+ }
+
+ $db_params = ($method === 'update')
+ ? array_column($db_scripts[$script['scriptid']]['parameters'], null, 'name')
+ : [];
+
+ foreach ($script['parameters'] as &$param) {
+ if (array_key_exists($param['name'], $db_params)) {
+ $db_param = $db_params[$param['name']];
+ $param['script_paramid'] = $db_param['script_paramid'];
+ unset($db_params[$param['name']]);
+
+ $upd_param = DB::getUpdatedValues('script_param', $param, $db_param);
+
+ if ($upd_param) {
+ $upd_params[] = [
+ 'values' => $upd_param,
+ 'where' => ['script_paramid' => $db_param['script_paramid']]
+ ];
+ }
+ }
+ else {
+ $ins_params[] = ['scriptid' => $script['scriptid']] + $param;
+ }
+ }
+ unset($param);
+
+ $del_paramids = array_merge($del_paramids, array_column($db_params, 'script_paramid'));
+ }
+ unset($script);
+
+ if ($ins_params) {
+ $script_paramids = DB::insertBatch('script_param', $ins_params);
+ }
+
+ if ($upd_params) {
+ DB::update('script_param', $upd_params);
+ }
+
+ if ($del_paramids) {
+ DB::delete('script_param', ['script_paramid' => $del_paramids]);
+ }
+
+ foreach ($scripts as &$script) {
+ if (!array_key_exists('parameters', $script)) {
+ continue;
+ }
+
+ foreach ($script['parameters'] as &$param) {
+ if (!array_key_exists('script_paramid', $param)) {
+ $param['script_paramid'] = array_shift($script_paramids);
+ }
+ }
+ unset($param);
+ }
+ unset($script);
+ }
+
+ /**
+ * Add the existing parameters to $db_scripts whether these are affected by the update.
+ *
+ * @static
+ *
+ * @param array $scripts
+ * @param array $db_scripts
+ */
+ private static function addAffectedObjects(array $scripts, array &$db_scripts): void {
+ $scriptids = [];
+
+ foreach ($scripts as $script) {
+ $scriptids[] = $script['scriptid'];
+ $db_scripts[$script['scriptid']]['parameters'] = [];
+ }
+
+ if (!$scriptids) {
+ return;
+ }
+
+ $options = [
+ 'output' => ['script_paramid', 'scriptid', 'name', 'value'],
+ 'filter' => ['scriptid' => $scriptids]
+ ];
+ $db_parameters = DBselect(DB::makeSql('script_param', $options));
+
+ while ($db_parameter = DBfetch($db_parameters)) {
+ $db_scripts[$db_parameter['scriptid']]['parameters'][$db_parameter['script_paramid']] =
+ array_diff_key($db_parameter, array_flip(['scriptid']));
+ }
+ }
}