diff options
Diffstat (limited to 'MLEB/Translate/TranslateHooks.php')
-rw-r--r-- | MLEB/Translate/TranslateHooks.php | 375 |
1 files changed, 81 insertions, 294 deletions
diff --git a/MLEB/Translate/TranslateHooks.php b/MLEB/Translate/TranslateHooks.php index 3d092870..7c26d147 100644 --- a/MLEB/Translate/TranslateHooks.php +++ b/MLEB/Translate/TranslateHooks.php @@ -8,19 +8,26 @@ */ use MediaWiki\Config\ServiceOptions; +use MediaWiki\Extension\Translate\PageTranslation\PageTranslationSpecialPage; use MediaWiki\Extension\Translate\SystemUsers\FuzzyBot; use MediaWiki\Extension\Translate\SystemUsers\TranslateUserManager; use MediaWiki\Extension\Translate\TranslatorSandbox\ManageTranslatorSandboxSpecialPage; use MediaWiki\Extension\Translate\TranslatorSandbox\TranslationStashSpecialPage; use MediaWiki\Hook\BeforeParserFetchTemplateRevisionRecordHook; -use MediaWiki\Hook\PageMoveCompleteHook; -use MediaWiki\Hook\SidebarBeforeOutputHook; use MediaWiki\MediaWikiServices; +use MediaWiki\Revision\Hook\RevisionRecordInsertedHook; +use MediaWiki\Revision\RevisionLookup; +use Wikimedia\Rdbms\ILoadBalancer; /** - * Some hooks for Translate extension. + * Hooks for Translate extension. + * + * Main subsystems, like page translation, should have their own hook handler. + * + * Most of the hooks on this class are still old style static functions, but new new hooks should + * use the new style hook handlers with interfaces. */ -class TranslateHooks { +class TranslateHooks implements RevisionRecordInsertedHook { /** * Any user of this list should make sure that the tables * actually exist, since they may be optional @@ -31,6 +38,15 @@ class TranslateHooks { 'translate_stash' => 'ts_user', 'translate_reviews' => 'trr_user', ]; + /** @var RevisionLookup */ + private $revisionLookup; + /** @var ILoadBalancer */ + private $loadBalancer; + + public function __construct( RevisionLookup $revisionLookup, ILoadBalancer $loadBalancer ) { + $this->revisionLookup = $revisionLookup; + $this->loadBalancer = $loadBalancer; + } /** * Do late setup that depends on configuration. @@ -50,19 +66,23 @@ class TranslateHooks { $wgTranslateYamlLibrary = function_exists( 'yaml_parse' ) ? 'phpyaml' : 'spyc'; } - $usePageSaveComplete = version_compare( TranslateUtils::getMWVersion(), '1.35', '>=' ); - if ( $usePageSaveComplete ) { - $wgHooks['PageSaveComplete'][] = 'TranslateEditAddons::onSaveComplete'; - } else { - $wgHooks['PageContentSaveComplete'][] = 'TranslateEditAddons::onSave'; - } + $wgHooks['PageSaveComplete'][] = 'TranslateEditAddons::onSaveComplete'; // Page translation setup check and init if enabled. global $wgEnablePageTranslation; if ( $wgEnablePageTranslation ) { // Special page and the right to use it global $wgSpecialPages, $wgAvailableRights; - $wgSpecialPages['PageTranslation'] = 'SpecialPageTranslation'; + $wgSpecialPages['PageTranslation'] = [ + 'class' => PageTranslationSpecialPage::class, + 'services' => [ + 'LanguageNameUtils', + 'LanguageFactory', + 'Translate:TranslationUnitStoreFactory', + 'Translate:TranslatablePageParser', + 'LinkBatchFactory' + ] + ]; $wgSpecialPages['PageTranslationDeletePage'] = 'SpecialPageTranslationDeletePage'; // right-pagetranslation action-pagetranslation @@ -131,16 +151,13 @@ class TranslateHooks { $wgHooks['BeforePageDisplay'][] = 'PageTranslationHooks::onBeforePageDisplay'; // Check syntax for \<translate> - $wgHooks['PageContentSave'][] = 'PageTranslationHooks::tpSyntaxCheck'; + $wgHooks['MultiContentSave'][] = 'PageTranslationHooks::tpSyntaxCheck'; $wgHooks['EditFilterMergedContent'][] = 'PageTranslationHooks::tpSyntaxCheckForEditContent'; // Add transtag to page props for discovery - if ( $usePageSaveComplete ) { - $wgHooks['PageSaveComplete'][] = 'PageTranslationHooks::addTranstagAfterSave'; - } else { - $wgHooks['PageContentSaveComplete'][] = 'PageTranslationHooks::addTranstag'; - } + $wgHooks['PageSaveComplete'][] = 'PageTranslationHooks::addTranstagAfterSave'; + $wgHooks['RevisionRecordInserted'][] = 'PageTranslationHooks::updateTranstagOnNullRevisions'; @@ -190,11 +207,7 @@ class TranslateHooks { $wgHooks['SkinTemplateNavigation'][] = 'PageTranslationHooks::translateTab'; // Update translated page when translation unit is moved - if ( interface_exists( PageMoveCompleteHook::class ) ) { - $wgHooks['PageMoveComplete'][] = 'PageTranslationHooks::onMovePageTranslationUnits'; - } else { - $wgHooks['TitleMoveComplete'][] = 'PageTranslationHooks::onMoveTranslationUnits'; - } + $wgHooks['PageMoveComplete'][] = 'PageTranslationHooks::onMovePageTranslationUnits'; // Update translated page when translation unit is deleted $wgHooks['ArticleDeleteComplete'][] = 'PageTranslationHooks::onDeleteTranslationUnit'; @@ -210,7 +223,7 @@ class TranslateHooks { 'Translate:TranslationStashReader', ], 'args' => [ - function () { + static function () { return new ServiceOptions( ManageTranslatorSandboxSpecialPage::CONSTRUCTOR_OPTIONS, MediaWikiServices::getInstance()->getMainConfig() @@ -225,7 +238,7 @@ class TranslateHooks { 'Translate:TranslationStashReader' ], 'args' => [ - function () { + static function () { return new ServiceOptions( TranslationStashSpecialPage::CONSTRUCTOR_OPTIONS, MediaWikiServices::getInstance()->getMainConfig() @@ -278,12 +291,7 @@ class TranslateHooks { } } - // Add the BaseTemplateToolbox handler only when the new hook hasn't been defined yet. - if ( interface_exists( SidebarBeforeOutputHook::class ) ) { - $wgHooks['SidebarBeforeOutput'][] = 'TranslateToolbox::toolboxAllTranslations'; - } else { - $wgHooks['BaseTemplateToolbox'][] = 'TranslateToolbox::toolboxAllTranslationsOld'; - } + $wgHooks['SidebarBeforeOutput'][] = 'TranslateToolbox::toolboxAllTranslations'; } /** @@ -660,37 +668,6 @@ class TranslateHooks { } /** - * Hook: Translate:MessageGroupStats:isIncluded - * @param int $id - * @param string $code - * @return bool - */ - public static function hideDiscouragedFromStats( $id, $code ) { - // Return true to keep, false to exclude - return MessageGroups::getPriority( $id ) !== 'discouraged'; - } - - /** - * Hook: Translate:MessageGroupStats:isIncluded - * @param int $id - * @param string $code - * @return false - */ - public static function hideRestrictedFromStats( $id, $code ) { - $filterLangs = TranslateMetadata::get( $id, 'prioritylangs' ); - $hasPriorityForce = TranslateMetadata::get( $id, 'priorityforce' ) === 'on'; - if ( strlen( $filterLangs ) === 0 || !$hasPriorityForce ) { - // No restrictions, keep everything - return true; - } - - $filter = array_flip( explode( ',', $filterLangs ) ); - - // If the language is in the list, return true to not hide it - return isset( $filter[$code] ); - } - - /** * Hook: LinksUpdate * @param LinksUpdate $updater */ @@ -754,7 +731,7 @@ class TranslateHooks { * @param User $newUser */ public static function onMergeAccountFromTo( User $oldUser, User $newUser ) { - $dbw = wfGetDB( DB_MASTER ); + $dbw = wfGetDB( DB_PRIMARY ); // Update the non-duplicate rows, we'll just delete // the duplicate ones later @@ -778,7 +755,7 @@ class TranslateHooks { * @param User $oldUser */ public static function onDeleteAccount( User $oldUser ) { - $dbw = wfGetDB( DB_MASTER ); + $dbw = wfGetDB( DB_PRIMARY ); // Delete any remaining rows that didn't get merged foreach ( self::$userMergeTables as $table => $field ) { @@ -868,234 +845,6 @@ class TranslateHooks { return ''; } - /** @param ResourceLoader $resourceLoader */ - public static function onResourceLoaderRegisterModules( ResourceLoader $resourceLoader ) { - // Support: MediaWiki <= 1.34 - $hasOldTokens = $hasOldNotify = version_compare( - TranslateUtils::getMWVersion(), '1.35', '<' - ); - - $tpl = [ - 'localBasePath' => __DIR__, - 'remoteExtPath' => 'Translate', - 'targets' => [ 'desktop', 'mobile' ], - ]; - - $modules = [ - 'ext.translate.recentgroups' => $tpl + [ - 'scripts' => 'resources/js/ext.translate.recentgroups.js', - 'dependencies' => [ - 'mediawiki.storage' - ], - ], - 'ext.translate.groupselector' => $tpl + [ - 'styles' => 'resources/css/ext.translate.groupselector.less', - 'scripts' => 'resources/js/ext.translate.groupselector.js', - 'dependencies' => [ - 'ext.translate.base', - 'ext.translate.loader', - 'ext.translate.statsbar', - 'jquery.ui', - 'mediawiki.jqueryMsg' - ], - 'messages' => [ - 'translate-msggroupselector-search-all', - 'translate-msggroupselector-search-placeholder', - 'translate-msggroupselector-search-recent', - 'translate-msggroupselector-view-subprojects' - ] - ], - 'ext.translate.special.aggregategroups' => $tpl + [ - 'scripts' => 'resources/js/ext.translate.special.aggregategroups.js', - 'dependencies' => [ - 'jquery.ui', - 'mediawiki.api', - 'mediawiki.util' - ], - 'messages' => [ - 'tpt-aggregategroup-add', - 'tpt-aggregategroup-edit-description', - 'tpt-aggregategroup-edit-name', - 'tpt-aggregategroup-remove-confirm', - 'tpt-aggregategroup-update', - 'tpt-aggregategroup-update-cancel', - 'tpt-invalid-group' - ] - ], - 'ext.translate.special.importtranslations' => $tpl + [ - 'scripts' => 'resources/js/ext.translate.special.importtranslations.js', - 'dependencies' => [ - 'jquery.ui', - ] - ], - 'ext.translate.special.managetranslatorsandbox' => $tpl + [ - 'scripts' => 'resources/js/ext.translate.special.managetranslatorsandbox.js', - 'dependencies' => array_merge( [ - 'ext.translate.loader', - 'ext.translate.translationstashstorage', - 'ext.uls.mediawiki', - 'jquery.ui', - 'mediawiki.api', - 'mediawiki.jqueryMsg', - 'mediawiki.language', - ], $hasOldNotify ? [ 'mediawiki.notify' ] : [] ), - 'messages' => [ - 'tsb-accept-all-button-label', - 'tsb-accept-button-label', - 'tsb-reject-confirmation', - 'tsb-accept-confirmation', - 'tsb-all-languages-button-label', - 'tsb-didnt-make-any-translations', - 'tsb-no-requests-from-new-users', - 'tsb-older-requests', - 'tsb-reject-all-button-label', - 'tsb-reject-button-label', - 'tsb-reminder-failed', - 'tsb-reminder-link-text', - 'tsb-reminder-sending', - 'tsb-reminder-sent', - 'tsb-reminder-sent-new', - 'tsb-request-count', - 'tsb-selected-count', - 'tsb-translations-current', - 'tsb-translations-source', - 'tsb-translations-user', - 'tsb-user-posted-a-comment' - ] - ], - 'ext.translate.special.searchtranslations.operatorsuggest' => $tpl + [ - 'scripts' => 'resources/js/ext.translate.special.operatorsuggest.js', - 'dependencies' => [ - 'jquery.ui', - ] - ], - 'ext.translate.special.pagetranslation' => $tpl + [ - 'packageFiles' => [ - 'resources/js/ext.translate.special.pagetranslation.js', - 'resources/js/LanguagesMultiselectWidget.js' - ], - 'dependencies' => [ - 'mediawiki.Uri', - 'mediawiki.api', - 'mediawiki.ui.button', - 'mediawiki.widgets', - 'oojs-ui-widgets', - $hasOldTokens ? 'user.tokens' : 'user.options', - ], - 'targets' => [ - 'desktop' - ] - ], - "ext.translate.editor" => $tpl + [ - "scripts" => [ - "resources/js/ext.translate.storage.js", - "resources/lib/jquery.autosize.js", - "resources/js/ext.translate.editor.helpers.js", - "resources/js/ext.translate.editor.js", - "resources/js/ext.translate.editor.shortcuts.js", - "resources/js/ext.translate.pagemode.js", - "resources/js/ext.translate.proofread.js" - ], - "styles" => [ - "resources/css/ext.translate.editor.css", - "resources/css/ext.translate.pagemode.css", - "resources/css/ext.translate.proofread.css" - ], - "dependencies" => array_merge( [ - "ext.translate.base", - "ext.translate.dropdownmenu", - "jquery.makeCollapsible", - "jquery.textSelection", - "jquery.textchange", - "mediawiki.Uri", - "mediawiki.api", - "mediawiki.jqueryMsg", - "mediawiki.language", - "mediawiki.user", - "mediawiki.util" - ], $hasOldNotify ? [ 'mediawiki.notify' ] : [] ), - "messages" => [ - "translate-edit-askpermission", - "translate-edit-nopermission", - "tux-editor-add-desc", - "tux-editor-ask-help", - "tux-editor-cancel-button-label", - "tux-editor-close-tooltip", - "tux-editor-collapse-tooltip", - "tux-editor-confirm-button-label", - "tux-editor-discard-changes-button-label", - "tux-editor-doc-editor-cancel", - "tux-editor-doc-editor-placeholder", - "tux-editor-doc-editor-save", - "tux-editor-edit-desc", - "tux-editor-expand-tooltip", - "tux-editor-in-other-languages", - "tux-editor-loading", - "tux-editor-loading-failed", - "tux-editor-message-desc-less", - "tux-editor-message-desc-more", - "tux-editor-message-tools-show-editor", - "tux-editor-message-tools-delete", - "tux-editor-message-tools-history", - "tux-editor-message-tools-translations", - "tux-editor-message-tools-linktothis", - "tux-editor-n-uses", - "tux-editor-need-more-help", - "tux-editor-outdated-notice", - "tux-editor-outdated-notice-diff-link", - "tux-editor-paste-original-button-label", - "tux-editor-placeholder", - "tux-editor-editsummary-placeholder", - "tux-editor-proofread-button-label", - "tux-editor-save-button-label", - "tux-editor-save-failed", - "tux-editor-shortcut-info", - "tux-editor-skip-button-label", - "tux-editor-suggestions-title", - "tux-editor-tm-match", - "tux-proofread-action-tooltip", - "tux-proofread-edit-label", - "tux-proofread-translated-by-self", - "tux-session-expired", - "tux-status-saving", - "tux-status-translated", - "tux-status-unsaved", - "tux-save-unknown-error", - "tux-notices-hide", - "tux-notices-more", - "spamprotectiontext" - ], - "targets" => [ - "desktop", - "mobile" - ] - ], - "ext.translate.special.managegroups" => $tpl + [ - "dependencies" => array_merge( [ - "ext.translate.messagerenamedialog" - ], $hasOldNotify ? [ 'mediawiki.notify' ] : [] ), - "messages" => [ - "translate-smg-rename-new", - "translate-smg-rename-rename", - "translate-smg-rename-dialog-title", - "translate-smg-loading", - "translate-smg-group-action-resolve", - "translate-smg-unknown-error", - "percent" - ], - "scripts" => [ - "resources/js/ext.translate.special.managegroups.js" - ], - "targets" => [ - "desktop", - "mobile" - ] - ], - ]; - - $resourceLoader->register( $modules ); - } - /** * Runs the configured validator to ensure that the message meets the required criteria. * Hook: EditFilterMergedContent @@ -1103,7 +852,7 @@ class TranslateHooks { * @param Content $content * @param Status $status * @param string $summary - * @param \User $user + * @param User $user * @return bool true if message is valid, false otherwise. */ public static function validateMessage( IContextSource $context, Content $content, @@ -1148,8 +897,7 @@ class TranslateHooks { $validationResponse = $messageValidator->validateMessage( $message, $handle->getCode() ); if ( $validationResponse->hasErrors() ) { - // @phan-suppress-next-line SecurityCheck-DoubleEscaped - $status->fatal( new \ApiRawMessage( + $status->fatal( new ApiRawMessage( $context->msg( 'translate-syntax-error' )->parse(), 'translate-validation-failed', [ @@ -1159,10 +907,49 @@ class TranslateHooks { ] ] ) ); + // @todo Remove this line after this extension do not support mediawiki version 1.36 and before + $status->value = EditPage::AS_HOOK_ERROR_EXPECTED; return false; } } return true; } + + /** @inheritDoc */ + public function onRevisionRecordInserted( $revisionRecord ): void { + $parentId = $revisionRecord->getParentId(); + if ( $parentId === 0 || $parentId === null ) { + // No parent, bail out. + return; + } + + $prevRev = $this->revisionLookup->getRevisionById( $parentId ); + if ( !$prevRev || !$revisionRecord->hasSameContent( $prevRev ) ) { + // Not a null revision, bail out. + return; + } + + // List of tags that should be copied over when updating + // tp:tag and tp:mark handling is in PageTranslationHooks::updateTranstagOnNullRevisions. + $tagsToCopy = [ 'fuzzy', 'tp:transver' ]; + + $db = $this->loadBalancer->getConnectionRef( DB_PRIMARY ); + $db->insertSelect( + 'revtag', + 'revtag', + [ + 'rt_type' => 'rt_type', + 'rt_page' => 'rt_page', + 'rt_revision' => $revisionRecord->getId(), + 'rt_value' => 'rt_value', + + ], + [ + 'rt_type' => $tagsToCopy, + 'rt_revision' => $parentId, + ], + __METHOD__ + ); + } } |