/** * createSchemaNodeForObject * * @param \DOMDocument $doc * @param $obj * @return \DOMElement */ private function createSchemaNodeForObject(\DOMDocument $doc, $obj) { $meta = ClassMetaStore::getMeta($obj); $complexType = $doc->createElement("xs:complexType"); $complexType->setAttribute("name", $this->getXsdType($meta->getClassName())); $sequence = $doc->createElement("xs:sequence"); $attributeBag = array(); foreach ($meta->getPropertyNames() as $propName) { $elementNames = $meta->getElementNamesForProperty($propName); if (count($elementNames) > 0) { $value = $meta->getPropertyValue($obj, $propName); $isCollection = is_array($value) || $value instanceof \Traversable; $propertyElement = count($elementNames) == 1 ? $this->createSchemaNodeForSingleElementProperty($doc, $meta, $elementNames[0]) : $this->createSchemaNodeForMultiElementProperty($doc, $meta, $elementNames); if ($isCollection) { $collectionChoice = $doc->createElement("xs:choice"); $collectionChoice->appendChild($propertyElement); $collectionChoice->setAttribute("minOccurs", 0); $collectionChoice->setAttribute("maxOccurs", "unbounded"); $propertyElement = $collectionChoice; } $sequence->appendChild($propertyElement); } $attrNames = $meta->getAttributeNamesForProperty($propName); foreach ($attrNames as $attrName) { $type = $meta->getPropertyTypeForAttribute($attrName); $this->mentionType($type); $attribute = $doc->createElement("xs:attribute"); $attribute->setAttribute("name", $attrName); $attribute->setAttribute("type", $this->getXsdType($type)); $attributeBag[] = $attribute; } } if ($sequence->hasChildNodes()) { $complexType->appendChild($sequence); } foreach ($attributeBag as $attribute) { $complexType->appendChild($attribute); } return $complexType; }
/** * unserializeObject * * @param $obj * @param \DOMElement $source */ private static function unserializeObject($obj, \DOMElement $source) { $meta = ClassMetaStore::getMeta($obj); $bag = array(); foreach ($source->attributes as $attribute) { $propName = $meta->getPropertyNameForAttribute($attribute->name); if (!$propName) { continue; } $valueType = $meta->getPropertyTypeForAttribute($attribute->name); $value = self::parseAtomicValue($attribute->value, $valueType); self::addPropertyToBag($propName, $value, $bag); } foreach ($source->childNodes as $child) { if (!$child instanceof \DOMElement) { continue; } $propName = $meta->getPropertyNameForElement($child->tagName); if (!$propName) { continue; } $valueType = $meta->getPropertyTypeForElement($child->tagName); $isObject = !self::isAtomicType($valueType); $value = $isObject ? new $valueType() : self::parseAtomicValue(trim($child->textContent), $valueType); self::addPropertyToBag($propName, $value, $bag); if ($isObject) { self::unserializeObject($value, $child); } } foreach ($bag as $propName => $data) { $currentValue = $meta->getPropertyValue($obj, $propName); if (is_array($currentValue)) { if (is_array($data)) { $meta->setPropertyValue($obj, $propName, array_merge($currentValue, $data)); } else { array_push($currentValue, $data); $meta->setPropertyValue($obj, $propName, $currentValue); } } elseif ($currentValue instanceof \ArrayAccess) { if (is_array($data)) { foreach ($data as $item) { $currentValue[] = $item; } } else { $currentValue[] = $data; } } else { $meta->setPropertyValue($obj, $propName, is_array($data) ? $data[count($data) - 1] : $data); } } }