Projet

Général

Profil

Paste
Télécharger (51,5 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / field_collection / field_collection.test @ 5e632cae

1
<?php
2

    
3
/**
4
 * @file
5
 * field_collections tests.
6
 */
7

    
8
/**
9
 * Test basics.
10
 */
11
class FieldCollectionBasicTestCase extends DrupalWebTestCase {
12

    
13
  public static function getInfo() {
14
    return array(
15
      'name' => 'Field collection',
16
      'description' => 'Tests creating and using field collections.',
17
      'group' => 'Field types',
18
    );
19
  }
20

    
21
  function setUp() {
22
    parent::setUp('field_collection', 'entity_crud_hook_test');
23

    
24
    // Create a field_collection field to use for the tests.
25
    $this->field_name = 'field_test_collection';
26
    $this->field = array(
27
      'field_name' => $this->field_name,
28
      'type' => 'field_collection',
29
      'cardinality' => 4,
30
    );
31
    $this->field = field_create_field($this->field);
32
    $this->field_id = $this->field['id'];
33

    
34
    $this->instance = array(
35
      'field_name' => $this->field_name,
36
      'entity_type' => 'node',
37
      'bundle' => 'article',
38
      'label' => self::randomName() . '_label',
39
      'description' => self::randomName() . '_description',
40
      'weight' => random_int(0, 127),
41
      'settings' => array(),
42
      'widget' => array(
43
        'type' => 'hidden',
44
        'label' => 'Test',
45
        'settings' => array(),
46
      ),
47
    );
48
    $this->instance = field_create_instance($this->instance);
49
  }
50

    
51
  /**
52
   * Pass if the message $text was set by one of the CRUD hooks in
53
   * entity_crud_hook_test.module, i.e., if the $text is an element of
54
   * $_SESSION['entity_crud_hook_test'].
55
   *
56
   * @see EntityCrudHookTestCase::assertHookMessage()
57
   * @see FieldCollectionBasicTestCase::assertNoHookMessage()
58
   * @see FieldCollectionBasicTestCase::clearHookMessages()
59
   *
60
   * @param $text
61
   *   Plain text to look for.
62
   * @param $message
63
   *   Message to display.
64
   * @param $group
65
   *   The group this message belongs to, defaults to 'Other'.
66
   * @return
67
   *   TRUE on pass, FALSE on fail.
68
   */
69
  protected function assertHookMessage($text, $message = NULL, $group = 'Other') {
70
    if (!isset($message)) {
71
      $message = $text;
72
    }
73
    return $this->assertTrue(in_array($text, $_SESSION['entity_crud_hook_test']), $message, $group);
74
  }
75

    
76
  /**
77
   * Fail if the message $text was set by one of the CRUD hooks in
78
   * entity_crud_hook_test.module, i.e., if the $text is an element of
79
   * $_SESSION['entity_crud_hook_test'].
80
   *
81
   * @see FieldCollectionBasicTestCase::assertHookMessage()
82
   * @see FieldCollectionBasicTestCase::clearHookMessages()
83
   *
84
   * @param $text
85
   *   Plain text to look for.
86
   * @param $message
87
   *   Message to display.
88
   * @param $group
89
   *   The group this message belongs to, defaults to 'Other'.
90
   *
91
   * @return bool
92
   *   TRUE on pass, FALSE on fail.
93
   */
94
  protected function assertNoHookMessage($text, $message = NULL, $group = 'Other') {
95
    if (!isset($message)) {
96
      $message = $text;
97
    }
98
    return $this->assertFalse(in_array($text, $_SESSION['entity_crud_hook_test']), $message, $group);
99
  }
100

    
101
  /**
102
   * Clear hook messages recorded by entity_crud_hook_test.
103
   *
104
   * @see FieldCollectionBasicTestCase::assertHookMessage()
105
   * @see FieldCollectionBasicTestCase::assertNoHookMessage()
106
   */
107
  protected function clearHookMessages() {
108
    $_SESSION['entity_crud_hook_test'] = array();
109
  }
110

    
111
  /**
112
   * Helper for creating a new node with a field collection item.
113
   */
114
  protected function createNodeWithFieldCollection() {
115
    $node = $this->drupalCreateNode(array('type' => 'article'));
116
    // Manually create a field_collection.
117
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
118
    $entity->setHostEntity('node', $node);
119
    $entity->save();
120

    
121
    return array($node, $entity);
122
  }
123

    
124
  /**
125
   * Tests CRUD.
126
   */
127
  function testCRUD() {
128
    list ($node, $entity) = $this->createNodeWithFieldCollection();
129
    $node = node_load($node->nid, NULL, TRUE);
130
    $this->assertEqual($entity->item_id, $node->{$this->field_name}[LANGUAGE_NONE][0]['value'], 'A field_collection has been successfully created and referenced.');
131
    $this->assertEqual($entity->revision_id, $node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id'], 'A field_collection has been successfully created and referenced.');
132

    
133
    // Test adding an additional field_collection during node edit.
134
    $entity2 = entity_create('field_collection_item', array('field_name' => $this->field_name));
135
    $node->{$this->field_name}[LANGUAGE_NONE][] = array('entity' => $entity2);
136
    node_save($node);
137

    
138
    $node = node_load($node->nid, NULL, TRUE);
139
    $this->assertTrue(!empty($entity2->item_id) && !empty($entity2->revision_id), 'Field_collection has been saved.');
140
    $this->assertEqual($entity->item_id, $node->{$this->field_name}[LANGUAGE_NONE][0]['value'], 'Existing reference has been kept during update.');
141
    $this->assertEqual($entity->revision_id, $node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id'], 'Existing reference has been kept during update (revision).');
142
    $this->assertEqual($entity2->item_id, $node->{$this->field_name}[LANGUAGE_NONE][1]['value'], 'New field_collection has been properly referenced');
143
    $this->assertEqual($entity2->revision_id, $node->{$this->field_name}[LANGUAGE_NONE][1]['revision_id'], 'New field_collection has been properly referenced (revision)');
144

    
145
    // Make sure deleting the field_collection removes the reference.
146
    $this->clearHookMessages();
147
    $entity2->delete();
148
    $this->assertHookMessage('entity_crud_hook_test_entity_presave called for type node');
149
    $node = node_load($node->nid, NULL, TRUE);
150
    $this->assertTrue(!isset($node->{$this->field_name}[LANGUAGE_NONE][1]), 'Reference correctly deleted.');
151

    
152
    // Make sure field_collections are removed during deletion of the host.
153
    $this->clearHookMessages();
154
    node_delete($node->nid);
155
    $this->assertNoHookMessage('entity_crud_hook_test_entity_presave called for type node');
156
    $this->assertTrue(entity_load('field_collection_item') === array(), 'Field collections are deleted when the host is deleted.');
157

    
158
    // Try deleting nodes with collections without any values.
159
    $node = $this->drupalCreateNode(array('type' => 'article'));
160
    node_delete($node->nid);
161
    $this->assertTrue(node_load($node->nid, NULL, TRUE) == FALSE, 'Node without collection values deleted.');
162

    
163
    // Test creating a field collection entity with a not-yet saved host entity.
164
    $node = entity_create('node', array('type' => 'article'));
165
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
166
    $entity->setHostEntity('node', $node);
167
    $entity->save();
168
    // Now the node should have been saved with the collection and the link
169
    // should have been established.
170
    $this->assertTrue(!empty($node->nid), 'Node has been saved with the collection.');
171
    $this->assertTrue(count($node->{$this->field_name}[LANGUAGE_NONE]) == 1 && !empty($node->{$this->field_name}[LANGUAGE_NONE][0]['value']) && !empty($node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id']), 'Link has been established.');
172

    
173
    // Again, test creating a field collection with a not-yet saved host entity,
174
    // but this time save both entities via the host.
175
    $node = entity_create('node', array('type' => 'article'));
176
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
177
    $entity->setHostEntity('node', $node);
178
    node_save($node);
179
    $this->assertTrue(!empty($entity->item_id) && !empty($entity->revision_id), 'Collection has been saved with the host.');
180
    $this->assertTrue(count($node->{$this->field_name}[LANGUAGE_NONE]) == 1 && !empty($node->{$this->field_name}[LANGUAGE_NONE][0]['value']) && !empty($node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id']), 'Link has been established.');
181

    
182
    // Test Revisions.
183
    list ($node, $item) = $this->createNodeWithFieldCollection();
184
    $entity2 = entity_create('field_collection_item', array('field_name' => $this->field_name));
185
    $node->{$this->field_name}[LANGUAGE_NONE][] = array('entity' => $entity2);
186
    node_save($node);
187
    $this->assertEqual($entity2->archived, FALSE, 'New field collection item with new content revision is not archived.');
188

    
189
    // Test saving a new revision of a node.
190
    $node->revision = TRUE;
191
    node_save($node);
192
    $item_updated = field_collection_item_load($node->{$this->field_name}[LANGUAGE_NONE][0]['value']);
193
    $this->assertNotEqual($item->revision_id, $item_updated->revision_id, 'Creating a new host entity revision creates a new field collection revision.');
194

    
195
    // Test saving a new revision with a new field collection item.
196
    $node->revision = TRUE;
197

    
198
    // Test saving the node without creating a new revision.
199
    $item = $item_updated;
200
    $node->revision = FALSE;
201
    node_save($node);
202
    $item_updated = field_collection_item_load($node->{$this->field_name}[LANGUAGE_NONE][0]['value']);
203
    $this->assertEqual($item->revision_id, $item_updated->revision_id, 'Updating a new host entity  without creating a new revision does not create a new field collection revision.');
204

    
205
    // Create a new revision of the node, such we have a non default node and
206
    // field collection revision. Then test using it.
207
    $vid = $node->vid;
208
    $item_revision_id = $item_updated->revision_id;
209
    $node->revision = TRUE;
210
    node_save($node);
211

    
212
    $item_updated = field_collection_item_load($node->{$this->field_name}[LANGUAGE_NONE][0]['value']);
213
    $this->assertNotEqual($item_revision_id, $item_updated->revision_id, 'Creating a new host entity revision creates a new field collection revision.');
214
    $this->assertTrue($item_updated->isDefaultRevision(), 'Field collection of default host entity revision is default too.');
215
    $this->assertEqual($item_updated->hostEntityId(), $node->nid, 'Can access host entity ID of default field collection revision.');
216
    $this->assertEqual($item_updated->hostEntity()->vid, $node->vid, 'Loaded default host entity revision.');
217

    
218
    $item = entity_revision_load('field_collection_item', $item_revision_id);
219
    $this->assertFalse($item->isDefaultRevision(), 'Field collection of non-default host entity is non-default too.');
220
    $this->assertEqual($item->hostEntityId(), $node->nid, 'Can access host entity ID of non-default field collection revision.');
221
    $this->assertEqual($item->hostEntity()->vid, $vid, 'Loaded non-default host entity revision.');
222

    
223
    // Delete the non-default revision and make sure the field collection item
224
    // revision has been deleted too.
225
    entity_revision_delete('node', $vid);
226
    $this->assertFalse(entity_revision_load('node', $vid), 'Host entity revision deleted.');
227
    $this->assertFalse(entity_revision_load('field_collection_item', $item_revision_id), 'Field collection item revision deleted.');
228

    
229
    // Test having archived field collections, i.e. collections referenced only
230
    // in non-default revisions.
231
    list ($node, $item) = $this->createNodeWithFieldCollection();
232
    // Create two revisions.
233
    $node_vid = $node->vid;
234
    $node->revision = TRUE;
235
    node_save($node);
236

    
237
    $node_vid2 = $node->vid;
238
    $node->revision = TRUE;
239
    node_save($node);
240

    
241
    // Now delete the field collection item for the default revision.
242
    $item = field_collection_item_load($node->{$this->field_name}[LANGUAGE_NONE][0]['value']);
243
    $item_revision_id = $item->revision_id;
244
    $item->deleteRevision();
245
    $node = node_load($node->nid);
246
    $this->assertTrue(!isset($node->{$this->field_name}[LANGUAGE_NONE][0]), 'Field collection item revision removed from host.');
247
    $this->assertFalse(field_collection_item_revision_load($item->revision_id), 'Field collection item default revision deleted.');
248

    
249
    $item = field_collection_item_load($item->item_id);
250
    $this->assertNotEqual($item->revision_id, $item_revision_id, 'Field collection default revision has been updated.');
251
    $this->assertTrue($item->archived, 'Field collection item has been archived.');
252
    $this->assertFalse($item->isInUse(), 'Field collection item specified as not in use.');
253
    $this->assertTrue($item->isDefaultRevision(), 'Field collection of non-default host entity is default (but archived).');
254
    $this->assertEqual($item->hostEntityId(), $node->nid, 'Can access host entity ID of non-default field collection revision.');
255
    $this->assertEqual($item->hostEntity()->nid, $node->nid, 'Loaded non-default host entity revision.');
256

    
257
    // Test deleting a revision of an archived field collection.
258
    $node_revision2 = node_load($node->nid, $node_vid2);
259
    $item = field_collection_item_revision_load($node_revision2->{$this->field_name}[LANGUAGE_NONE][0]['revision_id']);
260
    $item->deleteRevision();
261
    // There should be one revision left, so the item should still exist.
262
    $item = field_collection_item_load($item->item_id);
263
    $this->assertTrue($item->archived, 'Field collection item is still archived.');
264
    $this->assertFalse($item->isInUse(), 'Field collection item specified as not in use.');
265

    
266
    // Test that deleting the first node revision deletes the whole field
267
    // collection item as it contains its last revision.
268
    node_revision_delete($node_vid);
269
    $this->assertFalse(field_collection_item_load($item->item_id), 'Archived field collection deleted when last revision deleted.');
270

    
271
    // Test that removing a field-collection item also deletes it.
272
    list ($node, $item) = $this->createNodeWithFieldCollection();
273

    
274
    $node->{$this->field_name}[LANGUAGE_NONE] = array();
275
    $node->revision = FALSE;
276
    node_save($node);
277
    $this->assertFalse(field_collection_item_load($item->item_id), 'Removed field collection item has been deleted.');
278

    
279
    // Test removing a field-collection item while creating a new host revision.
280
    list ($node, $item) = $this->createNodeWithFieldCollection();
281
    $node->{$this->field_name}[LANGUAGE_NONE] = array();
282
    $node->revision = TRUE;
283
    node_save($node);
284
    // Item should not be deleted but archived now.
285
    $item = field_collection_item_load($item->item_id);
286
    $this->assertTrue($item, 'Removed field collection item still exists.');
287
    $this->assertTrue($item->archived, 'Removed field collection item is archived.');
288

    
289
    // Test removing an old node revision. Make sure that the field collection
290
    // is not removed.
291
    list ($node, $item) = $this->createNodeWithFieldCollection();
292
    $node_vid = $node->vid;
293
    $node->revision = TRUE;
294
    node_save($node);
295
    $node_vid2 = $node->vid;
296
    $item_vid2 = $node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id'];
297
    node_revision_delete($node_vid);
298
    $item2 = field_collection_item_revision_load($item_vid2);
299
    $item_id2 = isset($item2->item_id) ? $item2->item_id : -1;
300
    $this->assertEqual($item_id2, $item->item_id, 'Removing an old node revision does not delete newer field collection revisions');
301

    
302
  }
303

    
304
  /**
305
   * Make sure the basic UI and access checks are working.
306
   */
307
  function testBasicUI() {
308
    // Add a field to the collection.
309
    $field = array(
310
      'field_name' => 'field_text',
311
      'type' => 'text',
312
      'cardinality' => 1,
313
      'translatable' => FALSE,
314
    );
315
    field_create_field($field);
316
    $instance = array(
317
      'entity_type' => 'field_collection_item',
318
      'field_name' => 'field_text',
319
      'bundle' => $this->field_name,
320
      'label' => 'Test text field',
321
      'widget' => array(
322
        'type' => 'text_textfield',
323
      ),
324
    );
325
    field_create_instance($instance);
326

    
327
    $user = $this->drupalCreateUser();
328
    $node = $this->drupalCreateNode(array('type' => 'article'));
329

    
330
    $this->drupalLogin($user);
331
    // Make sure access is denied.
332
    $path = 'field-collection/field-test-collection/add/node/' . $node->nid;
333
    $this->drupalGet($path);
334
    $this->assertText(t('Access denied'), 'Access has been denied.');
335

    
336
    $user_privileged = $this->drupalCreateUser(array('access content', 'edit any article content'));
337
    $this->drupalLogin($user_privileged);
338
    $this->drupalGet("node/$node->nid");
339
    $this->assertLinkByHref($path, 0, 'Add link is shown.');
340
    $this->drupalGet($path);
341
    $this->assertText(t('Test text field'), 'Add form is shown.');
342

    
343
    $edit['field_text[und][0][value]'] = self::randomName();
344
    $this->drupalPost($path, $edit, t('Save'));
345
    $this->assertText(t('The changes have been saved.'), 'Field collection saved.');
346

    
347
    $this->assertText($edit['field_text[und][0][value]'], 'Added field value is shown.');
348

    
349
    $edit['field_text[und][0][value]'] = self::randomName();
350
    $this->drupalPost('field-collection/field-test-collection/1/edit', $edit, t('Save'));
351
    $this->assertText(t('The changes have been saved.'), 'Field collection saved.');
352
    $this->assertText($edit['field_text[und][0][value]'], 'Field collection has been edited.');
353

    
354
    $this->drupalGet('field-collection/field-test-collection/1');
355
    $this->assertText($edit['field_text[und][0][value]'], 'Field collection can be viewed.');
356

    
357
    // Add further 3 items, so we have reached 4 == maxium cardinality.
358
    $this->drupalPost($path, $edit, t('Save'));
359
    $this->drupalPost($path, $edit, t('Save'));
360
    $this->drupalPost($path, $edit, t('Save'));
361
    // Make sure adding doesn't work any more as we have restricted cardinality
362
    // to 1.
363
    $this->drupalGet($path);
364
    $this->assertResponse(403);
365

    
366
    $this->drupalPost('field-collection/field-test-collection/1/delete', array(), t('Delete'));
367
    $this->drupalGet($path);
368
    // Add form is shown again.
369
    $this->assertText(t('Test text field'), 'Field collection item has been deleted.');
370

    
371
    // Test the viewing a revision. There should be no links to change it.
372
    $vid = $node->vid;
373
    $node = node_load($node->nid, NULL, TRUE);
374
    $node->revision = TRUE;
375
    node_save($node);
376

    
377
    $this->drupalGet("node/$node->nid/revisions/$vid/view");
378
    $this->assertResponse(403, 'Access to view revision denied');
379
    // Login in as admin and try again.
380
    $user = $this->drupalCreateUser(array('administer nodes', 'bypass node access'));
381
    $this->drupalLogin($user);
382
    $this->drupalGet("node/$node->nid/revisions/$vid/view");
383
    $this->assertNoResponse(403, 'Access to view revision granted');
384

    
385
    $this->assertNoLinkByHref($path, 'No links on revision view.');
386
    $this->assertNoLinkByHref('field-collection/field-test-collection/2/edit', 'No links on revision view.');
387
    $this->assertNoLinkByHref('field-collection/field-test-collection/2/delete', 'No links on revision view.');
388

    
389
    $this->drupalGet("node/$node->nid/revisions");
390
  }
391

    
392
  /**
393
   * Make sure that field_collection-entities are copied when host-entities do.
394
   */
395
  public function testCopyingEntities() {
396
    list($node, $entity) = $this->createNodeWithFieldCollection();
397

    
398
    // Create a copy of that node.
399
    $node->nid = NULL;
400
    $node->vid = NULL;
401
    $node->is_new = TRUE;
402

    
403
    node_save($node);
404
    $item = $node->{$this->field_name}[LANGUAGE_NONE][0];
405
    $this->assertNotEqual($entity->item_id, $item['value']);
406

    
407
    // Do a php clone to the $node object and save it.
408
    $node2 = clone $node;
409
    $node2->nid = NULL;
410
    $node2->is_new = TRUE;
411
    $node2->vid = NULL;
412
    node_save($node2);
413

    
414
    $item2 = $node2->{$this->field_name}[LANGUAGE_NONE][0];
415
    $this->assertNotEqual($item2['value'], $item['value']);
416

    
417
    // Create another copy this time (needlessly) forcing a new revision.
418
    $node->nid = NULL;
419
    $node->vid = NULL;
420
    $node->is_new = TRUE;
421
    $node->revision = TRUE;
422
    node_save($node);
423
    $item3 = $node->{$this->field_name}[LANGUAGE_NONE][0];
424
    $this->assertNotEqual($item['value'], $item3['value']);
425
  }
426

    
427
}
428

    
429

    
430
/**
431
 * Test using field collection with Rules.
432
 */
433
class FieldCollectionRulesIntegrationTestCase extends DrupalWebTestCase {
434

    
435
  public static function getInfo() {
436
    return array(
437
      'name' => 'Field collection Rules integration',
438
      'description' => 'Tests using field collections with rules.',
439
      'group' => 'Field types',
440
      'dependencies' => array('rules'),
441
    );
442
  }
443

    
444
  function setUp() {
445
    parent::setUp(array('field_collection', 'rules'));
446
    variable_set('rules_debug_log', 1);
447
  }
448

    
449
  protected function createFields($cardinality = 4) {
450
    // Create a field_collection field to use for the tests.
451
    $this->field_name = 'field_test_collection';
452
    $this->field = array('field_name' => $this->field_name, 'type' => 'field_collection', 'cardinality' => $cardinality);
453
    $this->field = field_create_field($this->field);
454
    $this->field_id = $this->field['id'];
455

    
456
    $this->instance = array(
457
      'field_name' => $this->field_name,
458
      'entity_type' => 'node',
459
      'bundle' => 'article',
460
      'label' => self::randomName() . '_label',
461
      'description' => self::randomName() . '_description',
462
      'weight' => random_int(0, 127),
463
      'settings' => array(),
464
      'widget' => array(
465
        'type' => 'hidden',
466
        'label' => 'Test',
467
        'settings' => array(),
468
      ),
469
    );
470
    $this->instance = field_create_instance($this->instance);
471
    // Add a field to the collection.
472
    $field = array(
473
      'field_name' => 'field_text',
474
      'type' => 'text',
475
      'cardinality' => 1,
476
      'translatable' => FALSE,
477
    );
478
    field_create_field($field);
479
    $instance = array(
480
      'entity_type' => 'field_collection_item',
481
      'field_name' => 'field_text',
482
      'bundle' => $this->field_name,
483
      'label' => 'Test text field',
484
      'widget' => array(
485
        'type' => 'text_textfield',
486
      ),
487
    );
488
    field_create_instance($instance);
489
  }
490

    
491
  /**
492
   * Test creation field collection items.
493
   */
494
  function testCreation() {
495
    $this->createFields();
496

    
497
    $node = $this->drupalCreateNode(array('type' => 'article'));
498
    // Create a field collection.
499
    $action_set = rules_action_set(array('node' => array('type' => 'node', 'bundle' => 'article')));
500
    $action_set->action('entity_create', array(
501
      'type' => 'field_collection_item',
502
      'param_field_name' => $this->field_name,
503
      'param_host_entity:select' => 'node',
504
    ));
505
    $action_set->action('data_set', array('data:select' => 'entity-created:field-text', 'value' => 'foo'));
506
    $action_set->execute($node);
507

    
508
    $node = node_load($node->nid, NULL, TRUE);
509
    $this->assertTrue(!empty($node->{$this->field_name}[LANGUAGE_NONE][0]['value']), 'A field_collection has been successfully created.');
510
    $this->assertTrue(!empty($node->{$this->field_name}[LANGUAGE_NONE][0]['revision_id']), 'A field_collection has been successfully created (revision).');
511

    
512
    // Now try making use of the field collection in rules.
513
    $action_set = rules_action_set(array('node' => array('type' => 'node', 'bundle' => 'article')));
514
    $action_set->action('drupal_message', array('message:select' => 'node:field-test-collection:0:field-text'));
515
    $action_set->execute($node);
516

    
517
    $msg = drupal_get_messages();
518
    $this->assertEqual(array_pop($msg['status']), 'foo', 'Field collection can be used.');
519
    RulesLog::logger()->checkLog();
520
  }
521

    
522
  /**
523
   * Test using field collection items via the host while they are being created.
524
   */
525
  function testUsageDuringCreation() {
526
    // Test using a single-cardinality field collection.
527
    $this->createFields(1);
528

    
529
    $node = $this->drupalCreateNode(array('type' => 'article'));
530
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
531
    $entity->setHostEntity('node', $node);
532
    // Now the field collection is linked to the host, but not yet saved.
533

    
534
    // Test using the wrapper on it.
535
    $wrapper = entity_metadata_wrapper('node', $node);
536
    $wrapper->get($this->field_name)->field_text->set('foo');
537
    $this->assertEqual($entity->field_text[LANGUAGE_NONE][0]['value'], 'foo', 'Field collection item used during creation via the wrapper.');
538

    
539
    // Now test it via Rules, which should save our changes.
540
    $set = rules_action_set(array('node' => array('type' => 'node', 'bundle' => 'article')));
541
    $set->action('data_set', array('data:select' => 'node:' . $this->field_name . ':field-text', 'value' => 'bar'));
542
    $set->execute($node);
543
    $this->assertEqual($entity->field_text[LANGUAGE_NONE][0]['value'], 'bar', 'Field collection item used during creation via Rules.');
544
    $this->assertTrue(!empty($entity->item_id) && !empty($entity->revision_id), 'Field collection item has been saved by Rules and the host entity.');
545
    RulesLog::logger()->checkLog();
546
  }
547
}
548

    
549
/**
550
 * Test using field collection with content that gets translated.
551
 */
552
class FieldCollectionContentTranslationTestCase extends DrupalWebTestCase {
553

    
554
  public static function getInfo() {
555
    return array(
556
      'name' => 'Field collection content translation',
557
      'description' => 'Tests using content under translation.',
558
      'group' => 'Field types',
559
      'dependencies' => array('translation'),
560
    );
561
  }
562

    
563
  public function setUp() {
564
    parent::setUp(array('field_collection', 'translation'));
565
    // Create a field_collection field to use for the tests.
566
    $this->field_name = 'field_test_collection';
567
    $this->field = array('field_name' => $this->field_name, 'type' => 'field_collection', 'cardinality' => 4);
568
    $this->field = field_create_field($this->field);
569
    $this->field_id = $this->field['id'];
570

    
571
    $this->instance = array(
572
      'field_name' => $this->field_name,
573
      'entity_type' => 'node',
574
      'bundle' => 'article',
575
      'label' => self::randomName() . '_label',
576
      'description' => self::randomName() . '_description',
577
      'weight' => random_int(0, 127),
578
      'settings' => array(),
579
      'widget' => array(
580
        'type' => 'field_collection_embed',
581
        'label' => 'Test',
582
        'settings' => array(),
583
      ),
584
    );
585
    $this->instance = field_create_instance($this->instance);
586

    
587
    // Add a field to the collection.
588
    $field = array(
589
      'field_name' => 'field_text',
590
      'type' => 'text',
591
      'cardinality' => 1,
592
      'translatable' => FALSE,
593
    );
594
    field_create_field($field);
595
    $instance = array(
596
      'entity_type' => 'field_collection_item',
597
      'field_name' => 'field_text',
598
      'bundle' => $this->field_name,
599
      'label' => 'Test text field',
600
      'widget' => array(
601
        'type' => 'text_textfield',
602
      ),
603
    );
604
    field_create_instance($instance);
605

    
606
    $admin_user = $this->drupalCreateUser(array('administer languages', 'administer content types', 'access administration pages', 'create article content', 'edit any article content', 'translate content'));
607

    
608
    $this->drupalLogin($admin_user);
609
    // Add German language.
610
    locale_add_language('de');
611

    
612
    // Set "Article" content type to use multilingual support.
613
    variable_set('language_content_type_article', TRANSLATION_ENABLED);
614
  }
615

    
616
  /**
617
   * Ensure field collections are cloned to new entities on content translation.
618
   */
619
  public function testContentTranslation() {
620
    // Create "Article" content.
621
    $edit['title'] = self::randomName();
622
    $edit['body[' . LANGUAGE_NONE . '][0][value]'] = self::randomName();
623
    $edit['language'] = 'en';
624
    $field_collection_name = 'field_test_collection[' . LANGUAGE_NONE . '][0][field_text][' . LANGUAGE_NONE . '][0][value]';
625
    $edit[$field_collection_name] = self::randomName();
626

    
627
    $this->drupalPost('node/add/article', $edit, t('Save'));
628
    $this->assertRaw(t('Article %title has been created.', array('%title' => $edit['title'])), 'Article created.');
629
    $node1 = $this->drupalGetNodeByTitle($edit['title']);
630

    
631
    $this->drupalGet('node/' . $node1->nid . '/edit');
632
    $this->drupalGet('node/' . $node1->nid . '/translate');
633
    $this->drupalGet('node/add/article', array('query' => array('translation' => $node1->nid, 'target' => 'de')));
634

    
635
    // Suffix translations with the langcode.
636
    unset($edit['language']);
637
    $edit['title'] .= 'DE';
638
    $edit[$field_collection_name] .= 'DE';
639
    $this->drupalPost('node/add/article', $edit, t('Save'), array('query' => array('translation' => $node1->nid, 'target' => 'de')));
640
    $node2 = $this->drupalGetNodeByTitle($edit['title']);
641

    
642
    // Ensure that our new node is the translation of the first one.
643
    $this->assertEqual($node1->nid, $node2->tnid, 'Succesfully created translation.');
644
    // And check to see that their field collections are different.
645
    $this->assertNotEqual($node1->field_test_collection, $node2->field_test_collection, 'Field collections between translation source and translation differ.');
646
  }
647

    
648
}
649

    
650
/**
651
 * Test using field collection with content that gets translated with Entity Translation.
652
 */
653
class FieldCollectionEntityTranslationTestCase extends DrupalWebTestCase {
654
  const TRANS_FIELD_EN = 'Translatable EN';
655
  const TRANS_FIELD_DE = 'Translatable DE';
656
  const TRANS_FIELD_DE_MOD = 'Translatable DE Mod';
657
  const UNTRANS_FIELD_EN = 'Untranslatable EN';
658
  const UNTRANS_FIELD_DE = 'Untranslatable DE';
659
  const UNTRANS_FIELD_DE_MOD = 'Untranslatable DE Mod';
660
  const NUM_VALUES = 4;
661

    
662
  public static function getInfo() {
663
    return array(
664
      'name' => 'Field collection entity translation',
665
      'description' => 'Tests using content under translation with Entity Translation.',
666
      'group' => 'Field types',
667
      'dependencies' => array('entity_translation'),
668
    );
669
  }
670

    
671
  /**
672
   * Login the given user only if she has not changed.
673
   */
674
  function login($user) {
675
    if (!isset($this->current_user) || $this->current_user->uid != $user->uid) {
676
      $this->current_user = $user;
677
      $this->drupalLogin($user);
678
    }
679
  }
680

    
681
  /**
682
   * Returns a user with administration rights.
683
   *
684
   * @param $permissions
685
   *   Additional permissions for administrative user.
686
   */
687
  function getAdminUser(array $permissions = array()) {
688
    if (!isset($this->admin_user)) {
689
      $this->admin_user = $this->drupalCreateUser(array_merge(array(
690
        'bypass node access',
691
        'administer nodes',
692
        'administer languages',
693
        'administer content types',
694
        'administer blocks',
695
        'access administration pages',
696
        'administer site configuration',
697
        'administer entity translation',
698
      ), $permissions));
699
    }
700
    return $this->admin_user;
701
  }
702

    
703
  /**
704
   * Returns a user with minimal translation rights.
705
   *
706
   * @param $permissions
707
   *   Additional permissions for administrative user.
708
   */
709
  function getTranslatorUser(array $permissions = array()) {
710
    if (!isset($this->translator_user)) {
711
      $this->translator_user = $this->drupalCreateUser(array_merge(array(
712
        'create page content',
713
        'edit own page content',
714
        'delete own page content',
715
        'translate any entity',
716
      ), $permissions));
717
    }
718
    return $this->translator_user;
719
  }
720

    
721
  /**
722
   * Install a specified language if it has not been already, otherwise make
723
   * sure that the language is enabled.
724
   *
725
   * @param string $langcode
726
   *   The language code to check.
727
   */
728
  function addLanguage($langcode) {
729
    // Check to make sure that language has not already been installed.
730
    $this->drupalGet('admin/config/regional/language');
731

    
732
    if (strpos($this->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) {
733
      // Doesn't have language installed so add it.
734
      $edit = array();
735
      $edit['langcode'] = $langcode;
736
      $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
737

    
738
      // Make sure we are not using a stale list.
739
      drupal_static_reset('language_list');
740
      $languages = language_list();
741
      $this->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.'));
742

    
743
      if (array_key_exists($langcode, $languages)) {
744
        $this->assertRaw(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => $languages[$langcode]->name, '@locale-help' => url('admin/help/locale'))), t('Language has been created.'));
745
      }
746
    }
747
    elseif ($this->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(':name' => 'enabled[' . $langcode . ']'))) {
748
      // It is installed and enabled. No need to do anything.
749
      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.');
750
    }
751
    else {
752
      // It is installed but not enabled. Enable it.
753
      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.');
754
      $this->drupalPost(NULL, array('enabled[' . $langcode . ']' => TRUE), t('Save configuration'));
755
      $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.'));
756
    }
757
  }
758

    
759
  public function setUp() {
760
    parent::setUp(array('field_collection', 'entity_translation'));
761
    $language_none = LANGUAGE_NONE;
762
    // Login with an admin user.
763
    $this->login($this->getAdminUser());
764
    // Add English and German languages.
765
    $this->addLanguage('en');
766
    $this->addLanguage('de');
767

    
768
    // Set "Article" content type to use multilingual support with translation.
769
    $edit = array();
770
    $edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED;
771
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
772
    $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
773

    
774
    // Create a field collection field to use for the tests.
775
    $this->field_name = 'field_test_collection';
776
    $this->field_base = "{$this->field_name}[$language_none]";
777
    $this->field = array(
778
      'field_name' => $this->field_name,
779
      'type' => 'field_collection',
780
      'cardinality' => -1,
781
      'translatable' => TRUE,
782
    );
783
    $this->field = field_create_field($this->field);
784
    $this->field_id = $this->field['id'];
785

    
786
    $this->instance = array(
787
      'field_name' => $this->field_name,
788
      'entity_type' => 'node',
789
      'bundle' => 'page',
790
      'label' => self::randomName() . '_label',
791
      'description' => self::randomName() . '_description',
792
      'weight' => random_int(0, 127),
793
      'settings' => array(),
794
      'widget' => array(
795
        'type' => 'field_collection_embed',
796
        'label' => 'Test',
797
        'settings' => array(),
798
      ),
799
    );
800
    $this->instance = field_create_instance($this->instance);
801

    
802
    // Enable entity translation of field collections.
803
    $this->drupalGet('admin/config/regional/entity_translation');
804
    $this->drupalPost('admin/config/regional/entity_translation', array('entity_translation_entity_types[field_collection_item]' => TRUE), t('Save configuration'));
805
    $this->assertRaw(t('The configuration options have been saved.'), t('Entity translation of field collections enabled.'));
806

    
807
    // Add an untraslatable field to the collection.
808
    $this->field_untrans_name = 'field_text_untrans';
809
    $this->field_untrans_base = "[{$this->field_untrans_name}][$language_none][0][value]";
810
    $field = array(
811
      'field_name' => $this->field_untrans_name,
812
      'type' => 'text',
813
      'cardinality' => 1,
814
      'translatable' => FALSE,
815
    );
816
    field_create_field($field);
817
    $instance = array(
818
      'entity_type' => 'field_collection_item',
819
      'field_name' => $this->field_untrans_name,
820
      'bundle' => $this->field_name,
821
      'label' => 'Test untranslatable text field',
822
      'widget' => array(
823
        'type' => 'text_textfield',
824
      ),
825
    );
826
    field_create_instance($instance);
827

    
828
    // Add a translatable field to the collection.
829
    $this->field_trans_name = 'field_text_trans';
830
    $this->field_trans_base = "[{$this->field_trans_name}][$language_none][0][value]";
831
    $this->field_trans_dest = "[{$this->field_trans_name}][de][0][value]";
832
    $field = array(
833
      'field_name' => $this->field_trans_name,
834
      'type' => 'text',
835
      'cardinality' => 1,
836
      'translatable' => TRUE,
837
    );
838
    field_create_field($field);
839
    $instance = array(
840
      'entity_type' => 'field_collection_item',
841
      'field_name' => $this->field_trans_name,
842
      'bundle' => $this->field_name,
843
      'label' => 'Test translatable text field',
844
      'widget' => array(
845
        'type' => 'text_textfield',
846
      ),
847
    );
848
    field_create_instance($instance);
849

    
850
    $this->login($this->getTranslatorUser());
851
  }
852

    
853
  /**
854
   * Creates a basic page with a value in the field collection.
855
   *
856
   *  @param integer $num_values
857
   *    The number of values to include in the field collection.
858
   *  @param string $langcode
859
   *    Language for the node.
860
   */
861
  protected function createPage($num_values, $langcode = 'en') {
862
    // Check if num_values is greater than the field cardinality.
863
    if ($num_values > self::NUM_VALUES) {
864
      $num_values = self::NUM_VALUES;
865
    }
866

    
867
    $title = self::randomName();
868

    
869
    $this->drupalGet('node/add/page');
870

    
871
    $edit = array();
872
    $edit['title'] = $title;
873
    for ($i = 0; $i < $num_values; $i++) {
874
      if ($i != 0) {
875
        $this->drupalPost(NULL, array(), t('Add another item'));
876
      }
877
      $edit[$this->field_base . '[' . $i . ']' . $this->field_untrans_base] = self::UNTRANS_FIELD_EN . '_' . $i;
878
      $edit[$this->field_base . '[' . $i . ']' . $this->field_trans_base] = self::TRANS_FIELD_EN . '_' . $i;
879
    }
880

    
881
    $edit['language'] = $langcode;
882
    $this->drupalPost(NULL, $edit, t('Save'));
883
    $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.'));
884

    
885
    // Check to make sure the node was created.
886
    $node = $this->drupalGetNodeByTitle($title);
887
    $this->assertTrue($node, t('Node found in database.'));
888

    
889
    return $node;
890

    
891
  }
892

    
893
  /**
894
   * Create a translation using the Entity Translation Form.
895
   *
896
   * @param mixed $node
897
   *   Node of the basic page to create translation for.
898
   * @param string $langcode
899
   *   The language code of the translation.
900
   * @param string $source_langcode
901
   *   The original language code.
902
   */
903
  protected function createTranslationForm($node, $langcode, $source_langcode = 'en') {
904
    $language_none = LANGUAGE_NONE;
905
    $edit = array();
906

    
907
    $this->drupalGet('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' .$langcode);
908

    
909
    // Get the field collection in the original language.
910
    $fc_values = $node->{$this->field_name}[$source_langcode];
911

    
912
    // Check if all the fields were populated and fill it with the new value.
913
    foreach ($fc_values as $delta => $fc_value) {
914
      // Load the field collection item.
915
      $fc_item_array = entity_load('field_collection_item', array($fc_value['value']));
916
      $fc_item = reset($fc_item_array);
917
      $fc_untrans_key = "{$this->field_name}[$langcode][$delta]{$this->field_untrans_base}";
918
      $fc_trans_key = "{$this->field_name}[$langcode][$delta]{$this->field_trans_dest}";
919
      $this->assertFieldByXPath(
920
          "//input[@name='$fc_untrans_key']",
921
          $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'],
922
          'Original value of untranslatable field correctly populated'
923
              );
924
      $this->assertFieldByXPath(
925
          "//input[@name='$fc_trans_key']",
926
          $fc_item->{$this->field_trans_name}['en'][0]['value'],
927
          'Original value of translatable field correctly populated'
928
              );
929

    
930
      $edit[$fc_untrans_key] = self::UNTRANS_FIELD_DE . '_' . $delta;
931
      $edit[$fc_trans_key] = self::TRANS_FIELD_DE . '_' . $delta;
932
    }
933

    
934
    // Save the translation.
935
    $this->drupalPost(NULL, $edit, t('Save'));
936
    $this->drupalGet('node/' . $node->nid . '/translate');
937
    $this->assertLinkByHref('node/' . $node->nid . '/edit/' . $langcode, 0, t('Translation edit link found. Translation created.'));
938

    
939
    // Reload the node.
940
    $node = node_load($node->nid, NULL, TRUE);
941

    
942
    // Check the values of the translated field.
943
    $this->checkFieldCollectionContent($node, $langcode);
944

    
945
    // Check the values of the field in the original language.
946
    $this->checkFieldCollectionContent($node, $source_langcode);
947

    
948
    return $node;
949
  }
950

    
951
  /**
952
   * Removes a translation using the entity translation form.
953
   *
954
   * @param mixed $node
955
   *   The node to remove the translation from.
956
   * @param string $langcode
957
   *   The language of the translation to remove.
958
   * @param string $source_langcode
959
   *   The source language of the node.
960
   */
961
  protected function removeTranslationForm($node, $langcode, $source_langcode) {
962
    // Number of field collection items in the source language.
963
    $num_original_fc_items = count($node->{$this->field_name}[$source_langcode]);
964

    
965
    // Fetch the translation edit form.
966
    $this->drupalGet('node/' . $node->nid . '/edit/' . $langcode);
967

    
968
    // Remove the translation.
969
    $this->drupalPost(NULL, array(), t('Delete translation'));
970
    // Confirm deletion.
971
    $this->drupalPost(NULL, array(), t('Delete'));
972

    
973
    // Reload the node.
974
    $node = node_load($node->nid, NULL, TRUE);
975

    
976
    // Check that the translation is removed.
977
    $this->drupalGet('node/' . $node->nid . '/translate');
978
    $this->assertLinkByHref('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' . $langcode, 0, 'The add translation link appears');
979
    $this->assert(empty($node->{$this->field_name}[$langcode]));
980

    
981
    // Check that the field collection in the original language has not changed.
982
    $num_fc_items = count($node->{$this->field_name}[$source_langcode]);
983
    $this->assertEqual($num_original_fc_items, $num_fc_items, 'The number of field collection items in the original language has not changed.');
984
    $this->checkFieldCollectionContent($node, $source_langcode);
985
  }
986

    
987
  /**
988
   * Creates a translation programmatically using Entity Translation.
989
   *
990
   * @param mixed $node
991
   *   Node of the basic page to create translation for.
992
   * @param string $langcode
993
   *   The language code of the translation.
994
   */
995
  protected function createTranslation($node, $langcode) {
996
    $source_langcode = $node->language;
997

    
998
    // Get the Entity Translation Handler.
999
    $handler = entity_translation_get_handler('node', $node, TRUE);
1000
    // Variable to hold the fields values.
1001
    $values = array();
1002
    // Translation settings.
1003
    $translation = array(
1004
      'translate' => 0,
1005
      'status' => 1,
1006
      'language' => $langcode,
1007
      'source' => $source_langcode,
1008
      'uid' => $node->uid,
1009
    );
1010
    // Copy field values.
1011
    foreach (field_info_instances('node', $node->type) as $instance) {
1012
      $field_name = $instance['field_name'];
1013
      $field = field_info_field($field_name);
1014
      $field_value = array();
1015
      // Copy the value of the translated field if it's translatable.
1016
      if ($field['translatable']
1017
        && isset($node->{$field_name}[$node->language])) {
1018
        $field_value = $node->{$field_name}[$source_langcode];
1019
        $values[$field_name][$langcode] = $field_value;
1020
        $node->{$field_name}[$langcode] = $field_value;
1021
      }
1022
    }
1023

    
1024
    $handler->setTranslation($translation, $values);
1025
    $handler->saveTranslations();
1026
    field_attach_update('node', $node);
1027

    
1028
    // Reload an return the node.
1029
    $node = node_load($node->nid, NULL, TRUE);
1030
    return $node;
1031
  }
1032

    
1033
  /**
1034
   * Removes a translation programmatically using the entity translation api.
1035
   *
1036
   * @param mixed $node
1037
   *   The node to remove the translation from.
1038
   * @param string $langcode
1039
   *   The language of the translation to remove.
1040
   */
1041
  protected function removeTranslation($node, $langcode) {
1042
    // Get a translation entity handler.
1043
    $handler = entity_translation_get_handler('node', $node, TRUE);
1044

    
1045
    // Remove the translation.
1046
    $handler->removeTranslation($langcode);
1047
    node_save($node);
1048

    
1049
    // Reload and return the node.
1050
    $node = node_load($node->nid, NULL, TRUE);
1051

    
1052
    return $node;
1053
  }
1054

    
1055
  /**
1056
   * Creates a new revision of the node and checks the result.
1057
   *
1058
   * @param mixed $node
1059
   *   The node to remove the translation from.
1060
   * @param string $langcode
1061
   *   The language of the translation to remove.
1062
   * @param string $source_langcode
1063
   *   The source language of the node.
1064
   *
1065
   * @return mixed
1066
   *   The new revision of the node.
1067
   */
1068
  protected function createRevision($node, $langcode, $source_langcode) {
1069
    $node_original_revision = $node->vid;
1070
    // The original entries of the translated field.
1071
    $original_fc_item_ids = $node->{$this->field_name}[$langcode];
1072

    
1073
    // Create the revision.
1074
    $node->revision = TRUE;
1075
    node_save($node);
1076

    
1077
    // The new entries of the translated field.
1078
    $new_fc_item_ids = $node->{$this->field_name}[$langcode];
1079

    
1080
    // Check that the field collection items are the same and a new revision of
1081
    // each one has been created.
1082
    foreach ($original_fc_item_ids as $delta => $value) {
1083
      $this->assertEqual($value['value'], $new_fc_item_ids[$delta]['value'], t('We have the same field collection item'));
1084
      $this->assertNotEqual($value['revision_id'], $new_fc_item_ids[$delta]['revision_id'], t('We have a new revision of the field collection item'));
1085
    }
1086

    
1087
    return $node;
1088
  }
1089

    
1090
  /**
1091
   * Check the content of the field collection for a specified language.
1092
   *
1093
   * @param mixed $node
1094
   *   The node to check.
1095
   * @param string $langcode
1096
   *   The language to check.
1097
   */
1098
  protected function checkFieldCollectionContent($node, $langcode) {
1099
    switch ($langcode) {
1100
      case 'en':
1101
        $untrans_field = self::UNTRANS_FIELD_EN;
1102
        $trans_field = self::TRANS_FIELD_EN;
1103
        break;
1104

    
1105
      case 'de':
1106
        $untrans_field = self::UNTRANS_FIELD_DE;
1107
        $trans_field = self::TRANS_FIELD_DE;
1108
        break;
1109
    }
1110
    // Get the field collection in the specified language.
1111
    $fc_values = $node->{$this->field_name}[$langcode];
1112

    
1113
    foreach ($fc_values as $delta => $fc_value) {
1114
      // Load the field collection item.
1115
      $fc_item_array = entity_load('field_collection_item', array($fc_value['value']));
1116
      $fc_item = reset($fc_item_array);
1117
      $fc_untrans_key = "{$this->field_name}[$langcode][$delta]{$this->field_untrans_base}";
1118
      $fc_trans_key = "{$this->field_name}[$langcode][$delta]{$this->field_trans_base}";
1119

    
1120
      $this->assertEqual($untrans_field . '_' . $delta, $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value']);
1121
      $this->assertEqual($trans_field . '_' . $delta, $fc_item->{$this->field_trans_name}[$langcode][0]['value']);
1122
    }
1123
  }
1124

    
1125
  /**
1126
   * Returns the text field values of an specified node, language and delta.
1127
   *
1128
   * @param mixed $node
1129
   * @param string $langcode
1130
   * @param integer $delta
1131
   * @return array
1132
   */
1133
  protected function getFieldValues($node, $langcode, $delta) {
1134
    $return = array();
1135

    
1136
    if (isset($node->{$this->field_name}[$langcode][$delta]['value'])) {
1137
      $fc_item_id = $node->{$this->field_name}[$langcode][$delta]['value'];
1138
      // Load the field collection.
1139
      $fc_item_array = entity_load('field_collection_item', array($fc_item_id));
1140
      $fc_item = reset($fc_item_array);
1141

    
1142
      $return = array(
1143
        'field_untrans' => $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'],
1144
        'field_trans' => $fc_item->{$this->field_trans_name}[$langcode][0]['value'],
1145
      );
1146
    }
1147

    
1148
    return $return;
1149
  }
1150

    
1151
  /**
1152
   * Ensures the right behaviour in all Entity Translation use cases.
1153
   */
1154
  public function testEntityTranslation() {
1155
    $source_langcode = 'en';
1156
    $translation_langcode = 'de';
1157

    
1158
    /*
1159
     * Test with a page with only one value in the field collection
1160
     */
1161
    // Create an article in the original language with only one field collection
1162
    // value.
1163
    $node = $this->createPage(1, $source_langcode);
1164

    
1165
    // Create a traslation of the page through the entity translation form.
1166
    $node = $this->createTranslationForm($node, $translation_langcode, $source_langcode);
1167

    
1168
    /*
1169
     * Test with a page with multiple values in the field collection.
1170
     */
1171
    $num_values = 4;
1172
    // Create a page in the original language with multiple field collection
1173
    // values.
1174
    $node = $this->createPage($num_values, $source_langcode);
1175

    
1176
    // Create a traslation of the page through the entity translation form.
1177
    $node = $this->createTranslationForm($node, $translation_langcode, $source_langcode);
1178

    
1179
    // Assign a new field collection item to an existing node.
1180
    $values = array();
1181
    $values['field_name'] = $this->field_name;
1182
    $fc_entity = entity_create('field_collection_item', $values);
1183
    $fc_entity->setHostEntity('node', $node, $translation_langcode);
1184

    
1185
    $fc_entity->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'] = self::UNTRANS_FIELD_DE_MOD;
1186
    $fc_entity->{$this->field_trans_name}['de'][0]['value'] = self::TRANS_FIELD_DE_MOD;
1187
    $fc_entity->save(TRUE);
1188

    
1189
    node_save($node);
1190

    
1191
    // Reload the node to check it.
1192
    $node = node_load($node->nid, NULL, TRUE);
1193
    // Check that there is a new element in the translation.
1194
    $this->assertEqual($num_values + 1, count($node->{$this->field_name}[$translation_langcode]), t('We have one item more in translation.'));
1195
    // Check that the new element is correctly saved.
1196
    $fc_item_values = $this->getFieldValues($node, $translation_langcode, $num_values);
1197
    $this->assertEqual($fc_item_values['field_untrans'], self::UNTRANS_FIELD_DE_MOD);
1198
    $this->assertEqual($fc_item_values['field_trans'], self::TRANS_FIELD_DE_MOD);
1199
    // Check that we have the same items in the original language.
1200
    $this->assertEqual($num_values, count($node->{$this->field_name}[$source_langcode]), t('We have same items in the original language.'));
1201

    
1202
    // Remove a field collection item from the translation.
1203
    $fc_item_id = $node->{$this->field_name}[$translation_langcode][0]['value'];
1204
    unset($node->{$this->field_name}[$translation_langcode][0]);
1205
    node_save($node);
1206
    // Reload the node.
1207
    $node = node_load($node->nid, NULL, TRUE);
1208
    // Check that we have one item less in the translation.
1209
    // We should take into account that we added a field one step before.
1210
    $this->assertEqual($num_values, count($node->{$this->field_name}[$translation_langcode]), t('We have one item less in translation.'));
1211
    // Check that we have the same items in the original language.
1212
    $this->assertEqual($num_values, count($node->{$this->field_name}[$source_langcode]), t('We have same items in the original language.'));
1213
    // Check that the field collection is removed from the database.
1214
    $fc_items = entity_load('field_collection_item', array($fc_item_id));
1215
    $this->assert(empty($fc_items), t('The field collection item has been removed from the database.'));
1216

    
1217
    // Delete the translation.
1218
    $this->removeTranslationForm($node, $translation_langcode, $source_langcode);
1219

    
1220
    /*
1221
     * Check the revisioning of an entity with translations.
1222
     */
1223
    $num_values = 4;
1224
    // Create a page in the original language with multiple field collection
1225
    // values.
1226
    $node_rev = $this->createPage($num_values, $source_langcode);
1227

    
1228
    // Create a traslation of the page.
1229
    $node_rev = $this->createTranslationForm($node_rev, $translation_langcode, $source_langcode);
1230

    
1231
    $original_revision = $node_rev->vid;
1232

    
1233
    // Create a new revision of the node.
1234
    $node_rev = $this->createRevision($node_rev, $translation_langcode, $source_langcode);
1235

    
1236
    /*
1237
     * Test creating programmatically.
1238
     */
1239
    $num_values = 4;
1240
    // Create a page in the original language.
1241
    $node_prog = $this->createPage($num_values, $source_langcode);
1242

    
1243
    // Create programmatically a translation of the page.
1244
    $node_prog = $this->createTranslation($node_prog, $translation_langcode);
1245

    
1246
    $orig_fc_items = $node_prog->{$this->field_name}[$source_langcode];
1247
    $trans_fc_items = $node_prog->{$this->field_name}[$translation_langcode];
1248

    
1249
    $orig_fc_item_ids = array();
1250
    $trans_fc_item_ids = array();
1251

    
1252
    // Check each item.
1253
    foreach ($orig_fc_items as $delta => $value) {
1254
      $orig_fc_item_ids[] = $value['value'];
1255
      $trans_fc_item_ids[] = $trans_fc_items[$delta]['value'];
1256

    
1257
      // Check if we have new items for the translation.
1258
      $this->assertNotEqual($value['value'], $trans_fc_items[$delta]['value'], t('New item generated for translation.'));
1259
    }
1260

    
1261
    // Check that the original item still exists in the database.
1262
    $fc_items = entity_load('field_collection_item', $orig_fc_item_ids);
1263
    $this->assert(!empty($fc_items), t('Field Collections in the source language still exist.'));
1264
    // Check that the translated item exists in the database.
1265
    $fc_items = entity_load('field_collection_item', $trans_fc_item_ids);
1266
    $this->assert(!empty($fc_items), t('Translations for the Field Collection exist.'));
1267

    
1268
    // Remove the translation and check that the original field collection items
1269
    // are still there.
1270
    $node_prog = $this->removeTranslation($node, $translation_langcode);
1271

    
1272
    // Check the content in the source language.
1273
    $this->checkFieldCollectionContent($node_prog, $source_langcode);
1274

    
1275
    // Check that the field translated content has been removed.
1276
    $this->assert(empty($node->{$this->field_name}[$translation_langcode]), t('Translated content removed.'));
1277
  }
1278

    
1279
}