public function saveInTags(DatabaseInterface $db, NodeRef $originNodeRef, $recordid, $inPartials = 'fields', array $inTags, $restrictedPartials = '') { if (empty($recordid)) { throw new Exception('Cannot save in tags without recordid'); } TagUtils::validateTags($inTags); $originalRestrictedPartials = $restrictedPartials; $restrictedPartials = PartialUtils::unserializeInPartials($restrictedPartials); if ($restrictedPartials == 'all' || ($x = array_search('all', $restrictedPartials)) !== false) { return false; } // $originNodeRef = $node->getNodeRef(); // $outtable = $this->NodeDBMeta->getOutTagsTable($originNodeRef); $intable = $this->NodeDBMeta->getInTagsTable($originNodeRef); $tableid = $this->NodeDBMeta->getPrimaryKey($originNodeRef); // $now = $this->DateFactory->newStorageDate(); // $schema = $originNodeRef->getElement()->getSchema(); $tagsToDelete = array(); $tagsToUpdate = array(); // remove duplicates from tags foreach ($inTags as $o => $tag) { if ($originNodeRef->getElement()->hasTagDef($tag->getTagRole())) { $tagDef = $originNodeRef->getElement()->getSchema()->getTagDef($tag->getTagRole()); } else { $externalElement = $this->ElementService->getBySlug($tag->getTagElement()); $tagDef = $externalElement->getSchema()->getTagDef($tag->getTagRole()); } $tag->MatchPartial = TagUtils::determineMatchPartial($tagDef, $originNodeRef->getSlug()); $this->Logger->debug('MATCH PARTIAL for [' . $tag->toString() . '] is [' . $tag->MatchPartial->toString() . ']'); if (!$tagDef->isSortable()) { $tag->TagSortOrder = 0; } else { $tag->ShouldMatchSort = true; } foreach ($inTags as $i => $dtag) { if ($o != $i && $tag->matchExact($dtag)) { // error_log("REMOVING DUPE ".$dtag->toString()); unset($inTags[$o]); } } foreach ($restrictedPartials as $partial) { if ($this->TagsHelper->matchPartial($partial, $tag)) { unset($inTags[$o]); } } } $currentInTags = $this->findTags('in', $db, $originNodeRef, $recordid, $inPartials, true, false, $originalRestrictedPartials, $resolveLinkedRecords = false); TagUtils::validateTags($currentInTags, 'in'); foreach ($currentInTags as $k => $tag) { //if($tag->getTagOutID() == false) throw new Exception('Cannot save in tags without TagOutIDs for current tags'); $foundThisTag = false; foreach ($inTags as $k2 => $dtag) { // Get a list of fields that differ between the current tag and the tag to be saved $tagDiff = $tag->diff($dtag, $dtag->ShouldMatchSort); if (empty($tagDiff)) { // remove it from inTags, since it exists already unset($inTags[$k2]); $foundThisTag = true; break; } elseif (count($tagDiff) == 1 && $tagDiff[0] == 'TagSortOrder') { // If the only difference between the tags is sort order, we don't // want to remove the tag and then add it back. Just do an update. // Save the tag to run through updates later. $tag->setTagSortOrder($dtag->getTagSortOrder()); $tagsToUpdate[] = $tag; // Remove it from intags because we don't want it added again unset($inTags[$k2]); $foundThisTag = true; break; } } if (!$foundThisTag) { $tagsToDelete[] = $tag; } } if (empty($tagsToDelete) && empty($inTags) && empty($tagsToUpdate)) { return false; } foreach ($tagsToDelete as $tag) { $this->Logger->debug("Delete {$tag->getTagDirection()} tag: {$tag->toString()}"); // delete corresponding out tag $outElement = $this->ElementService->getBySlug($tag->getTagElement()); $outNodeRef = new NodeRef($outElement, $tag->getTagSlug()); $outtable = $this->NodeDBMeta->getOutTagsTable($outNodeRef); $outtableid = $this->NodeDBMeta->getPrimaryKey($outNodeRef); try { $outrecordid = $this->getRecordIDFromNodeRef($outNodeRef); } catch (NodeException $ne) { continue; } $affectedRows = $this->getConnectionForWrite($outNodeRef)->write("\n DELETE FROM {$db->quoteIdentifier($outtable)} WHERE\n {$outtableid} = {$db->quote($outrecordid)} AND\n ElementID = {$db->quote($originNodeRef->getElement()->getElementID())} AND\n Slug = {$db->quote($originNodeRef->getSlug())} AND\n Role = {$db->quote($tag->getTagRole())} AND\n Value = {$db->quote($tag->getTagValue())}", DatabaseInterface::AFFECTED_ROWS); if ($affectedRows > 0) { $this->NodeEvents->fireTagEvents('outtags', 'remove', $outNodeRef, $originNodeRef, $tag); } $affectedRows = $db->deleteRecord($db->quoteIdentifier($intable), "TagID = {$db->quote($tag['TagID'])}"); if ($affectedRows > 0) { $this->NodeEvents->fireTagEvents('intags', 'remove', $originNodeRef, $outNodeRef, $tag); } } // Tags that only have their sort order changed, do an update on both sides of the tag and fire an sortOrder.edit // event for the side of the tag that is ordered. foreach ($tagsToUpdate as $tag) { $this->Logger->debug("Update {$tag->getTagDirection()} tag: {$tag->toString()}"); // update corresponding out tag $outNodeRef = $tag->TagLinkNodeRef; $outtable = $this->NodeDBMeta->getOutTagsTable($outNodeRef); $outtableid = $this->NodeDBMeta->getPrimaryKey($outNodeRef); try { $outrecordid = $this->getRecordIDFromNodeRef($outNodeRef); } catch (NodeException $ne) { continue; } $updateArray = array('SortOrder' => $tag->getTagSortOrder()); $affectedRows = $db->updateRecord($db->quoteIdentifier($outtable), $updateArray, "{$outtableid} = {$db->quote($outrecordid)} AND\n ElementID = {$db->quote($originNodeRef->getElement()->getElementID())} AND\n Slug = {$db->quote($originNodeRef->getSlug())} AND\n Role = {$db->quote($tag->getTagRole())} AND\n Value = {$db->quote($tag->getTagValue())}"); $affectedRows = $db->updateRecord($db->quoteIdentifier($intable), $updateArray, "TagID = {$db->quote($tag['TagID'])}"); if ($affectedRows > 0) { $this->NodeEvents->fireTagEvents('intags', 'sortOrder.edit', $originNodeRef, $outNodeRef, $tag); } } if (!empty($inTags)) { foreach ($inTags as $inTag) { // if($inTag->getTagSectionID() != 0) // throw new NodeException('Cannot save in tags coming from a section'); $externalElement = $this->ElementService->getBySlug($inTag->getTagElement()); $externalNodeRef = new NodeRef($externalElement, $inTag->getTagSlug()); try { $externalRecordID = $this->getRecordIDFromNodeRef($externalNodeRef); } catch (NodeException $ne) { continue; } if ('' . $externalNodeRef == '' . $originNodeRef) { continue; } $this->Logger->debug("Add {$inTag->getTagDirection()} tag: {$inTag->toString()}"); //$inTagPartial = new TagPartial($inTag); $db = $this->getConnectionForWrite($externalNodeRef); $newTag = new Tag($originNodeRef->getElement()->getSlug(), $originNodeRef->getSlug(), $inTag->getTagRole(), $inTag->getTagValue(), $inTag->getTagValueDisplay()); $newTag->setTagSortOrder($inTag->getTagSortOrder()); // match partial is used to guarantee that only 1 outbound link exists for that element or element/value combo $this->saveOutTags($db, $externalNodeRef, $externalRecordID, $inTag->getMatchPartial()->toString(), array($newTag)); } } return true; }
public function setOutTags(array $tags) { TagUtils::validateTags($tags, 'out'); $this->fields['OutTags'] = $tags; unset($tags); }