From 1cc266467daefa268d7cd4cdb630f4b601c0cad4 Mon Sep 17 00:00:00 2001 From: ralf Date: Wed, 3 Apr 2024 21:12:31 +0200 Subject: [PATCH] allow to specify conditions, when the serial number get generated, use value= = --- admin/inc/class.admin_customfields.inc.php | 19 +++++++------ api/src/Etemplate/Widget/Customfields.php | 33 ++++++++++++++++------ api/src/Etemplate/Widget/Tabbox.php | 17 ++++++----- api/src/Storage/Customfields.php | 20 +++++++++---- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/admin/inc/class.admin_customfields.inc.php b/admin/inc/class.admin_customfields.inc.php index 6ea35cae32..1b596857d4 100644 --- a/admin/inc/class.admin_customfields.inc.php +++ b/admin/inc/class.admin_customfields.inc.php @@ -379,16 +379,11 @@ class admin_customfields if (!empty($content['cf_values'])) { $values = array(); - if ($content['cf_type'] === 'serial') + if ($content['cf_type'] === 'serial' && !str_starts_with($content['cf_values'], 'value=')) { - if (!preg_match(Api\Storage\Customfields::SERIAL_PREG, $content['cf_values'])) - { - Api\Etemplate::set_validation_error('cf_values', lang('Invalid Format, must end in a group of digits e.g. %1 or %2', "'0000'", "'RE2024-0000'")); - break; - } - $values = $content['cf_values']; + $content['cf_values'] = 'value=' . $content['cf_values']; } - elseif($content['cf_values'][0] === '@') + if($content['cf_values'][0] === '@') { $values['@'] = substr($content['cf_values'], $content['cf_values'][1] === '=' ? 2:1); } @@ -416,6 +411,11 @@ class admin_customfields $values[$var] = trim($value)==='' ? $var : $value; } } + if ($content['cf_type'] === 'serial' && !preg_match(Api\Storage\Customfields::SERIAL_PREG, $values['value'])) + { + Api\Etemplate::set_validation_error('cf_values', lang('Invalid Format, must end in a group of digits e.g. %1 or %2', "'0000'", "'RE2024-0000'")); + break; + } $content['cf_values'] = $values; } $update_content = array(); @@ -559,8 +559,9 @@ class admin_customfields 'cf_id' => $cf_id, 'cf_app' => $this->appname, 'cf_name' => $content['cf_name'], + 'cf_values' => $content['cf_values'], 'use_private' => $this->use_private, - ), 2); + ), 2); } /** diff --git a/api/src/Etemplate/Widget/Customfields.php b/api/src/Etemplate/Widget/Customfields.php index 93e2cb7e15..1521a6ff1f 100644 --- a/api/src/Etemplate/Widget/Customfields.php +++ b/api/src/Etemplate/Widget/Customfields.php @@ -295,7 +295,7 @@ class Customfields extends Transformer } /** - * Instanciate (server-side) widget used to implement custom-field, to run its beforeSendToClient or validate method + * Instantiate (server-side) widget used to implement custom-field, to run its beforeSendToClient or validate method * * @param string $fname custom field name * @param array $field custom field data @@ -546,12 +546,35 @@ class Customfields extends Transformer } //error_log(__METHOD__."() $field_name: ".array2string($value).' --> '.array2string($valid)); } + } + if ($this->type == 'customfields-types') + { + // Transformation doesn't handle validation + $valid =& self::get_array($validated, $this->id ? $form_name : $field, true); + if (true) $valid = $value_in; + //error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value)); + } + else + { // serials do NOT return a value, as they are always readonly foreach(array_filter($customfields, static function($field) { return $field['type'] === 'serial'; }) as $field) { + if (!empty($this->attrs['exclude']) && in_array($field['name'], + explode(',', self::expand_name($this->attrs['exclude'], 0, 0, 0, 0, self::$request->content)))) + { + continue; + } + // check if we have condition(s) beside the value, and they are NOT meet --> do NOT generate the serial + if (is_array($field['values']) && array_filter($field['values'], static function($val, $name) use ($content) + { + return $name === 'value' ? false : $val != $content[$name]; + }, ARRAY_FILTER_USE_BOTH)) + { + continue; + } $valid =& self::get_array($validated, self::$prefix.$field['name'], true); if (empty($valid = self::$request->content[self::$prefix.$field['name']])) { @@ -560,13 +583,7 @@ class Customfields extends Transformer self::$request->content = $content; } } - } - elseif ($this->type == 'customfields-types') - { - // Transformation doesn't handle validation - $valid =& self::get_array($validated, $this->id ? $form_name : $field, true); - if (true) $valid = $value_in; - //error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value)); + } } } \ No newline at end of file diff --git a/api/src/Etemplate/Widget/Tabbox.php b/api/src/Etemplate/Widget/Tabbox.php index f3dbce4cdd..011d85fcd8 100644 --- a/api/src/Etemplate/Widget/Tabbox.php +++ b/api/src/Etemplate/Widget/Tabbox.php @@ -146,13 +146,12 @@ class Tabbox extends Etemplate\Widget public function beforeSendToClient($cname, array $expand=null) { [$app] = explode('.', self::$request->template['name']); - // no need to run again for responses, or if we have no custom fields - if (!empty(self::$response) || empty($app) || !($cfs = Api\Storage\Customfields::get($app, false, null, null, true))) + // no need to run if we have no custom fields + if (empty($app) || !($cfs = Api\Storage\Customfields::get($app, false, null, null, true))) { return; } - $form_name = self::form_name($cname, $this->id, $expand); - $extra_private_tab = self::expand_name(self::getElementAttribute($form_name, 'cfPrivateTab') ?? $this->attrs['cfPrivateTab'] ?? false, + $extra_private_tab = self::expand_name($this->attrs['cfPrivateTab'] ?? false, 0, 0, 0, 0, self::$request->content); if (is_string($extra_private_tab) && $extra_private_tab[0] === '!') { @@ -173,10 +172,10 @@ class Tabbox extends Etemplate\Widget // check if template still contains a legacy customfield tab $have_legacy_cf_tab = $this->haveLegacyCfTab(); - $exclude = self::getElementAttribute($form_name, 'cfExclude') ?? $this->attrs['cfExclude'] ?? null; + $exclude = $this->attrs['cfExclude'] ?? null; $exclude = $exclude ? explode(',', $exclude) : []; - $type_filter = self::expand_name(self::getElementAttribute($form_name, 'cfTypeFilter') ?? $this->attrs['cfTypeFilter'] ?? null, + $type_filter = self::expand_name($this->attrs['cfTypeFilter'] ?? null, 0, 0, 0, 0, self::$request->content); $type_filter = $type_filter ? explode(',', $type_filter) : []; @@ -247,7 +246,11 @@ class Tabbox extends Etemplate\Widget $content['cfExclude'] = implode(',', $exclude); self::$request->content = $content; } - + // we must not add tabs again! + if (!empty(self::$response)) + { + return; + } // addTabs is default false (= replace tabs), we need a default of true $add_tabs =& self::setElementAttribute($this->id, 'addTabs', null); if (!isset($add_tabs)) $add_tabs = true; diff --git a/api/src/Storage/Customfields.php b/api/src/Storage/Customfields.php index 8e04aab6c4..41cc72964f 100644 --- a/api/src/Storage/Customfields.php +++ b/api/src/Storage/Customfields.php @@ -669,20 +669,30 @@ class Customfields implements \IteratorAggregate 'cf_type' => 'serial', ], __LINE__, __FILE__, false, 'FOR UPDATE') as $row) { - // we increment the last digit-group - if (empty($row['cf_values']) || !preg_match(self::SERIAL_PREG, $row['cf_values'], $matches)) + if (!empty($row['cf_values']) && ($v = json_decode($row['cf_values'], true))) { - $row['cf_values'] = 1; + $values = $v; } else { - $row['cf_values'] = preg_replace(self::SERIAL_PREG, sprintf('%0'.strlen($matches[0]).'d', 1+(int)$matches[0]), $row['cf_values']); + $values = ['value' => $row['cf_values'] ?? null]; } + // we increment the last digit-group + if (empty($values['value']) || !preg_match(self::SERIAL_PREG, $values['value'], $matches)) + { + $values['value'] = 1; + } + else + { + $values['value'] = preg_replace(self::SERIAL_PREG, + sprintf('%0'.strlen($matches[0]).'d', 1+(int)$matches[0]), $values['value']); + } + $row['cf_values'] = json_encode($values); break; } if (isset($row) && self::$db->update(self::TABLE, $row, $where, __LINE__, __FILE__) && self::$db->transaction_commit()) { - return $row['cf_values']; + return $values['value']; } self::$db->transaction_abort(); throw new Api\Db\Exception("Could not generate serial number for custom-field #$id!");