/** * 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')); }
/** * This function does the heavy duty of marking a page. * - Updates the source page with section markers. * - Updates translate_sections table * - Updates revtags table * - Setups renderjobs to update the translation pages * - Invalidates caches * @param $page TranslatablePage * @param $sections array * @return array|bool */ public function markForTranslation( TranslatablePage $page, Array $sections ) { global $wgRequest; // Add the section markers to the source page $article = new Article( $page->getTitle(), 0 ); $status = $article->doEdit( $page->getParse()->getSourcePageText(), // Content wfMsgForContent( 'tpt-mark-summary' ), // Summary EDIT_FORCE_BOT | EDIT_UPDATE, // Flags $page->getRevision() // Based-on revision ); if ( !$status->isOK() ) { self::superDebug( __METHOD__, 'edit-fail', $this->user, $page->getTitle(), $status ); return array( 'tpt-edit-failed', $status->getWikiText() ); } $newrevision = $status->value['revision']; // In theory it is either null or Revision object, // never revision object with null id, but who knows if ( $newrevision instanceof Revision ) { $newrevision = $newrevision->getId(); } if ( $newrevision === null ) { // Probably a no-change edit, so no new revision was assigned. // Get the latest revision manually $newrevision = $page->getTitle()->getLatestRevId(); } self::superDebug( __METHOD__, 'latestrev', $page->getTitle(), $newrevision ); $inserts = array(); $changed = array(); $pageId = $page->getTitle()->getArticleId(); foreach ( array_values( $sections ) as $index => $s ) { if ( $s->type === 'changed' ) { // Allow silent changes to avoid fuzzying unnecessary. if ( !$wgRequest->getCheck( "tpt-sect-{$s->id}-action-nofuzzy" ) ) { $changed[] = $s->name; } } $inserts[] = array( 'trs_page' => $pageId, 'trs_key' => $s->name, 'trs_text' => $s->getText(), 'trs_order' => $index ); } // Don't add stuff if no changes, use the plain null instead for prettiness if ( !count( $changed ) ) { $changed = null; } $dbw = wfGetDB( DB_MASTER ); if ( !$dbw->fieldExists( 'translate_sections', 'trs_order', __METHOD__ ) ) { error_log( 'Field trs_order does not exist. Please run update.php.' ); foreach ( array_keys( $inserts ) as $index ) { unset( $inserts[$index]['trs_order'] ); } } $dbw->delete( 'translate_sections', array( 'trs_page' => $page->getTitle()->getArticleId() ), __METHOD__ ); $dbw->insert( 'translate_sections', $inserts, __METHOD__ ); /* Stores the names of changed sections in the database. * Used for calculating completion percentages for outdated messages */ $page->addMarkedTag( $newrevision, $changed ); $this->addFuzzyTags( $page, $changed ); global $wgUser; $logger = new LogPage( 'pagetranslation' ); $params = array( 'user' => $wgUser->getName(), 'revision' => $newrevision, 'changed' => count( $changed ), ); $logger->addEntry( 'mark', $page->getTitle(), null, array( serialize( $params ) ) ); $page->getTitle()->invalidateCache(); $this->setupRenderJobs( $page ); // Re-generate caches MessageGroups::clearCache(); MessageIndexRebuildJob::newJob()->insert(); return false; }