Projet

Général

Profil

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

root / drupal7 / sites / all / modules / field_collection / field_collection.test @ 31a5a6d6

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('field_name' => $this->field_name, 'type' => 'field_collection', 'cardinality' => 4);
27
    $this->field = field_create_field($this->field);
28
    $this->field_id = $this->field['id'];
29

    
30
    $this->instance = array(
31
      'field_name' => $this->field_name,
32
      'entity_type' => 'node',
33
      'bundle' => 'article',
34
      'label' => $this->randomName() . '_label',
35
      'description' => $this->randomName() . '_description',
36
      'weight' => mt_rand(0, 127),
37
      'settings' => array(),
38
      'widget' => array(
39
        'type' => 'hidden',
40
        'label' => 'Test',
41
        'settings' => array(),
42
      ),
43
    );
44
    $this->instance = field_create_instance($this->instance);
45
  }
46

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

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

    
96
  /**
97
   * Clear hook messages recorded by entity_crud_hook_test.
98
   *
99
   * @see FieldCollectionBasicTestCase::assertHookMessage()
100
   * @see FieldCollectionBasicTestCase::assertNoHookMessage()
101
   */
102
  protected function clearHookMessages() {
103
    $_SESSION['entity_crud_hook_test'] = array();
104
  }
105

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

    
116
    return array($node, $entity);
117
  }
118

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

    
128
    // Test adding an additional field_collection during node edit.
129
    $entity2 = entity_create('field_collection_item', array('field_name' => $this->field_name));
130
    $node->{$this->field_name}[LANGUAGE_NONE][] = array('entity' => $entity2);
131
    node_save($node);
132

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

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

    
147
    // Make sure field_collections are removed during deletion of the host.
148
    $this->clearHookMessages();
149
    node_delete($node->nid);
150
    $this->assertNoHookMessage('entity_crud_hook_test_entity_presave called for type node');
151
    $this->assertTrue(entity_load('field_collection_item', FALSE) === array(), 'Field collections are deleted when the host is deleted.');
152

    
153
    // Try deleting nodes with collections without any values.
154
    $node = $this->drupalCreateNode(array('type' => 'article'));
155
    node_delete($node->nid);
156
    $this->assertTrue(node_load($node->nid, NULL, TRUE) == FALSE, 'Node without collection values deleted.');
157

    
158
    // Test creating a field collection entity with a not-yet saved host entity.
159
    $node = entity_create('node', array('type' => 'article'));
160
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
161
    $entity->setHostEntity('node', $node);
162
    $entity->save();
163
    // Now the node should have been saved with the collection and the link
164
    // should have been established.
165
    $this->assertTrue(!empty($node->nid), 'Node has been saved with the collection.');
166
    $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.');
167

    
168
    // Again, test creating a field collection with a not-yet saved host entity,
169
    // but this time save both entities via the host.
170
    $node = entity_create('node', array('type' => 'article'));
171
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
172
    $entity->setHostEntity('node', $node);
173
    node_save($node);
174
    $this->assertTrue(!empty($entity->item_id) && !empty($entity->revision_id), 'Collection has been saved with the host.');
175
    $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.');
176

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

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

    
190
    // Test saving a new revision with a new field collection item.
191
    $node->revision = TRUE;
192

    
193
    // Test saving the node without creating a new revision.
194
    $item = $item_updated;
195
    $node->revision = FALSE;
196
    node_save($node);
197
    $item_updated = field_collection_item_load($node->{$this->field_name}[LANGUAGE_NONE][0]['value']);
198
    $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.');
199

    
200
    // Create a new revision of the node, such we have a non default node and
201
    // field collection revision. Then test using it.
202
    $vid = $node->vid;
203
    $item_revision_id = $item_updated->revision_id;
204
    $node->revision = TRUE;
205
    node_save($node);
206

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

    
213
    $item = entity_revision_load('field_collection_item', $item_revision_id);
214
    $this->assertFalse($item->isDefaultRevision(), 'Field collection of non-default host entity is non-default too.');
215
    $this->assertEqual($item->hostEntityId(), $node->nid, 'Can access host entity ID of non-default field collection revision.');
216
    $this->assertEqual($item->hostEntity()->vid, $vid, 'Loaded non-default host entity revision.');
217

    
218
    // Delete the non-default revision and make sure the field collection item
219
    // revision has been deleted too.
