summaryrefslogtreecommitdiff
blob: 51674921c651a1a294edf50c551190c69d99a751 (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
<?php

/**
 * Finds external changes for file based message groups.
 *
 * @author Niklas Laxström
 * @license GPL-2.0-or-later
 * @since 2016.02
 */

use MediaWiki\Extensions\Translate\MessageSync\MessageSourceChange;

class ExternalMessageSourceStateImporter {

	/**
	 * @param MessageSourceChange[] $changeData
	 * @return array
	 */
	public function importSafe( array $changeData ) {
		$processed = [];
		$skipped = [];
		$jobs = [];
		$jobs[] = MessageIndexRebuildJob::newJob();

		/**
		 * @var MessageSourceChange $changesForGroup
		 */
		foreach ( $changeData as $groupId => $changesForGroup ) {
			/**
			 * @var FileBasedMessageGroup
			 */
			$group = MessageGroups::getGroup( $groupId );
			if ( !$group ) {
				unset( $changeData[$groupId] );
				continue;
			}
			'@phan-var FileBasedMessageGroup $group';

			$processed[$groupId] = [];
			$languages = $changesForGroup->getLanguages();

			foreach ( $languages as $language ) {
				if ( !self::isSafe( $changesForGroup, $language ) ) {
					// changes other than additions were present
					$skipped[$groupId] = true;
					continue;
				}

				$additions = $changesForGroup->getAdditions( $language );
				if ( $additions === [] ) {
					continue;
				}

				[ $groupJobs, $groupProcessed ] = $this->createMessageUpdateJobs(
					$group, $additions, $language
				);

				$jobs = array_merge( $jobs, $groupJobs );
				$processed[$groupId][$language] = $groupProcessed;

				$changesForGroup->removeChangesForLanguage( $language );
				$group->getMessageGroupCache( $language )->create();
			}
		}

		// Remove groups where everything was imported
		$changeData = array_filter( $changeData, function ( MessageSourceChange $change ) {
			return $change->getAllModifications() !== [];
		} );

		// Remove groups with no imports
		$processed = array_filter( $processed );

		$name = 'unattended';
		$file = MessageChangeStorage::getCdbPath( $name );
		MessageChangeStorage::writeChanges( $changeData, $file );
		JobQueueGroup::singleton()->push( $jobs );

		return [
			'processed' => $processed,
			'skipped' => $skipped,
			'name' => $name,
		];
	}

	/**
	 * Checks if changes for a language in a group are safe.
	 * @param MessageSourceChange $changesForGroup
	 * @param string $language
	 * @return bool
	 */
	public static function isSafe( MessageSourceChange $changesForGroup, $language ) {
		return $changesForGroup->hasOnly( $language, MessageSourceChange::ADDITION );
	}

	/**
	 * Creates MessagUpdateJobs additions for a language under a group
	 *
	 * @param MessageGroup $group
	 * @param string[][] $additions
	 * @param string $language
	 * @return array
	 */
	private function createMessageUpdateJobs(
		MessageGroup $group, array $additions, string $language
	) {
		$groupId = $group->getId();
		$jobs = [];
		$processed = 0;
		foreach ( $additions as $addition ) {
			$namespace = $group->getNamespace();
			$name = "{$addition['key']}/$language";

			$title = Title::makeTitleSafe( $namespace, $name );
			if ( !$title ) {
				wfWarn( "Invalid title for group $groupId key {$addition['key']}" );
				continue;
			}

			$jobs[] = MessageUpdateJob::newJob( $title, $addition['content'] );
			$processed++;
		}

		return [ $jobs, $processed ];
	}
}