/** * @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); }
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); }
/** * 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)); }
protected function getPageDiff() { $this->mustBeKnownMessage(); $title = $this->handle->getTitle(); $key = $this->handle->getKey(); if (!$title->exists()) { return null; } $definitionTitle = Title::makeTitleSafe($title->getNamespace(), "{$key}/en"); if (!$definitionTitle || !$definitionTitle->exists()) { return null; } $db = wfGetDB(DB_MASTER); $conds = array('rt_page' => $title->getArticleID(), 'rt_type' => RevTag::getType('tp:transver')); $options = array('ORDER BY' => 'rt_revision DESC'); $latestRevision = $definitionTitle->getLatestRevID(); $translationRevision = $db->selectField('revtag', 'rt_value', $conds, __METHOD__, $options); if ($translationRevision === false) { return null; } // Using newFromId instead of newFromTitle, because the page might have been renamed $oldrev = Revision::newFromId($translationRevision); if (!$oldrev) { // And someone might still have deleted it return null; } $oldtext = ContentHandler::getContentText($oldrev->getContent()); $newContent = Revision::newFromTitle($definitionTitle, $latestRevision)->getContent(); $newtext = ContentHandler::getContentText($newContent); if ($oldtext === $newtext) { return null; } $diff = new DifferenceEngine(); if (method_exists('DifferenceEngine', 'setTextLanguage')) { $diff->setTextLanguage($this->group->getSourceLanguage()); } $oldContent = ContentHandler::makeContent($oldtext, $diff->getTitle()); $newContent = ContentHandler::makeContent($newtext, $diff->getTitle()); $diff->setContent($oldContent, $newContent); $diff->setReducedLineNumbers(); $diff->showDiffStyle(); return $diff->getDiff(wfMessage('tpt-diff-old')->escaped(), wfMessage('tpt-diff-new')->escaped()); }
/** * Displays the sections and changes for the user to review * @param TranslatablePage $page * @param array $sections */ public function showPage(TranslatablePage $page, array $sections) { global $wgContLang; $out = $this->getOutput(); $out->setSubtitle(Linker::link($page->getTitle())); $out->addModules('ext.translate.special.pagetranslation'); $out->addWikiMsg('tpt-showpage-intro'); $formParams = array('method' => 'post', 'action' => $this->getPageTitle()->getFullURL(), 'class' => 'mw-tpt-sp-markform'); $out->addHTML(Xml::openElement('form', $formParams) . Html::hidden('title', $this->getPageTitle()->getPrefixedText()) . Html::hidden('revision', $page->getRevision()) . Html::hidden('target', $page->getTitle()->getPrefixedtext()) . Html::hidden('token', $this->getUser()->getEditToken())); $out->wrapWikiMsg('==$1==', 'tpt-sections-oldnew'); $diffOld = $this->msg('tpt-diff-old')->escaped(); $diffNew = $this->msg('tpt-diff-new')->escaped(); $hasChanges = false; // Check whether page title was previously marked for translation. // If the page is marked for translation the first time, default to checked. $defaultChecked = $page->hasPageDisplayTitle(); /** * @var TPSection $s */ foreach ($sections as $s) { if ($s->name === 'Page display title') { // Set section type as new if title previously unchecked $s->type = $defaultChecked ? $s->type : 'new'; // Checkbox for page title optional translation $this->getOutput()->addHTML(Xml::checkLabel($this->msg('tpt-translate-title')->text(), 'translatetitle', 'mw-translate-title', $defaultChecked)); } if ($s->type === 'new') { $hasChanges = true; $name = $this->msg('tpt-section-new', $s->name)->escaped(); } else { $name = $this->msg('tpt-section', $s->name)->escaped(); } if ($s->type === 'changed') { $hasChanges = true; $diff = new DifferenceEngine(); if (method_exists('DifferenceEngine', 'setTextLanguage')) { $diff->setTextLanguage($wgContLang); } $diff->setReducedLineNumbers(); $oldContent = ContentHandler::makeContent($s->getOldText(), $diff->getTitle()); $newContent = ContentHandler::makeContent($s->getText(), $diff->getTitle()); $diff->setContent($oldContent, $newContent); $text = $diff->getDiff($diffOld, $diffNew); $diffOld = $diffNew = null; $diff->showDiffStyle(); $id = "tpt-sect-{$s->id}-action-nofuzzy"; $checkLabel = Xml::checkLabel($this->msg('tpt-action-nofuzzy')->text(), $id, $id, false); $text = $checkLabel . $text; } else { $text = TranslateUtils::convertWhiteSpaceToHTML($s->getText()); } # For changed text, the language is set by $diff->setTextLanguage() $lang = $s->type === 'changed' ? null : $wgContLang; $out->addHTML(MessageWebImporter::makeSectionElement($name, $s->type, $text, $lang)); } $deletedSections = $page->getParse()->getDeletedSections(); if (count($deletedSections)) { $hasChanges = true; $out->wrapWikiMsg('==$1==', 'tpt-sections-deleted'); /** * @var TPSection $s */ foreach ($deletedSections as $s) { $name = $this->msg('tpt-section-deleted', $s->id)->escaped(); $text = TranslateUtils::convertWhiteSpaceToHTML($s->getText()); $out->addHTML(MessageWebImporter::makeSectionElement($name, $s->type, $text, $wgContLang)); } } // Display template changes if applicable if ($page->getMarkedTag() !== false) { $hasChanges = true; $newTemplate = $page->getParse()->getTemplatePretty(); $oldPage = TranslatablePage::newFromRevision($page->getTitle(), $page->getMarkedTag()); $oldTemplate = $oldPage->getParse()->getTemplatePretty(); if ($oldTemplate !== $newTemplate) { $out->wrapWikiMsg('==$1==', 'tpt-sections-template'); $diff = new DifferenceEngine(); if (method_exists('DifferenceEngine', 'setTextLanguage')) { $diff->setTextLanguage($wgContLang); } $oldContent = ContentHandler::makeContent($oldTemplate, $diff->getTitle()); $newContent = ContentHandler::makeContent($newTemplate, $diff->getTitle()); $diff->setContent($oldContent, $newContent); $text = $diff->getDiff($this->msg('tpt-diff-old')->escaped(), $this->msg('tpt-diff-new')->escaped()); $diff->showDiffStyle(); $diff->setReducedLineNumbers(); $contentParams = array('class' => 'mw-tpt-sp-content'); $out->addHTML(Xml::tags('div', $contentParams, $text)); } } if (!$hasChanges) { $out->wrapWikiMsg('<div class="successbox">$1</div>', 'tpt-mark-nochanges'); } $this->priorityLanguagesForm($page); $out->addHTML(Xml::submitButton($this->msg('tpt-submit')->text()) . Xml::closeElement('form')); }
public function execute($messages) { $context = RequestContext::getMain(); $this->out = $context->getOutput(); // 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) { $para = '<code class="mw-tmi-new">' . htmlspecialchars($key) . '</code>'; $name = $context->msg('translate-manage-import-new')->rawParams($para)->escaped(); $text = TranslateUtils::convertWhiteSpaceToHTML($value); $changed[] = self::makeSectionElement($name, 'new', $text); } else { $oldContent = ContentHandler::makeContent($old, $diff->getTitle()); $newContent = ContentHandler::makeContent($value, $diff->getTitle()); $diff->setContent($oldContent, $newContent); $text = $diff->getDiff('', ''); $type = 'changed'; $action = $context->getRequest()->getVal(self::escapeNameForPHP("action-{$type}-{$key}")); if ($process) { if (!count($changed)) { $changed[] = '<ul>'; } if ($action === null) { $message = $context->msg('translate-manage-inconsistent', wfEscapeWikiText("action-{$type}-{$key}"))->parse(); $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 = $context->msg($key, $params)->parse(); $changed[] = "<li>{$message}</li>"; if ($this->checkProcessTime()) { $process = false; $message = $context->msg('translate-manage-toolong')->numParams($this->processingTime)->parse(); $changed[] = "<li>{$message}</li></ul>"; } continue; } } $alldone = false; $actions = $this->getActions(); $defaction = $this->getDefaultAction($fuzzy, $action); $act = array(); // Give grep a chance to find the usages: // translate-manage-action-import, translate-manage-action-conflict, // translate-manage-action-ignore, translate-manage-action-fuzzy foreach ($actions as $action) { $label = $context->msg("translate-manage-action-{$action}")->text(); $name = self::escapeNameForPHP("action-{$type}-{$key}"); $id = Sanitizer::escapeId("action-{$key}-{$action}"); $act[] = Xml::radioLabel($label, $name, $action, $id, $action === $defaction); } $param = '<code class="mw-tmi-diff">' . htmlspecialchars($key) . '</code>'; $name = $context->msg('translate-manage-import-diff', $param, implode(' ', $act))->text(); $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) { $para = '<code class="mw-tmi-deleted">' . htmlspecialchars($s) . '</code>'; $name = $context->msg('translate-manage-import-deleted')->rawParams($para)->escaped(); $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 = $context->msg('translate-manage-import-done')->parse(); $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, $context->getLanguage()->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($context->msg('translate-manage-submit')->text())); } else { $this->out->addWikiMsg('translate-manage-nochanges'); } } $this->out->addHTML($this->doFooter()); return $alldone; }