From b694c81be205c0da1fa7d2315c774f35232f834d Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Sat, 4 Jan 2025 11:24:39 +0100 Subject: [PATCH] mvc:model - add Default() method to reset a model to it's factory defaults, required for https://github.com/opnsense/core/issues/7249 Sometimes its practical to be able to reset model settings to their defaults, in which case it makes sense to have a simple handle on the base model to flush all for a specific model. Although this is a "hammer" (unable to validate referential constraints on its own), there is practical use when trying to reset a component to its factory state. If useful, we could add a factory reset handle to the ApiMutableModelControllerBase class at some point as well to facility a "flush" in a more generic way. --- .../app/models/OPNsense/Base/BaseModel.php | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php b/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php index 5167fb808..b9cd6da37 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php +++ b/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php @@ -306,18 +306,13 @@ abstract class BaseModel } /** - * Construct new model type, using its own xml template + * fetch model definition after basic validations + * @return SimpleXMLElement * @throws ModelException if the model xml is not found or invalid * @throws ReflectionException */ - public function __construct() + private function getModelXML() { - // setup config handle to singleton config singleton - $internalConfigHandle = Config::getInstance(); - - // init new root node, all details are linked to this - $this->internalData = new ContainerField(); - // determine our caller's filename and try to find the model definition xml // throw error on failure $class_info = new ReflectionClass($this); @@ -335,6 +330,23 @@ abstract class BaseModel if (!$model_xml->mount) { throw new ModelException('model xml ' . $model_filename . ' missing mount definition'); } + return $model_xml; + } + + /** + * Construct new model type, using its own xml template + * @throws ModelException if the model xml is not found or invalid + * @throws ReflectionException + */ + public function __construct() + { + // setup config handle to singleton config singleton + $internalConfigHandle = Config::getInstance(); + + // init new root node, all details are linked to this + $this->internalData = new ContainerField(); + + $model_xml = $this->getModelXML(); if (!empty($model_xml->version)) { $this->internal_model_version = (string)$model_xml->version; } @@ -817,4 +829,24 @@ abstract class BaseModel { return $this->internal_current_model_version ?? ''; } + + /** + * reset model to its defaults (flush all content) + * @throws ModelException if the model xml is not found or invalid + * @throws ReflectionException + * @return this + */ + public function Default() + { + $this->internalData = new ContainerField(); + $config_array = new SimpleXMLElement(''); + $model_xml = $this->getModelXML(); + if (!empty($model_xml->version) && $this->internal_model_version != (string)$model_xml->version) { + throw new ModelException('Unable to reset to defaults as model on disk is not the same as in memory'); + } + $this->parseXml($model_xml->items, $config_array, $this->internalData); + // trigger post loading event + $this->internalData->eventPostLoading(); + return $this; + } }