220
    entity_revision_delete('node', $vid);
221
    $this->assertFalse(entity_revision_load('node', $vid), 'Host entity revision deleted.');
222
    $this->assertFalse(entity_revision_load('field_collection_item', $item_revision_id), 'Field collection item revision deleted.');
223

    
224
    // Test having archived field collections, i.e. collections referenced only
225
    // in non-default revisions.
226
    list ($node, $item) = $this->createNodeWithFieldCollection();
227
    // Create two revisions.
228
    $node_vid = $node->vid;
229
    $node->revision = TRUE;
230
    node_save($node);
231

    
232
    $node_vid2 = $node->vid;
233
    $node->revision = TRUE;
234
    node_save($node);
235

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

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

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

    
261
    // Test that deleting the first node revision deletes the whole field
262
    // collection item as it contains its last revision.
263
    node_revision_delete($node_vid);
264
    $this->assertFalse(field_collection_item_load($item->item_id), 'Archived field collection deleted when last revision deleted.');
265

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

    
269
    $node->{$this->field_name}[LANGUAGE_NONE] = array();
270
    $node->revision = FALSE;
271
    node_save($node);
272
    $this->assertFalse(field_collection_item_load($item->item_id), 'Removed field collection item has been deleted.');
273

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

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

    
297
  }
298

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

    
322
    $user = $this->drupalCreateUser();
323
    $node = $this->drupalCreateNode(array('type' => 'article'));
324

    
325
    $this->drupalLogin($user);
326
    // Make sure access is denied.
327
    $path = 'field-collection/field-test-collection/add/node/' . $node->nid;
328
    $this->drupalGet($path);
329
    $this->assertText(t('Access denied'), 'Access has been denied.');
330

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

    
338
    $edit['field_text[und][0][value]'] = $this->randomName();
339
    $this->drupalPost($path, $edit, t('Save'));
340
    $this->assertText(t('The changes have been saved.'), 'Field collection saved.');
341

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

    
344
    $edit['field_text[und][0][value]'] = $this->randomName();
345
    $this->drupalPost('field-collection/field-test-collection/1/edit', $edit, t('Save'));
346
    $this->assertText(t('The changes have been saved.'), 'Field collection saved.');
347
    $this->assertText($edit['field_text[und][0][value]'], "Field collection has been edited.");
348

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

    
352
    // Add further 3 items, so we have reached 4 == maxium cardinality.
353
    $this->drupalPost($path, $edit, t('Save'));
354
    $this->drupalPost($path, $edit, t('Save'));
355
    $this->drupalPost($path, $edit, t('Save'));
356
    // Make sure adding doesn't work any more as we have restricted cardinality
357
    // to 1.
358
    $this->drupalGet($path);
359
    $this->assertText(t('Too many items.'), 'Maxium cardinality has been reached.');
360

    
361
    $this->drupalPost('field-collection/field-test-collection/1/delete', array(), t('Delete'));
362
    $this->drupalGet($path);
363
    // Add form is shown again.
364
    $this->assertText(t('Test text field'), 'Field collection item has been deleted.');
365

    
366
    // Test the viewing a revision. There should be no links to change it.
367
    $vid = $node->vid;
368
    $node = node_load($node->nid, NULL, TRUE);
369
    $node->revision = TRUE;
370
    node_save($node);
371

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

    
380
    $this->assertNoLinkByHref($path, 'No links on revision view.');
381
    $this->assertNoLinkByHref('field-collection/field-test-collection/2/edit', 'No links on revision view.');
382
    $this->assertNoLinkByHref('field-collection/field-test-collection/2/delete', 'No links on revision view.');
383

    
384
    $this->drupalGet("node/$node->nid/revisions");
385
  }
386

    
387
  /**
388
   * Make sure that field_collection-entities are copied when host-entities do.
389
   */
390
  public function testCopyingEntities() {
391
    list($node, $entity) = $this->createNodeWithFieldCollection();
392

    
393
    // Create a copy of that node.
394
    $node->nid = NULL;
395
    $node->vid = NULL;
396
    $node->is_new = TRUE;
397

    
398
    node_save($node);
399
    $item = $node->{$this->field_name}[LANGUAGE_NONE][0];
400
    $this->assertNotEqual($entity->item_id, $item['value']);
401

    
402
    // Do a php clone to the $node object and save it.
403
    $node2 = clone $node;
404
    $node2->nid = NULL;
405
    $node2->is_new = TRUE;
406
    $node2->vid = NULL;
407
    node_save($node2);
408

    
409
    $item2 = $node2->{$this->field_name}[LANGUAGE_NONE][0];
410
    $this->assertNotEqual($item2['value'], $item['value']);
411

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

    
422
}
423

    
424

    
425
/**
426
 * Test using field collection with Rules.
427
 */
