예제 #1
0
 /**
  * parse model and config xml to object model using types in FieldTypes
  * @param SimpleXMLElement $xml model xml data (from items section)
  * @param SimpleXMLElement $config_data (current) config data
  * @param BaseField $internal_data output structure using FieldTypes,rootnode is internalData
  * @throws ModelException parse error
  */
 private function parseXml($xml, &$config_data, &$internal_data)
 {
     // copy xml tag attributes to Field
     if ($config_data != null) {
         foreach ($config_data->attributes() as $AttrKey => $AttrValue) {
             $internal_data->setAttributeValue($AttrKey, $AttrValue->__toString());
         }
     }
     // iterate model children
     foreach ($xml->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, $tagName);
         // 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) {
                     $method_name = "set" . $fieldMethod->getName();
                     if ($field_rfcls->hasMethod($method_name)) {
                         $fieldObject->{$method_name}($this->parseOptionData($fieldMethod));
                     }
                 }
             }
             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) {
                     foreach ($config_section_data as $conf_section) {
                         // Array items are identified by a UUID, read from attribute or create a new one
                         if (isset($conf_section->attributes()->uuid)) {
                             $tagUUID = $conf_section->attributes()['uuid']->__toString();
                         } else {
                             $tagUUID = $internal_data->generateUUID();
                         }
                         // iterate array items from config data
                         $child_node = new ContainerField($fieldObject->__reference . "." . $tagUUID, $tagName);
                         $this->parseXml($xmlNode, $conf_section, $child_node);
                         if (!isset($conf_section->attributes()->uuid)) {
                             // if the node misses a uuid, copy it to this nodes attributes
                             $child_node->setAttributeValue('uuid', $tagUUID);
                         }
                         $fieldObject->addChildNode($tagUUID, $child_node);
                     }
                 } else {
                     // There's no content in config.xml for this array node.
                     $tagUUID = $internal_data->generateUUID();
                     $child_node = new ContainerField($fieldObject->__reference . "." . $tagUUID, $tagName);
                     $child_node->setInternalIsVirtual();
                     $this->parseXml($xmlNode, $config_section_data, $child_node);
                     $fieldObject->addChildNode($tagUUID, $child_node);
                 }
             } else {
                 // All other node types (Text,Email,...)
                 $this->parseXml($xmlNode, $config_section_data, $fieldObject);
             }
             // add object as child to this node
             $internal_data->addChildNode($xmlNode->getName(), $fieldObject);
         }
     }
 }