public function writeBunchPatrolTableContent(&$dbr, $target, $readOnly) { global $wgOut, $wgUser; $wgOut->addHTML("<table width='100%' align='center' class='bunchtable'><tr>"); if (!$readOnly) { $wgOut->addHTML("<td><b>Patrol?</b></td>"); } $wgOut->addHTML("<td align='center'><b>Diff</b></td></tr>"); $opts = array('rc_user_text' => $target, 'rc_patrolled=0'); $opts[] = ' (rc_namespace = 2 OR rc_namespace = 3) '; $res = $dbr->select('recentchanges', array('rc_id', 'rc_title', 'rc_namespace', 'rc_this_oldid', 'rc_cur_id', 'rc_last_oldid'), $opts, "wfSpecialBunchpatrol", array('LIMIT' => 15)); $count = 0; while (($row = $dbr->fetchObject($res)) != null) { $t = Title::makeTitle($row->rc_namespace, $row->rc_title); $diff = $row->rc_this_oldid; $rcid = $row->rc_id; $oldid = $row->rc_last_oldid; $de = new DifferenceEngine($t, $oldid, $diff, $rcid); $wgOut->addHTML("<tr>"); if (!$readOnly) { $wgOut->addHTML("<td valign='middle' style='padding-right:24px; border-right: 1px solid #eee;'><input type='checkbox' name='rc_{$rcid}'></td>"); } $wgOut->addHTML("<td style='border-top: 1px solid #eee;'>"); $wgOut->addHTML($wgUser->getSkin()->makeLinkObj($t)); $de->showDiffPage(true); $wgOut->addHTML("</td></tr>"); $count++; } $dbr->freeResult($res); $wgOut->addHTML("</table><br/><br/>"); return $count; }
public function execute() { $params = $this->extractRequestParams(); $rev1 = $this->revisionOrTitleOrId($params['fromrev'], $params['fromtitle'], $params['fromid']); $rev2 = $this->revisionOrTitleOrId($params['torev'], $params['totitle'], $params['toid']); $de = new DifferenceEngine($this->getContext(), $rev1, $rev2, null, true, false); $vals = array(); if (isset($params['fromtitle'])) { $vals['fromtitle'] = $params['fromtitle']; } if (isset($params['fromid'])) { $vals['fromid'] = $params['fromid']; } $vals['fromrevid'] = $rev1; if (isset($params['totitle'])) { $vals['totitle'] = $params['totitle']; } if (isset($params['toid'])) { $vals['toid'] = $params['toid']; } $vals['torevid'] = $rev2; $difftext = $de->getDiffBody(); if ($difftext === false) { $this->dieUsage('The diff cannot be retrieved. ' . 'Maybe one or both revisions do not exist or you do not have permission to view them.', 'baddiff'); } else { ApiResult::setContent($vals, $difftext); } $this->getResult()->addValue(null, $this->getModuleName(), $vals); }
public function testGetDiff() { $engine = new DifferenceEngine(); $textA = 'foo'; $textB = 'foobar'; $diff = $engine->generateDiffBody($textA, $textB); $this->assertContains('<span class="diffchange diffchange-inline">foo</span>', $diff); }
public static function showDiff($data) { $rev1 = self::revOrTitle($data['Revision1'], $data['Page1']); $rev2 = self::revOrTitle($data['Revision2'], $data['Page2']); if ($rev1 && $rev2) { $de = new DifferenceEngine(null, $rev1, $rev2, null, $data["Action"] == 'purge', false); $de->showDiffPage(true); } }
public static function showDiff($data, HTMLForm $form) { $rev1 = self::revOrTitle($data['Revision1'], $data['Page1']); $rev2 = self::revOrTitle($data['Revision2'], $data['Page2']); if ($rev1 && $rev2) { $de = new DifferenceEngine($form->getContext(), $rev1, $rev2, null, $data['Action'] == 'purge', $data['Unhide'] == '1'); $de->showDiffPage(true); } }
public static function formatDiffRow($title, $oldid, $newid, $timestamp, $comment, $actiontext = '') { global $wgFeedDiffCutoff, $wgContLang, $wgUser; wfProfileIn(__FUNCTION__); $skin = $wgUser->getSkin(); # log enties $completeText = '<p>' . implode(' ', array_filter(array($actiontext, $skin->formatComment($comment)))) . "</p>\n"; //NOTE: Check permissions for anonymous users, not current user. // No "privileged" version should end up in the cache. // Most feed readers will not log in anway. $anon = new User(); $accErrors = $title->getUserPermissionsErrors('read', $anon, true); if ($title->getNamespace() >= 0 && !$accErrors) { if ($oldid) { wfProfileIn(__FUNCTION__ . "-dodiff"); #$diffText = $de->getDiff( wfMsg( 'revisionasof', # $wgContLang->timeanddate( $timestamp ) ), # wfMsg( 'currentrev' ) ); // Don't bother generating the diff if we won't be able to show it if ($wgFeedDiffCutoff > 0) { $de = new DifferenceEngine($title, $oldid, $newid); $diffText = $de->getDiff(wfMsg('previousrevision'), wfMsg('revisionasof', $wgContLang->timeanddate($timestamp))); } if (strlen($diffText) > $wgFeedDiffCutoff || $wgFeedDiffCutoff <= 0) { // Omit large diffs $diffLink = $title->escapeFullUrl('diff=' . $newid . '&oldid=' . $oldid); $diffText = '<a href="' . $diffLink . '">' . htmlspecialchars(wfMsgForContent('showdiff')) . '</a>'; } elseif ($diffText === false) { // Error in diff engine, probably a missing revision $diffText = "<p>Can't load revision {$newid}</p>"; } else { // Diff output fine, clean up any illegal UTF-8 $diffText = UtfNormal::cleanUp($diffText); $diffText = self::applyDiffStyle($diffText); } wfProfileOut(__FUNCTION__ . "-dodiff"); } else { $rev = Revision::newFromId($newid); if (is_null($rev)) { $newtext = ''; } else { $newtext = $rev->getText(); } $diffText = '<p><b>' . wfMsg('newpage') . '</b></p>' . '<div>' . nl2br(htmlspecialchars($newtext)) . '</div>'; } $completeText .= $diffText; } wfProfileOut(__FUNCTION__); return $completeText; }
/** * @param MessageGroup $group * @param string $code * @param string $type * @param array $params * @param int $limit * @return string HTML */ protected function formatChange(MessageGroup $group, $code, $type, $params, &$limit) { $key = $params['key']; $title = Title::makeTitleSafe($group->getNamespace(), "{$key}/{$code}"); $id = self::changeId($group->getId(), $code, $type, $key); if ($title && $title->exists() && $type === 'addition') { // The message has for some reason dropped out from cache // or perhaps it is being reused. In any case treat it // as a change for display, so the admin can see if // action is needed and let the message be processed. // Otherwise it will end up in the postponed category // forever and will prevent rebuilding the cache, which // leads to many other annoying problems. $type = 'change'; } elseif ($title && !$title->exists() && ($type === 'deletion' || $type === 'change')) { return ''; } $text = ''; if ($type === 'deletion') { $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent()); $oldContent = ContentHandler::makeContent($wiki, $title); $newContent = ContentHandler::makeContent('', $title); $this->diff->setContent($oldContent, $newContent); $text = $this->diff->getDiff(Linker::link($title), ''); } elseif ($type === 'addition') { $oldContent = ContentHandler::makeContent('', $title); $newContent = ContentHandler::makeContent($params['content'], $title); $this->diff->setContent($oldContent, $newContent); $text = $this->diff->getDiff('', Linker::link($title)); } elseif ($type === 'change') { $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent()); $handle = new MessageHandle($title); if ($handle->isFuzzy()) { $wiki = '!!FUZZY!!' . str_replace(TRANSLATE_FUZZY, '', $wiki); } $label = $this->msg('translate-manage-action-ignore')->text(); $actions = Xml::checkLabel($label, "i/{$id}", "i/{$id}"); $limit--; if ($group->getSourceLanguage() === $code) { $label = $this->msg('translate-manage-action-fuzzy')->text(); $actions .= ' ' . Xml::checkLabel($label, "f/{$id}", "f/{$id}", true); $limit--; } $oldContent = ContentHandler::makeContent($wiki, $title); $newContent = ContentHandler::makeContent($params['content'], $title); $this->diff->setContent($oldContent, $newContent); $text .= $this->diff->getDiff(Linker::link($title), $actions); } $hidden = Html::hidden($id, 1); $limit--; $text .= $hidden; $classes = "mw-translate-smg-change smg-change-{$type}"; if ($limit < 0) { // Don't add if one of the fields might get dropped of at submission return ''; } return Html::rawElement('div', array('class' => $classes), $text); }
function execute($par) { $request = $this->getRequest(); $output = $this->getOutput(); $this->setHeaders(); $this->checkPermissions(); $inputValue = htmlspecialchars($request->getText('page', $par)); $pagenamePlaceholder = $this->msg('pp-pagename-placeholder')->escaped(); $prepareButtonValue = $this->msg('pp-prepare-button-label')->escaped(); $saveButtonValue = $this->msg('pp-save-button-label')->escaped(); $cancelButtonValue = $this->msg('pp-cancel-button-label')->escaped(); $summaryValue = $this->msg('pp-save-summary')->inContentLanguage()->escaped(); $output->addModules('ext.translate.special.pagepreparation'); $output->addModuleStyles('jquery.uls.grid'); $out = ''; $diff = new DifferenceEngine($this->getContext()); $diffHeader = $diff->addHeader(" ", $this->msg('pp-diff-old-header')->escaped(), $this->msg('pp-diff-new-header')->escaped()); $out = <<<HTML <div class="grid"> \t<form class="mw-tpp-sp-form row" name="mw-tpp-sp-input-form" action=""> \t\t<input id="pp-summary" type="hidden" value="{$summaryValue}" /> \t\t<input name="page" id="page" class="mw-searchInput mw-ui-input" \t\t\tplaceholder="{$pagenamePlaceholder}" value="{$inputValue}"/> \t\t<button id="action-prepare" class="mw-ui-button mw-ui-primary" type="button"> \t\t\t{$prepareButtonValue}</button> \t\t<button id="action-save" class="mw-ui-button mw-ui-constructive hide" type="button"> \t\t\t{$saveButtonValue}</button> \t\t<button id="action-cancel" class="mw-ui-button mw-ui-quiet hide" type="button"> \t\t\t{$cancelButtonValue}</button> \t</form> \t<div class="messageDiv hide"></div> \t<div class="divDiff hide"> \t\t{$diffHeader} \t</div> </div> HTML; $output->addHTML($out); }
/** * Diff would format against two revisions */ public function formatApi(FormatterRow $newRow, FormatterRow $oldRow, IContextSource $ctx) { $oldRes = $this->revisionViewFormatter->formatApi($oldRow, $ctx); $newRes = $this->revisionViewFormatter->formatApi($newRow, $ctx); $oldContent = $oldRow->revision->getContent('wikitext'); $newContent = $newRow->revision->getContent('wikitext'); $differenceEngine = new \DifferenceEngine(); $differenceEngine->setContent(new \TextContent($oldContent), new \TextContent($newContent)); if ($oldRow->revision->isFirstRevision()) { $prevLink = null; } else { $prevLink = $this->urlGenerator->diffLink($oldRow->revision, $ctx->getTitle(), UUID::create($oldRes['workflowId']))->getLocalURL(); } // this is probably a network request which typically goes in the query // half, but we don't have to worry about batching because we only show // one diff at a time so just do it. $nextRevision = $newRow->revision->getCollection()->getNextRevision($newRow->revision); if ($nextRevision === null) { $nextLink = null; } else { $nextLink = $this->urlGenerator->diffLink($nextRevision, $ctx->getTitle(), UUID::create($newRes['workflowId']))->getLocalURL(); } return array('new' => $newRes, 'old' => $oldRes, 'diff_content' => $differenceEngine->getDiffBody(), 'links' => array('previous' => $prevLink, 'next' => $nextLink)); }
/** * Render the footer including userinfos (Name, Role, Editcount) */ function showFooter() { $output = $this->getOutput(); $output->addHtml(Html::openElement('div', array('id' => 'mw-mf-userinfo', 'class' => 'position-fixed')) . Html::openElement('div', array('class' => 'post-content'))); $userId = $this->rev->getUser(); if ($userId) { $user = User::newFromId($userId); $edits = $user->getEditCount(); $attrs = array('class' => MobileUI::iconClass('user', 'before', 'mw-mf-user icon-16px'), 'data-revision-id' => $this->revId, 'data-user-name' => $user->getName(), 'data-user-gender' => $user->getOption('gender')); $output->addHtml(Html::openElement('div', $attrs) . Linker::link($user->getUserPage(), htmlspecialchars($user->getName()), array('class' => 'mw-mf-user-link')) . '</div>' . '<div class="mw-mf-roles meta">' . $this->listGroups($user) . '</div>' . '<div class="mw-mf-edit-count meta">' . $this->msg('mobile-frontend-diffview-editcount', $this->getLanguage()->formatNum($edits))->parse() . '</div>'); } else { $ipAddr = $this->rev->getUserText(); $userPage = SpecialPage::getTitleFor('Contributions', $ipAddr); $output->addHtml(Html::element('div', array('class' => MobileUI::iconClass('anonymous', 'before', 'mw-mf-user icon-16px mw-mf-anon')), $this->msg('mobile-frontend-diffview-anonymous')) . '<div>' . Linker::link($userPage, htmlspecialchars($ipAddr)) . '</div>'); } if ($this->mDiffEngine instanceof InlineDifferenceEngine) { $output->addHtml($this->mDiffEngine->getPatrolledLink()); } $output->addHtml(Html::closeElement('div') . Html::closeElement('div')); }
public function getData() { $db = wfGetDB(DB_MASTER); $conds = array('rt_page' => $this->handle->getTitle()->getArticleID(), 'rt_type' => RevTag::getType('tp:transver')); $options = array('ORDER BY' => 'rt_revision DESC'); $translationRevision = $db->selectField('revtag', 'rt_value', $conds, __METHOD__, $options); if ($translationRevision === false) { throw new TranslationHelperException("No definition revision recorded"); } $definitionTitle = Title::makeTitleSafe($this->handle->getTitle()->getNamespace(), $this->handle->getKey() . '/' . $this->group->getSourceLanguage()); if (!$definitionTitle || !$definitionTitle->exists()) { throw new TranslationHelperException("Definition page doesn't exist"); } // Using newFromId instead of newFromTitle, because the page might have been renamed $oldrev = Revision::newFromId($translationRevision); if (!$oldrev) { throw new TranslationHelperException("Old definition version doesn't exist anymore"); } $oldContent = $oldrev->getContent(); $newContent = $this->getDefinitionContent(); if (!$oldContent) { throw new TranslationHelperException("Old definition version doesn't exist anymore"); } if (!$oldContent instanceof WikitextContent || !$newContent instanceof WikitextContent) { throw new TranslationHelperException('Can only work on Wikitext content'); } if ($oldContent->equals($newContent)) { throw new TranslationHelperException('No changes'); } $diff = new DifferenceEngine($this->context); if (method_exists('DifferenceEngine', 'setTextLanguage')) { $diff->setTextLanguage($this->group->getSourceLanguage()); } $diff->setContent($oldContent, $newContent); $diff->setReducedLineNumbers(); $diff->showDiffStyle(); $html = $diff->getDiff($this->context->msg('tpt-diff-old')->escaped(), $this->context->msg('tpt-diff-new')->escaped()); return array('value_old' => $oldContent->getNativeData(), 'value_new' => $newContent->getNativeData(), 'revisionid_old' => $oldrev->getId(), 'revisionid_new' => $definitionTitle->getLatestRevId(), 'language' => $this->group->getSourceLanguage(), 'html' => $html); }
/** * Adds stable version tags to page when editing */ public function addToEditView(EditPage $editPage) { global $wgParser; $reqUser = $this->getUser(); $this->load(); # Must be reviewable. UI may be limited to unobtrusive patrolling system. if (!$this->article->isReviewable()) { return true; } $items = array(); # Show stabilization log $log = $this->stabilityLogNotice(); if ($log) { $items[] = $log; } # Check the newest stable version $frev = $this->article->getStableRev(); if ($frev) { $quality = $frev->getQuality(); # Find out revision id of base version $latestId = $this->article->getLatest(); $revId = $editPage->oldid ? $editPage->oldid : $latestId; # Let users know if their edit will have to be reviewed. # Note: if the log excerpt was shown then this is redundant. if (!$log && $this->editWillRequireReview($editPage)) { $items[] = wfMsgExt('revreview-editnotice', 'parseinline'); } # Add a notice if there are pending edits... if ($this->article->revsArePending()) { $revsSince = $this->article->getPendingRevCount(); $items[] = FlaggedRevsXML::pendingEditNotice($this->article, $frev, $revsSince); } # Show diff to stable, to make things less confusing. # This can be disabled via user preferences and other conditions... if ($frev->getRevId() < $latestId && $reqUser->getBoolOption('flaggedrevseditdiffs') && $revId == $latestId && $editPage->section != 'new' && $editPage->formtype != 'diff') { # Left diff side... $leftNote = $quality ? 'revreview-hist-quality' : 'revreview-hist-basic'; $lClass = FlaggedRevsXML::getQualityColor((int) $quality); $leftNote = "<span class='{$lClass}'>[" . wfMsgHtml($leftNote) . "]</span>"; # Right diff side... $rClass = FlaggedRevsXML::getQualityColor(false); $rightNote = "<span class='{$rClass}'>[" . wfMsgHtml('revreview-hist-pending') . "]</span>"; # Get the stable version source $text = $frev->getRevText(); # Are we editing a section? $section = $editPage->section == "" ? false : intval($editPage->section); if ($section !== false) { $text = $wgParser->getSection($text, $section); } if ($text !== false && strcmp($text, $editPage->textbox1) !== 0) { $diffEngine = new DifferenceEngine($this->article->getTitle()); $diffBody = $diffEngine->generateDiffBody($text, $editPage->textbox1); $diffHtml = wfMsgExt('review-edit-diff', 'parseinline') . ' ' . FlaggedRevsXML::diffToggle() . "<div id='mw-fr-stablediff'>" . self::getFormattedDiff($diffBody, '', $leftNote, $rightNote) . "</div>\n"; $items[] = $diffHtml; $diffEngine->showDiffStyle(); // add CSS } } # Output items if (count($items)) { $html = "<table class='flaggedrevs_editnotice plainlinks'>"; foreach ($items as $item) { $html .= '<tr><td>' . $item . '</td></tr>'; } $html .= '</table>'; $this->out->addHTML($html); } } return true; }
function makeADifference($text, $title, $section) { global $wgOut; /* make an article object */ $rtitle = Title::newFromText($title); $rarticle = new Article($rtitle, $rtitle->getArticleID()); $epage = new EditPage($rarticle); $epage->section = $section; /* customized getDiff from EditPage */ $oldtext = $epage->mArticle->fetchContent(); $edittime = $epage->mArticle->getTimestamp(); $newtext = $epage->mArticle->replaceSection($section, $text, '', $edittime); $newtext = $epage->mArticle->preSaveTransform($newtext); $oldtitle = wfMsgExt('currentrev', array('parseinline')); $newtitle = wfMsgExt('yourtext', array('parseinline')); if ($oldtext !== false || $newtext != '') { $de = new DifferenceEngine($epage->mTitle); $de->setText($oldtext, $newtext); $difftext = $de->getDiff($oldtitle, $newtitle); } else { $difftext = ''; } $diffdiv = '<div id="wikiDiff">' . $difftext . '</div>'; $wgOut->addHTML($diffdiv); }
/** * Replace entire showEditForm, need to add our own textbox and stuff */ function showEditForm($formCallback = null) { global $wgOut, $wgUser, $wgLang, $wgContLang, $wgMaxArticleSize, $wgTitle, $wgRequest; # If $wgTitle is null, that means we're in API mode. # Some hook probably called this function without checking # for is_null($wgTitle) first. Bail out right here so we don't # do lots of work just to discard it right after. if (is_null($wgTitle)) { return; } $fname = 'EditPage::showEditForm'; wfProfileIn($fname); $sk = $wgUser->getSkin(); wfRunHooks('EditPage::showEditForm:initial', array(&$this)); #need to parse the preview early so that we know which templates are used, #otherwise users with "show preview after edit box" will get a blank list #we parse this near the beginning so that setHeaders can do the title #setting work instead of leaving it in getPreviewText $previewOutput = ''; if ($this->formtype == 'preview') { $previewOutput = $this->getPreviewText(); } $this->setHeaders(); # Enabled article-related sidebar, toplinks, etc. $wgOut->setArticleRelated(true); if ($this->isConflict) { $wgOut->wrapWikiMsg("<div class='mw-explainconflict'>\n\$1</div>", 'explainconflict'); $this->textbox2 = $this->textbox1; $this->textbox1 = $this->getContent(); $this->edittime = $this->mArticle->getTimestamp(); # MeanEditor: too complicated for visual editing $this->noVisualEditor = false; } else { if ($this->section != '' && $this->section != 'new') { $matches = array(); if (!$this->summary && !$this->preview && !$this->diff) { preg_match("/^(=+)(.+)\\1/mi", $this->textbox1, $matches); if (!empty($matches[2])) { global $wgParser; $this->summary = "/* " . $wgParser->stripSectionName(trim($matches[2])) . " */ "; } } } if ($this->missingComment) { $wgOut->wrapWikiMsg('<div id="mw-missingcommenttext">$1</div>', 'missingcommenttext'); } if ($this->missingSummary && $this->section != 'new') { $wgOut->wrapWikiMsg('<div id="mw-missingsummary">$1</div>', 'missingsummary'); } if ($this->missingSummary && $this->section == 'new') { $wgOut->wrapWikiMsg('<div id="mw-missingcommentheader">$1</div>', 'missingcommentheader'); } if ($this->hookError !== '') { $wgOut->addWikiText($this->hookError); } if (!$this->checkUnicodeCompliantBrowser()) { $wgOut->addWikiMsg('nonunicodebrowser'); } if (isset($this->mArticle) && isset($this->mArticle->mRevision)) { // Let sysop know that this will make private content public if saved if (!$this->mArticle->mRevision->userCan(Revision::DELETED_TEXT)) { $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-permission'); } else { if ($this->mArticle->mRevision->isDeleted(Revision::DELETED_TEXT)) { $wgOut->wrapWikiMsg("<div class='mw-warning plainlinks'>\n\$1</div>\n", 'rev-deleted-text-view'); } } if (!$this->mArticle->mRevision->isCurrent()) { $this->mArticle->setOldSubtitle($this->mArticle->mRevision->getId()); $wgOut->addWikiMsg('editingold'); } } } if (wfReadOnly()) { $wgOut->wrapWikiMsg("<div id=\"mw-read-only-warning\">\n\$1\n</div>", array('readonlywarning', wfReadOnlyReason())); # MeanEditor: visual editing makes no sense here $this->noVisualEditor = true; } elseif ($wgUser->isAnon() && $this->formtype != 'preview') { $wgOut->wrapWikiMsg('<div id="mw-anon-edit-warning">$1</div>', 'anoneditwarning'); } else { if ($this->isCssJsSubpage) { # Check the skin exists if ($this->isValidCssJsSubpage) { if ($this->formtype !== 'preview') { $wgOut->addWikiMsg('usercssjsyoucanpreview'); } } else { $wgOut->addWikiMsg('userinvalidcssjstitle', $wgTitle->getSkinFromCssJsSubpage()); } } } $classes = array(); // Textarea CSS if ($this->mTitle->getNamespace() == NS_MEDIAWIKI) { } elseif ($this->mTitle->isProtected('edit')) { # Is the title semi-protected? if ($this->mTitle->isSemiProtected()) { $noticeMsg = 'semiprotectedpagewarning'; $classes[] = 'mw-textarea-sprotected'; } else { # Then it must be protected based on static groups (regular) $noticeMsg = 'protectedpagewarning'; $classes[] = 'mw-textarea-protected'; } $wgOut->addHTML("<div class='mw-warning-with-logexcerpt'>\n"); $wgOut->addWikiMsg($noticeMsg); LogEventsList::showLogExtract($wgOut, 'protect', $this->mTitle->getPrefixedText(), '', 1); $wgOut->addHTML("</div>\n"); } if ($this->mTitle->isCascadeProtected()) { # Is this page under cascading protection from some source pages? list($cascadeSources, ) = $this->mTitle->getCascadeProtectionSources(); $notice = "<div class='mw-cascadeprotectedwarning'>\$1\n"; $cascadeSourcesCount = count($cascadeSources); if ($cascadeSourcesCount > 0) { # Explain, and list the titles responsible foreach ($cascadeSources as $page) { $notice .= '* [[:' . $page->getPrefixedText() . "]]\n"; } } $notice .= '</div>'; $wgOut->wrapWikiMsg($notice, array('cascadeprotectedwarning', $cascadeSourcesCount)); } if (!$this->mTitle->exists() && $this->mTitle->getRestrictions('create')) { $wgOut->wrapWikiMsg('<div class="mw-titleprotectedwarning">$1</div>', 'titleprotectedwarning'); } if ($this->kblength === false) { # MeanEditor: the length will probably be different in HTML $this->kblength = (int) (strlen($this->textbox1) / 1024); } if ($this->tooBig || $this->kblength > $wgMaxArticleSize) { $wgOut->addHTML("<div class='error' id='mw-edit-longpageerror'>\n"); $wgOut->addWikiMsg('longpageerror', $wgLang->formatNum($this->kblength), $wgLang->formatNum($wgMaxArticleSize)); $wgOut->addHTML("</div>\n"); } elseif ($this->kblength > 29) { $wgOut->addHTML("<div id='mw-edit-longpagewarning'>\n"); $wgOut->addWikiMsg('longpagewarning', $wgLang->formatNum($this->kblength)); $wgOut->addHTML("</div>\n"); } $q = 'action=' . $this->action; #if ( "no" == $redirect ) { $q .= "&redirect=no"; } $action = $wgTitle->escapeLocalURL($q); $summary = wfMsg('summary'); $subject = wfMsg('subject'); $cancel = $sk->makeKnownLink($wgTitle->getPrefixedText(), wfMsgExt('cancel', array('parseinline'))); $separator = wfMsgExt('pipe-separator', 'escapenoentities'); $edithelpurl = Skin::makeInternalOrExternalUrl(wfMsgForContent('edithelppage')); $edithelp = '<a target="helpwindow" href="' . $edithelpurl . '">' . htmlspecialchars(wfMsg('edithelp')) . '</a> ' . htmlspecialchars(wfMsg('newwindow')); global $wgRightsText; if ($wgRightsText) { $copywarnMsg = array('copyrightwarning', '[[' . wfMsgForContent('copyrightpage') . ']]', $wgRightsText); } else { $copywarnMsg = array('copyrightwarning2', '[[' . wfMsgForContent('copyrightpage') . ']]'); } /* MeanEditor: always disable the toolbar */ if ($wgUser->getOption('showtoolbar') and !$this->isCssJsSubpage) { # prepare toolbar for edit buttons $toolbar = ''; } else { $toolbar = ''; } // activate checkboxes if user wants them to be always active if (!$this->preview && !$this->diff) { # Sort out the "watch" checkbox if ($wgUser->getOption('watchdefault')) { # Watch all edits $this->watchthis = true; } elseif ($wgUser->getOption('watchcreations') && !$this->mTitle->exists()) { # Watch creations $this->watchthis = true; } elseif ($this->mTitle->userIsWatching()) { # Already watched $this->watchthis = true; } # May be overriden by request parameters if ($wgRequest->getBool('watchthis')) { $this->watchthis = true; } if ($wgUser->getOption('minordefault')) { $this->minoredit = true; } # MeanEditor: User preference if ($wgUser->getOption('prefer_traditional_editor')) { $this->userWantsTraditionalEditor = true; } } $wgOut->addHTML($this->editFormPageTop); if ($wgUser->getOption('previewontop')) { $this->displayPreviewArea($previewOutput, true); } $wgOut->addHTML($this->editFormTextTop); # if this is a comment, show a subject line at the top, which is also the edit summary. # Otherwise, show a summary field at the bottom $summarytext = $wgContLang->recodeForEdit($this->summary); # If a blank edit summary was previously provided, and the appropriate # user preference is active, pass a hidden tag as wpIgnoreBlankSummary. This will stop the # user being bounced back more than once in the event that a summary # is not required. ##### # For a bit more sophisticated detection of blank summaries, hash the # automatic one and pass that in the hidden field wpAutoSummary. $summaryhiddens = ''; if ($this->missingSummary) { $summaryhiddens .= Xml::hidden('wpIgnoreBlankSummary', true); } $autosumm = $this->autoSumm ? $this->autoSumm : md5($this->summary); $summaryhiddens .= Xml::hidden('wpAutoSummary', $autosumm); if ($this->section == 'new') { $commentsubject = ''; if (!$wgRequest->getBool('nosummary')) { # Add a class if 'missingsummary' is triggered to allow styling of the summary line $summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary'; $commentsubject = Xml::tags('label', array('for' => 'wpSummary'), $subject); $commentsubject = Xml::tags('span', array('class' => $summaryClass, 'id' => "wpSummaryLabel"), $commentsubject); $commentsubject .= ' '; $commentsubject .= Xml::input('wpSummary', 60, $summarytext, array('id' => 'wpSummary', 'maxlength' => '200', 'tabindex' => '1')); } $editsummary = "<div class='editOptions'>\n"; global $wgParser; $formattedSummary = wfMsgForContent('newsectionsummary', $wgParser->stripSectionName($this->summary)); $subjectpreview = $summarytext && $this->preview ? "<div class=\"mw-summary-preview\">" . wfMsg('subject-preview') . $sk->commentBlock($formattedSummary, $this->mTitle, true) . "</div>\n" : ''; $summarypreview = ''; } else { $commentsubject = ''; # Add a class if 'missingsummary' is triggered to allow styling of the summary line $summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary'; $editsummary = Xml::tags('label', array('for' => 'wpSummary'), $summary); $editsummary = Xml::tags('span', array('class' => $summaryClass, 'id' => "wpSummaryLabel"), $editsummary) . ' '; $editsummary .= Xml::input('wpSummary', 60, $summarytext, array('id' => 'wpSummary', 'maxlength' => '200', 'tabindex' => '1')); // No idea where this is closed. $editsummary = Xml::openElement('div', array('class' => 'editOptions')) . $editsummary . '<br/>'; $summarypreview = ''; if ($summarytext && $this->preview) { $summarypreview = Xml::tags('div', array('class' => 'mw-summary-preview'), wfMsg('summary-preview') . $sk->commentBlock($this->summary, $this->mTitle)); } $subjectpreview = ''; } $commentsubject .= $summaryhiddens; # Set focus to the edit box on load, except on preview or diff, where it would interfere with the display if (!$this->preview && !$this->diff) { $wgOut->setOnloadHandler('document.editform.wpTextbox1.focus()'); } $templates = $this->getTemplates(); $formattedtemplates = $sk->formatTemplates($templates, $this->preview, $this->section != ''); $hiddencats = $this->mArticle->getHiddenCategories(); $formattedhiddencats = $sk->formatHiddenCategories($hiddencats); global $wgUseMetadataEdit; if ($wgUseMetadataEdit) { $metadata = $this->mMetaData; $metadata = htmlspecialchars($wgContLang->recodeForEdit($metadata)); $top = wfMsgWikiHtml('metadata_help'); /* ToDo: Replace with clean code */ $ew = $wgUser->getOption('editwidth'); if ($ew) { $ew = " style=\"width:100%\""; } else { $ew = ''; } $cols = $wgUser->getIntOption('cols'); /* /ToDo */ $metadata = $top . "<textarea name='metadata' rows='3' cols='{$cols}'{$ew}>{$metadata}</textarea>"; } else { $metadata = ""; } $recreate = ''; if ($this->wasDeletedSinceLastEdit()) { if ('save' != $this->formtype) { $wgOut->wrapWikiMsg("<div class='error mw-deleted-while-editing'>\n\$1</div>", 'deletedwhileediting'); } else { // Hide the toolbar and edit area, user can click preview to get it back // Add an confirmation checkbox and explanation. $toolbar = ''; $recreate = '<div class="mw-confirm-recreate">' . $wgOut->parse(wfMsg('confirmrecreate', $this->lastDelete->user_name, $this->lastDelete->log_comment)) . Xml::checkLabel(wfMsg('recreate'), 'wpRecreate', 'wpRecreate', false, array('title' => $sk->titleAttrib('recreate'), 'tabindex' => 1, 'id' => 'wpRecreate')) . '</div>'; } } $tabindex = 2; $checkboxes = $this->getCheckboxes($tabindex, $sk, array('minor' => $this->minoredit, 'watch' => $this->watchthis, 'want_traditional_editor' => $this->userWantsTraditionalEditor)); $checkboxhtml = implode($checkboxes, "\n"); $buttons = $this->getEditButtons($tabindex); $buttonshtml = implode($buttons, "\n"); $safemodehtml = $this->checkUnicodeCompliantBrowser() ? '' : Xml::hidden('safemode', '1'); $wgOut->addHTML(<<<END {$toolbar} <form id="editform" name="editform" method="post" action="{$action}" enctype="multipart/form-data"> END ); if (is_callable($formCallback)) { call_user_func_array($formCallback, array(&$wgOut)); } wfRunHooks('EditPage::showEditForm:fields', array(&$this, &$wgOut)); // Put these up at the top to ensure they aren't lost on early form submission $this->showFormBeforeText(); $wgOut->addHTML(<<<END {$recreate} {$commentsubject} {$subjectpreview} {$this->editFormTextBeforeContent} END ); if ($this->isConflict || $this->diff) { # MeanEditor: should be redundant, but let's be sure $this->noVisualEditor = true; } # MeanEditor: also apply htmlspecialchars? See $encodedtext $html_text = $this->safeUnicodeOutput($this->textbox1); if (!($this->noVisualEditor || $this->userWantsTraditionalEditor)) { $this->noVisualEditor = wfRunHooks('EditPage::wiki2html', array($this->mArticle, $wgUser, &$this, &$html_text)); } if (!$this->noVisualEditor && !$this->userWantsTraditionalEditor) { $this->noVisualEditor = wfRunHooks('EditPage::showBox', array(&$this, $html_text, $rows, $cols, $ew)); } if (!$this->noVisualEditor && !$this->userWantsTraditionalEditor) { $wgOut->addHTML("<input type='hidden' value=\"0\" name=\"wpNoVisualEditor\" />\n"); } else { $wgOut->addHTML("<input type='hidden' value=\"1\" name=\"wpNoVisualEditor\" />\n"); $this->showTextbox1($classes); } $wgOut->wrapWikiMsg("<div id=\"editpage-copywarn\">\n\$1\n</div>", $copywarnMsg); $wgOut->addHTML(<<<END {$this->editFormTextAfterWarn} {$metadata} {$editsummary} {$summarypreview} {$checkboxhtml} {$safemodehtml} END ); $wgOut->addHTML("<div class='editButtons'>\n{$buttonshtml}\n\t<span class='editHelp'>{$cancel}{$separator}{$edithelp}</span>\n</div><!-- editButtons -->\n</div><!-- editOptions -->"); /** * To make it harder for someone to slip a user a page * which submits an edit form to the wiki without their * knowledge, a random token is associated with the login * session. If it's not passed back with the submission, * we won't save the page, or render user JavaScript and * CSS previews. * * For anon editors, who may not have a session, we just * include the constant suffix to prevent editing from * broken text-mangling proxies. */ $token = htmlspecialchars($wgUser->editToken()); $wgOut->addHTML("\n<input type='hidden' value=\"{$token}\" name=\"wpEditToken\" />\n"); $this->showEditTools(); $wgOut->addHTML(<<<END {$this->editFormTextAfterTools} <div class='templatesUsed'> {$formattedtemplates} </div> <div class='hiddencats'> {$formattedhiddencats} </div> END ); if ($this->isConflict && wfRunHooks('EditPageBeforeConflictDiff', array(&$this, &$wgOut))) { $wgOut->wrapWikiMsg('==$1==', "yourdiff"); $de = new DifferenceEngine($this->mTitle); $de->setText($this->textbox2, $this->textbox1); $de->showDiff(wfMsg("yourtext"), wfMsg("storedversion")); $wgOut->wrapWikiMsg('==$1==', "yourtext"); $this->showTextbox2(); } $wgOut->addHTML($this->editFormTextBottom); $wgOut->addHTML("</form>\n"); if (!$wgUser->getOption('previewontop')) { $this->displayPreviewArea($previewOutput, false); } wfProfileOut($fname); }
/** * User interface for rollback operations */ public function rollback() { global $wgUser, $wgOut, $wgRequest; $details = null; $result = $this->doRollback($wgRequest->getVal('from'), $wgRequest->getText('summary'), $wgRequest->getVal('token'), $wgRequest->getBool('bot'), $details); if (in_array(array('actionthrottledtext'), $result)) { $wgOut->rateLimited(); return; } if (isset($result[0][0]) && ($result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback')) { $wgOut->setPageTitle(wfMsg('rollbackfailed')); $errArray = $result[0]; $errMsg = array_shift($errArray); $wgOut->addWikiMsgArray($errMsg, $errArray); if (isset($details['current'])) { $current = $details['current']; if ($current->getComment() != '') { $wgOut->addWikiMsgArray('editcomment', array($wgUser->getSkin()->formatComment($current->getComment())), array('replaceafter')); } } return; } # Display permissions errors before read-only message -- there's no # point in misleading the user into thinking the inability to rollback # is only temporary. if (!empty($result) && $result !== array(array('readonlytext'))) { # array_diff is completely broken for arrays of arrays, sigh. # Remove any 'readonlytext' error manually. $out = array(); foreach ($result as $error) { if ($error != array('readonlytext')) { $out[] = $error; } } $wgOut->showPermissionsErrorPage($out); return; } if ($result == array(array('readonlytext'))) { $wgOut->readOnlyPage(); return; } $current = $details['current']; $target = $details['target']; $newId = $details['newid']; $wgOut->setPageTitle(wfMsg('actioncomplete')); $wgOut->setRobotPolicy('noindex,nofollow'); if ($current->getUserText() === '') { $old = wfMsg('rev-deleted-user'); } else { $old = $wgUser->getSkin()->userLink($current->getUser(), $current->getUserText()) . $wgUser->getSkin()->userToolLinks($current->getUser(), $current->getUserText()); } $new = $wgUser->getSkin()->userLink($target->getUser(), $target->getUserText()) . $wgUser->getSkin()->userToolLinks($target->getUser(), $target->getUserText()); $wgOut->addHTML(wfMsgExt('rollback-success', array('parse', 'replaceafter'), $old, $new)); $wgOut->returnToMain(false, $this->mTitle); if (!$wgRequest->getBool('hidediff', false) && !$wgUser->getBoolOption('norollbackdiff', false)) { $de = new DifferenceEngine($this->mTitle, $current->getId(), $newId, false, true); $de->showDiff('', ''); } }
private function extractRowInfo($row) { $revision = new Revision($row); $title = $revision->getTitle(); $vals = array(); if ($this->fld_ids) { $vals['revid'] = intval($revision->getId()); // $vals['oldid'] = intval( $row->rev_text_id ); // todo: should this be exposed? if (!is_null($revision->getParentId())) { $vals['parentid'] = intval($revision->getParentId()); } } if ($this->fld_flags && $revision->isMinor()) { $vals['minor'] = ''; } if ($this->fld_user || $this->fld_userid) { if ($revision->isDeleted(Revision::DELETED_USER)) { $vals['userhidden'] = ''; } else { if ($this->fld_user) { $vals['user'] = $revision->getUserText(); } $userid = $revision->getUser(); if (!$userid) { $vals['anon'] = ''; } if ($this->fld_userid) { $vals['userid'] = $userid; } } } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $revision->getTimestamp()); } if ($this->fld_size) { if (!is_null($revision->getSize())) { $vals['size'] = intval($revision->getSize()); } else { $vals['size'] = 0; } } if ($this->fld_sha1) { if ($revision->getSha1() != '') { $vals['sha1'] = wfBaseConvert($revision->getSha1(), 36, 16, 40); } else { $vals['sha1'] = ''; } } if ($this->fld_comment || $this->fld_parsedcomment) { if ($revision->isDeleted(Revision::DELETED_COMMENT)) { $vals['commenthidden'] = ''; } else { $comment = $revision->getComment(); if ($this->fld_comment) { $vals['comment'] = $comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($comment, $title); } } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); $this->getResult()->setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if (!is_null($this->token)) { $tokenFunctions = $this->getTokenFunctions(); foreach ($this->token as $t) { $val = call_user_func($tokenFunctions[$t], $title->getArticleID(), $title, $revision); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $vals[$t . 'token'] = $val; } } } $text = null; global $wgParser; if ($this->fld_content || !is_null($this->difftotext)) { $text = $revision->getText(); // Expand templates after getting section content because // template-added sections don't count and Parser::preprocess() // will have less input if ($this->section !== false) { $text = $wgParser->getSection($text, $this->section, false); if ($text === false) { $this->dieUsage("There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection'); } } } if ($this->fld_content && !$revision->isDeleted(Revision::DELETED_TEXT)) { if ($this->generateXML) { $wgParser->startExternalParse($title, ParserOptions::newFromContext($this->getContext()), OT_PREPROCESS); $dom = $wgParser->preprocessToDom($text); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $vals['parsetree'] = $xml; } if ($this->expandTemplates && !$this->parseContent) { $text = $wgParser->preprocess($text, $title, ParserOptions::newFromContext($this->getContext())); } if ($this->parseContent) { $text = $wgParser->parse($text, $title, ParserOptions::newFromContext($this->getContext()))->getText(); } ApiResult::setContent($vals, $text); } elseif ($this->fld_content) { $vals['texthidden'] = ''; } if (!is_null($this->diffto) || !is_null($this->difftotext)) { global $wgAPIMaxUncachedDiffs; static $n = 0; // Number of uncached diffs we've had if ($n < $wgAPIMaxUncachedDiffs) { $vals['diff'] = array(); $context = new DerivativeContext($this->getContext()); $context->setTitle($title); if (!is_null($this->difftotext)) { $engine = new DifferenceEngine($context); $engine->setText($text, $this->difftotext); } else { $engine = new DifferenceEngine($context, $revision->getID(), $this->diffto); $vals['diff']['from'] = $engine->getOldid(); $vals['diff']['to'] = $engine->getNewid(); } $difftext = $engine->getDiffBody(); ApiResult::setContent($vals['diff'], $difftext); if (!$engine->wasCacheHit()) { $n++; } } else { $vals['diff']['notcached'] = ''; } } return $vals; }
function perform($bPerformEdits = true) { global $wgRequest, $wgOut, $wgUser, $wgTitle, $wgLang; $iMaxPerCriterion = $bPerformEdits ? MER_MAX_EXECUTE_PAGES : MER_MAX_PREVIEW_DIFFS; $aErrors = array(); $aPages = $this->getPages($aErrors, $iMaxPerCriterion); if ($aPages === null) { $this->showForm(wfMsg('masseditregex-err-nopages')); return; } // Show the form again ready for further editing if we're just previewing if (!$bPerformEdits) { $this->showForm(); } $diff = new DifferenceEngine(); $diff->showDiffStyle(); // send CSS link to the browser for diff colours $wgOut->addHTML('<ul>'); if (count($aErrors)) { $wgOut->addHTML('<li>' . join('</li><li> ', $aErrors) . '</li>'); } $htmlDiff = ''; $editToken = $wgUser->editToken(); $iArticleCount = 0; foreach ($aPages as $p) { $iArticleCount++; if (!isset($p['revisions'])) { $wgOut->addHTML('<li>' . wfMsg('masseditregex-page-not-exists', $p['title']) . '</li>'); continue; // empty page } $curContent = $p['revisions'][0]['*']; $iCount = 0; $newContent = $curContent; foreach ($this->aMatch as $i => $strMatch) { $this->strNextReplace = $this->aReplace[$i]; $result = @preg_replace_callback($strMatch, array($this, 'regexCallback'), $newContent, -1, $iCount); if ($result !== null) { $newContent = $result; } else { $strErrorMsg = '<li>' . wfMsg('masseditregex-badregex') . ' <b>' . htmlspecialchars($strMatch) . '</b></li>'; $wgOut->addHTML($strErrorMsg); unset($this->aMatch[$i]); } } if ($bPerformEdits) { // Not in preview mode, make the edits $wgOut->addHTML('<li>' . wfMsg('masseditregex-num-changes', $p['title'], $iCount) . '</li>'); $req = new DerivativeRequest($wgRequest, array('action' => 'edit', 'bot' => true, 'title' => $p['title'], 'summary' => $this->strSummary, 'text' => $newContent, 'basetimestamp' => $p['starttimestamp'], 'watchlist' => 'nochange', 'nocreate' => 1, 'token' => $editToken), true); $processor = new ApiMain($req, true); try { $processor->execute(); } catch (UsageException $e) { $wgOut->addHTML('<li><ul><li>' . wfMsg('masseditregex-editfailed') . ' ' . $e . '</li></ul></li>'); } } else { // In preview mode, display the first few diffs $diff->setText($curContent, $newContent); $htmlDiff .= $diff->getDiff('<b>' . $p['title'] . ' - ' . wfMsg('masseditregex-before') . '</b>', '<b>' . wfMsg('masseditregex-after') . '</b>'); if ($iArticleCount >= MER_MAX_PREVIEW_DIFFS) { $htmlDiff .= Xml::element('p', null, wfMsg('masseditregex-max-preview-diffs', $wgLang->formatNum(MER_MAX_PREVIEW_DIFFS))); break; } } } $wgOut->addHTML('</ul>'); if ($bPerformEdits) { $wgOut->addWikiMsg('masseditregex-num-articles-changed', $iArticleCount); $wgOut->addHTML($this->sk->makeKnownLinkObj(SpecialPage::getSafeTitleFor('Contributions', $wgUser->getName()), wfMsgHtml('masseditregex-view-full-summary'))); } else { // Only previewing, show the diffs now (after any errors) $wgOut->addHTML($htmlDiff); } }
/** * Show "your edit contains spam" page with your diff and text * * @param $match Text which triggered one or more filters */ public function spamPageWithContent($match = false) { global $wgOut; $this->textbox2 = $this->textbox1; $wgOut->prepareErrorPage(wfMessage('spamprotectiontitle')); $wgOut->addHTML('<div id="spamprotected">'); $wgOut->addWikiMsg('spamprotectiontext'); if ($match) { $wgOut->addWikiMsg('spamprotectionmatch', wfEscapeWikiText($match)); } $wgOut->addHTML('</div>'); $wgOut->wrapWikiMsg('<h2>$1</h2>', "yourdiff"); $de = new DifferenceEngine($this->mArticle->getContext()); $de->setText($this->getCurrentText(), $this->textbox2); $de->showDiff(wfMsg("storedversion"), wfMsgExt('yourtext', 'parseinline')); $wgOut->wrapWikiMsg('<h2>$1</h2>', "yourtext"); $this->showTextbox2(); $wgOut->addReturnTo($this->getContextTitle(), array('action' => 'edit')); }
public function execute( $messages ) { global $wgOut, $wgLang; $this->out = $wgOut; // Set up diff engine $diff = new DifferenceEngine; $diff->showDiffStyle(); $diff->setReducedLineNumbers(); // Check whether we do processing $process = $this->allowProcess(); // Initialise collection $group = $this->getGroup(); $code = $this->getCode(); $collection = $group->initCollection( $code ); $collection->loadTranslations(); $this->out->addHTML( $this->doHeader() ); // Determine changes $alldone = $process; $changed = array(); foreach ( $messages as $key => $value ) { $fuzzy = $old = false; if ( isset( $collection[$key] ) ) { $old = $collection[$key]->translation(); } // No changes at all, ignore if ( strval( $old ) === strval( $value ) ) { continue; } if ( $old === false ) { $name = wfMsgHtml( 'translate-manage-import-new', '<code style="font-weight:normal;">' . htmlspecialchars( $key ) . '</code>' ); $text = TranslateUtils::convertWhiteSpaceToHTML( $value ); $changed[] = self::makeSectionElement( $name, 'new', $text ); } else { $diff->setText( $old, $value ); $text = $diff->getDiff( '', '' ); $type = 'changed'; global $wgRequest; $action = $wgRequest->getVal( self::escapeNameForPHP( "action-$type-$key" ) ); if ( $process ) { if ( !count( $changed ) ) { $changed[] = '<ul>'; } if ( $action === null ) { $message = wfMsgExt( 'translate-manage-inconsistent', 'parseinline', wfEscapeWikiText( "action-$type-$key" ) ); $changed[] = "<li>$message</li></ul>"; $process = false; } else { // Check processing time if ( !isset( $this->time ) ) { $this->time = wfTimestamp(); } $message = self::doAction( $action, $group, $key, $code, $value ); $key = array_shift( $message ); $params = $message; $message = wfMsgExt( $key, 'parseinline', $params ); $changed[] = "<li>$message</li>"; if ( $this->checkProcessTime() ) { $process = false; $duration = $wgLang->formatNum( $this->processingTime ); $message = wfMsgExt( 'translate-manage-toolong', 'parseinline', $duration ); $changed[] = "<li>$message</li></ul>"; } continue; } } $alldone = false; $actions = $this->getActions(); $defaction = $this->getDefaultAction( $fuzzy, $action ); $act = array(); foreach ( $actions as $action ) { $label = wfMsg( "translate-manage-action-$action" ); $name = self::escapeNameForPHP( "action-$type-$key" ); $id = Sanitizer::escapeId( "action-$key-$action" ); $act[] = Xml::radioLabel( $label, $name, $action, $id, $action === $defaction ); } $name = wfMsg( 'translate-manage-import-diff', '<code style="font-weight:normal;">' . htmlspecialchars( $key ) . '</code>', implode( ' ', $act ) ); $changed[] = self::makeSectionElement( $name, $type, $text ); } } if ( !$process ) { $collection->filter( 'hastranslation', false ); $keys = $collection->getMessageKeys(); $diff = array_diff( $keys, array_keys( $messages ) ); foreach ( $diff as $s ) { // @todo FIXME: Use CSS file. $name = wfMsgHtml( 'translate-manage-import-deleted', '<code style="font-weight:normal;">' . htmlspecialchars( $s ) . '</code>' ); $text = TranslateUtils::convertWhiteSpaceToHTML( $collection[$s]->translation() ); $changed[] = self::makeSectionElement( $name, 'deleted', $text ); } } if ( $process || ( !count( $changed ) && $code !== 'en' ) ) { if ( !count( $changed ) ) { $this->out->addWikiMsg( 'translate-manage-nochanges-other' ); } if ( !count( $changed ) || strpos( $changed[count( $changed ) - 1], '<li>' ) !== 0 ) { $changed[] = '<ul>'; } $message = wfMsgExt( 'translate-manage-import-done', 'parseinline' ); $changed[] = "<li>$message</li></ul>"; $this->out->addHTML( implode( "\n", $changed ) ); } else { // END if ( count( $changed ) ) { if ( $code === 'en' ) { $this->out->addWikiMsg( 'translate-manage-intro-en' ); } else { $lang = TranslateUtils::getLanguageName( $code, false, $wgLang->getCode() ); $this->out->addWikiMsg( 'translate-manage-intro-other', $lang ); } $this->out->addHTML( Html::hidden( 'language', $code ) ); $this->out->addHTML( implode( "\n", $changed ) ); $this->out->addHTML( Xml::submitButton( wfMsg( 'translate-manage-submit' ) ) ); } else { $this->out->addWikiMsg( 'translate-manage-nochanges' ); } } $this->out->addHTML( $this->doFooter() ); return $alldone; }
/** * DiffViewHeader hook handler * @see https://www.mediawiki.org/wiki/Manual:Hooks/DiffViewHeader * * Redirect Diff page to mobile version if appropriate * * @param DifferenceEngine $diff DifferenceEngine object that's calling * @param Revision $oldRev Revision object of the "old" revision (may be null/invalid) * @param Revision $newRev Revision object of the "new" revision * @return bool */ public static function onDiffViewHeader($diff, $oldRev, $newRev) { $context = MobileContext::singleton(); // Only do redirects to MobileDiff if user is in mobile view and it's not a special page if ($context->shouldDisplayMobileView() && !$diff->getContext()->getTitle()->isSpecialPage()) { $output = $context->getOutput(); $newRevId = $newRev->getId(); // The MobileDiff page currently only supports showing a single revision, so // only redirect to MobileDiff if we are sure this isn't a multi-revision diff. if ($oldRev) { // Get the revision immediately before the new revision $prevRev = $newRev->getPrevious(); if ($prevRev) { $prevRevId = $prevRev->getId(); $oldRevId = $oldRev->getId(); if ($prevRevId === $oldRevId) { $output->redirect(SpecialPage::getTitleFor('MobileDiff', $newRevId)->getFullURL()); } } } else { $output->redirect(SpecialPage::getTitleFor('MobileDiff', $newRevId)->getFullURL()); } } return true; }
public function writeDiff(&$dbr, $target) { global $wgOut, $wgUser; $wgOut->addHTML("<table width='100%' align='center' class='bunchtable'><tr>"); $opts = array('rc_user_text' => $target); $opts[] = ' (rc_namespace = 0) '; $res = $dbr->select('recentchanges', array('rc_id', 'rc_title', 'rc_namespace', 'rc_this_oldid', 'rc_cur_id', 'rc_last_oldid'), $opts, __METHOD__, array('LIMIT' => 15)); $count = 0; foreach ($res as $row) { $t = Title::makeTitle($row->rc_namespace, $row->rc_title); $diff = $row->rc_this_oldid; $rcid = $row->rc_id; $oldid = $row->rc_last_oldid; $de = new DifferenceEngine($t, $oldid, $diff, $rcid); $wgOut->addHTML("<tr>"); $wgOut->addHTML("<td>"); $wgOut->addHTML($wgUser->getSkin()->makeLinkObj($t)); $de->showDiffPage(true); $wgOut->addHTML("</td></tr>"); $count++; } $dbr->freeResult($res); $wgOut->addHTML("</table><br/><br/>"); return $count; }
public function onView() { $details = null; $request = $this->getRequest(); $result = $this->page->doRollback($request->getVal('from'), $request->getText('summary'), $request->getVal('token'), $request->getBool('bot'), $details, $this->getUser()); if (in_array(array('actionthrottledtext'), $result)) { throw new ThrottledError(); } if (isset($result[0][0]) && ($result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback')) { $this->getOutput()->setPageTitle($this->msg('rollbackfailed')); $errArray = $result[0]; $errMsg = array_shift($errArray); $this->getOutput()->addWikiMsgArray($errMsg, $errArray); if (isset($details['current'])) { $current = $details['current']; if ($current->getComment() != '') { $this->getOutput()->addHTML($this->msg('editcomment')->rawParams(Linker::formatComment($current->getComment()))->parse()); } } return; } # Display permissions errors before read-only message -- there's no # point in misleading the user into thinking the inability to rollback # is only temporary. if (!empty($result) && $result !== array(array('readonlytext'))) { # array_diff is completely broken for arrays of arrays, sigh. # Remove any 'readonlytext' error manually. $out = array(); foreach ($result as $error) { if ($error != array('readonlytext')) { $out[] = $error; } } throw new PermissionsError('rollback', $out); } if ($result == array(array('readonlytext'))) { throw new ReadOnlyError(); } $current = $details['current']; $target = $details['target']; $newId = $details['newid']; $this->getOutput()->setPageTitle($this->msg('actioncomplete')); $this->getOutput()->setRobotPolicy('noindex,nofollow'); if ($current->getUserText() === '') { $old = $this->msg('rev-deleted-user')->escaped(); } else { $old = Linker::userLink($current->getUser(), $current->getUserText()) . Linker::userToolLinks($current->getUser(), $current->getUserText()); } $new = Linker::userLink($target->getUser(), $target->getUserText()) . Linker::userToolLinks($target->getUser(), $target->getUserText()); $this->getOutput()->addHTML($this->msg('rollback-success')->rawParams($old, $new)->parseAsBlock()); $this->getOutput()->returnToMain(false, $this->getTitle()); if (!$request->getBool('hidediff', false) && !$this->getUser()->getBoolOption('norollbackdiff', false)) { $de = new DifferenceEngine($this->getContext(), $current->getId(), $newId, false, true); $de->showDiff('', ''); } }
public static function getNotificationDiffHtml($oldRevId, $revId) { $oldRevisionObj = Revision::newFromId($oldRevId); $newRevisionObj = Revision::newFromId($revId); if ($oldRevisionObj->getTitle() != $newRevisionObj->getTitle()) { return '<span class="error">' . htmlspecialchars(wfMsg('notificator-revs-not-from-same-title')) . '</span>'; } $titleObj = $oldRevisionObj->getTitle(); $differenceEngineObj = new DifferenceEngine($titleObj, $oldRevId, $revId); $notificationDiffHtml = '<style media="screen" type="text/css">' . file_get_contents(dirname(__FILE__) . '/diff-in-mail.css') . '</style><table class="diff"> <col class="diff-marker" /> <col class="diff-content" /> <col class="diff-marker" /> <col class="diff-content" /> ' . $differenceEngineObj->getDiffBody() . ' </table>'; return $notificationDiffHtml; }
public static function addModules(OutputPage $out) { $out->addModules('ext.translate.quickedit'); // Might be needed, but ajax doesn't load it // Globals :( /// @todo: remove when 1.17 is no longer supported. // The RL module name is different in 1.17 and >1.17 $diff = new DifferenceEngine(); $diff->showDiffStyle(); }
/** * Get a diff between the current contents of the edit box and the * version of the page we're editing from. * * If this is a section edit, we'll replace the section as for final * save and then make a comparison. * * @return string HTML */ function getDiff() { require_once 'DifferenceEngine.php'; $oldtext = $this->mArticle->fetchContent(); $newtext = $this->mArticle->getTextOfLastEditWithSectionReplacedOrAdded($this->section, $this->textbox1, $this->summary, $this->edittime); $oldtitle = wfMsg('currentrev'); $newtitle = wfMsg('yourtext'); if ($oldtext != wfMsg('noarticletext') || $newtext != '') { $difftext = DifferenceEngine::getDiff($oldtext, $newtext, $oldtitle, $newtitle); } return '<div id="wikiDiff">' . $difftext . '</div>'; }
/** * Get a diff between the current contents of the edit box and the * version of the page we're editing from. * * If this is a section edit, we'll replace the section as for final * save and then make a comparison. * * @return string HTML */ function getDiff() { $oldtext = $this->mArticle->fetchContent(); $newtext = $this->mArticle->replaceSection($this->section, $this->textbox1, $this->summary, $this->edittime); $newtext = $this->mArticle->preSaveTransform($newtext); $oldtitle = wfMsgExt('currentrev', array('parseinline')); $newtitle = wfMsgExt('yourtext', array('parseinline')); if ($oldtext !== false || $newtext != '') { $de = new DifferenceEngine($this->mTitle); $de->setText($oldtext, $newtext); $difftext = $de->getDiff($oldtitle, $newtitle); } else { $difftext = ''; } return '<div id="wikiDiff">' . $difftext . '</div>'; }
function showEditForm($formCallback = null) { global $wgOut, $wgLanguageCode, $wgRequest, $wgTitle, $wgUser, $wgLang; $whow = null; // conflict resolution if (!$wgRequest->wasPosted()) { EditPage::showEditForm(); } $wgOut->clearHTML(); //echo $this->textbox1; exit; wfRunHooks('EditPage::showEditForm:initial', array(&$this)); // are we called with just action=edit and no title? $newArticle = false; if (($wgRequest->getVal("title") == "" || $wgTitle->getArticleID() == 0) && !$this->preview) { $newArticle = true; } $sk = $wgUser->getSkin(); if (!$this->mTitle->getArticleID() && !$this->preview) { # new article $wgOut->addHTML(wfMsg("newarticletext")); } // do we have a new article? if so, format the title if it's English $wgRequest->getVal("new_article"); if ($new_article && $wgLanguageCode == "en") { $title = $this->mTitle->getText(); $old_title = $title; $title = $this->formatTitle($title); $titleObj = Title::newFromText($title); $this->mTitle = $titleObj; $this->mArticle = new Article($titleObj); } $conflictWikiHow = null; $conflictTitle = false; if ($this->isConflict) { $s = wfMsg("editconflict", $this->mTitle->getPrefixedText()); $wgOut->setPageTitle($s); if ($new_article) { $wgOut->addHTML("<b><font color=red>" . wfMsg('page-name-exists') . "</b></font><br/><br/>"); $conflictTitle = true; } else { $this->edittime = $this->mArticle->getTimestamp(); $wgOut->addHTML(wfMsg("explainconflict")); // let the advanced editor handle the situation if ($this->isConflict) { EditPage::showEditForm(); return; } } $this->textbox2 = $this->textbox1; $conflictWikiHow = WikihowArticleEditor::newFromText($this->textbox1); $this->textbox1 = $this->mArticle->getContent(true, true); $this->edittime = $this->mArticle->getTimestamp(); } else { if ($this->mTitle->getArticleID() == 0) { $s = wfMsg('creating', "\"" . wfMsg('howto', $this->mTitle->getPrefixedText()) . "\""); } else { $s = wfMsg('editing', "\"" . wfMsg('howto', $this->mTitle->getPrefixedText()) . "\""); } if ($this->section != "") { if ($this->section == "new") { $s .= wfMsg("commentedit"); } else { $s .= wfMsg("sectionedit"); } if (!$this->preview) { $sectitle = preg_match("/^=+(.*?)=+/mi", $this->textbox1, $matches); if (!empty($matches[1])) { $this->summary = "/* " . trim($matches[1]) . " */ "; } } } $wgOut->setPageTitle($s); if ($this->oldid) { $this->mArticle->setOldSubtitle($this->oldid); $wgOut->addHTML(wfMsg("editingold")); } } if (wfReadOnly()) { $wgOut->addHTML("<strong>" . wfMsg("readonlywarning") . "</strong>"); } elseif ($isCssJsSubpage and "preview" != $formtype) { $wgOut->addHTML(wfMsg("usercssjsyoucanpreview")); } if (!$newArticle && $this->mTitle->isProtected('edit')) { if ($this->mTitle->isSemiProtected()) { $notice = wfMsg('semiprotectedpagewarning'); if (wfEmptyMsg('semiprotectedpagewarning', $notice) || $notice == '-') { $notice = ''; } } else { $notice = wfMsg('protectedpagewarning'); } $wgOut->addHTML("<div class='article_inner'>\n "); $wgOut->addWikiText($notice); $wgOut->addHTML("</div>\n"); } $q = "action=submit2&override=yes"; #if ( "no" == $redirect ) { $q .= "&redirect=no"; } $action = $this->mTitle->escapeLocalURL($q); if ($newArticle) { $main = str_replace(' ', '-', wfMsg('mainpage')); $action = str_replace("&title=" . $main, "", $action); } $summary = wfMsg("summary"); $subject = wfMsg("subject"); $minor = wfMsg("minoredit"); $watchthis = wfMsg("watchthis"); $save = wfMsg("savearticle"); $prev = wfMsg("showpreview"); $cancel = $sk->makeKnownLink($this->mTitle->getPrefixedText(), wfMsg("cancel")); $edithelpurl = Skin::makeInternalOrExternalUrl(wfMsgForContent('edithelppage')); $edithelp = '<a target="helpwindow" href="' . $edithelpurl . '">' . htmlspecialchars(wfMsg('edithelp')) . '</a> ' . htmlspecialchars(wfMsg('newwindow')); $copywarn = wfMsg("copyrightwarning", $sk->makeKnownLink(wfMsg("copyrightpage"))); $minoredithtml = ''; if ($wgUser->isAllowed('minoredit')) { $minoredithtml = "<input tabindex='11' type='checkbox' value='1' name='wpMinoredit'" . ($this->minoredit ? " checked='checked'" : "") . " accesskey='" . wfMsg('accesskey-minoredit') . "' id='wpMinoredit' />\n" . "<label for='wpMinoredit' title='" . wfMsg('tooltip-minoredit') . "'>{$minor}</label>\n"; } $watchhtml = ''; if ($wgUser->isLoggedIn()) { $watchhtml = "<input tabindex='12' type='checkbox' name='wpWatchthis'" . ($this->watchthis ? " checked='checked'" : "") . " accesskey=\"" . htmlspecialchars(wfMsg('accesskey-watch')) . "\" id='wpWatchthis' />\n" . "<label for='wpWatchthis' title=\"" . htmlspecialchars(wfMsg('tooltip-watch')) . "\">{$watchthis}</label>\n"; } $checkboxhtml = $minoredithtml . $watchhtml; $tabindex = 14; $buttons = $this->getEditButtons($tabindex); $footerbuttons = ""; $buttons['preview'] = "<span id='gatGuidedPreview'>{$buttons['preview']}</span>"; if ($wgUser->getOption('hidepersistantsavebar', 0) == 0) { $footerbuttons .= "<span id='gatPSBSave'>{$buttons['save']}</span>"; $footerbuttons .= "<span id='gatPSBPreview'>{$buttons['preview']}</span>"; } $saveBtn = str_replace('accesskey="s"', "", $buttons['save']); $buttons['save'] = "<span id='gatGuidedSave'>{$saveBtn}</span>"; $buttonshtml = implode($buttons, "\n"); # if this is a comment, show a subject line at the top, which is also the edit summary. # Otherwise, show a summary field at the bottom $summarytext = htmlspecialchars($wgLang->recodeForEdit($this->summary)); # FIXME $editsummary1 = ""; if ($wgRequest->getVal('suggestion')) { $summarytext .= ($summarytext == "" ? "" : ", ") . wfMsg('suggestion_edit_summary'); } if ($this->section == "new") { $commentsubject = "{$subject}: <input tabindex='1' type='text' value=\"{$summarytext}\" name=\"wpSummary\" id='wpSummary' maxlength='200' size='60' />"; $editsummary = ""; } else { $commentsubject = ""; if ($wgTitle->getArticleID() == 0 && $wgTitle->getNamespace() == NS_MAIN && $summarytext == "") { $summarytext = wfMsg('creating_new_article'); } $editsummary = "<input tabindex='10' type='text' value=\"{$summarytext}\" name=\"wpSummary\" id='wpSummary' maxlength='200' size='60' /><br />"; $editsummary1 = "<input tabindex='10' type='text' value=\"{$summarytext}\" name=\"wpSummary1\" id='wpSummary1' maxlength='200' size='60' /><br />"; } // create the wikiHow if ($conflictWikiHow == null) { if ($this->textbox1 != "") { $whow = WikihowArticleEditor::newFromText($this->textbox1); } else { $whow = WikihowArticleEditor::newFromArticle($this->mArticle); } } else { $whow = $conflictWikiHow; } //********** SETTING UP THE FORM // // // // $confirm = "window.onbeforeunload = confirmExit;"; if ($wgUser->getOption('disablewarning') == '1') { $confirm = ""; } $wgOut->addHTML("<script language=\"JavaScript\">\n\t\t\t\tvar isGuided = true;\n\t\t\t\tvar needToConfirm = false;\n\t\t\t\tvar checkMinLength = true;\n\t\t\t\t{$confirm}\n\t\t\t\tfunction confirmExit() {\n\t\t\t\t\tif (needToConfirm)\n\t\t\t\t\t\treturn \"" . wfMsg('all-changes-lost') . "\";\n\t\t\t\t}\n\t\t\t\tfunction addrows(element) {\n\t\t\t\t\tif (element.rows < 32) {\n\t\t\t\t\t\telement.rows += 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfunction removerows(element) {\n\t\t\t\t\tif (element.rows > 4) {\n\t\t\t\t\t\telement.rows -= 4;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telement.rows = 4;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfunction saveandpublish() {\n\t\t\t\t\twindow.onbeforeunload = null;\n\t\t\t\t\tdocument.editform.submit();\n\t\t\t\t}\n\t\t\t\t(function (\$) {\n\t\t\t\t\t\$(document).ready(function() {\n\t\t\t\t\t\t\$('.button').click(function () {\n\t\t\t\t\t\t\tvar button = \$(this).not('.submit_button');\n\t\t\t\t\t\t\tif (button.length) {\n\t\t\t\t\t\t\t\tneedToConfirm = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\$('textarea').focus(function () {\n\t\t\t\t\t\t\tneedToConfirm = true;\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t\t\$('#ep_cat').live('click', function(e) {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tvar title = 'Categorize ' + wgTitle;\n\t\t\t\t\t\tif (title.length > 54) {\n\t\t\t\t\t\t\ttitle = title.substr(0, 54) + '...';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjQuery('#dialog-box').html('');\n\t\t\t\t\t\t\n\t\t\t\t\t\tjQuery('#dialog-box').load('/Special:Categorizer?a=editpage&id=' + wgArticleId, function() {\n\t\t\t\t\t\t\tjQuery('#dialog-box').dialog({\n\t\t\t\t\t\t\t\twidth: 673,\n\t\t\t\t\t\t\t\theight: 600,\n\t\t\t\t\t\t\t\tmodal: true,\n\t\t\t\t\t\t\t\ttitle: title,\n\t\t\t\t\t\t\t\tcloseText: 'Close',\t\n\t\t\t\t\t\t\t\tdialogClass: 'modal2',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treCenter = function() {\n\t\t\t\t\t\t\t\tjQuery('#dialog-box').dialog('option', 'position', 'center');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsetTimeout('reCenter()', 100);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\$.getScript('/extensions/wikihow/cattool/categorizer.js');\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t})(jQuery);\n\t\t\t</script>\n\t\t\t<script type=\"text/javascript\" src=\"" . wfGetPad('/extensions/min/f/skins/common/clientscript.js,/skins/common/ac.js,/extensions/wikihow/video/importvideo.js&rev=') . WH_SITEREV . "\"></script>\n\n\t\t"); if (!$this->preview) { # Don't select the edit box on preview; this interferes with seeing what's going on. $wgOut->setOnloadHandler("document.editform.title.focus(); load_cats();"); } $title = ""; //$wgOut->setOnloadHandler( "' onbeforeunload='return confirm(\"Are you sure you want to navigate away from this page? All changes will be lost!\");" ); $suggested_title = ""; if (isset($_GET["requested"])) { $t = Title::makeTitle(NS_MAIN, $_GET["requested"]); $suggested_title = $t->getText(); } if ($wgRequest->getVal('title', null) == null || $conflictTitle || $suggested_title != "") { $title = "<div id='title'><h3>" . wfMsg('title') . "</h3><br/>" . wfMsg('howto', '') . " \n\t\t\t<input autocomplete=\"off\" size=60 type=\"text\" name=\"title\" id=category tabindex=\"1\" value=\"{$suggested_title}\"></div>"; } $steps = htmlspecialchars($wgLang->recodeForEdit($whow->getSteps(true)), ENT_QUOTES); $video = htmlspecialchars($wgLang->recodeForEdit($whow->getSection(wfMsg('video')))); $tips = htmlspecialchars($wgLang->recodeForEdit($whow->getSection(wfMsg('tips')))); $warns = htmlspecialchars($wgLang->recodeForEdit($whow->getSection(wfMsg('warnings')))); $related_text = htmlspecialchars($wgLang->recodeForEdit($whow->getSection(wfMsg('relatedwikihows')))); $summary = htmlspecialchars($wgLang->recodeForEdit($whow->getSummary())); if ($newArticle || $whow->mIsNew) { if ($steps == "") { $steps = "# "; } if ($tips == "") { $tips = "* "; } if ($warns == "") { $warns = "* "; } if ($ingredients == "") { $ingredients = "* "; } } $cat = $whow->getCategoryString(); $advanced = ""; $cat_array = explode("|", $whow->getCategoryString()); $i = 0; $cat_string = ""; foreach ($cat_array as $cat) { if ($cat == "") { continue; } if ($i != 0) { $cat_string .= "," . $cat; } else { $cat_string = $cat; } $i++; } $removeButton = ""; $cat_advisory = ""; if ($cat_string != "") { $removeButton = "<input type=\"button\" name=\"change_cats\" onclick=\"removeCategories();\" value=\"" . wfMsg('remove-categories') . "\">"; } else { $cat_advisory = wfMsg('categorization-optional'); } //$cat_string = str_replace("|", ", ", $whow->getCategoryString()); //$cat_string = implode(", ", $raa); if (!$newArticle && !$whow->mIsNew && !$conflictTitle) { $oldparameters = ""; if ($wgRequest->getVal("oldid") != "") { $oldparameters = "&oldid=" . $wgRequest->getVal("oldid"); } if (!$this->preview) { $advanced = "<a class='' href='{$wgScript}?title=" . $wgTitle->getPrefixedURL() . "&action=edit&advanced=true{$oldparameters}'>" . wfMsg('advanced-editing') . "</a>"; } } elseif ($newArticle && $wgRequest->getVal('title', null) != null) { $t = Title::newFromText("CreatePage", NS_SPECIAL); //$advanced = str_replace("href=", "class='guided-button' href=", $sk->makeLinkObj($t, wfMsg('advanced-editing'))) . " |"; //$advanced = "<a href='{$wgScript}?title=" . $wgTitle->getPrefixedURL() . "&action=edit&advanced=true$oldparameters';\">".wfMsg('advanced-editing')."</a>"; $advanced = "<a class='button secondary' style='float:left;' href='{$wgScript}?title=" . $wgTitle->getPrefixedURL() . "&action=edit&advanced=true{$oldparameters}'>" . wfMsg('advanced-editing') . "</a>"; } $section_class = 'minor_section'; // MODIFIED FOR POPUP $categoryHTML = ""; if ($wgUser->getID() > 0) { $ctitle = $this->mTitle->getText(); $css = HtmlSnips::makeUrlTags('css', array('categoriespopup.css'), 'extensions/wikihow', false); if ($wgLanguageCode == 'en') { $editCatMore = "<a href=\"{$wgScriptPath}/Writer%27s-Guide?section=2#" . wfMsg('more-info-categorization') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>"; $editCatHtml = "<a href='#' id='ep_cat'>[" . wfMsg('editcategory') . "]</a><strong>{$editCatLink}</strong>"; } $categoryHTML = "\n\t\t\t\t{$css}\n\t\t\t\t<div id='categories'>\n\t\t\t\t\t<h5>" . wfMsg('add-optional-categories') . "{$editCatMore}</h5>\n\t\t\t\t\t<div id='option_cats'>\n\t\t\t\t\t{$editCatHtml}" . Categoryhelper::getCategoryOptionsForm2($cat_string, $whow->mCategories) . "\t</div>\n\t\t\t\t</div>"; } $requested = ""; if (isset($_GET['requested'])) { $requested = $_GET['requested']; } $related_vis = "hide"; $related_checked = ""; $relatedHTML = ""; if ($whow->getSection(wfMsg('relatedwikihows')) != "") { $related_vis = "show"; $relatedHTML = $whow->getSection(wfMsg('relatedwikihows')); $relatedHTML = str_replace("*", "", $relatedHTML); $relatedHTML = str_replace("[[", "", $relatedHTML); $relatedHTML = str_replace("]]", "", $relatedHTML); $lines = split("\n", $relatedHTML); $relatedHTML = ""; foreach ($lines as $line) { $xx = strpos($line, "|"); if ($xx !== false) { $line = substr($line, 0, $xx); } // Google+ hack. We don't normally allow + but will for the Goog if (false === stripos($line, 'Google+')) { $line = trim(urldecode($line)); } if ($line == "") { continue; } $relatedHTML .= "<OPTION VALUE=\"" . htmlspecialchars($line) . "\">{$line}</OPTION>\n"; } $related_checked = " CHECKED "; } $vidpreview_vis = "hide"; $vidbtn_vis = "show"; $vidpreview = "<img src='" . wfGetPad('/extensions/wikihow/rotate.gif') . "'/>"; if ($whow->getSection(wfMsg('video')) != "") { $vidpreview_vis = "show"; $vidbtn_vis = "hide"; try { #$vt = Title::makeTitle(NS_VIDEO, $this->mTitle->getText()); #$r = Revision::newFromTitle($vt); $vidtext = $whow->getSection(wfMsg('video')); $vidpreview = $wgOut->parse($vidtext); } catch (Exception $e) { $vidpreview = "Sorry, preview is currently not available."; } } else { $vidpreview = wfMsg('video_novideoyet'); } $video_disabled = ""; $vid_alt = ""; $video_msg = ""; $video_button = "<a id='gatVideoImportEdit' type='button' onclick=\"changeVideo('" . urlencode($wgTitle->getDBKey()) . "'); return false;\" href='#' id='show_preview_button' class='button secondary' >" . wfMsg('video_change') . "</a>"; if ($wgUser->getID() == 0) { $video_disabled = "disabled"; $video_alt = "<input type='hidden' name='video' value=\"" . htmlspecialchars($video) . "\"/>"; $video_msg = wfMsg('video_loggedin'); $video_button = ""; } $things_vis = "hide"; $things = "* "; $things_checked = ""; $tyn = $whow->getSection(wfMsg("thingsyoullneed")); if ($tyn != '') { $things_vis = "show"; $things = $tyn; $things_checked = " CHECKED "; } $ingredients_vis = "hide"; $section = $whow->getSection(wfMsg("ingredients")); $ingredients_checked = ""; if ($section != '') { $ingredients_vis = "show"; $ingredients = $section; $ingredients_checked = " CHECKED "; } $sources_vis = "hide"; $sources = "* "; $sources_checked = ""; $sources = $whow->getSection(wfMsg("sources")); $sources = str_replace('<div class="references-small"><references/></div>', '', $sources); $sources = str_replace('{{reflist}}', '', $sources); if ($sources != "") { $sources_vis = "show"; $sources_checked = " CHECKED "; } $new_field = ""; if ($newArticle || $new_article) { $new_field = "<input type=hidden name=new_article value=true>"; } $lang_links = htmlspecialchars($whow->getLangLinks()); $vt = Title::makeTitle(NS_VIDEO, $this->mTitle->getText()); $vp = SpecialPage::getTitleFor("Previewvideo", $vt->getFullText()); $newArticleWarn = '<script type="text/javascript" src="' . wfGetPad('/extensions/min/f/extensions/wikihow/winpop.js?') . WH_SITEREV . '"></script>'; $popup = Title::newFromText("UploadPopup", NS_SPECIAL); if ($wgUser->isLoggedIn()) { $token = htmlspecialchars($wgUser->editToken()); } else { $token = EDIT_TOKEN_SUFFIX; } if ('preview' == $this->formtype) { $previewOutput = $this->getPreviewText(); $this->showPreview($previewOutput); $show_weave = true; } else { $wgOut->addHTML('<div id="wikiPreview"></div>'); } if ('diff' == $this->formtype) { $this->showDiff(); $show_weave = true; } if ($show_weave) { $relBtn = $wgLanguageCode == 'en' ? PopBox::getGuidedEditorButton() : ''; $relHTML = PopBox::getPopBoxJSGuided() . PopBox::getPopBoxDiv() . PopBox::getPopBoxCSS(); $weave_links = $relHTML . '<div class="wh_block editpage_sublinks">' . $relBtn . '</div>'; } $undo = ''; if ($wgRequest->getVal('undo', null) != null) { $undo_id = $wgRequest->getVal('undo', null); $undo = "\n<input type='hidden' value=\"{$undo_id}\" name=\"wpUndoEdit\" />\n"; } $wgOut->addHTML(Easyimageupload::getUploadBoxJS()); $wgOut->addHTML("\t\n{$newArticleWarn}\n\n<div id='editpage'>\n<form id=\"editform\" name=\"editform\" method=\"post\" action=\"{$action}\"\nenctype=\"application/x-www-form-urlencoded\" onSubmit=\"return checkForm();\">\t\t"); if (is_callable($formCallback)) { call_user_func_array($formCallback, array(&$wgOut)); } $hidden_cats = ""; if (!$wgUser->isLoggedIn()) { $hidden_cats = "<input type=\"hidden\" name=\"categories22\" value=\"{$cat_string}\">"; } $token1 = md5($wgUser->getName() . $this->mTitle->getArticleID() . time()); wfTrackEditToken($wgUser, $token1, $this->mTitle, $this instanceof EditPageWrapper); $wgOut->addHTML("\n\t\t{$new_field}\n\t\t{$hidden_cats}\n\t\t<input type='hidden' value=\"{$this->starttime}\" name=\"wpStarttime\" />\n\n\t\t<input type=\"hidden\" name=\"requested\" value=\"{$requested}\">\n\t\t<input type=\"hidden\" name=\"langlinks\" value=\"{$lang_links}\">\n\t\t<input type='hidden' value=\"{$this->edittime}\" name=\"wpEdittime\" />\n\n\n\t\t{$commentsubject}\n\t\t{$title}\n\t\t<br clear='all'/>\n<script language='javascript'>\n\tvar vp_URL = '{$vp->getLocalUrl()}';\n</script>\n<script language='javascript' src='" . wfGetPad('/extensions/min/f/extensions/wikihow/previewvideo.js?rev=') . "'></script>\n<style type='text/css' media='all'>/*<![CDATA[*/ @import '" . wfGetPad('/extensions/min/f/extensions/wikihow/editpagewrapper.css,/extensions/wikihow/winpop.css,/extensions/wikihow/video/importvideo.css,/extensions/wikihow/cattool/categorizer.css,/extensions/wikihow/cattool/categorizer_editpage.css&rev=') . WH_SITEREV . "'; /*]]>*/</style>\n\n\t{$weave_links}\n\n\t<div id='introduction' class='{$section_class}'>\n\t\t<h2>" . wfMsg('introduction') . "\n\t\t\t<div class='head_details'>" . wfMsg('summaryinfo') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('introduction-url') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea rows='4' cols='100' name='summary' id='summary' tabindex=\"2\" wrap=virtual>{$summary}</textarea>\n\t\t<!--a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"intro\"); return false;'>" . wfMsg('eiu-add-image-to-introduction') . "</a-->\n\t\t<div class='clearall'></div>\n\t</div>\n\n\n\t<div id='ingredients' class='{$ingredients_vis} {$section_class}'>\n\t\t<h2>" . wfMsg('ingredients') . "\n\t\t\t<div class='head_details'>" . wfMsg('ingredients_tooltip') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('ingredients') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='ingredients' rows='4' cols='100' onKeyUp=\"addStars(event, document.editform.ingredients);\" tabindex='3' id='ingredients_text'>{$ingredients}</textarea>\n\t\t<a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"ingredients\"); return false;'>" . wfMsg('eiu-add-image-to-ingredients') . "</a>\n\t</div>\n\n\t<div id='steps' class='{$section_class}'>\n\t\t<h2>" . wfMsg('steps') . "\n\t\t\t<div class='head_details'>" . wfMsg('stepsinfo') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('steps') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='steps' rows='{$wgRequest->getVal('txtarea_steps_text', 12)}' cols='100' wrap='virtual' onKeyUp=\"addNumToSteps(event);\" tabindex='4' id='steps_text'>{$steps}</textarea>\n\t\t<a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"steps\", 0); return false;'>" . wfMsg('eiu-add-image-to-steps') . "</a>\n\t</div>"); $wgOut->addHTML("<div id='video' class='{$section_class}'>\n\t\t<h2>" . wfMsg('video') . "\n\t\t\t<div class='head_details'>" . wfMsg('videoinfo') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('video') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t{$video_alt}\n\t\t<input type='text' name='video{$video_disabled}' size='60' id='video_text' style='float:left;' value=\"{$video}\" {$video_disabled}/><br />\n\t\t{$video_button}\n\t\t<a href='javascript:showHideVideoPreview();' id='show_preview_button' class='button secondary {$vidbtn_vis}'>" . wfMsg('show_preview') . "</a>\n\t\t{$video_msg}\n\t</div>\n\t<div id='viewpreview' class='{$vidpreview_vis} {$section_class}' style='text-align: center; margin-top: 5px;'>\n\t\t<center><a onclick='showHideVideoPreview();'>" . wfMsg('ep_hide_preview') . "</a></center><br/>\n\t\t<div id='viewpreview_innards'>{$vidpreview}</div>\n\t</div>\n\n\t<div id='tips' class='{$section_class}'>\n\t\t<h2>" . wfMsg('tips') . "\n\t\t\t<div class='head_details'>" . wfMsg('listhints') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('tips') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='tips' rows='{$wgRequest->getVal('txtarea_tips_text', 12)}' cols='100' wrap='virtual' onKeyUp='addStars(event, document.editform.tips);' tabindex='5' id='tips_text'>{$tips}</textarea>\n\t\t<a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"tips\"); return false;'>" . wfMsg('eiu-add-image-to-tips') . "</a>\n\t</div>\n\n\t<div id='warnings' class='{$section_class}'>\n\t\t<h2>" . wfMsg('warnings') . "\n\t\t\t<div class='head_details'>" . wfMsg('optionallist') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=3#" . wfMsg('warnings') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='warnings' rows='{$wgRequest->getVal('txtarea_warnings_text', 4)}' cols='100' wrap='virtual' onKeyUp='addStars(event, document.editform.warnings);' id='warnings_text' tabindex=\"6\" id='warnings_text'>{$warns}</textarea>\n\t\t<a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"warnings\"); return false;'>" . wfMsg('eiu-add-image-to-warnings') . "</a>\n\t</div>\n\n\t<div id='thingsyoullneed' class='{$things_vis} {$section_class}'>\n\t\t<h2>" . wfMsg('thingsyoullneed') . "\n\t\t\t<div class='head_details'>" . wfMsg('items') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=4#" . wfMsg('thingsyoullneed') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='thingsyoullneed' rows='4' cols='65' wrap='virtual' onKeyUp='addStars(event, document.editform.thingsyoullneed);' tabindex='7' id='thingsyoullneed_text'>{$things}</textarea>\n\t\t<a href='#' class='button secondary add_image_button' onclick='easyImageUpload.doEIUModal(\"thingsyoullneed\"); return false;'>" . wfMsg('eiu-add-image-to-thingsyoullneed') . "</a>\n\t</div>\n\n\t<div id='relatedwikihows' class='{$related_vis} {$section_class}'>\n\t\t<h2>" . wfMsg('relatedarticlestext') . "\n\t\t\t<div class='head_details'>" . wfMsg('relatedlist') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=5#" . wfMsg('related-wikihows-url') . "\" target=\"new\">" . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<div id='related_buttons'>\n\t\t\t<a href='#' class='button secondary' onclick='moveRelated(true);return false;' >" . wfMsg('epw_move_up') . "</a>\n\t\t\t<a href='#' class='button secondary' onclick='moveRelated(false);return false;'>" . wfMsg('epw_move_down') . "</a>\n\t\t\t<a href='#' class='button red' onclick='removeRelated(); return false;'>" . wfMsg('epw_remove') . "</a>\n\t\t\t<br />\n\t\t\t<br />\n\t\t</div>\n\t\t<input type=hidden value=\"\" name=\"related_list\">\n\t\t<select size='4' name='related' id='related_select' ondblclick='viewRelated();'>\n\t\t\t{$relatedHTML}\n\t\t</select>\n\t\t<br />\n\t\t<br />\n\t\t<br class='clearall'/>\n\t\t<div>\n\t\t\t<b>" . wfMsg('addtitle') . "</b><br />\n\t\t\t<input type='text' autocomplete=\"off\" maxLength='256' name='q' value='' onKeyPress=\"return keyxxx(event);\" tabindex='8'>\n\t\t</div>\n\t\t<a href='#' id='add_button' class='button secondary' onclick='add_related();return false;'>" . wfMsg('epw_add') . "</a>\n\t\t<br class='clearall'/>\n\t</div>\n\n<script language=\"JavaScript\">\n\tvar js_enabled = document.getElementById('related');\n\t\t if (js_enabled != null) {\n\t\t\t\t js_enabled.className = 'display';\n\t\t\t}\n\t</script>\n\t<noscript>\n\t\t<input type='hidden' name='no_js' value='true'>\n\t\t<div id='related'>\n\t\t\t<textarea name='related_no_js' rows='4' cols='65' wrap='virtual' onKeyUp='addStars(event, document.editform.related_no_js);' id='related_no_js' tabindex='8'>{$related_text}</textarea>\n\t\t</div>\n\t</noscript>\n\n\t<div id='sources' class='{$sources_vis} {$section_class}'>\n\t\t<h2>" . wfMsg('sources') . "\n\t\t\t<div class='head_details'>" . wfMsg('linkstosites') . "</div>\n\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('sources-links-url') . "\" target=\"new\"> " . wfMsg('moreinfo') . "</a>\n\t\t</h2>\n\t\t<textarea name='sources' rows='3' cols='100' wrap='virtual' onKeyUp='addStars(event, document.editform.sources);' id='sources' tabindex='9'>{$sources}</textarea>\n\t</div>\n\n\t<div class='{$section_class}'>\n\t\t<h2>" . wfMsg('optional_options') . "</h2>\n\t\t{$categoryHTML}\n\n\t\t<div id='optional_sections'>\n\t\t\t<h5>" . wfMsg('optionalsections') . "</h5>\n\t\t\t<ul>\n\t\t\t\t<li><input type='checkbox' id='thingsyoullneed_checkbox' name='thingsyoullneed_checkbox' onclick='showhiderow(\"thingsyoullneed\", \"thingsyoullneed_checkbox\");' {$things_checked} /> <label for='thingsyoullneed_checkbox'>" . wfMsg('thingsyoullneed') . "</label></li>\n\t\t\t\t<li><input type='checkbox' id='related_checkbox' name='related_checkbox' onclick='showhiderow(\"relatedwikihows\", \"related_checkbox\");' {$related_checked} > <label for='related_checkbox'>" . wfMsg('relatedwikihows') . "</label></li>\n\t\t\t\t<li><input type='checkbox' id='sources_checkbox' name='sources_checkbox' onclick='showhiderow(\"sources\", \"sources_checkbox\");' {$sources_checked} > <label for='sources_checkbox'>" . wfMsg('sources') . "</label></li>\n\t\t\t\t<li><input type='checkbox' id='ingredients_checkbox' name='ingredients_checkbox' onclick='showhiderow(\"ingredients\", \"ingredients_checkbox\");' {$ingredients_checked} > <label for='ingredients_checkbox'>" . wfMsg('ingredients_checkbox') . "</label></li>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n\t\n\t<div class='{$section_class}'>\n\t\t<div class='editOptions'>\n\t\t\t<h2>" . wfMsg('editdetails') . "\n\t\t\t\t<div class='head_details'>" . wfMsg('summaryedit') . "</div>\n\t\t\t\t<a href=\"{$wgScriptPath}/" . wfMsg('writers-guide-url') . "?section=2#" . wfMsg('summary') . "\" target=\"new\"> " . wfMsg('moreinfo') . "</a>\n\t\t\t</h2>\n\t\t\t{$editsummary}\n\t\t\t{$checkboxhtml}\n\t\t\t{$undo}\n\t\t\t<input type='hidden' value=\"{$token}\" name=\"wpEditToken\" />\n\t\t\t<input type='hidden' value=\"{$token1}\" name=\"wpEditTokenTrack\" />\n\t\t\t<div class='editButtons'>\n\t\t\t\t<a href=\"javascript:history.back()\" id=\"wpCancel\" class=\"button secondary\">" . wfMsg('cancel') . "</a>\n\t\t\t\t{$buttonshtml}\n\t\t\t</div>\n\t\t\t{$copywarn}\n\t\t</div>\n\t</div>\n\t<input type='hidden' value=\"" . htmlspecialchars($this->section) . "\" name=\"wpSection\" />\n\t<input type='hidden' value=\"{$this->edittime}\" name=\"wpEdittime\" />\n"); if ($this->isConflict) { require_once "DifferenceEngine.php"; $wgOut->addHTML("<h2>" . wfMsg("yourdiff") . "</h2>\n"); DifferenceEngine::showDiff($this->textbox2, $this->textbox1, wfMsg("yourtext"), wfMsg("storedversion")); } if ($wgUser->getOption('hidepersistantsavebar', 0) == 0) { $wgOut->addHTML(" <div id='edit_page_footer'>\n\t\t\t\t<table class='edit_footer'><tr><td class='summary'>\n\t\t\t\t" . wfMsg('editsummary') . ": {$editsummary1}</td>\n\t\t\t\t<td class='buttons'>{$footerbuttons}</td></tr></table>\n\t\t\t\t</div> "); } $wgOut->addHTML("</form></div>\n"); }
/** * Generates a diff txt * @param Title $title * @return string */ function generateDiffBodyTxt( $title ) { $revision = Revision::newFromTitle( $title, 0 ); $diff = new DifferenceEngine( $title, $revision->getId(), 'prev' ); // The getDiffBody() method generates html, so let's generate the txt diff manualy: global $wgContLang; $diff->loadText(); $otext = str_replace( "\r\n", "\n", $diff->mOldtext ); $ntext = str_replace( "\r\n", "\n", $diff->mNewtext ); $ota = explode( "\n", $wgContLang->segmentForDiff( $otext ) ); $nta = explode( "\n", $wgContLang->segmentForDiff( $ntext ) ); // We use here the php diff engine included in MediaWiki $diffs = new Diff( $ota, $nta ); // And we ask for a txt formatted diff $formatter = new UnifiedDiffFormatter(); $diff_text = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ); return $diff_text; }
/** * Gets the HTML of the diff that MediaWiki displays to the user. */ public function getHtmlDiff($pageTitle, $oldText, $newText) { $de = new DifferenceEngine($pageTitle); $de->setText($oldText, $newText); $difftext = $de->getDiff("Old", "New"); return $difftext; }
protected function diffWikitext($title, $wikitext) { $apiParams = array('action' => 'query', 'prop' => 'revisions', 'titles' => $title->getPrefixedDBkey(), 'rvdifftotext' => $this->pstWikitext($title, $wikitext)); $api = new ApiMain(new DerivativeRequest($this->getRequest(), $apiParams, false), false); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $result = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array())); } else { $result = $api->getResultData(); } if (!isset($result['query']['pages'][$title->getArticleID()]['revisions'][0]['diff']['*'])) { return array('result' => 'fail'); } $diffRows = $result['query']['pages'][$title->getArticleID()]['revisions'][0]['diff']['*']; if ($diffRows !== '') { $context = new DerivativeContext($this->getContext()); $context->setTitle($title); $engine = new DifferenceEngine($context); return array('result' => 'success', 'diff' => $engine->addHeader($diffRows, $context->msg('currentrev')->parse(), $context->msg('yourtext')->parse())); } else { return array('result' => 'nochanges'); } }