3 namespace Drupal\Tests\content_translation\Kernel;
5 use Drupal\content_translation\FieldTranslationSynchronizer;
6 use Drupal\KernelTests\KernelTestBase;
9 * Tests the field synchronization logic.
11 * @group content_translation
13 class ContentTranslationSyncUnitTest extends KernelTestBase {
16 * The synchronizer class to be tested.
18 * @var \Drupal\content_translation\FieldTranslationSynchronizer
20 protected $synchronizer;
23 * The columns to be synchronized.
27 protected $synchronized;
30 * All the field columns.
37 * The available language codes.
44 * The field cardinality.
48 protected $cardinality;
51 * The unchanged field values.
55 protected $unchangedFieldValues;
57 public static $modules = ['language', 'content_translation'];
59 protected function setUp() {
62 $this->synchronizer = new FieldTranslationSynchronizer($this->container->get('entity.manager'));
63 $this->synchronized = ['sync1', 'sync2'];
64 $this->columns = array_merge($this->synchronized, ['var1', 'var2']);
65 $this->langcodes = ['en', 'it', 'fr', 'de', 'es'];
66 $this->cardinality = 4;
67 $this->unchangedFieldValues = [];
69 // Set up an initial set of values in the correct state, that is with
70 // "synchronized" values being equal.
71 foreach ($this->langcodes as $langcode) {
72 for ($delta = 0; $delta < $this->cardinality; $delta++) {
73 foreach ($this->columns as $column) {
74 $sync = in_array($column, $this->synchronized) && $langcode != $this->langcodes[0];
75 $value = $sync ? $this->unchangedFieldValues[$this->langcodes[0]][$delta][$column] : $langcode . '-' . $delta . '-' . $column;
76 $this->unchangedFieldValues[$langcode][$delta][$column] = $value;
83 * Tests the field synchronization algorithm.
85 public function testFieldSync() {
86 // Add a new item to the source items and check that its added to all the
88 $sync_langcode = $this->langcodes[2];
89 $unchanged_items = $this->unchangedFieldValues[$sync_langcode];
90 $field_values = $this->unchangedFieldValues;
92 foreach ($this->columns as $column) {
93 $item[$column] = $this->randomMachineName();
95 $field_values[$sync_langcode][] = $item;
96 $this->synchronizer->synchronizeItems($field_values, $unchanged_items, $sync_langcode, $this->langcodes, $this->synchronized);
98 foreach ($this->unchangedFieldValues as $langcode => $items) {
99 // Check that the old values are still in place.
100 for ($delta = 0; $delta < $this->cardinality; $delta++) {
101 foreach ($this->columns as $column) {
102 $result = $result && ($this->unchangedFieldValues[$langcode][$delta][$column] == $field_values[$langcode][$delta][$column]);
105 // Check that the new item is available in all languages.
106 foreach ($this->columns as $column) {
107 $result = $result && ($field_values[$langcode][$delta][$column] == $field_values[$sync_langcode][$delta][$column]);
110 $this->assertTrue($result, 'A new item has been correctly synchronized.');
112 // Remove an item from the source items and check that its removed from all
114 $sync_langcode = $this->langcodes[1];
115 $unchanged_items = $this->unchangedFieldValues[$sync_langcode];
116 $field_values = $this->unchangedFieldValues;
117 $sync_delta = mt_rand(0, count($field_values[$sync_langcode]) - 1);
118 unset($field_values[$sync_langcode][$sync_delta]);
119 // Renumber deltas to start from 0.
120 $field_values[$sync_langcode] = array_values($field_values[$sync_langcode]);
121 $this->synchronizer->synchronizeItems($field_values, $unchanged_items, $sync_langcode, $this->langcodes, $this->synchronized);
123 foreach ($this->unchangedFieldValues as $langcode => $items) {
125 // Check that the old values are still in place.
126 for ($delta = 0; $delta < $this->cardinality; $delta++) {
127 // Skip the removed item.
128 if ($delta != $sync_delta) {
129 foreach ($this->columns as $column) {
130 $result = $result && ($this->unchangedFieldValues[$langcode][$delta][$column] == $field_values[$langcode][$new_delta][$column]);
136 $this->assertTrue($result, 'A removed item has been correctly synchronized.');
138 // Move the items around in the source items and check that they are moved
139 // in all the translations.
140 $sync_langcode = $this->langcodes[3];
141 $unchanged_items = $this->unchangedFieldValues[$sync_langcode];
142 $field_values = $this->unchangedFieldValues;
143 $field_values[$sync_langcode] = [];
144 // Scramble the items.
145 foreach ($unchanged_items as $delta => $item) {
146 $new_delta = ($delta + 1) % $this->cardinality;
147 $field_values[$sync_langcode][$new_delta] = $item;
149 // Renumber deltas to start from 0.
150 ksort($field_values[$sync_langcode]);
151 $this->synchronizer->synchronizeItems($field_values, $unchanged_items, $sync_langcode, $this->langcodes, $this->synchronized);
153 foreach ($field_values as $langcode => $items) {
154 for ($delta = 0; $delta < $this->cardinality; $delta++) {
155 foreach ($this->columns as $column) {
156 $value = $field_values[$langcode][$delta][$column];
157 if (in_array($column, $this->synchronized)) {
158 // If we are dealing with a synchronize column the current value is
159 // supposed to be the same of the source items.
160 $result = $result && $field_values[$sync_langcode][$delta][$column] == $value;
163 // Otherwise the values should be unchanged.
164 $old_delta = ($delta > 0 ? $delta : $this->cardinality) - 1;
165 $result = $result && $this->unchangedFieldValues[$langcode][$old_delta][$column] == $value;
170 $this->assertTrue($result, 'Scrambled items have been correctly synchronized.');
174 * Tests that items holding the same values are correctly synchronized.
176 public function testMultipleSyncedValues() {
177 $sync_langcode = $this->langcodes[1];
178 $unchanged_items = $this->unchangedFieldValues[$sync_langcode];
180 // Determine whether the unchanged values should be altered depending on
183 // Continuous field values: all values are equal.
187 // Alternated field values: only the even ones are equal.
189 return $delta % 2 !== 0;
191 // Sparse field values: only the "middle" ones are equal.
193 return $delta === 1 || $delta === 2;
195 // Sparse field values: only the "extreme" ones are equal.
197 return $delta === 0 || $delta === 3;
201 foreach ($delta_callbacks as $delta_callback) {
202 $field_values = $this->unchangedFieldValues;
204 for ($delta = 0; $delta < $this->cardinality; $delta++) {
205 if ($delta_callback($delta)) {
206 foreach ($this->columns as $column) {
207 if (in_array($column, $this->synchronized)) {
208 $field_values[$sync_langcode][$delta][$column] = $field_values[$sync_langcode][0][$column];
214 $changed_items = $field_values[$sync_langcode];
215 $this->synchronizer->synchronizeItems($field_values, $unchanged_items, $sync_langcode, $this->langcodes, $this->synchronized);
217 foreach ($this->unchangedFieldValues as $langcode => $unchanged_items) {
218 for ($delta = 0; $delta < $this->cardinality; $delta++) {
219 foreach ($this->columns as $column) {
220 // The first item is always unchanged hence it is retained by the
221 // synchronization process. The other ones are retained or synced
222 // depending on the logic implemented by the delta callback and
223 // whether it is a sync column or not.
224 $value = $delta > 0 && $delta_callback($delta) && in_array($column, $this->synchronized) ? $changed_items[0][$column] : $unchanged_items[$delta][$column];
225 $this->assertEqual($field_values[$langcode][$delta][$column], $value, "Item $delta column $column for langcode $langcode synced correctly");
233 * Tests that one change in a synchronized column triggers a change in all columns.
235 public function testDifferingSyncedColumns() {
236 $sync_langcode = $this->langcodes[2];
237 $unchanged_items = $this->unchangedFieldValues[$sync_langcode];
238 $field_values = $this->unchangedFieldValues;
240 for ($delta = 0; $delta < $this->cardinality; $delta++) {
241 $index = ($delta % 2) + 1;
242 $field_values[$sync_langcode][$delta]['sync' . $index] .= '-updated';
245 $changed_items = $field_values[$sync_langcode];
246 $this->synchronizer->synchronizeItems($field_values, $unchanged_items, $sync_langcode, $this->langcodes, $this->synchronized);
248 foreach ($this->unchangedFieldValues as $langcode => $unchanged_items) {
249 for ($delta = 0; $delta < $this->cardinality; $delta++) {
250 foreach ($this->columns as $column) {
251 // If the column is synchronized, the value should have been synced,
252 // for unsychronized columns, the value must not change.
253 $expected_value = in_array($column, $this->synchronized) ? $changed_items[$delta][$column] : $this->unchangedFieldValues[$langcode][$delta][$column];
254 $this->assertEqual($field_values[$langcode][$delta][$column], $expected_value, "Differing Item $delta column $column for langcode $langcode synced correctly");