/** * Creates a XmlTag object and for each xml tag found in the document, * this function is called recursively to make sure we add all tags and their * children * * @param XmlTag $tag * @return XmlTag */ private function _parse(XmlTag $tag) { while ($this->_reader->read() && $this->_reader->nodeType !== \XMLReader::END_ELEMENT) { if ($this->_reader->nodeType == \XMLReader::ELEMENT) { $newTag = new XmlTag(); $newTag->setTagName($this->_reader->name); $newTag->setTagId($this->_tagCounter); if ($this->_reader->moveToFirstAttribute()) { $attr = new XmlAttribute(); $attr->setName($this->_reader->name); $attr->setValue($this->_reader->value); $newTag->addAttribute($attr); } $tag->addChild($newTag); $this->_tagCounter++; $this->_parse($newTag); } elseif ($this->_reader->nodeType == \XMLReader::TEXT || $this->_reader->nodeType == \XMLReader::CDATA) { $lastTag = $this->_xmlDocument->getTagByTagId($tag->getTagId()); if (!$lastTag instanceof XmlTag) { // something went very wrong throw new \Exception('Impossible to find tag with id: ', $tag->getId()); } $tag->setValue($this->_reader->value); } } return $tag; }
/** * * @param XmlDocument $document * @throws \Exception */ public function saveDocument(XmlDocument $document) { $insertDocument = 'INSERT INTO documents (name) VALUES (:name)'; $st = $this->_db->prepare($insertDocument); $st->bindValue(':name', $document->getName(), \PDO::PARAM_STR); $this->_db->beginTransaction(); $this->_execute($st); $documentId = $this->_db->lastInsertId(); /** * Tags */ $insertTags = 'INSERT INTO documents_tags ' . '(document_id, tag_id, parent_tag_id, tag_name, value) VALUES '; $values = array(); $flatTags = $document->getTagsFlat(); foreach ($flatTags as $tag) { $id = (int) $tag->getTagId(); $values[] = "(:documentId{$id}, :tagId{$id}, :parentTagId{$id}, :tagName{$id}, :value{$id})"; } $insertTags .= implode(', ', $values); $st = $this->_db->prepare($insertTags); foreach ($flatTags as $tag) { $id = (int) $tag->getTagId(); $st->bindValue(":documentId{$id}", $documentId, \PDO::PARAM_INT); $st->bindValue(":tagId{$id}", $tag->getTagId(), \PDO::PARAM_INT); $st->bindValue(":parentTagId{$id}", $tag->getParentTagId(), \PDO::PARAM_INT); $st->bindValue(":tagName{$id}", $tag->getTagName(), \PDO::PARAM_INT); $st->bindValue(":value{$id}", $tag->getValue(), \PDO::PARAM_INT); } $this->_execute($st); /** * must commit here in order to retrieve the tags ids from db */ $this->_db->commit(); /** * Save attributes */ $tagsCollectionWithAttributes = array_filter($flatTags, function ($var) { return $var->hasAttributes(); }); /** * there's no attribute to save */ if (empty($tagsCollectionWithAttributes)) { return; } $tags = array_filter($this->getDocument($documentId), function ($var) use($tagsCollectionWithAttributes) { return array_key_exists($var['tag_id'], $tagsCollectionWithAttributes); }); $attributes = array(); foreach ($tags as $tag) { $tagId = (int) $tag['documents_tags_id']; $attributes[] = "(:documentTagsId{$tagId}, :name{$tagId}, :value{$tagId})"; } $insertAttributes = 'INSERT INTO tags_attributes ' . '(documents_tags_id, attribute_name, attribute_value) VALUES ' . implode(', ', $attributes); $st = $this->_db->prepare($insertAttributes); foreach ($tags as $tagId => $tag) { $tagObj = $tagsCollectionWithAttributes[$tagId]; $tagObj->setId($tag['documents_tags_id']); foreach ($tagObj->getAttributes() as $attribute) { $st->bindValue(":documentTagsId{$tagObj->getId()}", $tagObj->getId(), \PDO::PARAM_INT); $st->bindValue(":name{$tagObj->getId()}", $attribute->getName(), \PDO::PARAM_STR); $st->bindValue(":value{$tagObj->getId()}", $attribute->getValue(), \PDO::PARAM_STR); } } $this->_execute($st); }