diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Sample/PageController.php b/src/opnsense/mvc/app/controllers/OPNsense/Sample/PageController.php index acf8da865..f191cd746 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Sample/PageController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Sample/PageController.php @@ -46,6 +46,7 @@ class PageController extends ControllerBase $sample = new Sample(); $this->view->title = $sample->title; $this->view->items = array(array('field_name' =>'test', 'field_content'=>'1234567','field_type'=>"text") ); + $this->view->data = $sample ; // Pass the $postId parameter to the view //$this->view->setVar("postId", $postId); diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php b/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php new file mode 100644 index 000000000..a9478dd71 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Base/BaseModel.php @@ -0,0 +1,215 @@ +children() as $xmlNode) { + $tagName = $xmlNode->getName(); + // every item results in a Field type object, the first step is to determine which object to create + // based on the input model spec + $fieldObject = null ; + $classname = "OPNsense\\Base\\FieldTypes\\".$xmlNode->attributes()["type"]; + if (class_exists($classname)) { + // construct field type object + $field_rfcls = new \ReflectionClass($classname); + if (!$field_rfcls->getParentClass()->name == 'OPNsense\Base\FieldTypes\BaseField') { + // class found, but of wrong type. raise an exception. + throw new ModelException("class ".$field_rfcls->name." of wrong type in model definition"); + } + } else { + // no type defined, so this must be a standard container (without content) + $field_rfcls = new \ReflectionClass('OPNsense\Base\FieldTypes\ContainerField'); + } + + // generate full object name ( section.section.field syntax ) and create new Field + if ($internal_data->__reference == "") { + $new_ref = $tagName; + } else { + $new_ref = $internal_data->__reference . "." . $tagName; + } + $fieldObject = $field_rfcls->newInstance($new_ref); + + // now add content to this model (recursive) + if ($fieldObject->isContainer() == false) { + $internal_data->addChildNode($tagName, $fieldObject); + if ($xmlNode->count() > 0) { + // if fieldtype contains properties, try to call the setters + foreach ($xmlNode->children() as $fieldMethod) { + $param_value = $fieldMethod->__toString() ; + $method_name = "set".$fieldMethod->getName(); + if ($field_rfcls->hasMethod($method_name)) { + $fieldObject->$method_name($param_value); + } + } + } + if ($config_data != null && isset($config_data->$tagName)) { + // set field content from config (if available) + $fieldObject->setValue($config_data->$tagName->__toString()); + } + + } else { + // add new child node container, always try to pass config data + if ($config_data != null && isset($config_data->$tagName)) { + $config_section_data = $config_data->$tagName; + } else { + $config_section_data = null ; + } + + if ($fieldObject instanceof ArrayField) { + // handle Array types, recurring items + if ($config_section_data != null) { + $counter = 0 ; + foreach ($config_section_data as $conf_section) { + $child_node = new ArrayField($fieldObject->__reference . "." . ($counter++)); + $this->parseXml($xmlNode, $conf_section, $child_node); + $fieldObject->addChildNode(null, $child_node); + } + } else { + $child_node = new ArrayField($fieldObject->__reference . ".0"); + $child_node->setInternalEmptyStatus(true); + $this->parseXml($xmlNode, $config_section_data, $child_node); + $fieldObject->addChildNode(null, $child_node); + } + } else { + $this->parseXml($xmlNode, $config_section_data, $fieldObject); + } + + $internal_data->addChildNode($xmlNode->getName(), $fieldObject); + } + + } + + } + + /** + * Construct new model type, using it's own xml template + * @throws ModelException if the model xml is not found or invalid + */ + public function __construct() + { + // setup config handle to singleton config singleton + $this->internalConfigHandle = Config::getInstance(); + + // init new root node, all details are linked to this + $this->internalData = new FieldTypes\ContainerField(); + + // determine our caller's filename and try to find the model definition xml + // throw error on failure + $class_info = new \ReflectionClass($this); + $model_filename = substr($class_info->getFileName(), 0, strlen($class_info->getFileName())-3) . "xml" ; + if (!file_exists($model_filename)) { + throw new ModelException('model xml '.$model_filename.' missing') ; + } + $model_xml = simplexml_load_file($model_filename); + if ($model_xml === false) { + throw new ModelException('model xml '.$model_filename.' not valid') ; + } + if ($model_xml->getName() != "model") { + throw new ModelException('model xml '.$model_filename.' seems to be of wrong type') ; + } + + // use an xpath expression to find the root of our model in the config.xml file + // if found, convert the data to a simple structure (or create an empty array) + $tmp_config_data = $this->internalConfigHandle->xpath($model_xml->mount); + if ($tmp_config_data->length > 0) { + $config_array = simplexml_import_dom($tmp_config_data->item(0)) ; + } else { + $config_array = array(); + } + + // We've loaded the model template, now let's parse it into this object + $this->parseXml($model_xml->items, $config_array, $this->internalData) ; + + //print_r($this->internalData); + + // call Model initializer + $this->init(); + } + + /** + * reflect getter to internalData (ContainerField) + * @param $name property name + * @return mixed + */ + public function __get($name) + { + return $this->internalData->$name; + } + + /** + * reflect setter to internalData (ContainerField) + * @param $name property name + * @param $value property value + */ + public function __set($name, $value) + { + $this->internalData->$name = $value ; + } + +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php new file mode 100644 index 000000000..67b3797f3 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ArrayField.php @@ -0,0 +1,72 @@ +internalChildnodes[] = $node; + } else { + $this->internalChildnodes[$name] = $node; + } + } + + /** + * @return bool is empty array (only filled for template structure) + */ + public function isEmpty() + { + return $this->internalEmptyStatus; + } + + /** + * @param $status|bool set empty (status boolean) + */ + public function setInternalEmptyStatus($status) + { + $this->internalEmptyStatus = $status ; + } +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/BaseField.php b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/BaseField.php new file mode 100644 index 000000000..b7d79d817 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/BaseField.php @@ -0,0 +1,149 @@ +internalIsContainer; + } + + /** + * default constructor + * @param null|string $ref direct reference to this object + */ + public function __construct($ref = null) + { + $this->internalReference = $ref; + } + + /** + * @param $name property name + * @param $node content (must be of type BaseField) + */ + public function addChildNode($name, $node) + { + $this->internalChildnodes[$name] = $node; + } + + /** + * Reflect default getter to internal child nodes. + * Implements the special attribute __items to return all items and __reference to identify the field in this model. + * @param $name property name + * @return mixed + */ + public function __get($name) + { + if (array_key_exists($name, $this->internalChildnodes)) { + return $this->internalChildnodes[$name]; + } elseif ($name == '__items') { + return $this->internalChildnodes; + } elseif ($name == '__reference') { + return $this->internalReference; + } else { + // not found + return null; + } + + } + + /** + * reflect default setter to internal child nodes + * @param $name|string property name + * @param $value|string property value + */ + public function __set($name, $value) + { + if (array_key_exists($name, $this->internalChildnodes)) { + $this->internalChildnodes[$name]->setValue($value); + } + } + + public function __toString() + { + return $this->internalValue; + } + + /** + * set Default field value + * @param $value default value + */ + public function setDefault($value) + { + $this->internalValue = $value; + } + + /** + * default setter + * @param $value set field value + */ + public function setValue($value) + { + $this->internalValue = $value; + } + + /** + * @return array child items + */ + public function getChildren() + { + return $this->internalChildnodes; + } + +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ContainerField.php b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ContainerField.php new file mode 100644 index 000000000..c37819150 --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Base/FieldTypes/ContainerField.php @@ -0,0 +1,37 @@ +internalMask = $value ; + } +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Base/Model.php b/src/opnsense/mvc/app/models/OPNsense/Base/ModelException.php similarity index 86% rename from src/opnsense/mvc/app/models/OPNsense/Base/Model.php rename to src/opnsense/mvc/app/models/OPNsense/Base/ModelException.php index a7fcdaf09..576857b85 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Base/Model.php +++ b/src/opnsense/mvc/app/models/OPNsense/Base/ModelException.php @@ -27,17 +27,16 @@ -------------------------------------------------------------------------------------- package : Frontend Model Base - function: implements base model to bind config and definition to object + function: Basic Exception class for Model initialization */ - namespace OPNsense\Base; -abstract class BaseModel + +/** + * Class BaseModelException + * @package Base + */ +class ModelException extends \Exception { - public function __construct() - { - $class_info = new \ReflectionClass($this); - $class_info->getFileName(); - } -} +} \ No newline at end of file diff --git a/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.php b/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.php index 2f8b42e9f..029c10036 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.php +++ b/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.php @@ -34,5 +34,10 @@ use OPNsense\Base\BaseModel; class Sample extends BaseModel { - public $title = "123456"; +// protected function init() +// { +// print("\nxXx\n"); +// } + + } diff --git a/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.xml b/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.xml new file mode 100644 index 000000000..bd079577b --- /dev/null +++ b/src/opnsense/mvc/app/models/OPNsense/Sample/Sample.xml @@ -0,0 +1,29 @@ + + //test/sample + + Sample model + + + + [A-Z] + + + + test1234 + + + + + + +
+ + +
+ + + + +
+
+
\ No newline at end of file diff --git a/src/opnsense/mvc/app/views/OPNsense/Sample/page.show.volt b/src/opnsense/mvc/app/views/OPNsense/Sample/page.show.volt index b74913c19..25ed60d13 100644 --- a/src/opnsense/mvc/app/views/OPNsense/Sample/page.show.volt +++ b/src/opnsense/mvc/app/views/OPNsense/Sample/page.show.volt @@ -4,3 +4,8 @@ {% for item in items %} {{ partial('layout_partials/std_input_field',item) }} {% endfor %} + +
+{% for section in data.childnodes.section.__items %} + {{ section.node1 }}
+{% endfor %}