428
class FieldCollectionRulesIntegrationTestCase extends DrupalWebTestCase {
429

    
430
  public static function getInfo() {
431
    return array(
432
      'name' => 'Field collection Rules integration',
433
      'description' => 'Tests using field collections with rules.',
434
      'group' => 'Field types',
435
      'dependencies' => array('rules'),
436
    );
437
  }
438

    
439
  function setUp() {
440
    parent::setUp(array('field_collection', 'rules'));
441
    variable_set('rules_debug_log', 1);
442
  }
443

    
444
  protected function createFields($cardinality = 4) {
445
    // Create a field_collection field to use for the tests.
446
    $this->field_name = 'field_test_collection';
447
    $this->field = array('field_name' => $this->field_name, 'type' => 'field_collection', 'cardinality' => $cardinality);
448
    $this->field = field_create_field($this->field);
449
    $this->field_id = $this->field['id'];
450

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

    
486
  /**
487
   * Test creation field collection items.
488
   */
489
  function testCreation() {
490
    $this->createFields();
491

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

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

    
507
    // Now try making use of the field collection in rules.
508
    $action_set = rules_action_set(array('node' => array('type' => 'node', 'bundle' => 'article')));
509
    $action_set->action('drupal_message', array('message:select' => 'node:field-test-collection:0:field-text'));
510
    $action_set->execute($node);
511

    
512
    $msg = drupal_get_messages();
513
    $this->assertEqual(array_pop($msg['status']), 'foo', 'Field collection can be used.');
514
    RulesLog::logger()->checkLog();
515
  }
516

    
517
  /**
518
   * Test using field collection items via the host while they are being created.
519
   */
520
  function testUsageDuringCreation() {
521
    // Test using a single-cardinality field collection.
522
    $this->createFields(1);
523

    
524
    $node = $this->drupalCreateNode(array('type' => 'article'));
525
    $entity = entity_create('field_collection_item', array('field_name' => $this->field_name));
526
    $entity->setHostEntity('node', $node);
527
    // Now the field collection is linked to the host, but not yet saved.
528

    
529
    // Test using the wrapper on it.
530
    $wrapper = entity_metadata_wrapper('node', $node);
531
    $wrapper->get($this->field_name)->field_text->set('foo');
532
    $this->assertEqual($entity->field_text[LANGUAGE_NONE][0]['value'], 'foo', 'Field collection item used during creation via the wrapper.');
533

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

    
544
/**
545
 * Test using field collection with content that gets translated.
546
 */
547
class FieldCollectionContentTranslationTestCase extends DrupalWebTestCase {
548

    
549
  public static function getInfo() {
550
    return array(
551
      'name' => 'Field collection content translation',
552
      'description' => 'Tests using content under translation.',
553
      'group' => 'Field types',
554
      'dependencies' => array('translation'),
555
    );
556
  }
557

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

    
566
    $this->instance = array(
567
      'field_name' => $this->field_name,
568
      'entity_type' => 'node',
569
      'bundle' => 'article',
570
      'label' => $this->randomName() . '_label',
571
      'description' => $this->randomName() . '_description',
572
      'weight' => mt_rand(0, 127),
573
      'settings' => array(),
574
      'widget' => array(
575
        'type' => 'field_collection_embed',
576
        'label' => 'Test',
577
        'settings' => array(),
578
      ),
579
    );
580
    $this->instance = field_create_instance($this->instance);
581

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

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

    
603
    $this->drupalLogin($admin_user);
604
    // Add German language.
605
    locale_add_language('de');
606

    
607
    // Set "Article" content type to use multilingual support.
608
    variable_set('language_content_type_article', TRANSLATION_ENABLED);
609
  }
610

    
611
  /**
612
   * Ensure field collections are cloned to new entities on content translation.
613
   */
614
  public function testContentTranslation() {
615
    // Create "Article" content.
616
    $edit['title'] = $this->randomName();
617
    $edit['body[' . LANGUAGE_NONE . '][0][value]'] = $this->randomName();
618
    $edit['language'] = 'en';
619
    $field_collection_name = 'field_test_collection[' . LANGUAGE_NONE . '][0][field_text][' . LANGUAGE_NONE . '][0][value]';
620
    $edit[$field_collection_name] = $this->randomName();
621

    
622
    $this->drupalPost('node/add/article', $edit, t('Save'));
623
    $this->assertRaw(t('Article %title has been created.', array('%title' => $edit['title'])), 'Article created.');
624
    $node1 = $this->drupalGetNodeByTitle($edit['title']);
625

    
626
    $this->drupalGet('node/' . $node1->nid . '/edit');
627
    $this->drupalGet('node/' . $node1->nid . '/translate');
628
    $this->drupalGet('node/add/article', array('query' => array('translation' => $node1->nid, 'target' => 'de')));
629

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

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

    
643
}
644

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

    
657
  public static function getInfo() {
658
    return array(
659
      'name' => 'Field collection entity translation',
660
      'description' => 'Tests using content under translation with Entity Translation.',
661
      'group' => 'Field types',
662
      'dependencies' => array('entity_translation'),
663
    );
664
  }
665

    
666
  /**
667
   * Login the given user only if she has not changed.
668
   */
669
  function login($user) {
670
    if (!isset($this->current_user) || $this->current_user->uid != $user->uid) {
671
      $this->current_user = $user;
672
      $this->drupalLogin($user);
673
    }
674
  }
675

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

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

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

    
726
    if (strpos($this->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) {
727
      // Doesn't have language installed so add it.
728
      $edit = array();
729
      $edit['langcode'] = $langcode;
730
      $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
731

    
732
      // Make sure we are not using a stale list.
733
      drupal_static_reset('language_list');
734
      $languages = language_list('language');
735
      $this->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.'));
736

    
737
      if (array_key_exists($langcode, $languages)) {
738
        $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.'));
739
      }
740
    }
741
    elseif ($this->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(':name' => 'enabled[' . $langcode . ']'))) {
742
      // It is installed and enabled. No need to do anything.
743
      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.');
744
    }
745
    else {
746
      // It is installed but not enabled. Enable it.
747
      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.');
748
      $this->drupalPost(NULL, array('enabled[' . $langcode . ']' => TRUE), t('Save configuration'));
749
      $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.'));
750
    }
751
  }
752

    
753
  public function setUp() {
754
    parent::setUp(array('field_collection', 'entity_translation'));
755
    $language_none = LANGUAGE_NONE;
756
    // Login with an admin user.
757
    $this->login($this->getAdminUser());
758
    // Add English and German languages.
759
    $this->addLanguage('en');
760
    $this->addLanguage('de');
761

    
762
    // Set "Article" content type to use multilingual support with translation.
763
    $edit = array();
764
    $edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED;
765
    $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
766
    $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
767

    
768
    // Create a field collection field to use for the tests.
769
    $this->field_name = 'field_test_collection';
770
    $this->field_base = "{$this->field_name}[$language_none]";
771
    $this->field = array(
772
      'field_name' => $this->field_name,
773
      'type' => 'field_collection',
774
      'cardinality' => -1,
775
      'translatable' => TRUE,
776
    );
777
    $this->field = field_create_field($this->field);
778
    $this->field_id = $this->field['id'];
779

    
780
    $this->instance = array(
781
      'field_name' => $this->field_name,
782
      'entity_type' => 'node',
783
      'bundle' => 'page',
784
      'label' => $this->randomName() . '_label',
785
      'description' => $this->randomName() . '_description',
786
      'weight' => mt_rand(0, 127),
787
      'settings' => array(),
788
      'widget' => array(
789
        'type' => 'field_collection_embed',
790
        'label' => 'Test',
791
        'settings' => array(),
792
      ),
793
    );
794
    $this->instance = field_create_instance($this->instance);
795

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

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

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

    
844
    $this->login($this->getTranslatorUser());
845
  }
846

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

    
861
    $title = $this->randomName();
862

    
863
    $this->drupalGet('node/add/page');
864

    
865
    $edit = array();
866
    $edit['title'] = $title;
867
    for ($i = 0; $i < $num_values; $i++) {
868
      if ($i != 0) {
869
        $this->drupalPost(NULL, array(), t('Add another item'));
870
      }
871
      $edit[$this->field_base . '[' . $i . ']' . $this->field_untrans_base] = self::UNTRANS_FIELD_EN . '_' . $i;
872
      $edit[$this->field_base . '[' . $i . ']' . $this->field_trans_base] = self::TRANS_FIELD_EN . '_' . $i;
873
    }
874

    
875
    $edit['language'] = $langcode;
876
    $this->drupalPost(NULL, $edit, t('Save'));
877
    $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.'));
878

    
879
    // Check to make sure the node was created.
880
    $node = $this->drupalGetNodeByTitle($title);
881
    $this->assertTrue($node, t('Node found in database.'));
882

    
883
    return $node;
884

    
885
  }
886

    
887
  /**
888
   * Create a translation using the Entity Translation Form.
889
   *
890
   * @param $node
891
   *   Node of the basic page to create translation for.
892
   * @param $langcode
893
   *   The language code of the translation.
894
   * @param $source_langcode
895
   *   The original language code.
896
   */
897
  protected function createTranslationForm($node, $langcode, $source_langcode = 'en') {
898
    $language_none = LANGUAGE_NONE;
899
    $edit = array();
900

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

    
903
    // Get the field collection in the original language.
904
    $fc_values = $node->{$this->field_name}[$source_langcode];
905

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

    
924
      $edit[$fc_untrans_key] = self::UNTRANS_FIELD_DE . '_' . $delta;
925
      $edit[$fc_trans_key] = self::TRANS_FIELD_DE . '_' . $delta;
926
    }
927

    
928
    // Save the translation.
929
    $this->drupalPost(NULL, $edit, t('Save'));
930
    $this->drupalGet('node/' . $node->nid . '/translate');
931
    $this->assertLinkByHref('node/' . $node->nid . '/edit/' . $langcode, 0, t('Translation edit link found. Translation created.'));
932

    
933
    // Reload the node.
934
    $node = node_load($node->nid, NULL, TRUE);
935

    
936
    // Check the values of the translated field.
937
    $this->checkFieldCollectionContent($node, $langcode);
938

    
939
    // Check the values of the field in the original language.
940
    $this->checkFieldCollectionContent($node, $source_langcode);
941

    
942
    return $node;
943
  }
