protected function getUndoContent($startContent, $stopContent, $currentContent) { if ($currentContent === $stopContent) { return $startContent; } else { // 3-way merge $ok = wfMerge($stopContent, $startContent, $currentContent, $result); if ($ok) { return $result; } else { return false; } } }
/** * Attempts to merge differences between three versions. Returns a new * Content object for a clean merge and false for failure or a conflict. * * All three Content objects passed as parameters must have the same * content model. * * This text-based implementation uses wfMerge(). * * @param Content $oldContent The page's previous content. * @param Content $myContent One of the page's conflicting contents. * @param Content $yourContent One of the page's conflicting contents. * * @return Content|bool */ public function merge3(Content $oldContent, Content $myContent, Content $yourContent) { $this->checkModelID($oldContent->getModel()); $this->checkModelID($myContent->getModel()); $this->checkModelID($yourContent->getModel()); $format = $this->getDefaultFormat(); $old = $this->serializeContent($oldContent, $format); $mine = $this->serializeContent($myContent, $format); $yours = $this->serializeContent($yourContent, $format); $ok = wfMerge($old, $mine, $yours, $result); if (!$ok) { return false; } if (!$result) { return $this->makeEmptyContent(); } $mergedContent = $this->unserializeContent($result, $format); return $mergedContent; }
/** * @access private * @todo document */ function mergeChangesInto(&$editText) { $fname = 'EditPage::mergeChangesInto'; wfProfileIn($fname); $db =& wfGetDB(DB_MASTER); // This is the revision the editor started from $baseRevision = Revision::loadFromTimestamp($db, $this->mArticle->mTitle, $this->edittime); if (is_null($baseRevision)) { wfProfileOut($fname); return false; } $baseText = $baseRevision->getText(); // The current state, we want to merge updates into it $currentRevision = Revision::loadFromTitle($db, $this->mArticle->mTitle); if (is_null($currentRevision)) { wfProfileOut($fname); return false; } $currentText = $currentRevision->getText(); if (wfMerge($baseText, $editText, $currentText, $result)) { $editText = $result; wfProfileOut($fname); return true; } else { wfProfileOut($fname); return false; } }
/** * @param string $old Text as it was in the database * @param string $mine Text submitted while user was editing * @param string $yours Text submitted by the user * @param bool $expectedMergeResult Whether the merge should be a success * @param string $expectedText Text after merge has been completed * * @dataProvider provideMerge() * @group medium * @covers ::wfMerge */ public function testMerge($old, $mine, $yours, $expectedMergeResult, $expectedText) { $this->checkHasDiff3(); $mergedText = null; $isMerged = wfMerge($old, $mine, $yours, $mergedText); $msg = 'Merge should be a '; $msg .= $expectedMergeResult ? 'success' : 'failure'; $this->assertEquals($expectedMergeResult, $isMerged, $msg); if ($isMerged) { // Verify the merged text $this->assertEquals($expectedText, $mergedText, 'is merged text as expected?'); } }
/** * Get the text that needs to be saved in order to undo all revisions * between $undo and $undoafter. Revisions must belong to the same page, * must exist and must not be deleted * @param $undo Revision * @param $undoafter Revision Must be an earlier revision than $undo * @return mixed string on success, false on failure */ public function getUndoText(Revision $undo, Revision $undoafter = null) { $currentRev = Revision::newFromTitle($this->mTitle); if (!$currentRev) { return false; // no page } $undo_text = $undo->getText(); $undoafter_text = $undoafter->getText(); $cur_text = $currentRev->getText(); if ($cur_text == $undo_text) { # No use doing a merge if it's just a straight revert. return $undoafter_text; } $undone_text = ''; if (!wfMerge($undo_text, $undoafter_text, $cur_text, $undone_text)) { return false; } return $undone_text; }
/** * @private * @todo document * * @parma $editText string * * @return bool */ function mergeChangesInto(&$editText) { wfProfileIn(__METHOD__); $db = wfGetDB(DB_MASTER); // This is the revision the editor started from $baseRevision = $this->getBaseRevision(); if (is_null($baseRevision)) { wfProfileOut(__METHOD__); return false; } $baseText = $baseRevision->getText(); // The current state, we want to merge updates into it $currentRevision = Revision::loadFromTitle($db, $this->mTitle); if (is_null($currentRevision)) { wfProfileOut(__METHOD__); return false; } $currentText = $currentRevision->getText(); $result = ''; if (wfMerge($baseText, $editText, $currentText, $result)) { $editText = $result; wfProfileOut(__METHOD__); return true; } else { wfProfileOut(__METHOD__); return false; } }
/** * Get the text that needs to be saved in order to undo all revisions * between $undo and $undoafter. Revisions must belong to the same page, * must exist and must not be deleted * @param $undo Revision * @param $undoafter Revision Must be an earlier revision than $undo * @return mixed string on success, false on failure */ public function getUndoText(Revision $undo, Revision $undoafter = null) { $cur_text = $this->getRawText(); if ($cur_text === false) { return false; // no page } $undo_text = $undo->getText(); $undoafter_text = $undoafter->getText(); if ($cur_text == $undo_text) { # No use doing a merge if it's just a straight revert. return $undoafter_text; } $undone_text = ''; if (!wfMerge($undo_text, $undoafter_text, $cur_text, $undone_text)) { return false; } return $undone_text; }
/** * @desc Saving CSS content * If there is more recent edit it will try to merge text and save. * Returns false when conflict is found and cannot be resolved * * @param string $content * @param string $summary * @param bool $isMinor * @param int $editTime timestamp * @param User $user * @return Status|bool */ public function saveCssFileContent($content, $summary, $isMinor, $editTime, $user) { $cssTitle = $this->getCssFileTitle(); $flags = 0; if ($cssTitle instanceof Title) { $aid = $cssTitle->getArticleID(Title::GAID_FOR_UPDATE); $flags |= $aid == 0 ? EDIT_NEW : EDIT_UPDATE; if ($isMinor) { $flags |= EDIT_MINOR; } $db = wfGetDB(DB_MASTER); $currentRevision = Revision::loadFromTitle($db, $cssTitle); // we handle both - edit and creation conflicts below if (!empty($currentRevision) && $editTime != $currentRevision->getTimestamp()) { $result = ''; $currentText = $currentRevision->getText(); if (!$editTime) { // the css did not exist when the editor was started, so the base revision for // parallel edits is an empty file $baseText = ''; } else { $baseText = Revision::loadFromTimestamp($db, $this->getCssFileTitle(), $editTime)->getText(); } // remove windows endlines from input before merging texts $content = str_replace("\r", "", $content); if (wfMerge($baseText, $content, $currentText, $result)) { // This conflict can be resolved $content = $result; } else { // We have real conflict here return false; } } $page = new WikiPage($cssTitle); $status = $page->doEdit($content, $summary, $flags, false, $user); return $status; } return Status::newFatal('special-css-saving-internal-error'); }