public function build($runData) { $pl = $runData->getParameterList(); $fromRevisionId = $pl->getParameterValue("from_revision_id"); $toRevisionId = $pl->getParameterValue("to_revision_id"); if ($fromRevisionId == $toRevisionId) { throw new ProcessException(_("What is the point in comparing the revision with itself? Please choose different revisions of the page."), "same_revision"); } $fromRevision = DB_PageRevisionPeer::instance()->selectByPrimaryKey($fromRevisionId); $toRevision = DB_PageRevisionPeer::instance()->selectByPrimaryKey($toRevisionId); if ($fromRevision == null || $toRevision == null) { throw new ProcessException(_("Error selecting revisions to compare"), "no_revisions"); } $fromMetadata = $fromRevision->getMetadata(); $toMetadata = $toRevision->getMetadata(); $changed = array(); // compare titles and other things if ($fromMetadata->getTitle() !== $toMetadata->getTitle()) { $changed['title'] = true; } if ($fromMetadata->getUnixName() !== $toMetadata->getUnixName()) { $changed['unix_name'] = true; } if ($fromMetadata->getParentPageId() !== $toMetadata->getParentPageId()) { $changed['parent'] = true; if ($fromMetadata->getParentPageId()) { $fromParent = DB_PagePeer::instance()->selectByPrimaryKey($fromMetadata->getParentPageId())->getUnixName(); $runData->contextAdd("fromParent", $fromParent); } if ($toMetadata->getParentPageId()) { $toParent = DB_PagePeer::instance()->selectByPrimaryKey($toMetadata->getParentPageId())->getUnixName(); $runData->contextAdd("toParent", $toParent); } } //compare source now $fromPageSource = $fromRevision->getSourceText(); $toPageSource = $toRevision->getSourceText(); if ($fromPageSource !== $toPageSource) { $changed['source'] = true; // create page diff... wooo... $t1 = $fromPageSource; $t2 = $toPageSource; $inlineDiff = Wikidot_Util_Diff::generateInlineStringDiff($t1, $t2); $runData->contextAdd("inlineDiff", $inlineDiff); } $runData->contextAdd("fromPageSource", $fromPageSource); $runData->contextAdd("toPageSource", $toPageSource); $runData->contextAdd("fromRevision", $fromRevision); $runData->contextAdd("toRevision", $toRevision); $runData->contextAdd("fromMetadata", $fromMetadata); $runData->contextAdd("toMetadata", $toMetadata); $runData->contextAdd("changed", $changed); }
public function build($runData) { $pl = $runData->getParameterList(); $toPageSource = $pl->getParameterValue("source"); $mode = $pl->getParameterValue("mode"); $revisionId = $pl->getParameterValue("revision_id"); $revision = DB_PageRevisionPeer::instance()->selectByPrimaryKey($revisionId); $fromPageSource = $revision->getSourceText(); if ($mode == "section") { // compare only a fragment... $rangeStart = $pl->getParameterValue("range_start"); $rangeEnd = $pl->getParameterValue("range_end"); $s2 = explode("\n", $fromPageSource); $fromPageSource = implode("\n", array_slice($s2, $rangeStart, $rangeEnd - $rangeStart + 1)); } // create page diff... wooo... $t1 = $fromPageSource; $t2 = $toPageSource; $inlineDiff = Wikidot_Util_Diff::generateInlineStringDiff($t1, $t2); $runData->contextAdd("diff", $inlineDiff); }
/** * Generates a nice inline diff. * The config options are * - noChange = true - does not create 'change' blocks which uses word-level diffs * - asArray = false - outputs the an array of lines insted of text * * @param string $fromString * @param string $toString * @param array $config * @return string|array */ public static function generateInlineStringDiff($fromString, $toString, $config = array()) { $useChange = isset($config['noChange']) && $config['noChange'] == true ? false : true; $outputAsArray = isset($config['asArray']) && $config['asArray'] == true ? true : false; $xi = $yi = 1; $block = false; $context = array(); $nlead = 10000; $ntrail = 10000; $output = array(); // make a diff with the FULL output included too. $diff = Wikidot_Util_Diff::generateStringDiff($fromString, $toString, count(explode("\n", $toString))); $diffs2 = explode("\n", $diff); $diffs = array(); for ($i = 0; $i < count($diffs2); $i++) { $d = $diffs2[$i]; if (strlen($d) == 0) { continue; } $type = null; switch ($d[0]) { case ' ': $type = 'copy'; break; case '-': $type = 'delete'; break; case '+': $type = 'add'; break; } if ($type) { // handle a special situation if the previous line was 'delete' and this // one is 'add' - change this to 'change'. $c = count($diffs); if ($useChange && $c > 0 && $type == 'add' && $diffs[$c - 1]['type'] == 'delete') { $diffs[$c - 1]['type'] = 'change'; $diffs[$c - 1]['toline'] = substr($d, 1); } else { $diffs[] = array('type' => $type, 'line' => substr($d, 1)); } } } // generate output $output = array(); $currentType = 'copy'; $countDiffs = count($diffs); for ($i = 0; $i < $countDiffs; $i++) { $row = ''; $d = $diffs[$i]; $type = $d['type']; if ($type != $currentType) { switch ($type) { case 'add': $row .= '<ins>'; break; case 'delete': $row .= '<del>'; break; } $currentType = $type; } if ($type == 'change') { //special treatment $line = preg_replace(';(?<!\\s[^\\s]{1}|\\s[^\\s]{2})(\\s+);', "\\1\n", $d['line']); $toline = preg_replace(';(?<!\\s[^\\s]{1}|\\s[^\\s]{2})(\\s+);', "\\1\n", $d['toline']); // process this too $linediff = self::generateInlineStringDiff($line, $toline, array('asArray' => true, 'noChange' => true)); $row .= implode('', $linediff); } else { $row .= htmlspecialchars($d['line']); } if ($i < $countDiffs - 1) { $nextType = $diffs[$i + 1]['type']; } else { $nextType = null; } if ($type != $nextType) { // close the type switch ($type) { case 'add': $row .= '</ins>'; break; case 'delete': $row .= '</del>'; break; } } $output[] = $row; } if ($outputAsArray) { return $output; } else { return implode("\n", $output); } }