/** * Extends $param with option children, resolving xml:.... types. * * @param SimpleXMLElement $param Parameter to extend * @param bool $addErrorToXmlAsOption Should the error be added as an option instead of the options in case of error * @return null|string Error message */ function resolveXmlParamType( SimpleXMLElement $param, $addErrorToXmlAsOption = false ) { $errorMsg = null; $type = $param->attributes( 'type' ); if ( substr( $type, 0, 4 ) == 'xml:' ) { $xmlType = substr( $type, 4 ); if ( $this->_types ) { $typeModel = $this->_types->getChildByNameAttr( 'type', 'name' , $xmlType ); // find root type: if ( $typeModel ) { $root = $typeModel; $subbasetype = $root->attributes( 'base' ); for ( $i = 0; $i < 100; $i++ ) { if ( substr( $root->attributes( 'base' ), 0, 4 ) == 'xml:' ) { $subbasetype = $root->attributes( 'base' ); $root = $this->_types->getChildByNameAttr( 'type', 'name' , substr( $subbasetype, 4 ) ); if ( ! $root ) { $errorMsg = "Missing type definition of " . $subbasetype; break; } } else { // we found the root and type: $type = $root->attributes( 'base' ); break; } } if ( $i >= 99 ) { echo 'Error: recursion loop in XML type definition of ' . $typeModel->getName() . ' ' . $typeModel->attributes( 'name' ) . ' type: ' . $typeModel->attributes( 'type' ); exit; } $levelModel = $typeModel; $insertAfter = array(); for ( $i = 0; $i < 100; $i++ ) { switch ( $type ) { case 'list': case 'multilist': case 'radio': case 'checkbox': case 'checkmark': case 'published': case 'usergroup': case 'viewaccesslevel': case 'tag': $valueType = $root->attributes( 'valuetype' ); $subbasetype = $valueType ? $valueType : 'string'; /* if ( $view ) { $valueNode = $levelModel->getAnyChildByNameAttr( 'option', 'value', $value ); // recurse in children over optgroups if needed. if ( $valueNode ) { if ( $htmlFormatting == 'fieldsListArray' ) { $result[1] = $valueNode->data(); } else { $value = $valueNode->data(); } } } else { */ if ( $levelModel->attributes( 'insertbase' ) != 'before' ) { foreach ( $levelModel->children() as $option ) { /** @var SimpleXMLElement $option */ if ( $option->getName() == 'option' ) { $param->addChildWithAttr( 'option', $option->data(), null, $option->attributes() ); } elseif ( $option->getName() == 'optgroup' ) { $paramOptgroup = $param->addChildWithAttr( 'optgroup', $option->data(), null, $option->attributes() ); // in HTML 4, optgroups can not be nested (w3c) foreach ( $option->children() as $optChild ) { /** @var SimpleXMLElement $optChild */ if ( $optChild->getName() == 'option' ) { $paramOptgroup->addChildWithAttr( 'option', $optChild->data(), null, $optChild->attributes() ); } elseif ( $optChild->getName() == 'data' ) { $paramOptgroup->appendChild( $optChild ); } } } elseif ( $option->getName() == 'data' ) { $param->appendChild( $option ); } } } else { $insertAfter[] = $levelModel; } break; default: $errorMsg = "Unknown base type " . $type . " in XML"; break; } if ( ( $levelModel->attributes( 'name' ) == $typeModel->attributes( 'name' ) ) && ( substr( $levelModel->attributes( 'type' ), 0, 4 ) == 'xml:' ) ) { $levelModel = $this->_types->getChildByNameAttr( 'type', 'name' , substr( $levelModel->attributes( 'type' ), 4 ) ); } elseif ( substr( $levelModel->attributes( 'base' ), 0, 4 ) == 'xml:' ) { $levelModel = $this->_types->getChildByNameAttr( 'type', 'name' , substr( $levelModel->attributes( 'base' ), 4 ) ); } else { break; } } foreach ( $insertAfter as $levelModel ) { /** @var SimpleXMLElement $levelModel */ foreach ($levelModel->children() as $option ) { /** @var SimpleXMLElement $option */ if ( $option->getName() == 'option' ) { $param->addChildWithAttr( 'option', $option->data(), null, $option->attributes() ); } elseif ( $option->getName() == 'optgroup' ) { $paramOptgroup = $param->addChildWithAttr( 'optgroup', $option->data(), null, $option->attributes() ); foreach ( $option->children() as $optChild ) { if ( $optChild->getName() == 'option' ) { $paramOptgroup->addChildWithAttr( 'option', $optChild->data(), null, $optChild->attributes() ); } elseif ( $optChild->getName() == 'data' ) { $paramOptgroup->appendChild( $optChild ); } } } elseif ( $option->getName() == 'data' ) { $param->appendChild( $option ); } } } $param['type'] = $type; if ( $subbasetype ) { $param['base'] = $subbasetype; } } else { $errorMsg = "Missing type def. for param-type " . $param->attributes( 'type' ); } } else { $errorMsg = "No types defined in XML"; } if ( $errorMsg && $addErrorToXmlAsOption ) { $param->addChildWithAttr( 'option', $errorMsg, null, array( 'value' => '0') ); } } return $errorMsg; }