summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php')
-rw-r--r--www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php248
1 files changed, 248 insertions, 0 deletions
diff --git a/www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php b/www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php
new file mode 100644
index 00000000..5208d179
--- /dev/null
+++ b/www/wiki/extensions/Translate/messagegroups/WikiPageMessageGroup.php
@@ -0,0 +1,248 @@
+<?php
+/**
+ * This file contains an unmanaged message group implementation.
+ *
+ * @file
+ * @author Niklas Laxström
+ * @author Siebrand Mazeland
+ * @license GPL-2.0-or-later
+ */
+
+/**
+ * Wraps the translatable page sections into a message group.
+ * @ingroup PageTranslation MessageGroup
+ */
+class WikiPageMessageGroup extends WikiMessageGroup implements IDBAccessObject, \Serializable {
+ /**
+ * @var Title|string
+ */
+ protected $title;
+
+ /**
+ * @var int
+ */
+ protected $namespace = NS_TRANSLATIONS;
+
+ /**
+ * @param string $id
+ * @param Title|string $source
+ */
+ public function __construct( $id, $source ) {
+ $this->id = $id;
+ $this->title = $source;
+ }
+
+ public function getSourceLanguage() {
+ return $this->getTitle()->getPageLanguage()->getCode();
+ }
+
+ /**
+ * @return Title
+ */
+ public function getTitle() {
+ if ( is_string( $this->title ) ) {
+ $this->title = Title::newFromText( $this->title );
+ }
+
+ return $this->title;
+ }
+
+ /**
+ * Only used for caching to avoid repeating database queries
+ * for example during message index rebuild.
+ */
+ protected $definitions;
+
+ /**
+ * @return array
+ */
+ public function getDefinitions() {
+ if ( is_array( $this->definitions ) ) {
+ return $this->definitions;
+ }
+
+ $dbr = TranslateUtils::getSafeReadDB();
+ $tables = 'translate_sections';
+ $vars = [ 'trs_key', 'trs_text' ];
+ $conds = [ 'trs_page' => $this->getTitle()->getArticleID() ];
+ $options = [ 'ORDER BY' => 'trs_order' ];
+ $res = $dbr->select( $tables, $vars, $conds, __METHOD__, $options );
+
+ $defs = [];
+ $prefix = $this->getTitle()->getPrefixedDBkey() . '/';
+
+ foreach ( $res as $r ) {
+ $section = new TPSection();
+ $section->text = $r->trs_text;
+ $defs[$r->trs_key] = $section->getTextWithVariables();
+ }
+
+ $new_defs = [];
+ foreach ( $defs as $k => $v ) {
+ $k = str_replace( ' ', '_', $k );
+ $new_defs[$prefix . $k] = $v;
+ }
+
+ $this->definitions = $new_defs;
+ return $this->definitions;
+ }
+
+ /**
+ * Overriding the getLabel method and deriving the label from the title.
+ * Mainly to reduce the amount of data stored in the cache.
+ *
+ * @param IContextSource|null $context
+ * @return string
+ */
+ public function getLabel( IContextSource $context = null ) {
+ return $this->getTitle()->getPrefixedText();
+ }
+
+ /**
+ * Clear caches to avoid stale data.
+ *
+ * For example JobQueue can run for a longer time, and stale definitions would
+ * cause the total number of messages to be incorrect.
+ *
+ * @since 2016.04
+ */
+ public function clearCaches() {
+ $this->definitions = null;
+ }
+
+ public function load( $code ) {
+ if ( $this->isSourceLanguage( $code ) ) {
+ return $this->getDefinitions();
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns of stored translation of message specified by the $key in language
+ * code $code.
+ *
+ * @param string $key Message key
+ * @param string $code Language code
+ * @param int $flags READ_* class constant bitfield
+ * @return string|null Stored translation or null.
+ */
+ public function getMessage( $key, $code, $flags = self::READ_LATEST ) {
+ if ( $this->isSourceLanguage( $code ) ) {
+ $stuff = $this->load( $code );
+
+ $title = Title::newFromText( $key );
+ if ( $title ) {
+ $key = $title->getPrefixedDBkey();
+ }
+
+ return $stuff[$key] ?? null;
+ }
+
+ $title = Title::makeTitleSafe( $this->getNamespace(), "$key/$code" );
+ if ( PageTranslationHooks::$renderingContext ) {
+ $revFlags = Revision::READ_NORMAL; // bug T95753
+ } else {
+ $revFlags = ( $flags & self::READ_LATEST ) == self::READ_LATEST
+ ? Revision::READ_LATEST
+ : Revision::READ_NORMAL;
+ }
+ $rev = Revision::newFromTitle( $title, false, $revFlags );
+
+ if ( !$rev ) {
+ return null;
+ }
+
+ return ContentHandler::getContentText( $rev->getContent() );
+ }
+
+ /**
+ * @return MediaWikiMessageChecker
+ */
+ public function getChecker() {
+ $checker = new MediaWikiMessageChecker( $this );
+ $checker->setChecks( [
+ [ $checker, 'pluralCheck' ],
+ [ $checker, 'braceBalanceCheck' ],
+ [ $checker, 'miscMWChecks' ]
+ ] );
+
+ return $checker;
+ }
+
+ public function getInsertablesSuggester() {
+ return new TranslatablePageInsertablesSuggester();
+ }
+
+ public function getDescription( IContextSource $context = null ) {
+ $title = $this->getTitle()->getPrefixedText();
+ $target = ":$title";
+ $pageLanguageCode = $this->getSourceLanguage();
+ $inLanguageCode = $context ? $context->getLanguage()->getCode() : null;
+ $languageName = Language::fetchLanguageName( $pageLanguageCode, $inLanguageCode );
+
+ // Allow for adding a custom group description by using
+ // "MediaWiki:Tp-custom-<group ID>".
+ $customText = '';
+ $msg = wfMessage( 'tp-custom-' . $this->id );
+ self::addContext( $msg, $context );
+ if ( $msg->exists() ) {
+ $customText = $msg->plain();
+ }
+
+ $msg = wfMessage( 'translate-tag-page-desc', $title, $target, $languageName, $pageLanguageCode );
+ self::addContext( $msg, $context );
+
+ return $msg->plain() . $customText;
+ }
+
+ public function serialize() {
+ $toSerialize = [
+ 'title' => $this->getTitle()->getPrefixedText(),
+ 'id' => $this->id,
+ '_v' => 1 // version - to track incompatible changes
+ ];
+
+ // NOTE: get_class_vars returns properties before the constructor has run so if any default
+ // values have to be set for properties, do them while declaring the properties themselves.
+ // Also any properties that are object will automatically be serialized because `===`
+ // does not actually compare object properties to see that they are same.
+
+ // Using array_diff_key to unset the properties already set earlier.
+ $defaultProps = array_diff_key( get_class_vars( self::class ), $toSerialize );
+
+ foreach ( $defaultProps as $prop => $defaultVal ) {
+ if ( $this->{$prop} === $defaultVal ) {
+ continue;
+ }
+
+ $toSerialize[$prop] = $this->{$prop};
+ }
+
+ return FormatJson::encode( $toSerialize, false, FormatJson::ALL_OK );
+ }
+
+ public function unserialize( $serialized ) {
+ $deserialized = FormatJson::decode( $serialized );
+ if ( $deserialized === false ) {
+ // Unrecoverable. This should not happen but still.
+ throw new \UnexpectedValueException(
+ 'Error while deserializing to WikiPageMessageGroup object - FormatJson::decode failed. ' .
+ "Serialize string - $serialized."
+ );
+ }
+
+ // Use as needed in the future to track incompatible changes.
+ // $version = $deserialized->_v;
+ // unset($deserialized->_v);
+
+ // Only set the properties that are present in the class and the deserialized object.
+ $classProps = array_keys( get_class_vars( self::class ) );
+
+ foreach ( $classProps as $prop ) {
+ if ( property_exists( $deserialized, $prop ) ) {
+ $this->{$prop} = $deserialized->{$prop};
+ }
+ }
+ }
+}