944

    
945
  /**
946
   * Removes a translation using the entity translation form.
947
   *
948
   * @param mixed $node
949
   *   The node to remove the translation from.
950
   * @param unknown $langcode
951
   *   The language of the translation to remove.
952
   * @param unknown $source_langcode
953
   *   The source language of the node.
954
   */
955
  protected function removeTranslationForm($node, $langcode, $source_langcode) {
956
    // Number of field collection items in the source language.
957
    $num_original_fc_items = count($node->{$this->field_name}[$source_langcode]);
958

    
959
    // Fetch the translation edit form.
960
    $this->drupalGet('node/' . $node->nid . '/edit/' . $langcode);
961

    
962
    // Remove the translation.
963
    $this->drupalPost(NULL, array(), t('Delete translation'));
964
    // Confirm deletion.
965
    $this->drupalPost(NULL, array(), t('Delete'));
966

    
967
    // Reload the node.
968
    $node = node_load($node->nid, NULL, TRUE);
969

    
970
    // Check that the translation is removed.
971
    $this->drupalGet('node/' . $node->nid . '/translate');
972
    $this->assertLinkByHref('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' . $langcode, 0, 'The add translation link appears');
973
    $this->assert(empty($node->{$this->field_name}[$langcode]));
974

    
975
    // Check that the field collection in the original language has not changed.
976
    $num_fc_items = count($node->{$this->field_name}[$source_langcode]);
977
    $this->assertEqual($num_original_fc_items, $num_fc_items, 'The number of field collection items in the original language has not changed.');
978
    $this->checkFieldCollectionContent($node, $source_langcode);
979
  }
