Doctrine\OXM\Marshaller\XmlMarshaller::doUnmarshal PHP Method

doUnmarshal() private method

INTERNAL: Performance sensitive method
private doUnmarshal ( XMLReader $cursor ) : object
$cursor XMLReader
return object
    private function doUnmarshal(XMLReader $cursor)
    {
        $allMappedXmlNodes = $this->classMetadataFactory->getAllXmlNodes();
        $knownMappedNodes = array_keys($allMappedXmlNodes);
        if ($cursor->nodeType !== XMLReader::ELEMENT && $cursor->nodeType !== XMLReader::CDATA) {
            throw MarshallerException::invalidMarshallerState($cursor);
        }
        $elementName = $cursor->localName;
        if (!in_array($elementName, $knownMappedNodes)) {
            throw MappingException::invalidMapping($elementName);
        }
        $classMetadata = $this->classMetadataFactory->getMetadataFor($allMappedXmlNodes[$elementName]);
        $mappedObject = $classMetadata->newInstance();
        // Pre Unmarshal hook
        if ($classMetadata->hasLifecycleCallbacks(Events::preUnmarshal)) {
            $classMetadata->invokeLifecycleCallbacks(Events::preUnmarshal, $mappedObject);
        }
        if ($cursor->hasAttributes) {
            while ($cursor->moveToNextAttribute()) {
                if ($classMetadata->hasXmlField($cursor->name)) {
                    $fieldName = $classMetadata->getFieldName($cursor->name);
                    $fieldMapping = $classMetadata->getFieldMapping($fieldName);
                    $type = Type::getType($fieldMapping['type']);
                    if ($classMetadata->isRequired($fieldName) && $cursor->value === null) {
                        throw MappingException::fieldRequired($classMetadata->name, $fieldName);
                    }
                    if ($classMetadata->isCollection($fieldName)) {
                        $convertedValues = array();
                        foreach (explode(" ", $cursor->value) as $value) {
                            $convertedValues[] = $type->convertToPHPValue($value);
                        }
                        $classMetadata->setFieldValue($mappedObject, $fieldName, $convertedValues);
                    } else {
                        $classMetadata->setFieldValue($mappedObject, $fieldName, $type->convertToPHPValue($cursor->value));
                    }
                }
            }
            $cursor->moveToElement();
        }
        if (!$cursor->isEmptyElement) {
            $collectionElements = array();
            while ($cursor->read()) {
                if ($cursor->nodeType === XMLReader::END_ELEMENT && $cursor->name === $elementName) {
                    // we're at the original element closing node, bug out
                    break;
                }
                if ($cursor->nodeType !== XMLReader::ELEMENT && $cursor->nodeType !== XMLReader::TEXT && $cursor->nodeType !== XMLReader::CDATA) {
                    // skip insignificant elements
                    continue;
                }
                if ($classMetadata->hasXmlField($cursor->localName)) {
                    $fieldName = $classMetadata->getFieldName($cursor->localName);
                    // Check for mapped entity as child, add recursively
                    $fieldMapping = $classMetadata->getFieldMapping($fieldName);
                    if ($this->classMetadataFactory->hasMetadataFor($fieldMapping['type'])) {
                        if ($classMetadata->isCollection($fieldName)) {
                            $collectionElements[$fieldName][] = $this->doUnmarshal($cursor);
                        } else {
                            $classMetadata->setFieldValue($mappedObject, $fieldName, $this->doUnmarshal($cursor));
                        }
                    } else {
                        // assume text element (dangerous?)
                        $cursor->read();
                        if (!$cursor->isEmptyElement && $cursor->nodeType !== XMLReader::END_ELEMENT) {
                            if ($cursor->nodeType !== XMLReader::TEXT && $cursor->nodeType !== XMLReader::CDATA) {
                                throw MarshallerException::invalidMarshallerState($cursor);
                            }
                            $type = Type::getType($fieldMapping['type']);
                            if ($classMetadata->isCollection($fieldName)) {
                                $collectionElements[$fieldName][] = $type->convertToPHPValue($cursor->value);
                            } else {
                                $classMetadata->setFieldValue($mappedObject, $fieldName, $type->convertToPHPValue($cursor->value));
                            }
                            $cursor->read();
                        }
                    }
                } elseif ($cursor->nodeType === XMLReader::TEXT || $cursor->nodeType === XMLReader::CDATA) {
                    foreach ($classMetadata->getFieldNames() as $fieldName) {
                        if (ClassMetadata::XML_VALUE === $classMetadata->getFieldXmlNode($fieldName)) {
                            $fieldMapping = $classMetadata->getFieldMapping($fieldName);
                            $type = Type::getType($fieldMapping['type']);
                            $classMetadata->setFieldValue($mappedObject, $fieldName, $type->convertToPHPValue($cursor->value));
                        }
                    }
                } elseif (in_array($cursor->name, $knownMappedNodes)) {
                    // look for inherited child directly
                    $childClassMetadata = $this->classMetadataFactory->getMetadataFor($allMappedXmlNodes[$cursor->name]);
                    // todo: ensure this potential child inherits from parent correctly
                    $fieldName = null;
                    foreach ($classMetadata->getFieldMappings() as $fieldMapping) {
                        if ($fieldMapping['type'] == $allMappedXmlNodes[$cursor->name]) {
                            $fieldName = $fieldMapping['fieldName'];
                        } else {
                            // Walk parent tree
                            foreach ($childClassMetadata->getParentClasses() as $parentClass) {
                                if ($fieldMapping['type'] == $parentClass) {
                                    $fieldName = $fieldMapping['fieldName'];
                                }
                            }
                        }
                    }
                    if ($fieldName !== null) {
                        if ($classMetadata->isCollection($fieldName)) {
                            $collectionElements[$fieldName][] = $this->doUnmarshal($cursor);
                        } else {
                            $classMetadata->setFieldValue($mappedObject, $fieldName, $this->doUnmarshal($cursor));
                        }
                    }
                }
            }
            if (!empty($collectionElements)) {
                foreach ($collectionElements as $fieldName => $elements) {
                    $classMetadata->setFieldValue($mappedObject, $fieldName, $elements);
                }
            }
        }
        // PostUnmarshall hook
        if ($classMetadata->hasLifecycleCallbacks(Events::postUnmarshal)) {
            $classMetadata->invokeLifecycleCallbacks(Events::postUnmarshal, $mappedObject);
        }
        return $mappedObject;
    }