mvc: UnqiueIdField - enforce uniqueness and remove validation message. closes https://github.com/opnsense/core/issues/6877

This field type is hardly used, but the intention was to generate a new uniqueid on creation and make it stick. Trying to remember the last know stored value is rather tricky (certainly when it comes to cloning), but making sure we ignore values saved isn't that hard.

Although this doesn't win the beauty contest, at least it does make sure uniqid() is called for every new field. Either when cloning the field or calling a set on an empty entry.
This commit is contained in:
Ad Schellevis 2023-10-15 13:13:22 +02:00
parent 67f7d7ff46
commit 0c2c3b0c79

View File

@ -1,7 +1,7 @@
<?php
/*
* Copyright (C) 2016 Deciso B.V.
* Copyright (C) 2016-2023 Deciso B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -42,30 +42,39 @@ class UniqueIdField extends BaseField
protected $internalIsContainer = false;
/**
* @var null|string initial field value
* @var bool past actionPostLoadingEvent? (load unique id from disk, generate new when not)
*/
private $initialValue = null;
private $fieldLoaded = false;
/**
* retrieve field validators for this field type
* @return array
* {@inheritdoc}
*/
public function getValidators()
public function setValue($value)
{
if (empty($this->internalValue) && empty($this->initialValue)) {
// trigger initial value on change, before returning validators
// (new nodes will always be marked as "changed", see isFieldChanged())
// Maybe we should add an extra event handler if this kind of scenarios happen more often, similar to
// actionPostLoadingEvent. (which is not triggered on setting data for a complete new structure node)
$this->internalValue = uniqid('', true);
$this->initialValue = $this->internalValue;
if (empty((string)$this) && $this->fieldLoaded) {
parent::setValue(uniqid('', true));
} elseif (empty((string)$this) && !$this->fieldLoaded) {
parent::setValue($value);
}
$validators = parent::getValidators();
// unique id may not change..
$validators[] = new InclusionIn([
'message' => gettext('Unique ID is immutable.'),
'domain' => [$this->initialValue],
]);
return $validators;
}
/**
* {@inheritdoc}
*/
protected function actionPostLoadingEvent()
{
parent::actionPostLoadingEvent();
$this->fieldLoaded = true;
}
/**
* {@inheritdoc}
*/
public function applyDefault()
{
/** When cloned (add), set our default to a new uniqueid */
$this->fieldLoaded = true;
$this->setValue(null);
}
}