980

    
981
  /**
982
   * Creates a translation programmatically using Entity Translation.
983
   *
984
   * @param $node
985
   *   Node of the basic page to create translation for.
986
   * @param $langcode
987
   *   The language code of the translation.
988
   * @param $source_langcode
989
   *   The source language code.
990
   */
991
  protected function createTranslation($node, $langcode) {
992
    $source_langcode = $node->language;
993

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

    
1021
    $handler->setTranslation($translation, $values);
1022
    $handler->saveTranslations();
1023
    field_attach_update('node', $node);
1024

    
1025
    // Reload an return the node.
1026
    $node = node_load($node->nid, null, TRUE);
1027
    return $node;
1028
  }
1029

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

    
1042
    // Remove the translation.
1043
    $handler->removeTranslation($langcode);
1044
    node_save($node);
1045

    
1046
    // Reload and return the node.
1047
    $node = node_load($node->nid, null, TRUE);
1048

    
1049
    return $node;
1050
  }
1051

    
1052
  /**
1053
   * Creates a new revision of the node and checks the result.
1054
   *
1055
   * @param $node
1056
   * @param $langcode
1057
   * @param $source_langcode
1058
   * @return
1059
   *   The new revision of the node.
1060
   */
1061
  protected function createRevision($node, $langcode, $source_langcode) {
1062
    $node_original_revision = $node->vid;
1063
    // The original entries of the translated field.
1064
    $original_fc_item_ids = $node->{$this->field_name}[$langcode];
1065

    
1066
    // Create the revision.
1067
    $node->revision = TRUE;
1068
    node_save($node);
1069

    
1070
    // The new entries of the translated field.
1071
    $new_fc_item_ids = $node->{$this->field_name}[$langcode];
1072

    
1073
    // Check that the field collection items are the same and a new revision of
1074
    // each one has been created.
1075
    foreach ($original_fc_item_ids as $delta => $value) {
1076
      $this->assertEqual($value['value'], $new_fc_item_ids[$delta]['value'], t('We have the same field collection item'));
1077
      $this->assertNotEqual($value['revision_id'], $new_fc_item_ids[$delta]['revision_id'], t('We have a new revision of the field collection item'));
1078
    }
1079

    
1080
    return $node;
1081
  }
