summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Translate/translationaids/TranslationAidDataProvider.php
blob: 2f6672efc64bf27be08605d772e012fec1603c25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
/**
 * Translation aid code.
 *
 * @file
 * @author Niklas Laxström
 * @license GPL-2.0-or-later
 */

use Wikimedia\Rdbms\IDatabase;

/**
 * @since 2018.01
 */
class TranslationAidDataProvider {
	private $handle;
	private $group;

	private $definition;
	private $translations;

	public function __construct( MessageHandle $handle ) {
		$this->handle = $handle;
		$this->group = $handle->getGroup();
	}

	/**
	 * Get the message definition. Cached for performance.
	 *
	 * @return string
	 */
	public function getDefinition() {
		if ( $this->definition !== null ) {
			return $this->definition;
		}

		// Optional performance optimization
		if ( method_exists( $this->group, 'getMessageContent' ) ) {
			$this->definition = $this->group->getMessageContent( $this->handle );
		} else {
			$this->definition = $this->group->getMessage(
				$this->handle->getKey(),
				$this->group->getSourceLanguage()
			);
		}

		return $this->definition;
	}

	/**
	 * @return Content
	 */
	public function getDefinitionContent() {
		return ContentHandler::makeContent( $this->getDefinition(), $this->handle->getTitle() );
	}

	/**
	 * Get the translations in all languages. Cached for performance.
	 * Fuzzy translation are not included.
	 *
	 * @return array Language code => Translation
	 */
	public function getGoodTranslations() {
		if ( $this->translations !== null ) {
			return $this->translations;
		}

		$data = self::loadTranslationData( wfGetDB( DB_REPLICA ), $this->handle );
		$translations = [];
		$prefixLength = strlen( $this->handle->getTitleForBase()->getDBKey() . '/' );

		foreach ( $data as $page => $translation ) {
			// Could use MessageHandle here, but that queries the message index.
			// Instead we can get away with simple string manipulation.
			$code = substr( $page, $prefixLength );
			if ( !Language::isKnownLanguageTag( $code ) ) {
				continue;
			}

			$translations[ $code ] = $translation;
		}

		$this->translations = $translations;

		return $translations;
	}

	private static function loadTranslationData( IDatabase $db, MessageHandle $handle ) {
		if ( method_exists( 'Revision', 'getQueryInfo' ) ) {
			$queryInfo = Revision::getQueryInfo( [ 'page', 'text' ] );
			$tables = $queryInfo[ 'tables' ];
			$fields = $queryInfo[ 'fields' ];
			$conds = [];
			$options = [];
			$joins = $queryInfo[ 'joins' ];
		} else {
			// BC for <= MW 1.31
			$tables = [ 'page', 'text', 'revision' ];
			$fields = array_merge(
				Revision::selectFields(),
				Revision::selectPageFields(),
				Revision::selectTextFields()
			);
			$conds = [];
			$options = [];
			$joins = [
				'page' => Revision::pageJoinCond(),
				'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ]
			];
		}

		// The list of pages we want to select, and their latest versions
		$conds['page_namespace'] = $handle->getTitle()->getNamespace();
		$base = $handle->getKey();
		$conds[] = 'page_title ' . $db->buildLike( "$base/", $db->anyString() );
		$conds[] = 'rev_id=page_latest';

		// For fuzzy tags we also need:
		$tables[] = 'revtag';
		$conds[ 'rt_type' ] = null;
		$joins[ 'revtag' ] = [
			'LEFT JOIN',
			[ 'page_id=rt_page', 'page_latest=rt_revision', 'rt_type' => 'fuzzy' ]
		];

		$rows = $db->select( $tables, $fields, $conds, __METHOD__, $options, $joins );

		$pages = [];
		foreach ( $rows as $row ) {
			$pages[$row->page_title] = Revision::getRevisionText( $row );
		}

		return $pages;
	}
}