allow to specify conditions, when the serial number get generated, use

value=<start/format>
<name>=<value>
This commit is contained in:
ralf 2024-04-03 21:12:31 +02:00
parent 9f2d952fdf
commit 1cc266467d
4 changed files with 60 additions and 29 deletions

View File

@ -379,16 +379,11 @@ class admin_customfields
if (!empty($content['cf_values'])) if (!empty($content['cf_values']))
{ {
$values = array(); $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'])) $content['cf_values'] = 'value=' . $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'];
} }
elseif($content['cf_values'][0] === '@') if($content['cf_values'][0] === '@')
{ {
$values['@'] = substr($content['cf_values'], $content['cf_values'][1] === '=' ? 2:1); $values['@'] = substr($content['cf_values'], $content['cf_values'][1] === '=' ? 2:1);
} }
@ -416,6 +411,11 @@ class admin_customfields
$values[$var] = trim($value)==='' ? $var : $value; $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; $content['cf_values'] = $values;
} }
$update_content = array(); $update_content = array();
@ -559,8 +559,9 @@ class admin_customfields
'cf_id' => $cf_id, 'cf_id' => $cf_id,
'cf_app' => $this->appname, 'cf_app' => $this->appname,
'cf_name' => $content['cf_name'], 'cf_name' => $content['cf_name'],
'cf_values' => $content['cf_values'],
'use_private' => $this->use_private, 'use_private' => $this->use_private,
), 2); ), 2);
} }
/** /**

View File

@ -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 string $fname custom field name
* @param array $field custom field data * @param array $field custom field data
@ -546,12 +546,35 @@ class Customfields extends Transformer
} }
//error_log(__METHOD__."() $field_name: ".array2string($value).' --> '.array2string($valid)); //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 // serials do NOT return a value, as they are always readonly
foreach(array_filter($customfields, static function($field) foreach(array_filter($customfields, static function($field)
{ {
return $field['type'] === 'serial'; return $field['type'] === 'serial';
}) as $field) }) 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); $valid =& self::get_array($validated, self::$prefix.$field['name'], true);
if (empty($valid = self::$request->content[self::$prefix.$field['name']])) if (empty($valid = self::$request->content[self::$prefix.$field['name']]))
{ {
@ -560,13 +583,7 @@ class Customfields extends Transformer
self::$request->content = $content; 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));
} }
} }
} }

View File

@ -146,13 +146,12 @@ class Tabbox extends Etemplate\Widget
public function beforeSendToClient($cname, array $expand=null) public function beforeSendToClient($cname, array $expand=null)
{ {
[$app] = explode('.', self::$request->template['name']); [$app] = explode('.', self::$request->template['name']);
// no need to run again for responses, or if we have no custom fields // no need to run if we have no custom fields
if (!empty(self::$response) || empty($app) || !($cfs = Api\Storage\Customfields::get($app, false, null, null, true))) if (empty($app) || !($cfs = Api\Storage\Customfields::get($app, false, null, null, true)))
{ {
return; return;
} }
$form_name = self::form_name($cname, $this->id, $expand); $extra_private_tab = self::expand_name($this->attrs['cfPrivateTab'] ?? false,
$extra_private_tab = self::expand_name(self::getElementAttribute($form_name, 'cfPrivateTab') ?? $this->attrs['cfPrivateTab'] ?? false,
0, 0, 0, 0, self::$request->content); 0, 0, 0, 0, self::$request->content);
if (is_string($extra_private_tab) && $extra_private_tab[0] === '!') 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 // check if template still contains a legacy customfield tab
$have_legacy_cf_tab = $this->haveLegacyCfTab(); $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) : []; $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); 0, 0, 0, 0, self::$request->content);
$type_filter = $type_filter ? explode(',', $type_filter) : []; $type_filter = $type_filter ? explode(',', $type_filter) : [];
@ -247,7 +246,11 @@ class Tabbox extends Etemplate\Widget
$content['cfExclude'] = implode(',', $exclude); $content['cfExclude'] = implode(',', $exclude);
self::$request->content = $content; 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 // addTabs is default false (= replace tabs), we need a default of true
$add_tabs =& self::setElementAttribute($this->id, 'addTabs', null); $add_tabs =& self::setElementAttribute($this->id, 'addTabs', null);
if (!isset($add_tabs)) $add_tabs = true; if (!isset($add_tabs)) $add_tabs = true;

View File

@ -669,20 +669,30 @@ class Customfields implements \IteratorAggregate
'cf_type' => 'serial', 'cf_type' => 'serial',
], __LINE__, __FILE__, false, 'FOR UPDATE') as $row) ], __LINE__, __FILE__, false, 'FOR UPDATE') as $row)
{ {
// we increment the last digit-group if (!empty($row['cf_values']) && ($v = json_decode($row['cf_values'], true)))
if (empty($row['cf_values']) || !preg_match(self::SERIAL_PREG, $row['cf_values'], $matches))
{ {
$row['cf_values'] = 1; $values = $v;
} }
else 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; break;
} }
if (isset($row) && self::$db->update(self::TABLE, $row, $where, __LINE__, __FILE__) && self::$db->transaction_commit()) 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(); self::$db->transaction_abort();
throw new Api\Db\Exception("Could not generate serial number for custom-field #$id!"); throw new Api\Db\Exception("Could not generate serial number for custom-field #$id!");