1082

    
1083
  /**
1084
   * Check the content of the field collection for a specified language.
1085
   *
1086
   * @param mixed $node
1087
   *   The node to check.
1088
   * @param string $langcode
1089
   *   The language to check.
1090
   */
1091
  protected function checkFieldCollectionContent($node, $langcode) {
1092
    switch($langcode) {
1093
      case 'en':
1094
        $untrans_field = self::UNTRANS_FIELD_EN;
1095
        $trans_field = self::TRANS_FIELD_EN;
1096
        break;
1097
      case 'de':
1098
        $untrans_field = self::UNTRANS_FIELD_DE;
1099
        $trans_field = self::TRANS_FIELD_DE;
1100
        break;
1101
    }
1102
    // Get the field collection in the specified language.
1103
    $fc_values = $node->{$this->field_name}[$langcode];
1104

    
1105
    foreach ($fc_values as $delta => $fc_value) {
1106
      // Load the field collection item.
1107
      $fc_item_array = entity_load('field_collection_item', array($fc_value['value']));
1108
      $fc_item = reset($fc_item_array);
1109
      $fc_untrans_key = "{$this->field_name}[$langcode][$delta]{$this->field_untrans_base}";
1110
      $fc_trans_key = "{$this->field_name}[$langcode][$delta]{$this->field_trans_base}";
1111

    
1112
      $this->assertEqual($untrans_field . '_' . $delta, $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value']);
1113
      $this->assertEqual($trans_field . '_' . $delta, $fc_item->{$this->field_trans_name}[$langcode][0]['value']);
1114
    }
1115
  }
1116

    
1117
  /**
1118
   * Returns the text field values of an specified node, language and delta.
1119
   *
1120
   * @param mixed $node
1121
   * @param string $langcode
1122
   * @param integer $delta
1123
   * @return array
1124
   */
1125
  protected function getFieldValues($node, $langcode, $delta) {
1126
    $return = array();
1127

    
1128
    if (isset($node->{$this->field_name}[$langcode][$delta]['value'])) {
1129
      $fc_item_id = $node->{$this->field_name}[$langcode][$delta]['value'];
1130
      // Load the field collection.
1131
      $fc_item_array = entity_load('field_collection_item', array($fc_item_id));
1132
      $fc_item = reset($fc_item_array);
1133

    
1134
      $return = array(
1135
        'field_untrans' => $fc_item->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'],
1136
        'field_trans' => $fc_item->{$this->field_trans_name}[$langcode][0]['value'],
1137
      );
1138
    }
1139

    
1140
    return $return;
1141
  }
1142

    
1143
  /**
1144
   * Ensures the right behaviour in all Entity Translation use cases.
1145
   */
1146
  public function testEntityTranslation() {
1147
    $source_langcode = 'en';
1148
    $translation_langcode = 'de';
1149

    
1150
    /*
1151
     * Test with a page with only one value in the field collection
1152
     */
1153
    // Create an article in the original language with only one field collection
1154
    // value.
1155
    $node = $this->createPage(1, $source_langcode);
1156

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

    
1160
    /*
1161
     * Test with a page with multiple values in the field collection.
1162
     */
1163
    $num_values = 4;
1164
    // Create a page in the original language with multiple field collection
1165
    // values.
1166
    $node = $this->createPage($num_values, $source_langcode);
1167

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

    
1171
    // Assign a new field collection item to an existing node.
1172
    $values = array();
1173
    $values['field_name'] = $this->field_name;
1174
    $fc_entity = entity_create('field_collection_item', $values);
1175
    $fc_entity->setHostEntity('node', $node, $translation_langcode);
1176

    
1177
    $fc_entity->{$this->field_untrans_name}[LANGUAGE_NONE][0]['value'] = self::UNTRANS_FIELD_DE_MOD;
1178
    $fc_entity->{$this->field_trans_name}['de'][0]['value'] = self::TRANS_FIELD_DE_MOD;
1179
    $fc_entity->save(TRUE);
1180

    
1181
    node_save($node);
1182

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

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

    
1209
    // Delete the translation.
1210
    $this->removeTranslationForm($node, $translation_langcode, $source_langcode);
1211

    
1212
    /*
1213
     * Check the revisioning of an entity with translations.
1214
     */
1215
    $num_values = 4;
1216
    // Create a page in the original language with multiple field collection
1217
    // values.
1218
    $node_rev = $this->createPage($num_values, $source_langcode);
1219

    
1220
    // Create a traslation of the page.
1221
    $node_rev = $this->createTranslationForm($node_rev, $translation_langcode, $source_langcode);
1222

    
1223
    $original_revision = $node_rev->vid;
1224

    
1225
    // Create a new revision of the node.
1226
    $node_rev = $this->createRevision($node_rev, $translation_langcode, $source_langcode);
1227

    
1228
    /*
1229
     * Test creating programmatically.
1230
     */
1231
    $num_values = 4;
1232
    // Create a page in the original language.
1233
    $node_prog = $this->createPage($num_values, $source_langcode);
1234

    
1235
    // Create programmatically a translation of the page.
1236
    $node_prog = $this->createTranslation($node_prog, $translation_langcode);
1237

    
1238
    $orig_fc_items = $node_prog->{$this->field_name}[$source_langcode];
1239
    $trans_fc_items = $node_prog->{$this->field_name}[$translation_langcode];
1240

    
1241
    $orig_fc_item_ids = array();
1242
    $trans_fc_item_ids = array();
1243

    
1244
    // Check each item.
1245
    foreach ($orig_fc_items as $delta => $value) {
1246
      $orig_fc_item_ids[] = $value['value'];
1247
      $trans_fc_item_ids[] = $trans_fc_items[$delta]['value'];
1248

    
1249
      // Check if we have new items for the translation.
1250
      $this->assertNotEqual($value['value'], $trans_fc_items[$delta]['value'], t('New item generated for translation.'));
1251
    }
1252

    
1253
    // Check that the original item still exists in the database.
1254
    $fc_items = entity_load('field_collection_item', $orig_fc_item_ids);
1255
    $this->assert(!empty($fc_items), t('Field Collections in the source language still exist.'));
1256
    // Check that the translated item exists in the database.
1257
    $fc_items = entity_load('field_collection_item', $trans_fc_item_ids);
1258
    $this->assert(!empty($fc_items), t('Translations for the Field Collection exist.'));
1259

    
1260
    // Remove the translation and check that the original field collection items
1261
    // are still there.
1262
    $node_prog = $this->removeTranslation($node, $translation_langcode);
1263

    
1264
    // Check the content in the source language.
1265
    $this->checkFieldCollectionContent($node_prog, $source_langcode);
1266

    
1267
    // Check that the field translated content has been removed.
1268
    $this->assert(empty($node->{$this->field_name}[$translation_langcode]), t('Translated content removed.'));
1269
  }
1270

    
1271
}