private function findSubDeletedDiffs() { $oNode = $this->oNode; if (AnwXml::xmlIsTextNode($oNode) || AnwXml::xmlIsPhpNode($oNode) || AnwXml::xmlIsCommentNode($oNode)) { return; } $oChilds = $oNode->childNodes; if ($oChilds) { $this->aoSubDeletedDiffs = array(); for ($i = 0; $i < $oChilds->length; $i++) { $oChild = $oChilds->item($i); $oSubDiff = new AnwDiffDeleted($oChild, $this); $this->aoSubDeletedDiffs[] = $oSubDiff; } } }
private static function applyDiffsToTranslation($oRootNode, $oDiffs, $oContentField) { //AnwDebug::log("Applying diffs to : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); $aoDiffs = $oDiffs->getAllDiffs(); $oChildNodes = $oRootNode->childNodes; $i = 0; foreach ($aoDiffs as $oDiff) { $oChild = $oChildNodes->item($i); if (!$oChild) { //AnwDebug::logdetail("oChild=null"); } AnwDebug::logdetail("//step dump: " . htmlentities(AnwUtils::xmlDumpNode($oRootNode))); $sDiffType = $oDiff->getDiffType(); $bSkipIncrement = false; switch ($sDiffType) { case AnwDiff::TYPE_ADDED: if ($oDiff->hasSubMovedNode()) { $oNodeRef = $oDiff->getNode(); $oNewNode = $oRootNode->ownerDocument->createElement($oNodeRef->nodeName); //no need to check for UnmodifiableBlockNodes, a comment/php node can't have submoved nodes AnwXml::xmlCopyNodeAttributes($oNodeRef, $oNewNode); //recursive call for SubAdded nodes AnwDebug::log(" * SUBADDED : " . htmlentities(AnwUtils::xmlDumpNode($oNewNode))); if ($oChild) { AnwDebug::logdetail("added->insertBefore : before=" . htmlentities(AnwUtils::xmlDumpNode($oChild))); $oRootNode->insertBefore($oNewNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); $oRootNode->appendChild($oNewNode); } //continue on subadded diffs self::applyDiffsToTranslation($oNewNode, $oDiff, $oContentField); } else { //quick test for special case with xmlIsUnmodifiableBlockNode $oTmpNode = $oDiff->getMovedNode() ? $this->getMovedNode() : $oDiff->getNode(); if (AnwXml::xmlIsUnmodifiableBlockNode($oTmpNode)) { //keep it unchanged $oNodeToImport = $oTmpNode; } else { //mark it as untranslated only if translatable (contentfield check) $bMarkAsUntranslated = AnwXml::xmlAreTranslatableAncestors($oRootNode, $oContentField); //TODO: move code from getNodeWithTranslateTags() here $oNodeToImport = $oDiff->getNodeWithTranslateTags($bMarkAsUntranslated, $oContentField); } $oNewNode = $oRootNode->ownerDocument->importNode($oNodeToImport, true); AnwDebug::log(" * ADDED : " . htmlentities(AnwUtils::xmlDumpNode($oNewNode))); if ($oChild) { AnwDebug::logdetail("added->insertBefore : before=" . htmlentities(AnwUtils::xmlDumpNode($oChild))); $oRootNode->insertBefore($oNewNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); $oRootNode->appendChild($oNewNode); } } break; case AnwDiff::TYPE_MOVED: //No need to import node as we get a node from the same document $oMovedNode = $oDiff->getMovedNode(); //tmp check if (!$oMovedNode) { //print AnwDebug::log('-----'.AnwUtils::xmlDumpNode($oDiff->getDiffDeleted()->getNode())); AnwDebug::log("****ERROR**** getMovedNode() returned NULL on AnwDiffMoved !"); throw new AnwUnexpectedException("ERROR getMovedNode() returned NULL on AnwDiffMoved !"); break; } AnwDebug::log(" * MOVED : " . htmlentities(AnwUtils::xmlDumpNode($oMovedNode))); //did the textlayout change? if ($oDiff->hasTextLayoutChanged()) { //we need to apply the new textlayout... $oMovedNode->nodeValue = AnwXml::xmlPreserveTextLayout($oMovedNode->nodeValue, $oDiff->getTextLayoutReferenceValue()); } //the following operations will MOVE the node into the document if ($oChild) { AnwDebug::log("added->insertBefore" . htmlentities(AnwUtils::xmlDumpNode($oMovedNode))); $oRootNode->insertBefore($oMovedNode, $oChild); } else { AnwDebug::logdetail("added->appendChild"); if (!$oRootNode->appendChild($oMovedNode)) { throw new AnwUnexpectedException("appendChild failed"); } } break; case AnwDiff::TYPE_DELETED: //if (!$oDiff->getMovedDiff()) //{ AnwDebug::logdetail(" * DELETED : " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getNode())) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); //if (!$oRootNode->removeChild($oChild)) throw new AnwUnexpectedException("removeChild failed"); //$bSkipIncrement = true; // !!! We don't delete nodes now, because we may need it if it contains moved nodes... // these nodes will be deleted later ////self::$aoNodesMarkedForDeletion[] = array($oRootNode,$oChild); if (!$oRootNode->removeChild($oChild)) { throw new AnwUnexpectedException("removeChild failed"); } $bSkipIncrement = true; //} //else //{ // AnwDebug::log(" * DELETED : deletion skipped (node will be moved)"); //} break; case AnwDiff::TYPE_KEPT: //don't touch anything AnwDebug::log(" * KEPT : " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getNode())) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); break; case AnwDiff::TYPE_EDITED: AnwDebug::log(" * EDITED : " . htmlentities(AnwUtils::xmlDumpNode($oChild)) . " == " . htmlentities(AnwUtils::xmlDumpNode($oDiff->getDiffAdded()->getNode()))); //TODO: warning, this code is very crappy and needs to be cleaned and tested //update attributes $oNodeRef = $oDiff->getDiffAdded()->getNode(); if (AnwXml::xmlIsUnmodifiableBlockNode($oChild)) { $oNewNode = AnwXml::xmlReplaceUnmodifiableBlockNode($oChild, $oNodeRef); } else { if (!AnwXml::xmlIsTextNode($oChild)) { throw new AnwUnexpectedException("not a text node in TYPE_EDITED"); } if ($oDiff->isEmpty() || !AnwXml::xmlAreTranslatableAncestors($oRootNode, $oContentField)) { AnwDebug::log("//edited : empty/untranslatable content, copying value but keeping it as translated"); //copy new value, but keep it as translated $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); } else { if ($oDiff->getDiffDeleted()->getMovedDiff()) { //special - consider it as an added node : set new value & mark this as untranslated AnwDebug::log("//edited : special case, considering as added node"); $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); } else { //content has really changed, mark it as untranslated if translatable (contentfield check) //current node is translatable... set new value & mark this as untranslated if ($oChild->nodeValue != $oNodeRef->nodeValue) { //we need to check if text has really changed, or if it's just some layout (spaces, breaklines...) which changed the nodeValue... $oNodeRefOld = $oDiff->getDiffDeleted()->getNode(); if (AnwXml::xmlTrimTextLayout($oNodeRefOld->nodeValue) == AnwXml::xmlTrimTextLayout($oNodeRef->nodeValue)) { AnwDebug::log("//edited : case 3.1, only textLayout has changed"); $sOldValue = $oChild->nodeValue; //content has not really changed, we just added/removed a space, tab, line break before/after the text value //ex: "blah blah\n" --> "blah blah\n\n" //we silently apply the new text layout, without turning it untranslated $oChild->nodeValue = AnwXml::xmlPreserveTextLayout($oChild->nodeValue, $oNodeRef->nodeValue); } else { AnwDebug::log("//edited : case 3.2, content has really changed"); $oNewNode = AnwXml::xmlReplaceTextNode($oChild, $oNodeRef); $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); } } /* //current node is translatable... keep CURRENT value and mark it as untranslated $oNewNode = $oChild; if ($oNewNode->nodeValue != $oNodeRef->nodeValue) { $oNewNode = AnwXml::xmlSetTextUntranslated($oNewNode, true); }*/ } } } break; case AnwDiff::TYPE_DIFFS: $oNodeDiffRef = $oDiff->getNodeRootNew(); AnwDebug::log(" * DIFFS : " . htmlspecialchars(AnwUtils::xmlDumpNode($oNodeDiffRef)) . " == " . htmlentities(AnwUtils::xmlDumpNode($oChild))); //update attributes AnwXml::xmlCopyNodeAttributes($oNodeDiffRef, $oChild); //recursive call self::applyDiffsToTranslation($oChild, $oDiff, $oContentField); break; default: AnwDebug::log("ERROR - Unknown DiffType :" . $sDiffType); } //just to prevent erros... unset($oNewNode); unset($oNodeRef); if (!$bSkipIncrement) { //AnwDebug::logdetail(" * Loop i++"); $i++; //AnwDebug::logdetail("//step dump_end : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); } //AnwDebug::log("Loop[$i] applydiffs intermediate result : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); } //AnwDebug::log("applydiffs result : ".htmlentities(AnwUtils::xmlDumpNode($oRootNode))); return $oRootNode; }
private static function findEditedNodes($aoDiffs) { //AnwDebug::logdetail(" ------ findEditedNodes ------ "); $aoNewDiffs = array(); //find edited nodes (= near deletion + addition with the same tag) $nCountDiffs = count($aoDiffs); for ($i = 0; $i < $nCountDiffs; $i++) { //$bKeepDiffUnchanged = true; if (isset($aoDiffs[$i])) { $oDiff = $aoDiffs[$i]; if ($oDiff->getDiffType() == AnwDiff::TYPE_ADDED || $oDiff->getDiffType() == AnwDiff::TYPE_DELETED && !$oDiff->hasMovedDiff()) { $j = self::findEditedNodes_findNext($aoDiffs, $i); if ($j) { if ($oDiff->getDiffType() == AnwDiff::TYPE_ADDED) { $iDiffAdded = $i; $iDiffDeleted = $j; } else { $iDiffAdded = $j; $iDiffDeleted = $i; } $oDiffAdded = $aoDiffs[$iDiffAdded]; $oDiffDeleted = $aoDiffs[$iDiffDeleted]; //AnwDebug::logdetail("?!? ".htmlentities(AnwUtils::xmlDumpNode($oDiffAdded->getNode()))." (".$oDiffAdded->getNode()->nodeName.")"); if (AnwXml::xmlIsTextNode($oDiffAdded->getNode()) || AnwXml::xmlIsPhpNode($oDiffAdded->getNode())) { //--------------------------------------------------------- // EDITED NODE //--------------------------------------------------------- //AnwDebug::logdetail("?!?---> ".$oDiffAdded->getNode()->nodeValue); $oDiffReplacingAdded = new AnwDiffEdited($oDiffAdded, $oDiffDeleted); //AnwDebug::logdetail("findEditedNodes : AnwDiffEdited found : ".htmlentities(AnwUtils::xmlDumpNode($oDiffDeleted->getNode()))." --> ".htmlentities(AnwUtils::xmlDumpNode($oDiffAdded->getNode()))); //replace AnwDiffAdded with AnwDiffEdited, remove AnwDiffDeleted //$bKeepDiffUnchanged = false; //$aoNewDiffs[] = $oDiffReplacingAdded; //replace AnwDiffAdded $oDiff = $oDiffReplacingAdded; //replace AnwDiffAdded unset($aoDiffs[$iDiffDeleted]); //remove AnwDiffDeleted } else { //throw new AnwUnexpectedException("We shouldn't find anymore diffs here"); //--------------------------------------------------------- // DIFFS NODE //--------------------------------------------------------- } } } else { if ($oDiff->getDiffType() == AnwDiff::TYPE_DIFFS) { //continue search on childs $aoSubDiffs = self::findEditedNodes($oDiff->getAllDiffs()); $oDiff->setDiffs($aoSubDiffs); } } //if ($bKeepDiffUnchanged) //{ $aoNewDiffs[] = $oDiff; //} } } return $aoNewDiffs; }
static function runCallbacksOnTranslatableValue($oInstance, $oRootNode, $sFieldInput, $fOnTextValue, $fBeforeChilds = null, $fAfterChilds = null, $fOnUntranslatableNode = null, $bFirstCall = true) { static $j = 0; if ($bFirstCall) { $j = 0; } //reset if (AnwXml::xmlIsTranslatableParent($oRootNode)) { if (AnwXml::xmlIsTextNode($oRootNode)) { if (!AnwXml::xmlIsEmptyNode($oRootNode)) { if ($fOnTextValue) { $oInstance->{$fOnTextValue}($oRootNode, $sFieldInput); } } } else { if (AnwXml::xmlIsCommentNode($oRootNode)) { } else { if (AnwXml::xmlIsPhpNode($oRootNode)) { //do nothing } else { if ($fBeforeChilds && !AnwXml::xmlIsRootNode($oRootNode)) { $oInstance->{$fBeforeChilds}($oRootNode); } $oChildNodes = $oRootNode->childNodes; if ($oChildNodes) { //WARNING - don't use foreach here ! bug on some servers, as childs are getting modified... for ($i = 0; $i < $oChildNodes->length; $i++) { $oChild = $oChildNodes->item($i); $sFieldInputNew = self::runCallbacks_getInputName($sFieldInput, $j, '-'); self::runCallbacksOnTranslatableValue($oInstance, $oChild, $sFieldInputNew, $fOnTextValue, $fBeforeChilds, $fAfterChilds, $fOnUntranslatableNode, false); //recursive $j++; } } if ($fAfterChilds && !AnwXml::xmlIsRootNode($oRootNode)) { $oInstance->{$fAfterChilds}($oRootNode); } } } } } else { if ($fOnUntranslatableNode) { $oInstance->{$fOnUntranslatableNode}($oRootNode); } } }