1 <?php
2
3
4
5
6
7
8
9
10
11 class FieldTestCase extends DrupalWebTestCase {
12 var $default_storage = 'field_sql_storage';
13
14
15
16
17 function setUp() {
18
19
20
21 $modules = func_get_args();
22 if (isset($modules[0]) && is_array($modules[0])) {
23 $modules = $modules[0];
24 }
25 parent::setUp($modules);
26
27 variable_set('field_storage_default', $this->default_storage);
28 }
29
30
31
32
33
34
35
36
37
38 function _generateTestFieldValues($cardinality) {
39 $values = array();
40 for ($i = 0; $i < $cardinality; $i++) {
41
42 $values[$i]['value'] = mt_rand(1, 127);
43 }
44 return $values;
45 }
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 function assertFieldValues($entity, $field_name, $langcode, $expected_values, $column = 'value') {
64 $e = clone $entity;
65 field_attach_load('test_entity', array($e->ftid => $e));
66 $values = isset($e->{$field_name}[$langcode]) ? $e->{$field_name}[$langcode] : array();
67 $this->assertEqual(count($values), count($expected_values), t('Expected number of values were saved.'));
68 foreach ($expected_values as $key => $value) {
69 $this->assertEqual($values[$key][$column], $value, t('Value @value was saved correctly.', array('@value' => $value)));
70 }
71 }
72 }
73
74 class FieldAttachTestCase extends FieldTestCase {
75 function setUp() {
76
77
78
79 $modules = func_get_args();
80 if (isset($modules[0]) && is_array($modules[0])) {
81 $modules = $modules[0];
82 }
83 if (!in_array('field_test', $modules)) {
84 $modules[] = 'field_test';
85 }
86 parent::setUp($modules);
87
88 $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
89 $this->field = array('field_name' => $this->field_name, 'type' => 'test_field', 'cardinality' => 4);
90 $this->field = field_create_field($this->field);
91 $this->field_id = $this->field['id'];
92 $this->instance = array(
93 'field_name' => $this->field_name,
94 'entity_type' => 'test_entity',
95 'bundle' => 'test_bundle',
96 'label' => $this->randomName() . '_label',
97 'description' => $this->randomName() . '_description',
98 'weight' => mt_rand(0, 127),
99 'settings' => array(
100 'test_instance_setting' => $this->randomName(),
101 ),
102 'widget' => array(
103 'type' => 'test_field_widget',
104 'label' => 'Test Field',
105 'settings' => array(
106 'test_widget_setting' => $this->randomName(),
107 )
108 )
109 );
110 field_create_instance($this->instance);
111 }
112 }
113
114
115
116
117
118
119
120 class FieldAttachStorageTestCase extends FieldAttachTestCase {
121 public static function getInfo() {
122 return array(
123 'name' => 'Field attach tests (storage-related)',
124 'description' => 'Test storage-related Field Attach API functions.',
125 'group' => 'Field API',
126 );
127 }
128
129
130
131
132
133
134
135 function testFieldAttachSaveLoad() {
136
137
138 $this->instance['settings']['test_hook_field_load'] = TRUE;
139 field_update_instance($this->instance);
140 $langcode = LANGUAGE_NONE;
141
142 $entity_type = 'test_entity';
143 $values = array();
144
145
146
147
148 for ($revision_id = 0; $revision_id < 3; $revision_id++) {
149 $revision[$revision_id] = field_test_create_stub_entity(0, $revision_id, $this->instance['bundle']);
150
151 $values[$revision_id] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
152 $current_revision = $revision_id;
153
154 if (!$revision_id) {
155 $revision[$revision_id]->{$this->field_name}[$langcode] = $values[$revision_id];
156 field_attach_insert($entity_type, $revision[$revision_id]);
157 }
158 else {
159
160 $revision[$revision_id]->{$this->field_name}[$langcode] = $values[$revision_id];
161 field_attach_update($entity_type, $revision[$revision_id]);
162 }
163 }
164
165
166 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
167 field_attach_load($entity_type, array(0 => $entity));
168
169 $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], t('Current revision: expected number of values'));
170 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
171
172 $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'] , $values[$current_revision][$delta]['value'], t('Current revision: expected value %delta was found.', array('%delta' => $delta)));
173
174 $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['additional_key'], 'additional_value', t('Current revision: extra information for value %delta was found', array('%delta' => $delta)));
175 }
176
177
178 foreach (array_keys($revision) as $revision_id) {
179 $entity = field_test_create_stub_entity(0, $revision_id, $this->instance['bundle']);
180 field_attach_load_revision($entity_type, array(0 => $entity));
181
182 $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], t('Revision %revision_id: expected number of values.', array('%revision_id' => $revision_id)));
183 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
184
185 $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['value'], $values[$revision_id][$delta]['value'], t('Revision %revision_id: expected value %delta was found.', array('%revision_id' => $revision_id, '%delta' => $delta)));
186
187 $this->assertEqual($entity->{$this->field_name}[$langcode][$delta]['additional_key'], 'additional_value', t('Revision %revision_id: extra information for value %delta was found', array('%revision_id' => $revision_id, '%delta' => $delta)));
188 }
189 }
190 }
191
192
193
194
195 function testFieldAttachLoadMultiple() {
196 $entity_type = 'test_entity';
197 $langcode = LANGUAGE_NONE;
198
199
200 $bundles = array(
201 1 => 'test_bundle_1',
202 2 => 'test_bundle_2',
203 );
204 field_test_create_bundle($bundles[1]);
205 field_test_create_bundle($bundles[2]);
206
207
208
209
210 $field_bundles_map = array(
211 1 => array(1, 2),
212 2 => array(1),
213 3 => array(2),
214 );
215 for ($i = 1; $i <= 3; $i++) {
216 $field_names[$i] = 'field_' . $i;
217 $field = array('field_name' => $field_names[$i], 'type' => 'test_field');
218 $field = field_create_field($field);
219 $field_ids[$i] = $field['id'];
220 foreach ($field_bundles_map[$i] as $bundle) {
221 $instance = array(
222 'field_name' => $field_names[$i],
223 'entity_type' => 'test_entity',
224 'bundle' => $bundles[$bundle],
225 'settings' => array(
226
227
228 'test_hook_field_load' => TRUE,
229 ),
230 );
231 field_create_instance($instance);
232 }
233 }
234
235
236 foreach ($bundles as $index => $bundle) {
237 $entities[$index] = field_test_create_stub_entity($index, $index, $bundle);
238 $entity = clone($entities[$index]);
239 $instances = field_info_instances('test_entity', $bundle);
240 foreach ($instances as $field_name => $instance) {
241 $values[$index][$field_name] = mt_rand(1, 127);
242 $entity->$field_name = array($langcode => array(array('value' => $values[$index][$field_name])));
243 }
244 field_attach_insert($entity_type, $entity);
245 }
246
247
248 field_attach_load($entity_type, $entities);
249 foreach ($entities as $index => $entity) {
250 $instances = field_info_instances($entity_type, $bundles[$index]);
251 foreach ($instances as $field_name => $instance) {
252
253 $this->assertEqual($entity->{$field_name}[$langcode][0]['value'], $values[$index][$field_name], t('Entity %index: expected value was found.', array('%index' => $index)));
254
255 $this->assertEqual($entity->{$field_name}[$langcode][0]['additional_key'], 'additional_value', t('Entity %index: extra information was found', array('%index' => $index)));
256 }
257 }
258
259
260 $entity = field_test_create_stub_entity(1, 1, $bundles[1]);
261 field_attach_load($entity_type, array(1 => $entity), FIELD_LOAD_CURRENT, array('field_id' => $field_ids[1]));
262 $this->assertEqual($entity->{$field_names[1]}[$langcode][0]['value'], $values[1][$field_names[1]], t('Entity %index: expected value was found.', array('%index' => 1)));
263 $this->assertEqual($entity->{$field_names[1]}[$langcode][0]['additional_key'], 'additional_value', t('Entity %index: extra information was found', array('%index' => 1)));
264 $this->assert(!isset($entity->{$field_names[2]}), t('Entity %index: field %field_name is not loaded.', array('%index' => 2, '%field_name' => $field_names[2])));
265 $this->assert(!isset($entity->{$field_names[3]}), t('Entity %index: field %field_name is not loaded.', array('%index' => 3, '%field_name' => $field_names[3])));
266 }
267
268
269
270
271 function testFieldAttachSaveLoadDifferentStorage() {
272 $entity_type = 'test_entity';
273 $langcode = LANGUAGE_NONE;
274
275
276 $fields = array(
277 array(
278 'field_name' => 'field_1',
279 'type' => 'test_field',
280 'cardinality' => 4,
281 'storage' => array('type' => 'field_sql_storage')
282 ),
283 array(
284 'field_name' => 'field_2',
285 'type' => 'test_field',
286 'cardinality' => 4,
287 'storage' => array('type' => 'field_test_storage')
288 ),
289 );
290 foreach ($fields as $field) {
291 field_create_field($field);
292 $instance = array(
293 'field_name' => $field['field_name'],
294 'entity_type' => 'test_entity',
295 'bundle' => 'test_bundle',
296 );
297 field_create_instance($instance);
298 }
299
300 $entity_init = field_test_create_stub_entity();
301
302
303 $entity = clone($entity_init);
304 $values = array();
305 foreach ($fields as $field) {
306 $values[$field['field_name']] = $this->_generateTestFieldValues($this->field['cardinality']);
307 $entity->{$field['field_name']}[$langcode] = $values[$field['field_name']];
308 }
309 field_attach_insert($entity_type, $entity);
310
311
312 $entity = clone($entity_init);
313 field_attach_load($entity_type, array($entity->ftid => $entity));
314 foreach ($fields as $field) {
315 $this->assertEqual($values[$field['field_name']], $entity->{$field['field_name']}[$langcode], t('%storage storage: expected values were found.', array('%storage' => $field['storage']['type'])));
316 }
317 }
318
319
320
321
322
323
324 function testFieldStorageDetailsAlter() {
325 $field_name = 'field_test_change_my_details';
326 $field = array(
327 'field_name' => $field_name,
328 'type' => 'test_field',
329 'cardinality' => 4,
330 'storage' => array('type' => 'field_test_storage'),
331 );
332 $field = field_create_field($field);
333 $instance = array(
334 'field_name' => $field_name,
335 'entity_type' => 'test_entity',
336 'bundle' => 'test_bundle',
337 );
338 field_create_instance($instance);
339
340 $field = field_info_field($instance['field_name']);
341 $instance = field_info_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
342
343
344 $this->assertTrue(array_key_exists('drupal_variables', $field['storage']['details']), t('The storage type is Drupal variables.'));
345
346 $details = $field['storage']['details']['drupal_variables'];
347
348
349
350 $this->assertTrue(array_key_exists('moon', $details[FIELD_LOAD_CURRENT]), t('Moon is available in the instance array.'));
351 $this->assertTrue(array_key_exists('mars', $details[FIELD_LOAD_REVISION]), t('Mars is available in the instance array.'));
352
353
354
355 foreach ((array) $field['columns'] as $column_name => $attributes) {
356 $this->assertEqual($details[FIELD_LOAD_CURRENT]['moon'][$column_name], $column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'moon[FIELD_LOAD_CURRENT]')));
357 $this->assertEqual($details[FIELD_LOAD_REVISION]['mars'][$column_name], $column_name, t('Column name %value matches the definition in %bin.', array('%value' => $column_name, '%bin' => 'mars[FIELD_LOAD_REVISION]')));
358 }
359 }
360
361
362
363
364 function testFieldAttachSaveMissingData() {
365 $entity_type = 'test_entity';
366 $entity_init = field_test_create_stub_entity();
367 $langcode = LANGUAGE_NONE;
368
369
370 $entity = clone($entity_init);
371 field_attach_insert($entity_type, $entity);
372
373 $entity = clone($entity_init);
374 field_attach_load($entity_type, array($entity->ftid => $entity));
375 $this->assertTrue(empty($entity->{$this->field_name}), t('Insert: missing field results in no value saved'));
376
377
378 field_cache_clear();
379 $entity = clone($entity_init);
380 $entity->{$this->field_name} = NULL;
381 field_attach_insert($entity_type, $entity);
382
383 $entity = clone($entity_init);
384 field_attach_load($entity_type, array($entity->ftid => $entity));
385 $this->assertTrue(empty($entity->{$this->field_name}), t('Insert: NULL field results in no value saved'));
386
387
388 field_cache_clear();
389 $entity = clone($entity_init);
390 $values = $this->_generateTestFieldValues(1);
391 $entity->{$this->field_name}[$langcode] = $values;
392 field_attach_insert($entity_type, $entity);
393
394 $entity = clone($entity_init);
395 field_attach_load($entity_type, array($entity->ftid => $entity));
396 $this->assertEqual($entity->{$this->field_name}[$langcode], $values, t('Field data saved'));
397
398
399 field_cache_clear();
400 $entity = clone($entity_init);
401 field_attach_update($entity_type, $entity);
402
403 $entity = clone($entity_init);
404 field_attach_load($entity_type, array($entity->ftid => $entity));
405 $this->assertEqual($entity->{$this->field_name}[$langcode], $values, t('Update: missing field leaves existing values in place'));
406
407
408 field_cache_clear();
409 $entity = clone($entity_init);
410 $entity->{$this->field_name} = NULL;
411 field_attach_update($entity_type, $entity);
412
413 $entity = clone($entity_init);
414 field_attach_load($entity_type, array($entity->ftid => $entity));
415 $this->assertTrue(empty($entity->{$this->field_name}), t('Update: NULL field removes existing values'));
416
417
418 field_cache_clear();
419 $entity = clone($entity_init);
420 $values = $this->_generateTestFieldValues(1);
421 $entity->{$this->field_name}[$langcode] = $values;
422 field_attach_update($entity_type, $entity);
423
424 $entity = clone($entity_init);
425 field_attach_load($entity_type, array($entity->ftid => $entity));
426 $this->assertEqual($entity->{$this->field_name}[$langcode], $values, t('Field data saved'));
427
428
429 field_cache_clear();
430 $entity = clone($entity_init);
431 $entity->{$this->field_name} = array();
432 field_attach_update($entity_type, $entity);
433
434 $entity = clone($entity_init);
435 field_attach_load($entity_type, array($entity->ftid => $entity));
436 $this->assertTrue(empty($entity->{$this->field_name}), t('Update: empty array removes existing values'));
437 }
438
439
440
441
442 function testFieldAttachSaveMissingDataDefaultValue() {
443
444 $this->instance['default_value_function'] = 'field_test_default_value';
445 field_update_instance($this->instance);
446
447 $entity_type = 'test_entity';
448 $entity_init = field_test_create_stub_entity();
449 $langcode = LANGUAGE_NONE;
450
451
452 $entity = clone($entity_init);
453 $entity->{$this->field_name}[$langcode] = NULL;
454 field_attach_insert($entity_type, $entity);
455
456 $entity = clone($entity_init);
457 field_attach_load($entity_type, array($entity->ftid => $entity));
458 $this->assertTrue(empty($entity->{$this->field_name}[$langcode]), t('Insert: NULL field results in no value saved'));
459
460
461 field_cache_clear();
462 $entity = clone($entity_init);
463 field_attach_insert($entity_type, $entity);
464
465 $entity = clone($entity_init);
466 field_attach_load($entity_type, array($entity->ftid => $entity));
467 $values = field_test_default_value($entity_type, $entity, $this->field, $this->instance);
468 $this->assertEqual($entity->{$this->field_name}[$langcode], $values, t('Insert: missing field results in default value saved'));
469 }
470
471
472
473
474 function testFieldAttachDelete() {
475 $entity_type = 'test_entity';
476 $langcode = LANGUAGE_NONE;
477 $rev[0] = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
478
479
480 $values = $this->_generateTestFieldValues($this->field['cardinality']);
481 $rev[0]->{$this->field_name}[$langcode] = $values;
482 field_attach_insert($entity_type, $rev[0]);
483
484
485 $rev[1] = field_test_create_stub_entity(0, 1, $this->instance['bundle']);
486 $rev[1]->{$this->field_name}[$langcode] = $values;
487 field_attach_update($entity_type, $rev[1]);
488
489
490 $rev[2] = field_test_create_stub_entity(0, 2, $this->instance['bundle']);
491 $rev[2]->{$this->field_name}[$langcode] = $values;
492 field_attach_update($entity_type, $rev[2]);
493
494
495 foreach (array_keys($rev) as $vid) {
496 $read = field_test_create_stub_entity(0, $vid, $this->instance['bundle']);
497 field_attach_load_revision($entity_type, array(0 => $read));
498 $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
499 }
500
501
502 field_attach_delete_revision($entity_type, $rev[1]);
503 foreach (array(0, 2) as $vid) {
504 $read = field_test_create_stub_entity(0, $vid, $this->instance['bundle']);
505 field_attach_load_revision($entity_type, array(0 => $read));
506 $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity revision $vid has {$this->field['cardinality']} values.");
507 }
508
509
510 $read = field_test_create_stub_entity(0, 2, $this->instance['bundle']);
511 field_attach_load($entity_type, array(0 => $read));
512 $this->assertEqual(count($read->{$this->field_name}[$langcode]), $this->field['cardinality'], "The test entity current revision has {$this->field['cardinality']} values.");
513
514
515 field_attach_delete($entity_type, $rev[2]);
516 foreach (array(0, 1, 2) as $vid) {
517 $read = field_test_create_stub_entity(0, $vid, $this->instance['bundle']);
518 field_attach_load_revision($entity_type, array(0 => $read));
519 $this->assertIdentical($read->{$this->field_name}, array(), "The test entity revision $vid is deleted.");
520 }
521 $read = field_test_create_stub_entity(0, 2, $this->instance['bundle']);
522 field_attach_load($entity_type, array(0 => $read));
523 $this->assertIdentical($read->{$this->field_name}, array(), t('The test entity current revision is deleted.'));
524 }
525
526
527
528
529 function testFieldAttachCreateRenameBundle() {
530
531
532 $new_bundle = 'test_bundle_' . drupal_strtolower($this->randomName());
533 field_test_create_bundle($new_bundle);
534
535
536 $this->instance['bundle'] = $new_bundle;
537 field_create_instance($this->instance);
538
539
540 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
541 $langcode = LANGUAGE_NONE;
542 $values = $this->_generateTestFieldValues($this->field['cardinality']);
543 $entity->{$this->field_name}[$langcode] = $values;
544 $entity_type = 'test_entity';
545 field_attach_insert($entity_type, $entity);
546
547
548 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
549 field_attach_load($entity_type, array(0 => $entity));
550 $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], "Data is retrieved for the new bundle");
551
552
553
554 $new_bundle = 'test_bundle_' . drupal_strtolower($this->randomName());
555 field_test_rename_bundle($this->instance['bundle'], $new_bundle);
556
557
558 $this->instance = field_info_instance($entity_type, $this->field_name, $new_bundle);
559 $this->assertIdentical($this->instance['bundle'], $new_bundle, "Bundle name has been updated in the instance.");
560
561
562 $entity = field_test_create_stub_entity(0, 0, $new_bundle);
563 field_attach_load($entity_type, array(0 => $entity));
564 $this->assertEqual(count($entity->{$this->field_name}[$langcode]), $this->field['cardinality'], "Bundle name has been updated in the field storage");
565 }
566
567
568
569
570 function testFieldAttachDeleteBundle() {
571
572
573 $new_bundle = 'test_bundle_' . drupal_strtolower($this->randomName());
574 field_test_create_bundle($new_bundle);
575
576
577 $this->instance['bundle'] = $new_bundle;
578 field_create_instance($this->instance);
579
580
581 $field_name = drupal_strtolower($this->randomName() . '_field_name');
582 $field = array('field_name' => $field_name, 'type' => 'test_field', 'cardinality' => 1);
583 field_create_field($field);
584 $instance = array(
585 'field_name' => $field_name,
586 'entity_type' => 'test_entity',
587 'bundle' => $this->instance['bundle'],
588 'label' => $this->randomName() . '_label',
589 'description' => $this->randomName() . '_description',
590 'weight' => mt_rand(0, 127),
591
592 'widget' => array(
593 'type' => 'test_field_widget',
594 'settings' => array(
595 'size' => mt_rand(0, 255))));
596 field_create_instance($instance);
597
598
599 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
600 $langcode = LANGUAGE_NONE;
601 $values = $this->_generateTestFieldValues($this->field['cardinality']);
602 $entity->{$this->field_name}[$langcode] = $values;
603 $entity->{$field_name}[$langcode] = $this->_generateTestFieldValues(1);
604 field_attach_insert('test_entity', $entity);
605
606
607 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
608 field_attach_load('test_entity', array(0 => $entity));
609 $this->assertEqual(count($entity->{$this->field_name}[$langcode]), 4, 'First field got loaded');
610 $this->assertEqual(count($entity->{$field_name}[$langcode]), 1, 'Second field got loaded');
611
612
613
614 field_test_delete_bundle($this->instance['bundle']);
615
616
617 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
618 field_attach_load('test_entity', array(0 => $entity));
619 $this->assertFalse(isset($entity->{$this->field_name}[$langcode]), 'No data for first field');
620 $this->assertFalse(isset($entity->{$field_name}[$langcode]), 'No data for second field');
621
622
623 $this->assertFalse(field_read_instance('test_entity', $this->field_name, $this->instance['bundle']), "First field is deleted");
624 $this->assertFalse(field_read_instance('test_entity', $field_name, $instance['bundle']), "Second field is deleted");
625 }
626 }
627
628
629
630
631 class FieldAttachOtherTestCase extends FieldAttachTestCase {
632 public static function getInfo() {
633 return array(
634 'name' => 'Field attach tests (other)',
635 'description' => 'Test other Field Attach API functions.',
636 'group' => 'Field API',
637 );
638 }
639
640
641
642
643 function testFieldAttachView() {
644 $entity_type = 'test_entity';
645 $entity_init = field_test_create_stub_entity();
646 $langcode = LANGUAGE_NONE;
647
648
649 $values = $this->_generateTestFieldValues($this->field['cardinality']);
650 $entity_init->{$this->field_name}[$langcode] = $values;
651
652
653 $entity = clone($entity_init);
654 $formatter_setting = $this->randomName();
655 $this->instance['display'] = array(
656 'full' => array(
657 'label' => 'above',
658 'type' => 'field_test_default',
659 'settings' => array(
660 'test_formatter_setting' => $formatter_setting,
661 )
662 ),
663 );
664 field_update_instance($this->instance);
665 field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
666 $entity->content = field_attach_view($entity_type, $entity, 'full');
667 $output = drupal_render($entity->content);
668 $this->content = $output;
669 $this->assertRaw($this->instance['label'], "Label is displayed.");
670 foreach ($values as $delta => $value) {
671 $this->content = $output;
672 $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
673 }
674
675
676 $entity = clone($entity_init);
677 $this->instance['display']['full']['label'] = 'hidden';
678 field_update_instance($this->instance);
679 field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
680 $entity->content = field_attach_view($entity_type, $entity, 'full');
681 $output = drupal_render($entity->content);
682 $this->content = $output;
683 $this->assertNoRaw($this->instance['label'], "Hidden label: label is not displayed.");
684
685
686 $entity = clone($entity_init);
687 $this->instance['display'] = array(
688 'full' => array(
689 'label' => 'above',
690 'type' => 'hidden',
691 ),
692 );
693 field_update_instance($this->instance);
694 field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
695 $entity->content = field_attach_view($entity_type, $entity, 'full');
696 $output = drupal_render($entity->content);
697 $this->content = $output;
698 $this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed.");
699 foreach ($values as $delta => $value) {
700 $this->assertNoRaw($value['value'], "Hidden field: value $delta is not displayed.");
701 }
702
703
704 $entity = clone($entity_init);
705 $formatter_setting = $this->randomName();
706 $this->instance['display'] = array(
707 'full' => array(
708 'label' => 'above',
709 'type' => 'field_test_multiple',
710 'settings' => array(
711 'test_formatter_setting_multiple' => $formatter_setting,
712 )
713 ),
714 );
715 field_update_instance($this->instance);
716 field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
717 $entity->content = field_attach_view($entity_type, $entity, 'full');
718 $output = drupal_render($entity->content);
719 $display = $formatter_setting;
720 foreach ($values as $delta => $value) {
721 $display .= "|$delta:{$value['value']}";
722 }
723 $this->content = $output;
724 $this->assertRaw($display, "Multiple formatter: all values are displayed, formatter settings are applied.");
725
726
727 $entity = clone($entity_init);
728 $formatter_setting = $this->randomName();
729 $this->instance['display'] = array(
730 'full' => array(
731 'label' => 'above',
732 'type' => 'field_test_with_prepare_view',
733 'settings' => array(
734 'test_formatter_setting_additional' => $formatter_setting,
735 )
736 ),
737 );
738 field_update_instance($this->instance);
739 field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full');
740 $entity->content = field_attach_view($entity_type, $entity, 'full');
741 $output = drupal_render($entity->content);
742 $this->content = $output;
743 foreach ($values as $delta => $value) {
744 $this->content = $output;
745 $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1);
746 $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied.");
747 }
748
749
750
751
752
753 $variables = array();
754 field_attach_preprocess($entity_type, $entity, $entity->content, $variables);
755 $result = TRUE;
756 foreach ($values as $delta => $item) {
757 if ($variables[$this->field_name][$delta]['value'] !== $item['value']) {
758 $result = FALSE;
759 break;
760 }
761 }
762 $this->assertTrue($result, t('Variable $@field_name correctly populated.', array('@field_name' => $this->field_name)));
763 }
764
765
766
767
768 function testFieldAttachPrepareViewMultiple() {
769 $entity_type = 'test_entity';
770 $langcode = LANGUAGE_NONE;
771
772
773 $this->instance['display']['full']['type'] = 'hidden';
774 field_update_instance($this->instance);
775
776
777
778 field_test_create_bundle('test_bundle_2');
779 $formatter_setting = $this->randomName();
780 $this->instance2 = $this->instance;
781 $this->instance2['bundle'] = 'test_bundle_2';
782 $this->instance2['display']['full'] = array(
783 'type' => 'field_test_with_prepare_view',
784 'settings' => array(
785 'test_formatter_setting_additional' => $formatter_setting,
786 )
787 );
788 field_create_instance($this->instance2);
789
790
791 $entity1_init = field_test_create_stub_entity(1, 1, 'test_bundle');
792 $values1 = $this->_generateTestFieldValues($this->field['cardinality']);
793 $entity1_init->{$this->field_name}[$langcode] = $values1;
794
795 $entity2_init = field_test_create_stub_entity(2, 2, 'test_bundle_2');
796 $values2 = $this->_generateTestFieldValues($this->field['cardinality']);
797 $entity2_init->{$this->field_name}[$langcode] = $values2;
798
799
800 $entity1 = clone($entity1_init);
801 $entity2 = clone($entity2_init);
802 field_attach_prepare_view($entity_type, array($entity1->ftid => $entity1, $entity2->ftid => $entity2), 'full');
803 $this->assertFalse(isset($entity1->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 1 did not run through the prepare_view hook.');
804 $this->assertTrue(isset($entity2->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 2 ran through the prepare_view hook.');
805
806
807 $entity1 = clone($entity1_init);
808 $entity2 = clone($entity2_init);
809 field_attach_prepare_view($entity_type, array($entity2->ftid => $entity2, $entity1->ftid => $entity1), 'full');
810 $this->assertFalse(isset($entity1->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 1 did not run through the prepare_view hook.');
811 $this->assertTrue(isset($entity2->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 2 ran through the prepare_view hook.');
812 }
813
814
815
816
817 function testFieldAttachCache() {
818
819 $entity_init = field_test_create_stub_entity(1, 1, $this->instance['bundle']);
820 $langcode = LANGUAGE_NONE;
821 $values = $this->_generateTestFieldValues($this->field['cardinality']);
822
823
824 $entity_type = 'test_entity';
825 $cid = "field:$entity_type:{$entity_init->ftid}";
826
827
828 $this->assertFalse(cache_get($cid, 'cache_field'), t('Non-cached: no initial cache entry'));
829
830
831 $entity = clone($entity_init);
832 $entity->{$this->field_name}[$langcode] = $values;
833 field_attach_insert($entity_type, $entity);
834 $this->assertFalse(cache_get($cid, 'cache_field'), t('Non-cached: no cache entry on insert'));
835
836
837 $entity = clone($entity_init);
838 field_attach_load($entity_type, array($entity->ftid => $entity));
839 $this->assertFalse(cache_get($cid, 'cache_field'), t('Non-cached: no cache entry on load'));
840
841
842
843 $entity_type = 'test_cacheable_entity';
844 $cid = "field:$entity_type:{$entity_init->ftid}";
845 $instance = $this->instance;
846 $instance['entity_type'] = $entity_type;
847 field_create_instance($instance);
848
849
850 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no initial cache entry'));
851
852
853 $entity = clone($entity_init);
854 $entity->{$this->field_name}[$langcode] = $values;
855 field_attach_insert($entity_type, $entity);
856 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no cache entry on insert'));
857
858
859 $entity = clone($entity_init);
860 field_attach_load($entity_type, array($entity->ftid => $entity), FIELD_LOAD_CURRENT, array('field_id' => $this->field_id));
861 $cache = cache_get($cid, 'cache_field');
862 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no cache entry on loading a single field'));
863
864
865 $entity = clone($entity_init);
866 field_attach_load($entity_type, array($entity->ftid => $entity));
867 $cache = cache_get($cid, 'cache_field');
868 $this->assertEqual($cache->data[$this->field_name][$langcode], $values, t('Cached: correct cache entry on load'));
869
870
871 $values = $this->_generateTestFieldValues($this->field['cardinality']);
872 $entity = clone($entity_init);
873 $entity->{$this->field_name}[$langcode] = $values;
874 field_attach_update($entity_type, $entity);
875 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no cache entry on update'));
876
877
878 $entity = clone($entity_init);
879 field_attach_load($entity_type, array($entity->ftid => $entity));
880 $cache = cache_get($cid, 'cache_field');
881 $this->assertEqual($cache->data[$this->field_name][$langcode], $values, t('Cached: correct cache entry on load'));
882
883
884 $entity_init = field_test_create_stub_entity(1, 2, $this->instance['bundle']);
885 $values = $this->_generateTestFieldValues($this->field['cardinality']);
886 $entity = clone($entity_init);
887 $entity->{$this->field_name}[$langcode] = $values;
888 field_attach_update($entity_type, $entity);
889 $cache = cache_get($cid, 'cache_field');
890 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no cache entry on new revision creation'));
891
892
893 $entity = clone($entity_init);
894 field_attach_load($entity_type, array($entity->ftid => $entity));
895 $cache = cache_get($cid, 'cache_field');
896 $this->assertEqual($cache->data[$this->field_name][$langcode], $values, t('Cached: correct cache entry on load'));
897
898
899 field_attach_delete($entity_type, $entity);
900 $this->assertFalse(cache_get($cid, 'cache_field'), t('Cached: no cache entry after delete'));
901 }
902
903
904
905
906
907
908
909 function testFieldAttachValidate() {
910 $entity_type = 'test_entity';
911 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
912 $langcode = LANGUAGE_NONE;
913
914
915 $values = array();
916 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
917 $values[$delta]['value'] = -1;
918 }
919
920 $values[1]['value'] = 1;
921 $entity->{$this->field_name}[$langcode] = $values;
922
923 try {
924 field_attach_validate($entity_type, $entity);
925 }
926 catch (FieldValidationException $e) {
927 $errors = $e->errors;
928 }
929
930 foreach ($values as $delta => $value) {
931 if ($value['value'] != 1) {
932 $this->assertIdentical($errors[$this->field_name][$langcode][$delta][0]['error'], 'field_test_invalid', "Error set on value $delta");
933 $this->assertEqual(count($errors[$this->field_name][$langcode][$delta]), 1, "Only one error set on value $delta");
934 unset($errors[$this->field_name][$langcode][$delta]);
935 }
936 else {
937 $this->assertFalse(isset($errors[$this->field_name][$langcode][$delta]), "No error set on value $delta");
938 }
939 }
940 $this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set');
941
942
943 $entity->{$this->field_name}[$langcode] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
944 try {
945 field_attach_validate($entity_type, $entity);
946 }
947 catch (FieldValidationException $e) {
948 $errors = $e->errors;
949 }
950 $this->assertEqual($errors[$this->field_name][$langcode][0][0]['error'], 'field_cardinality', t('Cardinality validation failed.'));
951
952 }
953
954
955
956
957
958
959
960 function testFieldAttachForm() {
961 $entity_type = 'test_entity';
962 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
963
964 $form = array();
965 $form_state = form_state_defaults();
966 field_attach_form($entity_type, $entity, $form, $form_state);
967
968 $langcode = LANGUAGE_NONE;
969 $this->assertEqual($form[$this->field_name][$langcode]['#title'], $this->instance['label'], "Form title is {$this->instance['label']}");
970 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
971
972 $this->assertEqual($form[$this->field_name][$langcode][$delta]['value']['#type'], 'textfield', "Form delta $delta widget is textfield");
973 }
974 }
975
976
977
978
979 function testFieldAttachSubmit() {
980 $entity_type = 'test_entity';
981 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
982
983
984 $form = array();
985 $form_state = form_state_defaults();
986 field_attach_form($entity_type, $entity, $form, $form_state);
987
988
989 $values = array();
990 $weights = array();
991 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
992 $values[$delta]['value'] = mt_rand(1, 127);
993
994 do {
995 $weight = mt_rand(0, $this->field['cardinality']);
996 } while (in_array($weight, $weights));
997 $weights[$delta] = $weight;
998 $values[$delta]['_weight'] = $weight;
999 }
1000
1001 $values[1]['value'] = 0;
1002
1003 $langcode = LANGUAGE_NONE;
1004
1005 drupal_prepare_form('field_test_entity_form', $form, $form_state);
1006 drupal_process_form('field_test_entity_form', $form, $form_state);
1007 $form_state['values'][$this->field_name][$langcode] = $values;
1008 field_attach_submit($entity_type, $entity, $form, $form_state);
1009
1010 asort($weights);
1011 $expected_values = array();
1012 foreach ($weights as $key => $value) {
1013 if ($key != 1) {
1014 $expected_values[] = array('value' => $values[$key]['value']);
1015 }
1016 }
1017 $this->assertIdentical($entity->{$this->field_name}[$langcode], $expected_values, 'Submit filters empty values');
1018 }
1019 }
1020
1021 class FieldInfoTestCase extends FieldTestCase {
1022
1023 public static function getInfo() {
1024 return array(
1025 'name' => 'Field info tests',
1026 'description' => 'Get information about existing fields, instances and bundles.',
1027 'group' => 'Field API',
1028 );
1029 }
1030
1031 function setUp() {
1032 parent::setUp('field_test');
1033 }
1034
1035
1036
1037
1038 function testFieldInfo() {
1039
1040
1041 $field_test_info = field_test_field_info();
1042
1043 foreach (array_keys($field_test_info) as $name) {
1044 $field_test_info[$name]['instance_settings']['user_register_form'] = FALSE;
1045 }
1046 $info = field_info_field_types();
1047 foreach ($field_test_info as $t_key => $field_type) {
1048 foreach ($field_type as $key => $val) {
1049 $this->assertEqual($info[$t_key][$key], $val, t("Field type $t_key key $key is $val"));
1050 }
1051 $this->assertEqual($info[$t_key]['module'], 'field_test', t("Field type field_test module appears"));
1052 }
1053
1054 $formatter_info = field_test_field_formatter_info();
1055 $info = field_info_formatter_types();
1056 foreach ($formatter_info as $f_key => $formatter) {
1057 foreach ($formatter as $key => $val) {
1058 $this->assertEqual($info[$f_key][$key], $val, t("Formatter type $f_key key $key is $val"));
1059 }
1060 $this->assertEqual($info[$f_key]['module'], 'field_test', t("Formatter type field_test module appears"));
1061 }
1062
1063 $widget_info = field_test_field_widget_info();
1064 $info = field_info_widget_types();
1065 foreach ($widget_info as $w_key => $widget) {
1066 foreach ($widget as $key => $val) {
1067 $this->assertEqual($info[$w_key][$key], $val, t("Widget type $w_key key $key is $val"));
1068 }
1069 $this->assertEqual($info[$w_key]['module'], 'field_test', t("Widget type field_test module appears"));
1070 }
1071
1072 $storage_info = field_test_field_storage_info();
1073 $info = field_info_storage_types();
1074 foreach ($storage_info as $s_key => $storage) {
1075 foreach ($storage as $key => $val) {
1076 $this->assertEqual($info[$s_key][$key], $val, t("Storage type $s_key key $key is $val"));
1077 }
1078 $this->assertEqual($info[$s_key]['module'], 'field_test', t("Storage type field_test module appears"));
1079 }
1080
1081
1082 $instances = field_info_instances('test_entity');
1083 $expected = array('test_bundle' => array());
1084 $this->assertIdentical($instances, $expected, "field_info_instances('test_entity') returns " . var_export($expected, TRUE) . '.');
1085 $instances = field_info_instances('test_entity', 'test_bundle');
1086 $this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'test_bundle') returns an empty array.");
1087
1088
1089 $core_fields = field_info_fields();
1090 $field = array(
1091 'field_name' => drupal_strtolower($this->randomName()),
1092 'type' => 'test_field',
1093 );
1094 field_create_field($field);
1095 $fields = field_info_fields();
1096 $this->assertEqual(count($fields), count($core_fields) + 1, t('One new field exists'));
1097 $this->assertEqual($fields[$field['field_name']]['field_name'], $field['field_name'], t('info fields contains field name'));
1098 $this->assertEqual($fields[$field['field_name']]['type'], $field['type'], t('info fields contains field type'));
1099 $this->assertEqual($fields[$field['field_name']]['module'], 'field_test', t('info fields contains field module'));
1100 $settings = array('test_field_setting' => 'dummy test string');
1101 foreach ($settings as $key => $val) {
1102 $this->assertEqual($fields[$field['field_name']]['settings'][$key], $val, t("Field setting $key has correct default value $val"));
1103 }
1104 $this->assertEqual($fields[$field['field_name']]['cardinality'], 1, t('info fields contains cardinality 1'));
1105 $this->assertEqual($fields[$field['field_name']]['active'], 1, t('info fields contains active 1'));
1106
1107
1108 $instance = array(
1109 'field_name' => $field['field_name'],
1110 'entity_type' => 'test_entity',
1111 'bundle' => 'test_bundle',
1112 'label' => $this->randomName(),
1113 'description' => $this->randomName(),
1114 'weight' => mt_rand(0, 127),
1115
1116 'widget' => array(
1117 'type' => 'test_field_widget',
1118 'settings' => array(
1119 'test_setting' => 999)));
1120 field_create_instance($instance);
1121
1122 $info = entity_get_info('test_entity');
1123 $instances = field_info_instances('test_entity', $instance['bundle']);
1124 $this->assertEqual(count($instances), 1, format_string('One instance shows up in info when attached to a bundle on a @label.', array(
1125 '@label' => $info['label']
1126 )));
1127 $this->assertTrue($instance < $instances[$instance['field_name']], t('Instance appears in info correctly'));
1128
1129
1130 $instances = field_info_instances('test_entity', 'invalid_bundle');
1131 $this->assertIdentical($instances, array(), "field_info_instances('test_entity', 'invalid_bundle') returns an empty array.");
1132
1133
1134 $instances = field_info_instances('invalid_entity', $instance['bundle']);
1135 $this->assertIdentical($instances, array(), "field_info_instances('invalid_entity', 'test_bundle') returns an empty array.");
1136
1137
1138 $instances = field_info_instances('invalid_entity');
1139 $this->assertIdentical($instances, array(), "field_info_instances('invalid_entity') returns an empty array.");
1140
1141
1142 $instances = field_info_instances('user');
1143 $expected = array('user' => array());
1144 $this->assertIdentical($instances, $expected, "field_info_instances('user') returns " . var_export($expected, TRUE) . '.');
1145 $instances = field_info_instances('user', 'user');
1146 $this->assertIdentical($instances, array(), "field_info_instances('user', 'user') returns an empty array.");
1147 }
1148
1149
1150
1151
1152 function testFieldPrepare() {
1153 $field_definition = array(
1154 'field_name' => 'field',
1155 'type' => 'test_field',
1156 );
1157 field_create_field($field_definition);
1158
1159
1160
1161
1162 $data = db_query('SELECT data FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name']))->fetchField();
1163 $data = unserialize($data);
1164 $data['settings'] = array();
1165 db_update('field_config')
1166 ->fields(array('data' => serialize($data)))
1167 ->condition('field_name', $field_definition['field_name'])
1168 ->execute();
1169
1170 field_cache_clear();
1171
1172
1173 $field = field_info_field($field_definition['field_name']);
1174
1175
1176 $field_type = field_info_field_types($field_definition['type']);
1177 $this->assertIdentical($field['settings'], $field_type['settings'], t('All expected default field settings are present.'));
1178 }
1179
1180
1181
1182
1183 function testInstancePrepare() {
1184 $field_definition = array(
1185 'field_name' => 'field',
1186 'type' => 'test_field',
1187 );
1188 field_create_field($field_definition);
1189 $instance_definition = array(
1190 'field_name' => $field_definition['field_name'],
1191 'entity_type' => 'test_entity',
1192 'bundle' => 'test_bundle',
1193 );
1194 field_create_instance($instance_definition);
1195
1196
1197
1198
1199 $data = db_query('SELECT data FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $instance_definition['field_name'], ':bundle' => $instance_definition['bundle']))->fetchField();
1200 $data = unserialize($data);
1201 $data['settings'] = array();
1202 $data['widget']['settings'] = 'unavailable_widget';
1203 $data['widget']['settings'] = array();
1204 $data['display']['default']['type'] = 'unavailable_formatter';
1205 $data['display']['default']['settings'] = array();
1206 db_update('field_config_instance')
1207 ->fields(array('data' => serialize($data)))
1208 ->condition('field_name', $instance_definition['field_name'])
1209 ->condition('bundle', $instance_definition['bundle'])
1210 ->execute();
1211
1212 field_cache_clear();
1213
1214
1215 $instance = field_info_instance($instance_definition['entity_type'], $instance_definition['field_name'], $instance_definition['bundle']);
1216
1217
1218 $field_type = field_info_field_types($field_definition['type']);
1219 $this->assertIdentical($instance['settings'], $field_type['instance_settings'] , t('All expected instance settings are present.'));
1220
1221
1222 $this->assertIdentical($instance['widget']['type'], $field_type['default_widget'], t('Unavailable widget replaced with default widget.'));
1223 $widget_type = field_info_widget_types($instance['widget']['type']);
1224 $this->assertIdentical($instance['widget']['settings'], $widget_type['settings'] , t('All expected widget settings are present.'));
1225
1226
1227 $display = $instance['display']['default'];
1228 $this->assertIdentical($display['type'], $field_type['default_formatter'], t("Formatter is set for the 'default' view mode"));
1229 $formatter_type = field_info_formatter_types($display['type']);
1230 $this->assertIdentical($display['settings'], $formatter_type['settings'] , t("Formatter settings are set for the 'default' view mode"));
1231 }
1232
1233
1234
1235
1236 function testInstanceDisabledEntityType() {
1237
1238
1239 $field_definition = array(
1240 'field_name' => 'field',
1241 'type' => 'test_field',
1242 );
1243 field_create_field($field_definition);
1244 $instance_definition = array(
1245 'field_name' => 'field',
1246 'entity_type' => 'comment',
1247 'bundle' => 'comment_node_article',
1248 );
1249 field_create_instance($instance_definition);
1250
1251
1252 module_disable(array('comment'));
1253 $this->assertNull(field_info_instance('comment', 'field', 'comment_node_article'), t('No instances are returned on disabled entity types.'));
1254 }
1255
1256
1257
1258
1259 function testSettingsInfo() {
1260 $info = field_test_field_info();
1261
1262 foreach (array_keys($info) as $name) {
1263 $info[$name]['instance_settings']['user_register_form'] = FALSE;
1264 }
1265 foreach ($info as $type => $data) {
1266 $this->assertIdentical(field_info_field_settings($type), $data['settings'], "field_info_field_settings returns {$type}'s field settings");
1267 $this->assertIdentical(field_info_instance_settings($type), $data['instance_settings'], "field_info_field_settings returns {$type}'s field instance settings");
1268 }
1269
1270 $info = field_test_field_widget_info();
1271 foreach ($info as $type => $data) {
1272 $this->assertIdentical(field_info_widget_settings($type), $data['settings'], "field_info_widget_settings returns {$type}'s widget settings");
1273 }
1274
1275 $info = field_test_field_formatter_info();
1276 foreach ($info as $type => $data) {
1277 $this->assertIdentical(field_info_formatter_settings($type), $data['settings'], "field_info_formatter_settings returns {$type}'s formatter settings");
1278 }
1279 }
1280 }
1281
1282 class FieldFormTestCase extends FieldTestCase {
1283 public static function getInfo() {
1284 return array(
1285 'name' => 'Field form tests',
1286 'description' => 'Test Field form handling.',
1287 'group' => 'Field API',
1288 );
1289 }
1290
1291 function setUp() {
1292 parent::setUp('field_test');
1293
1294 $web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
1295 $this->drupalLogin($web_user);
1296
1297 $this->field_single = array('field_name' => 'field_single', 'type' => 'test_field');
1298 $this->field_multiple = array('field_name' => 'field_multiple', 'type' => 'test_field', 'cardinality' => 4);
1299 $this->field_unlimited = array('field_name' => 'field_unlimited', 'type' => 'test_field', 'cardinality' => FIELD_CARDINALITY_UNLIMITED);
1300
1301 $this->instance = array(
1302 'entity_type' => 'test_entity',
1303 'bundle' => 'test_bundle',
1304 'label' => $this->randomName() . '_label',
1305 'description' => $this->randomName() . '_description',
1306 'weight' => mt_rand(0, 127),
1307 'settings' => array(
1308 'test_instance_setting' => $this->randomName(),
1309 ),
1310 'widget' => array(
1311 'type' => 'test_field_widget',
1312 'label' => 'Test Field',
1313 'settings' => array(
1314 'test_widget_setting' => $this->randomName(),
1315 )
1316 )
1317 );
1318 }
1319
1320 function testFieldFormSingle() {
1321 $this->field = $this->field_single;
1322 $this->field_name = $this->field['field_name'];
1323 $this->instance['field_name'] = $this->field_name;
1324 field_create_field($this->field);
1325 field_create_instance($this->instance);
1326 $langcode = LANGUAGE_NONE;
1327
1328
1329 $this->drupalGet('test-entity/add/test-bundle');
1330 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget is displayed');
1331 $this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
1332
1333
1334
1335 $edit = array("{$this->field_name}[$langcode][0][value]" => -1);
1336 $this->drupalPost(NULL, $edit, t('Save'));
1337 $this->assertRaw(t('%name does not accept the value -1.', array('%name' => $this->instance['label'])), 'Field validation fails with invalid input.');
1338
1339
1340
1341 $value = mt_rand(1, 127);
1342 $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
1343 $this->drupalPost(NULL, $edit, t('Save'));
1344 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
1345 $id = $match[1];
1346 $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
1347 $entity = field_test_entity_test_load($id);
1348 $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was saved');
1349
1350
1351 $this->drupalGet('test-entity/manage/' . $id . '/edit');
1352 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", $value, 'Widget is displayed with the correct default value');
1353 $this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
1354
1355
1356 $value = mt_rand(1, 127);
1357 $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
1358 $this->drupalPost(NULL, $edit, t('Save'));
1359 $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
1360 $entity = field_test_entity_test_load($id);
1361 $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was updated');
1362
1363
1364 $value = '';
1365 $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
1366 $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
1367 $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
1368 $entity = field_test_entity_test_load($id);
1369 $this->assertIdentical($entity->{$this->field_name}, array(), 'Field was emptied');
1370
1371 }
1372
1373 function testFieldFormSingleRequired() {
1374 $this->field = $this->field_single;
1375 $this->field_name = $this->field['field_name'];
1376 $this->instance['field_name'] = $this->field_name;
1377 $this->instance['required'] = TRUE;
1378 field_create_field($this->field);
1379 field_create_instance($this->instance);
1380 $langcode = LANGUAGE_NONE;
1381
1382
1383 $edit = array();
1384 $this->drupalPost('test-entity/add/test-bundle', $edit, t('Save'));
1385 $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
1386
1387
1388 $value = mt_rand(1, 127);
1389 $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
1390 $this->drupalPost(NULL, $edit, t('Save'));
1391 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
1392 $id = $match[1];
1393 $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
1394 $entity = field_test_entity_test_load($id);
1395 $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was saved');
1396
1397
1398 $value = '';
1399 $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
1400 $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
1401 $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
1402 }
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412 function testFieldFormUnlimited() {
1413 $this->field = $this->field_unlimited;
1414 $this->field_name = $this->field['field_name'];
1415 $this->instance['field_name'] = $this->field_name;
1416 field_create_field($this->field);
1417 field_create_instance($this->instance);
1418 $langcode = LANGUAGE_NONE;
1419
1420
1421 $this->drupalGet('test-entity/add/test-bundle');
1422 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget 1 is displayed');
1423 $this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
1424
1425
1426 $this->drupalPost(NULL, array(), t('Add another item'));
1427 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget 1 is displayed');
1428 $this->assertFieldByName("{$this->field_name}[$langcode][1][value]", '', 'New widget is displayed');
1429 $this->assertNoField("{$this->field_name}[$langcode][2][value]", 'No extraneous widget is displayed');
1430
1431
1432
1433 $this->drupalPost(NULL, array(), t('Add another item'));
1434
1435
1436 $count = 3;
1437 $delta_range = $count - 1;
1438 $values = $weights = $pattern = $expected_values = $edit = array();
1439 for ($delta = 0; $delta <= $delta_range; $delta++) {
1440
1441 do {
1442 $value = mt_rand(1, 127);
1443 } while (in_array($value, $values));
1444 do {
1445 $weight = mt_rand(-$delta_range, $delta_range);
1446 } while (in_array($weight, $weights));
1447 $edit["$this->field_name[$langcode][$delta][value]"] = $value;
1448 $edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
1449
1450 $values[$delta] = $value;
1451 $weights[$delta] = $weight;
1452 $field_values[$weight]['value'] = (string) $value;
1453 $pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*";
1454 }
1455
1456
1457 $this->drupalPost(NULL, $edit, t('Add another item'));
1458 for ($delta = 0; $delta <= $delta_range; $delta++) {
1459 $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
1460 $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
1461 }
1462 ksort($pattern);
1463 $pattern = implode('.*', array_values($pattern));
1464 $this->assertPattern("|$pattern|s", 'Widgets are displayed in the correct order');
1465 $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", '', "New widget is displayed");
1466 $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "New widget has the right weight");
1467 $this->assertNoField("$this->field_name[$langcode][" . ($delta + 1) . '][value]', 'No extraneous widget is displayed');
1468
1469
1470 $this->drupalPost(NULL, $edit, t('Save'));
1471 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
1472 $id = $match[1];
1473 $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
1474 $entity = field_test_entity_test_load($id);
1475 ksort($field_values);
1476 $field_values = array_values($field_values);
1477 $this->assertIdentical($entity->{$this->field_name}[$langcode], $field_values, 'Field values were saved in the correct order');
1478
1479
1480
1481
1482
1483
1484
1485
1486 }
1487
1488
1489
1490
1491 function testFieldFormMultivalueWithRequiredRadio() {
1492
1493 $this->field = $this->field_unlimited;
1494 $this->field_name = $this->field['field_name'];
1495 $this->instance['field_name'] = $this->field_name;
1496 field_create_field($this->field);
1497 field_create_instance($this->instance);
1498 $langcode = LANGUAGE_NONE;
1499
1500
1501 field_create_field(array(
1502 'field_name' => 'required_radio_test',
1503 'type' => 'list_text',
1504 'settings' => array(
1505 'allowed_values' => array('yes' => 'yes', 'no' => 'no'),
1506 ),
1507 ));
1508 field_create_instance(array(
1509 'field_name' => 'required_radio_test',
1510 'entity_type' => 'test_entity',
1511 'bundle' => 'test_bundle',
1512 'required' => TRUE,
1513 'widget' => array(
1514 'type' => 'options_buttons',
1515 ),
1516 ));
1517
1518
1519 $this->drupalGet('test-entity/add/test-bundle');
1520
1521
1522 $this->drupalPost(NULL, array(), t('Add another item'));
1523
1524
1525 $this->assertNoFieldByXpath('//div[contains(@class, "error")]', FALSE, 'No error message is displayed.');
1526
1527
1528 $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget 1 is displayed');
1529 $this->assertFieldByName("{$this->field_name}[$langcode][1][value]", '', 'New widget is displayed');
1530 $this->assertNoField("{$this->field_name}[$langcode][2][value]", 'No extraneous widget is displayed');
1531 }
1532
1533 function testFieldFormJSAddMore() {
1534 $this->field = $this->field_unlimited;
1535 $this->field_name = $this->field['field_name'];
1536 $this->instance['field_name'] = $this->field_name;
1537 field_create_field($this->field);
1538 field_create_instance($this->instance);
1539 $langcode = LANGUAGE_NONE;
1540
1541
1542 $this->drupalGet('test-entity/add/test-bundle');
1543
1544
1545
1546
1547 $this->drupalPost(NULL, array(), t('Add another item'));
1548 $this->drupalPost(NULL, array(), t('Add another item'));
1549
1550
1551 $count = 3;
1552 $delta_range = $count - 1;
1553 $values = $weights = $pattern = $expected_values = $edit = array();
1554 for ($delta = 0; $delta <= $delta_range; $delta++) {
1555
1556 do {
1557 $value = mt_rand(1, 127);
1558 } while (in_array($value, $values));
1559 do {
1560 $weight = mt_rand(-$delta_range, $delta_range);
1561 } while (in_array($weight, $weights));
1562 $edit["$this->field_name[$langcode][$delta][value]"] = $value;
1563 $edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
1564
1565 $values[$delta] = $value;
1566 $weights[$delta] = $weight;
1567 $field_values[$weight]['value'] = (string) $value;
1568 $pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*";
1569 }
1570
1571
1572 $commands = $this->drupalPostAJAX(NULL, $edit, $this->field_name . '_add_more');
1573 $this->content = $commands[1]['data'];
1574
1575 for ($delta = 0; $delta <= $delta_range; $delta++) {
1576 $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
1577 $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
1578 }
1579 ksort($pattern);
1580 $pattern = implode('.*', array_values($pattern));
1581 $this->assertPattern("|$pattern|s", 'Widgets are displayed in the correct order');
1582 $this->assertFieldByName("$this->field_name[$langcode][$delta][value]", '', "New widget is displayed");
1583 $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "New widget has the right weight");
1584 $this->assertNoField("$this->field_name[$langcode][" . ($delta + 1) . '][value]', 'No extraneous widget is displayed');
1585 }
1586
1587
1588
1589
1590 function testFieldFormMultipleWidget() {
1591
1592
1593 $this->field = $this->field_multiple;
1594 $this->field_name = $this->field['field_name'];
1595 $this->instance['field_name'] = $this->field_name;
1596 $this->instance['widget']['type'] = 'test_field_widget_multiple';
1597 field_create_field($this->field);
1598 field_create_instance($this->instance);
1599 $langcode = LANGUAGE_NONE;
1600
1601
1602 $this->drupalGet('test-entity/add/test-bundle');
1603 $this->assertFieldByName("{$this->field_name}[$langcode]", '', t('Widget is displayed.'));
1604
1605
1606 $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3');
1607 $this->drupalPost(NULL, $edit, t('Save'));
1608 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
1609 $id = $match[1];
1610
1611
1612 $entity_init = field_test_create_stub_entity($id);
1613 $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
1614
1615
1616 $this->drupalGet('test-entity/manage/' . $id . '/edit');
1617 $this->assertFieldByName("{$this->field_name}[$langcode]", '1, 2, 3', t('Widget is displayed.'));
1618
1619
1620 $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3, 4, 5');
1621 $this->drupalPost(NULL, $edit, t('Save'));
1622 $this->assertRaw('this field cannot hold more than 4 values', t('Form validation failed.'));
1623
1624 $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
1625 }
1626
1627
1628
1629
1630 function testFieldFormAccess() {
1631
1632 $field = $this->field_single;
1633 $field_name = $field['field_name'];
1634 $instance = $this->instance;
1635 $instance['field_name'] = $field_name;
1636 field_create_field($field);
1637 field_create_instance($instance);
1638
1639
1640 $field_no_access = array(
1641 'field_name' => 'field_no_edit_access',
1642 'type' => 'test_field',
1643 );
1644 $field_name_no_access = $field_no_access['field_name'];
1645 $instance_no_access = array(
1646 'field_name' => $field_name_no_access,
1647 'entity_type' => 'test_entity',
1648 'bundle' => 'test_bundle',
1649 'default_value' => array(0 => array('value' => 99)),
1650 );
1651 field_create_field($field_no_access);
1652 field_create_instance($instance_no_access);
1653
1654 $langcode = LANGUAGE_NONE;
1655
1656
1657
1658 $entity_type = 'test_entity';
1659 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
1660
1661 $form = array();
1662 $form_state = form_state_defaults();
1663 field_attach_form($entity_type, $entity, $form, $form_state);
1664
1665 $this->assertEqual($form[$field_name_no_access][$langcode][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.');
1666 $this->assertFalse($form[$field_name_no_access]['#access'], 'Field #access is FALSE for the field without edit access.');
1667
1668
1669 $this->drupalGet('test-entity/add/test-bundle');
1670 $this->assertNoFieldByName("{$field_name_no_access}[$langcode][0][value]", '', t('Widget is not displayed if field access is denied.'));
1671
1672
1673 $edit = array("{$field_name}[$langcode][0][value]" => 1);
1674 $this->drupalPost(NULL, $edit, t('Save'));
1675 preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
1676 $id = $match[1];
1677
1678
1679 $entity = field_test_entity_test_load($id);
1680 $this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('Default value was saved for the field with no edit access.'));
1681 $this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 1, t('Entered value vas saved for the field with edit access.'));
1682
1683
1684 $edit = array("{$field_name}[$langcode][0][value]" => 2, 'revision' => TRUE);
1685 $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
1686
1687
1688 $entity = field_test_entity_test_load($id);
1689 $this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('New revision has the expected value for the field with no edit access.'));
1690 $this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 2, t('New revision has the expected value for the field with edit access.'));
1691
1692
1693 $entity = field_test_entity_test_load($id, $entity->ftvid);
1694 $this->assertEqual($entity->{$field_name_no_access}[$langcode][0]['value'], 99, t('New revision has the expected value for the field with no edit access.'));
1695 $this->assertEqual($entity->{$field_name}[$langcode][0]['value'], 2, t('New revision has the expected value for the field with edit access.'));
1696 }
1697
1698
1699
1700
1701 function testNestedFieldForm() {
1702
1703 field_create_field($this->field_single);
1704 field_create_field($this->field_unlimited);
1705 $this->instance['field_name'] = 'field_single';
1706 $this->instance['label'] = 'Single field';
1707 field_create_instance($this->instance);
1708 $this->instance['field_name'] = 'field_unlimited';
1709 $this->instance['label'] = 'Unlimited field';
1710 field_create_instance($this->instance);
1711
1712
1713 $entity_1 = field_test_create_stub_entity(1, 1);
1714 $entity_1->is_new = TRUE;
1715 $entity_1->field_single[LANGUAGE_NONE][] = array('value' => 0);
1716 $entity_1->field_unlimited[LANGUAGE_NONE][] = array('value' => 1);
1717 field_test_entity_save($entity_1);
1718
1719 $entity_2 = field_test_create_stub_entity(2, 2);
1720 $entity_2->is_new = TRUE;
1721 $entity_2->field_single[LANGUAGE_NONE][] = array('value' => 10);
1722 $entity_2->field_unlimited[LANGUAGE_NONE][] = array('value' => 11);
1723 field_test_entity_save($entity_2);
1724
1725
1726 $this->drupalGet('test-entity/nested/1/2');
1727 $this->assertFieldByName('field_single[und][0][value]', 0, t('Entity 1: field_single value appears correctly is the form.'));
1728 $this->assertFieldByName('field_unlimited[und][0][value]', 1, t('Entity 1: field_unlimited value 0 appears correctly is the form.'));
1729 $this->assertFieldByName('entity_2[field_single][und][0][value]', 10, t('Entity 2: field_single value appears correctly is the form.'));
1730 $this->assertFieldByName('entity_2[field_unlimited][und][0][value]', 11, t('Entity 2: field_unlimited value 0 appears correctly is the form.'));
1731
1732
1733 $edit = array(
1734 'field_single[und][0][value]' => 1,
1735 'field_unlimited[und][0][value]' => 2,
1736 'field_unlimited[und][1][value]' => 3,
1737 'entity_2[field_single][und][0][value]' => 11,
1738 'entity_2[field_unlimited][und][0][value]' => 12,
1739 'entity_2[field_unlimited][und][1][value]' => 13,
1740 );
1741 $this->drupalPost(NULL, $edit, t('Save'));
1742 field_cache_clear();
1743 $entity_1 = field_test_create_stub_entity(1);
1744 $entity_2 = field_test_create_stub_entity(2);
1745 $this->assertFieldValues($entity_1, 'field_single', LANGUAGE_NONE, array(1));
1746 $this->assertFieldValues($entity_1, 'field_unlimited', LANGUAGE_NONE, array(2, 3));
1747 $this->assertFieldValues($entity_2, 'field_single', LANGUAGE_NONE, array(11));
1748 $this->assertFieldValues($entity_2, 'field_unlimited', LANGUAGE_NONE, array(12, 13));
1749
1750
1751
1752 $edit = array(
1753 'field_unlimited[und][1][value]' => -1,
1754 );
1755 $this->drupalPost('test-entity/nested/1/2', $edit, t('Save'));
1756 $this->assertRaw(t('%label does not accept the value -1', array('%label' => 'Unlimited field')), t('Entity 1: the field validation error was reported.'));
1757 $error_field = $this->xpath('//input[@id=:id and contains(@class, "error")]', array(':id' => 'edit-field-unlimited-und-1-value'));
1758 $this->assertTrue($error_field, t('Entity 1: the error was flagged on the correct element.'));
1759 $edit = array(
1760 'entity_2[field_unlimited][und][1][value]' => -1,
1761 );
1762 $this->drupalPost('test-entity/nested/1/2', $edit, t('Save'));
1763 $this->assertRaw(t('%label does not accept the value -1', array('%label' => 'Unlimited field')), t('Entity 2: the field validation error was reported.'));
1764 $error_field = $this->xpath('//input[@id=:id and contains(@class, "error")]', array(':id' => 'edit-entity-2-field-unlimited-und-1-value'));
1765 $this->assertTrue($error_field, t('Entity 2: the error was flagged on the correct element.'));
1766
1767
1768 $edit = array(
1769 'field_unlimited[und][0][_weight]' => 0,
1770 'field_unlimited[und][1][_weight]' => -1,
1771 'entity_2[field_unlimited][und][0][_weight]' => 0,
1772 'entity_2[field_unlimited][und][1][_weight]' => -1,
1773 );
1774 $this->drupalPost('test-entity/nested/1/2', $edit, t('Save'));
1775 field_cache_clear();
1776 $this->assertFieldValues($entity_1, 'field_unlimited', LANGUAGE_NONE, array(3, 2));
1777 $this->assertFieldValues($entity_2, 'field_unlimited', LANGUAGE_NONE, array(13, 12));
1778
1779
1780
1781
1782
1783 $this->drupalGet('test-entity/nested/1/2');
1784 $this->drupalPostAJAX(NULL, array(), 'field_unlimited_add_more');
1785 $this->assertFieldByName('field_unlimited[und][0][value]', 3, t('Entity 1: field_unlimited value 0 appears correctly is the form.'));
1786 $this->assertFieldByName('field_unlimited[und][1][value]', 2, t('Entity 1: field_unlimited value 1 appears correctly is the form.'));
1787 $this->assertFieldByName('field_unlimited[und][2][value]', '', t('Entity 1: field_unlimited value 2 appears correctly is the form.'));
1788 $this->assertFieldByName('field_unlimited[und][3][value]', '', t('Entity 1: an empty widget was added for field_unlimited value 3.'));
1789
1790 $edit = array(
1791 'entity_2[field_unlimited][und][0][value]' => 13,
1792 'entity_2[field_unlimited][und][1][value]' => 14,
1793 'entity_2[field_unlimited][und][2][value]' => 15,
1794 );
1795 $this->drupalPostAJAX(NULL, $edit, 'entity_2_field_unlimited_add_more');
1796 $this->assertFieldByName('entity_2[field_unlimited][und][0][value]', 13, t('Entity 2: field_unlimited value 0 appears correctly is the form.'));
1797 $this->assertFieldByName('entity_2[field_unlimited][und][1][value]', 14, t('Entity 2: field_unlimited value 1 appears correctly is the form.'));
1798 $this->assertFieldByName('entity_2[field_unlimited][und][2][value]', 15, t('Entity 2: field_unlimited value 2 appears correctly is the form.'));
1799 $this->assertFieldByName('entity_2[field_unlimited][und][3][value]', '', t('Entity 2: an empty widget was added for field_unlimited value 3.'));
1800
1801 $this->drupalPost(NULL, array(), t('Save'));
1802 field_cache_clear();
1803 $this->assertFieldValues($entity_1, 'field_unlimited', LANGUAGE_NONE, array(3, 2));
1804 $this->assertFieldValues($entity_2, 'field_unlimited', LANGUAGE_NONE, array(13, 14, 15));
1805 }
1806 }
1807
1808 class FieldDisplayAPITestCase extends FieldTestCase {
1809 public static function getInfo() {
1810 return array(
1811 'name' => 'Field Display API tests',
1812 'description' => 'Test the display API.',
1813 'group' => 'Field API',
1814 );
1815 }
1816
1817 function setUp() {
1818 parent::setUp('field_test');
1819
1820
1821 $this->field_name = 'test_field';
1822 $this->label = $this->randomName();
1823 $this->cardinality = 4;
1824
1825 $this->field = array(
1826 'field_name' => $this->field_name,
1827 'type' => 'test_field',
1828 'cardinality' => $this->cardinality,
1829 );
1830 $this->instance = array(
1831 'field_name' => $this->field_name,
1832 'entity_type' => 'test_entity',
1833 'bundle' => 'test_bundle',
1834 'label' => $this->label,
1835 'display' => array(
1836 'default' => array(
1837 'type' => 'field_test_default',
1838 'settings' => array(
1839 'test_formatter_setting' => $this->randomName(),
1840 ),
1841 ),
1842 'teaser' => array(
1843 'type' => 'field_test_default',
1844 'settings' => array(
1845 'test_formatter_setting' => $this->randomName(),
1846 ),
1847 ),
1848 ),
1849 );
1850 field_create_field($this->field);
1851 field_create_instance($this->instance);
1852
1853
1854 $this->values = $this->_generateTestFieldValues($this->cardinality);
1855 $this->entity = field_test_create_stub_entity();
1856 $this->is_new = TRUE;
1857 $this->entity->{$this->field_name}[LANGUAGE_NONE] = $this->values;
1858 field_test_entity_save($this->entity);
1859 }
1860
1861
1862
1863
1864 function testFieldViewField() {
1865
1866 $output = field_view_field('test_entity', $this->entity, $this->field_name);
1867 $this->drupalSetContent(drupal_render($output));
1868 $settings = field_info_formatter_settings('field_test_default');
1869 $setting = $settings['test_formatter_setting'];
1870 $this->assertText($this->label, t('Label was displayed.'));
1871 foreach ($this->values as $delta => $value) {
1872 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1873 }
1874
1875
1876 $display = array(
1877 'label' => 'hidden',
1878 'type' => 'field_test_multiple',
1879 'settings' => array(
1880 'test_formatter_setting_multiple' => $this->randomName(),
1881 'alter' => TRUE,
1882 ),
1883 );
1884 $output = field_view_field('test_entity', $this->entity, $this->field_name, $display);
1885 $this->drupalSetContent(drupal_render($output));
1886 $setting = $display['settings']['test_formatter_setting_multiple'];
1887 $this->assertNoText($this->label, t('Label was not displayed.'));
1888 $this->assertText('field_test_field_attach_view_alter', t('Alter fired, display passed.'));
1889 $array = array();
1890 foreach ($this->values as $delta => $value) {
1891 $array[] = $delta . ':' . $value['value'];
1892 }
1893 $this->assertText($setting . '|' . implode('|', $array), t('Values were displayed with expected setting.'));
1894
1895
1896 $display = array(
1897 'label' => 'hidden',
1898 'type' => 'field_test_with_prepare_view',
1899 'settings' => array(
1900 'test_formatter_setting_additional' => $this->randomName(),
1901 ),
1902 );
1903 $output = field_view_field('test_entity', $this->entity, $this->field_name, $display);
1904 $view = drupal_render($output);
1905 $this->drupalSetContent($view);
1906 $setting = $display['settings']['test_formatter_setting_additional'];
1907 $this->assertNoText($this->label, t('Label was not displayed.'));
1908 $this->assertNoText('field_test_field_attach_view_alter', t('Alter not fired.'));
1909 foreach ($this->values as $delta => $value) {
1910 $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1911 }
1912
1913
1914
1915 $output = field_view_field('test_entity', $this->entity, $this->field_name, 'teaser');
1916 $this->drupalSetContent(drupal_render($output));
1917 $setting = $this->instance['display']['teaser']['settings']['test_formatter_setting'];
1918 $this->assertText($this->label, t('Label was displayed.'));
1919 foreach ($this->values as $delta => $value) {
1920 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1921 }
1922
1923
1924
1925 $output = field_view_field('test_entity', $this->entity, $this->field_name, 'unknown_view_mode');
1926 $this->drupalSetContent(drupal_render($output));
1927 $setting = $this->instance['display']['default']['settings']['test_formatter_setting'];
1928 $this->assertText($this->label, t('Label was displayed.'));
1929 foreach ($this->values as $delta => $value) {
1930 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1931 }
1932 }
1933
1934
1935
1936
1937 function testFieldViewValue() {
1938
1939 $settings = field_info_formatter_settings('field_test_default');
1940 $setting = $settings['test_formatter_setting'];
1941 foreach ($this->values as $delta => $value) {
1942 $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
1943 $output = field_view_value('test_entity', $this->entity, $this->field_name, $item);
1944 $this->drupalSetContent(drupal_render($output));
1945 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1946 }
1947
1948
1949 $display = array(
1950 'type' => 'field_test_multiple',
1951 'settings' => array(
1952 'test_formatter_setting_multiple' => $this->randomName(),
1953 ),
1954 );
1955 $setting = $display['settings']['test_formatter_setting_multiple'];
1956 $array = array();
1957 foreach ($this->values as $delta => $value) {
1958 $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
1959 $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, $display);
1960 $this->drupalSetContent(drupal_render($output));
1961 $this->assertText($setting . '|0:' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1962 }
1963
1964
1965 $display = array(
1966 'type' => 'field_test_with_prepare_view',
1967 'settings' => array(
1968 'test_formatter_setting_additional' => $this->randomName(),
1969 ),
1970 );
1971 $setting = $display['settings']['test_formatter_setting_additional'];
1972 $array = array();
1973 foreach ($this->values as $delta => $value) {
1974 $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
1975 $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, $display);
1976 $this->drupalSetContent(drupal_render($output));
1977 $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1978 }
1979
1980
1981
1982 $setting = $this->instance['display']['teaser']['settings']['test_formatter_setting'];
1983 foreach ($this->values as $delta => $value) {
1984 $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
1985 $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'teaser');
1986 $this->drupalSetContent(drupal_render($output));
1987 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1988 }
1989
1990
1991
1992 $setting = $this->instance['display']['default']['settings']['test_formatter_setting'];
1993 foreach ($this->values as $delta => $value) {
1994 $item = $this->entity->{$this->field_name}[LANGUAGE_NONE][$delta];
1995 $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'unknown_view_mode');
1996 $this->drupalSetContent(drupal_render($output));
1997 $this->assertText($setting . '|' . $value['value'], t('Value @delta was displayed with expected setting.', array('@delta' => $delta)));
1998 }
1999 }
2000 }
2001
2002 class FieldCrudTestCase extends FieldTestCase {
2003 public static function getInfo() {
2004 return array(
2005 'name' => 'Field CRUD tests',
2006 'description' => 'Test field create, read, update, and delete.',
2007 'group' => 'Field API',
2008 );
2009 }
2010
2011 function setUp() {
2012
2013 parent::setUp('field_test', 'number');
2014 }
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024 function testCreateField() {
2025 $field_definition = array(
2026 'field_name' => 'field_2',
2027 'type' => 'test_field',
2028 );
2029 field_test_memorize();
2030 $field_definition = field_create_field($field_definition);
2031 $mem = field_test_memorize();
2032 $this->assertIdentical($mem['field_test_field_create_field'][0][0], $field_definition, 'hook_field_create_field() called with correct arguments.');
2033
2034
2035 $result = db_query('SELECT * FROM {field_config} WHERE field_name = :field_name', array(':field_name' => $field_definition['field_name']));
2036 $record = $result->fetchAssoc();
2037 $record['data'] = unserialize($record['data']);
2038
2039
2040 $this->assertEqual($record['field_name'], $field_definition['field_name'], t('The field name is properly saved.'));
2041 $this->assertEqual($record['type'], $field_definition['type'], t('The field type is properly saved.'));
2042
2043
2044 $this->assertEqual($record['cardinality'], 1, t('Cardinality defaults to 1.'));
2045
2046
2047 $field_type = field_info_field_types($field_definition['type']);
2048 $this->assertIdentical($record['data']['settings'], $field_type['settings'], t('Default field settings have been written.'));
2049
2050
2051 $this->assertEqual($record['storage_type'], variable_get('field_storage_default'), t('The field type is properly saved.'));
2052
2053
2054 try {
2055 field_create_field($field_definition);
2056 $this->fail(t('Cannot create two fields with the same name.'));
2057 }
2058 catch (FieldException $e) {
2059 $this->pass(t('Cannot create two fields with the same name.'));
2060 }
2061
2062
2063 try {
2064 $field_definition = array(
2065 'field_name' => 'field_1',
2066 );
2067 field_create_field($field_definition);
2068 $this->fail(t('Cannot create a field with no type.'));
2069 }
2070 catch (FieldException $e) {
2071 $this->pass(t('Cannot create a field with no type.'));
2072 }
2073
2074
2075 try {
2076 $field_definition = array(
2077 'type' => 'test_field'
2078 );
2079 field_create_field($field_definition);
2080 $this->fail(t('Cannot create an unnamed field.'));
2081 }
2082 catch (FieldException $e) {
2083 $this->pass(t('Cannot create an unnamed field.'));
2084 }
2085
2086
2087 try {
2088 $field_definition = array(
2089 'field_name' => '2field_2',
2090 'type' => 'test_field',
2091 );
2092 field_create_field($field_definition);
2093 $this->fail(t('Cannot create a field with a name starting with a digit.'));
2094 }
2095 catch (FieldException $e) {
2096 $this->pass(t('Cannot create a field with a name starting with a digit.'));
2097 }
2098
2099
2100 try {
2101 $field_definition = array(
2102 'field_name' => 'field#_3',
2103 'type' => 'test_field',
2104 );
2105 field_create_field($field_definition);
2106 $this->fail(t('Cannot create a field with a name containing an illegal character.'));
2107 }
2108 catch (FieldException $e) {
2109 $this->pass(t('Cannot create a field with a name containing an illegal character.'));
2110 }
2111
2112
2113 try {
2114 $field_definition = array(
2115 'field_name' => '_12345678901234567890123456789012',
2116 'type' => 'test_field',
2117 );
2118 field_create_field($field_definition);
2119 $this->fail(t('Cannot create a field with a name longer than 32 characters.'));
2120 }
2121 catch (FieldException $e) {
2122 $this->pass(t('Cannot create a field with a name longer than 32 characters.'));
2123 }
2124
2125
2126
2127 try {
2128 $field_definition = array(
2129 'type' => 'test_field',
2130 'field_name' => 'ftvid',
2131 );
2132 $field = field_create_field($field_definition);
2133 $this->fail(t('Cannot create a field bearing the name of an entity key.'));
2134 }
2135 catch (FieldException $e) {
2136 $this->pass(t('Cannot create a field bearing the name of an entity key.'));
2137 }
2138 }
2139
2140
2141
2142
2143 function testCreateFieldFail() {
2144 $field_name = 'duplicate';
2145 $field_definition = array('field_name' => $field_name, 'type' => 'test_field', 'storage' => array('type' => 'field_test_storage_failure'));
2146 $query = db_select('field_config')->condition('field_name', $field_name)->countQuery();
2147
2148
2149 $count = $query->execute()->fetchField();
2150 $this->assertEqual($count, 0, 'A field_config row for the field does not exist.');
2151
2152
2153 try {
2154 $field = field_create_field($field_definition);
2155 $this->assertTrue(FALSE, 'Field creation (correctly) fails.');
2156 }
2157 catch (Exception $e) {
2158 $this->assertTrue(TRUE, 'Field creation (correctly) fails.');
2159 }
2160
2161
2162 $count = $query->execute()->fetchField();
2163 $this->assertEqual($count, 0, 'A field_config row for the field does not exist.');
2164 }
2165
2166
2167
2168
2169 function testReadField() {
2170 $field_definition = array(
2171 'field_name' => 'field_1',
2172 'type' => 'test_field',
2173 );
2174 field_create_field($field_definition);
2175
2176
2177 $field = field_read_field($field_definition['field_name']);
2178 $this->assertTrue($field_definition < $field, t('The field was properly read.'));
2179 }
2180
2181
2182
2183
2184 function testFieldIndexes() {
2185
2186 $field_definition = array(
2187 'field_name' => 'field_1',
2188 'type' => 'test_field',
2189 );
2190 field_create_field($field_definition);
2191 $field = field_read_field($field_definition['field_name']);
2192 $expected_indexes = array('value' => array('value'));
2193 $this->assertEqual($field['indexes'], $expected_indexes, t('Field type indexes saved by default'));
2194
2195
2196
2197 $field_definition = array(
2198 'field_name' => 'field_2',
2199 'type' => 'test_field',
2200 'indexes' => array(
2201 'value' => array(),
2202 ),
2203 );
2204 field_create_field($field_definition);
2205 $field = field_read_field($field_definition['field_name']);
2206 $expected_indexes = array('value' => array());
2207 $this->assertEqual($field['indexes'], $expected_indexes, t('Field definition indexes override field type indexes'));
2208
2209
2210
2211 $field_definition = array(
2212 'field_name' => 'field_3',
2213 'type' => 'test_field',
2214 'indexes' => array(
2215 'value_2' => array('value'),
2216 ),
2217 );
2218 field_create_field($field_definition);
2219 $field = field_read_field($field_definition['field_name']);
2220 $expected_indexes = array('value' => array('value'), 'value_2' => array('value'));
2221 $this->assertEqual($field['indexes'], $expected_indexes, t('Field definition indexes are merged with field type indexes'));
2222 }
2223
2224
2225
2226
2227 function testDeleteField() {
2228
2229
2230
2231 $this->field = array('field_name' => 'field_1', 'type' => 'test_field');
2232 field_create_field($this->field);
2233 $this->another_field = array('field_name' => 'field_2', 'type' => 'test_field');
2234 field_create_field($this->another_field);
2235
2236
2237 $this->instance_definition = array(
2238 'field_name' => $this->field['field_name'],
2239 'entity_type' => 'test_entity',
2240 'bundle' => 'test_bundle',
2241 'widget' => array(
2242 'type' => 'test_field_widget',
2243 ),
2244 );
2245 field_create_instance($this->instance_definition);
2246 $this->another_instance_definition = $this->instance_definition;
2247 $this->another_instance_definition['field_name'] = $this->another_field['field_name'];
2248 field_create_instance($this->another_instance_definition);
2249
2250
2251 $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
2252 $this->assertTrue(!empty($field) && empty($field['deleted']), t('A new field is not marked for deletion.'));
2253 field_delete_field($this->field['field_name']);
2254
2255
2256
2257 $field = field_read_field($this->field['field_name'], array('include_deleted' => TRUE));
2258 $this->assertTrue(!empty($field['deleted']), t('A deleted field is marked for deletion.'));
2259
2260
2261
2262 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
2263 $this->assertTrue(!empty($instance['deleted']), t('An instance for a deleted field is marked for deletion.'));
2264
2265
2266 $field = field_read_field($this->field['field_name']);
2267 $this->assertTrue(empty($field), t('A deleted field is not loaded by default.'));
2268
2269
2270 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2271 $this->assertTrue(empty($instance), t('An instance for a deleted field is not loaded by default.'));
2272
2273
2274 $another_field = field_read_field($this->another_field['field_name']);
2275 $this->assertTrue(!empty($another_field) && empty($another_field['deleted']), t('A non-deleted field is not marked for deletion.'));
2276 $another_instance = field_read_instance('test_entity', $this->another_instance_definition['field_name'], $this->another_instance_definition['bundle']);
2277 $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), t('An instance of a non-deleted field is not marked for deletion.'));
2278
2279
2280
2281 field_create_field($this->field);
2282 field_create_instance($this->instance_definition);
2283 $field = field_read_field($this->field['field_name']);
2284 $this->assertTrue(!empty($field) && empty($field['deleted']), t('A new field with a previously used name is created.'));
2285 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2286 $this->assertTrue(!empty($instance) && empty($instance['deleted']), t('A new instance for a previously used field name is created.'));
2287
2288
2289 $entity = field_test_create_stub_entity(0, 0, $instance['bundle']);
2290 $langcode = LANGUAGE_NONE;
2291 $values[0]['value'] = mt_rand(1, 127);
2292 $entity->{$field['field_name']}[$langcode] = $values;
2293 $entity_type = 'test_entity';
2294 field_attach_insert('test_entity', $entity);
2295
2296
2297 $entity = field_test_create_stub_entity(0, 0, $this->instance_definition['bundle']);
2298 field_attach_load($entity_type, array(0 => $entity));
2299 $this->assertIdentical(count($entity->{$field['field_name']}[$langcode]), count($values), "Data in previously deleted field saves and loads correctly");
2300 foreach ($values as $delta => $value) {
2301 $this->assertEqual($entity->{$field['field_name']}[$langcode][$delta]['value'], $values[$delta]['value'], "Data in previously deleted field saves and loads correctly");
2302 }
2303 }
2304
2305 function testUpdateNonExistentField() {
2306 $test_field = array('field_name' => 'does_not_exist', 'type' => 'number_decimal');
2307 try {
2308 field_update_field($test_field);
2309 $this->fail(t('Cannot update a field that does not exist.'));
2310 }
2311 catch (FieldException $e) {
2312 $this->pass(t('Cannot update a field that does not exist.'));
2313 }
2314 }
2315
2316 function testUpdateFieldType() {
2317 $field = array('field_name' => 'field_type', 'type' => 'number_decimal');
2318 $field = field_create_field($field);
2319
2320 $test_field = array('field_name' => 'field_type', 'type' => 'number_integer');
2321 try {
2322 field_update_field($test_field);
2323 $this->fail(t('Cannot update a field to a different type.'));
2324 }
2325 catch (FieldException $e) {
2326 $this->pass(t('Cannot update a field to a different type.'));
2327 }
2328 }
2329
2330
2331
2332
2333 function testUpdateField() {
2334
2335
2336
2337 $cardinality = 4;
2338 $field_definition = array(
2339 'field_name' => 'field_update',
2340 'type' => 'test_field',
2341 'cardinality' => $cardinality,
2342 );
2343 $field_definition = field_create_field($field_definition);
2344 $instance = array(
2345 'field_name' => 'field_update',
2346 'entity_type' => 'test_entity',
2347 'bundle' => 'test_bundle',
2348 );
2349 $instance = field_create_instance($instance);
2350
2351 do {
2352
2353 $id = $cardinality;
2354 $entity = field_test_create_stub_entity($id, $id, $instance['bundle']);
2355
2356 for ($i = 0; $i < 20; $i++) {
2357 $entity->field_update[LANGUAGE_NONE][$i]['value'] = $i;
2358 }
2359
2360 field_attach_insert('test_entity', $entity);
2361
2362 $entity = field_test_create_stub_entity($id, $id, $instance['bundle']);
2363 field_attach_load('test_entity', array($id => $entity));
2364 $this->assertEqual(count($entity->field_update[LANGUAGE_NONE]), $field_definition['cardinality'], 'Cardinality is kept');
2365
2366 for ($delta = 0; $delta < $cardinality; $delta++) {
2367 $this->assertEqual($entity->field_update[LANGUAGE_NONE][$delta]['value'], $delta, 'Value is kept');
2368 }
2369
2370 $field_definition['cardinality'] = ++$cardinality;
2371 field_update_field($field_definition);
2372 } while ($cardinality < 6);
2373 }
2374
2375
2376
2377
2378 function testUpdateFieldForbid() {
2379 $field = array('field_name' => 'forbidden', 'type' => 'test_field', 'settings' => array('changeable' => 0, 'unchangeable' => 0));
2380 $field = field_create_field($field);
2381 $field['settings']['changeable']++;
2382 try {
2383 field_update_field($field);
2384 $this->pass(t("A changeable setting can be updated."));
2385 }
2386 catch (FieldException $e) {
2387 $this->fail(t("An unchangeable setting cannot be updated."));
2388 }
2389 $field['settings']['unchangeable']++;
2390 try {
2391 field_update_field($field);
2392 $this->fail(t("An unchangeable setting can be updated."));
2393 }
2394 catch (FieldException $e) {
2395 $this->pass(t("An unchangeable setting cannot be updated."));
2396 }
2397 }
2398
2399
2400
2401
2402 function testActive() {
2403 $field_definition = array(
2404 'field_name' => 'field_1',
2405 'type' => 'test_field',
2406
2407
2408 'storage' => array(
2409 'type' => 'field_sql_storage',
2410 ),
2411 );
2412 field_create_field($field_definition);
2413
2414
2415
2416
2417
2418 $this->_testActiveHelper($field_definition, array('field_test'));
2419 $this->_testActiveHelper($field_definition, array('field_sql_storage'));
2420 $this->_testActiveHelper($field_definition, array('field_test', 'field_sql_storage'));
2421 }
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434 function _testActiveHelper($field_definition, $modules) {
2435 $field_name = $field_definition['field_name'];
2436
2437
2438 $field = field_read_field($field_name);
2439 $this->assertTrue($field_definition <= $field, t('The field was properly read.'));
2440
2441 module_disable($modules, FALSE);
2442
2443 $fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE));
2444 $this->assertTrue(isset($fields[$field_name]) && $field_definition < $field, t('The field is properly read when explicitly fetching inactive fields.'));
2445
2446
2447
2448 while ($modules) {
2449 $field = field_read_field($field_name);
2450 $this->assertTrue(empty($field), t('%modules disabled. The field is marked inactive.', array('%modules' => implode(', ', $modules))));
2451
2452 $module = array_shift($modules);
2453 module_enable(array($module), FALSE);
2454 }
2455
2456
2457
2458 $field = field_read_field($field_name);
2459 $this->assertTrue($field_definition <= $field, t('The field was was marked active.'));
2460 }
2461 }
2462
2463 class FieldInstanceCrudTestCase extends FieldTestCase {
2464 protected $field;
2465
2466 public static function getInfo() {
2467 return array(
2468 'name' => 'Field instance CRUD tests',
2469 'description' => 'Create field entities by attaching fields to entities.',
2470 'group' => 'Field API',
2471 );
2472 }
2473
2474 function setUp() {
2475 parent::setUp('field_test');
2476
2477 $this->field = array(
2478 'field_name' => drupal_strtolower($this->randomName()),
2479 'type' => 'test_field',
2480 );
2481 field_create_field($this->field);
2482 $this->instance_definition = array(
2483 'field_name' => $this->field['field_name'],
2484 'entity_type' => 'test_entity',
2485 'bundle' => 'test_bundle',
2486 );
2487 }
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498 function testCreateFieldInstance() {
2499 field_create_instance($this->instance_definition);
2500
2501
2502 $result = db_query('SELECT * FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $this->instance_definition['field_name'], ':bundle' => $this->instance_definition['bundle']));
2503 $record = $result->fetchAssoc();
2504 $record['data'] = unserialize($record['data']);
2505
2506 $field_type = field_info_field_types($this->field['type']);
2507 $widget_type = field_info_widget_types($field_type['default_widget']);
2508 $formatter_type = field_info_formatter_types($field_type['default_formatter']);
2509
2510
2511 $this->assertIdentical($record['data']['required'], FALSE, t('Required defaults to false.'));
2512 $this->assertIdentical($record['data']['label'], $this->instance_definition['field_name'], t('Label defaults to field name.'));
2513 $this->assertIdentical($record['data']['description'], '', t('Description defaults to empty string.'));
2514 $this->assertIdentical($record['data']['widget']['type'], $field_type['default_widget'], t('Default widget has been written.'));
2515 $this->assertTrue(isset($record['data']['display']['default']), t('Display for "full" view_mode has been written.'));
2516 $this->assertIdentical($record['data']['display']['default']['type'], $field_type['default_formatter'], t('Default formatter for "full" view_mode has been written.'));
2517
2518
2519 $this->assertIdentical($record['data']['settings'], $field_type['instance_settings'] , t('Default instance settings have been written.'));
2520 $this->assertIdentical($record['data']['widget']['settings'], $widget_type['settings'] , t('Default widget settings have been written.'));
2521 $this->assertIdentical($record['data']['display']['default']['settings'], $formatter_type['settings'], t('Default formatter settings for "full" view_mode have been written.'));
2522
2523
2524 try {
2525 field_create_instance($this->instance_definition);
2526 $this->fail(t('Cannot create two instances with the same field / bundle combination.'));
2527 }
2528 catch (FieldException $e) {
2529 $this->pass(t('Cannot create two instances with the same field / bundle combination.'));
2530 }
2531
2532
2533 try {
2534 $this->instance_definition['field_name'] = $this->randomName();
2535 field_create_instance($this->instance_definition);
2536 $this->fail(t('Cannot create an instance of a non-existing field.'));
2537 }
2538 catch (FieldException $e) {
2539 $this->pass(t('Cannot create an instance of a non-existing field.'));
2540 }
2541
2542
2543 $field_restricted = array(
2544 'field_name' => drupal_strtolower($this->randomName()),
2545 'type' => 'test_field',
2546 'entity_types' => array('test_cacheable_entity'),
2547 );
2548 field_create_field($field_restricted);
2549
2550
2551
2552 try {
2553 $instance = $this->instance_definition;
2554 $instance['field_name'] = $field_restricted['field_name'];
2555 $instance['entity_type'] = 'test_cacheable_entity';
2556 field_create_instance($instance);
2557 $this->pass(t('Can create an instance on an entity type allowed by the field.'));
2558 }
2559 catch (FieldException $e) {
2560 $this->fail(t('Can create an instance on an entity type allowed by the field.'));
2561 }
2562
2563
2564
2565 try {
2566 $instance = $this->instance_definition;
2567 $instance['field_name'] = $field_restricted['field_name'];
2568 field_create_instance($instance);
2569 $this->fail(t('Cannot create an instance on an entity type forbidden by the field.'));
2570 }
2571 catch (FieldException $e) {
2572 $this->pass(t('Cannot create an instance on an entity type forbidden by the field.'));
2573 }
2574
2575
2576 }
2577
2578
2579
2580
2581 function testReadFieldInstance() {
2582 field_create_instance($this->instance_definition);
2583
2584
2585 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2586 $this->assertTrue($this->instance_definition < $instance, t('The field was properly read.'));
2587 }
2588
2589
2590
2591
2592 function testUpdateFieldInstance() {
2593 field_create_instance($this->instance_definition);
2594 $field_type = field_info_field_types($this->field['type']);
2595
2596
2597 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2598 $instance['required'] = !$instance['required'];
2599 $instance['label'] = $this->randomName();
2600 $instance['description'] = $this->randomName();
2601 $instance['settings']['test_instance_setting'] = $this->randomName();
2602 $instance['widget']['settings']['test_widget_setting'] =$this->randomName();
2603 $instance['widget']['weight']++;
2604 $instance['display']['default']['settings']['test_formatter_setting'] = $this->randomName();
2605 $instance['display']['default']['weight']++;
2606 field_update_instance($instance);
2607
2608 $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2609 $this->assertEqual($instance['required'], $instance_new['required'], t('"required" change is saved'));
2610 $this->assertEqual($instance['label'], $instance_new['label'], t('"label" change is saved'));
2611 $this->assertEqual($instance['description'], $instance_new['description'], t('"description" change is saved'));
2612 $this->assertEqual($instance['widget']['settings']['test_widget_setting'], $instance_new['widget']['settings']['test_widget_setting'], t('Widget setting change is saved'));
2613 $this->assertEqual($instance['widget']['weight'], $instance_new['widget']['weight'], t('Widget weight change is saved'));
2614 $this->assertEqual($instance['display']['default']['settings']['test_formatter_setting'], $instance_new['display']['default']['settings']['test_formatter_setting'], t('Formatter setting change is saved'));
2615 $this->assertEqual($instance['display']['default']['weight'], $instance_new['display']['default']['weight'], t('Widget weight change is saved'));
2616
2617
2618 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2619 $instance['widget']['type'] = 'test_field_widget_multiple';
2620 $instance['display']['default']['type'] = 'field_test_multiple';
2621 field_update_instance($instance);
2622
2623 $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2624 $this->assertEqual($instance['widget']['type'], $instance_new['widget']['type'] , t('Widget type change is saved.'));
2625 $settings = field_info_widget_settings($instance_new['widget']['type']);
2626 $this->assertIdentical($settings, array_intersect_key($instance_new['widget']['settings'], $settings) , t('Widget type change updates default settings.'));
2627 $this->assertEqual($instance['display']['default']['type'], $instance_new['display']['default']['type'] , t('Formatter type change is saved.'));
2628 $info = field_info_formatter_types($instance_new['display']['default']['type']);
2629 $settings = $info['settings'];
2630 $this->assertIdentical($settings, array_intersect_key($instance_new['display']['default']['settings'], $settings) , t('Changing formatter type updates default settings.'));
2631
2632
2633 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2634 $instance['display']['teaser'] = array();
2635 field_update_instance($instance);
2636
2637 $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2638 $this->assertTrue(isset($instance_new['display']['teaser']), t('Display for the new view_mode has been written.'));
2639 $this->assertIdentical($instance_new['display']['teaser']['type'], $field_type['default_formatter'], t('Default formatter for the new view_mode has been written.'));
2640 $info = field_info_formatter_types($instance_new['display']['teaser']['type']);
2641 $settings = $info['settings'];
2642 $this->assertIdentical($settings, $instance_new['display']['teaser']['settings'] , t('Default formatter settings for the new view_mode have been written.'));
2643
2644
2645 }
2646
2647
2648
2649
2650 function testDeleteFieldInstance() {
2651
2652
2653
2654
2655
2656
2657 field_create_instance($this->instance_definition);
2658 $this->another_instance_definition = $this->instance_definition;
2659 $this->another_instance_definition['bundle'] .= '_another_bundle';
2660 $instance = field_create_instance($this->another_instance_definition);
2661
2662
2663 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
2664 $this->assertTrue(!empty($instance) && empty($instance['deleted']), t('A new field instance is not marked for deletion.'));
2665 field_delete_instance($instance);
2666
2667
2668
2669 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle'], array('include_deleted' => TRUE));
2670 $this->assertTrue(!empty($instance['deleted']), t('A deleted field instance is marked for deletion.'));
2671
2672
2673 $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']);
2674 $this->assertTrue(empty($instance), t('A deleted field instance is not loaded by default.'));
2675
2676
2677 $another_instance = field_read_instance('test_entity', $this->another_instance_definition['field_name'], $this->another_instance_definition['bundle']);
2678 $this->assertTrue(!empty($another_instance) && empty($another_instance['deleted']), t('A non-deleted field instance is not marked for deletion.'));
2679
2680
2681 field_delete_instance($another_instance);
2682 $field = field_read_field($another_instance['field_name'], array('include_deleted' => TRUE));
2683 $this->assertTrue(!empty($field['deleted']), t('A deleted field is marked for deletion after all its instances have been marked for deletion.'));
2684 }
2685 }
2686
2687
2688
2689
2690
2691
2692
2693 class FieldTranslationsTestCase extends FieldTestCase {
2694 public static function getInfo() {
2695 return array(
2696 'name' => 'Field translations tests',
2697 'description' => 'Test multilanguage fields logic.',
2698 'group' => 'Field API',
2699 );
2700 }
2701
2702 function setUp() {
2703 parent::setUp('locale', 'field_test');
2704
2705 $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
2706
2707 $this->entity_type = 'test_entity';
2708
2709 $field = array(
2710 'field_name' => $this->field_name,
2711 'type' => 'test_field',
2712 'cardinality' => 4,
2713 'translatable' => TRUE,
2714 );
2715 field_create_field($field);
2716 $this->field = field_read_field($this->field_name);
2717
2718 $instance = array(
2719 'field_name' => $this->field_name,
2720 'entity_type' => $this->entity_type,
2721 'bundle' => 'test_bundle',
2722 );
2723 field_create_instance($instance);
2724 $this->instance = field_read_instance('test_entity', $this->field_name, 'test_bundle');
2725
2726 require_once DRUPAL_ROOT . '/includes/locale.inc';
2727 for ($i = 0; $i < 3; ++$i) {
2728 locale_add_language('l' . $i, $this->randomString(), $this->randomString());
2729 }
2730 }
2731
2732
2733
2734
2735 function testFieldAvailableLanguages() {
2736
2737 field_test_entity_info_translatable('test_entity', FALSE);
2738 $field = $this->field;
2739 $field['field_name'] .= '_untranslatable';
2740
2741
2742 field_test_entity_info_translatable('test_entity', TRUE);
2743
2744
2745 variable_set('field_test_field_available_languages_alter', TRUE);
2746 $enabled_languages = field_content_languages();
2747 $available_languages = field_available_languages($this->entity_type, $this->field);
2748 foreach ($available_languages as $delta => $langcode) {
2749 if ($langcode != 'xx' && $langcode != 'en') {
2750 $this->assertTrue(in_array($langcode, $enabled_languages), t('%language is an enabled language.', array('%language' => $langcode)));
2751 }
2752 }
2753 $this->assertTrue(in_array('xx', $available_languages), t('%language was made available.', array('%language' => 'xx')));
2754 $this->assertFalse(in_array('en', $available_languages), t('%language was made unavailable.', array('%language' => 'en')));
2755
2756
2757 $this->field['translatable'] = FALSE;
2758 field_update_field($this->field);
2759 $available_languages = field_available_languages($this->entity_type, $this->field);
2760 $this->assertTrue(count($available_languages) == 1 && $available_languages[0] === LANGUAGE_NONE, t('For untranslatable fields only LANGUAGE_NONE is available.'));
2761 }
2762
2763
2764
2765
2766 function testFieldInvoke() {
2767
2768 field_test_entity_info_translatable('test_entity', TRUE);
2769
2770 $entity_type = 'test_entity';
2771 $entity = field_test_create_stub_entity(0, 0, $this->instance['bundle']);
2772
2773
2774
2775 $values = array();
2776 $extra_languages = mt_rand(1, 4);
2777 $languages = $available_languages = field_available_languages($this->entity_type, $this->field);
2778 for ($i = 0; $i < $extra_languages; ++$i) {
2779 $languages[] = $this->randomName(2);
2780 }
2781
2782
2783 foreach ($languages as $langcode) {
2784 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
2785 $values[$langcode][$delta]['value'] = mt_rand(1, 127);
2786 }
2787 }
2788 $entity->{$this->field_name} = $values;
2789
2790 $results = _field_invoke('test_op', $entity_type, $entity);
2791 foreach ($results as $langcode => $result) {
2792 $hash = hash('sha256', serialize(array($entity_type, $entity, $this->field_name, $langcode, $values[$langcode])));
2793
2794
2795 $this->assertEqual($hash, $result, t('The result for %language is correctly stored.', array('%language' => $langcode)));
2796 }
2797
2798 $this->assertEqual(count($results), count($available_languages), t('No unavailable language has been processed.'));
2799 }
2800
2801
2802
2803
2804 function testFieldInvokeMultiple() {
2805
2806 field_test_entity_info_translatable('test_entity', TRUE);
2807
2808 $values = array();
2809 $options = array();
2810 $entities = array();
2811 $entity_type = 'test_entity';
2812 $entity_count = 5;
2813 $available_languages = field_available_languages($this->entity_type, $this->field);
2814
2815 for ($id = 1; $id <= $entity_count; ++$id) {
2816 $entity = field_test_create_stub_entity($id, $id, $this->instance['bundle']);
2817 $languages = $available_languages;
2818
2819
2820
2821 $extra_languages = mt_rand(1, 4);
2822 for ($i = 0; $i < $extra_languages; ++$i) {
2823 $languages[] = $this->randomName(2);
2824 }
2825
2826
2827 $language_count = count($languages);
2828 for ($i = 0; $i < $language_count; ++$i) {
2829 $langcode = $languages[$i];
2830
2831
2832
2833 if ($i !== $id) {
2834 for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
2835 $values[$id][$langcode][$delta]['value'] = mt_rand(1, 127);
2836 }
2837 }
2838
2839
2840 elseif (!isset($display_language)) {
2841 $display_language = $langcode;
2842 }
2843 }
2844
2845 $entity->{$this->field_name} = $values[$id];
2846 $entities[$id] = $entity;
2847
2848
2849 $options['language'][$id] = field_language($entity_type, $entity, NULL, $display_language);
2850 }
2851
2852 $grouped_results = _field_invoke_multiple('test_op_multiple', $entity_type, $entities);
2853 foreach ($grouped_results as $id => $results) {
2854 foreach ($results as $langcode => $result) {
2855 if (isset($values[$id][$langcode])) {
2856 $hash = hash('sha256', serialize(array($entity_type, $entities[$id], $this->field_name, $langcode, $values[$id][$langcode])));
2857
2858
2859 $this->assertEqual($hash, $result, t('The result for entity %id/%language is correctly stored.', array('%id' => $id, '%language' => $langcode)));
2860 }
2861 }
2862 $this->assertEqual(count($results), count($available_languages), t('No unavailable language has been processed for entity %id.', array('%id' => $id)));
2863 }
2864
2865 $null = NULL;
2866 $grouped_results = _field_invoke_multiple('test_op_multiple', $entity_type, $entities, $null, $null, $options);
2867 foreach ($grouped_results as $id => $results) {
2868 foreach ($results as $langcode => $result) {
2869 $this->assertTrue(isset($options['language'][$id]), t('The result language %language for entity %id was correctly suggested (display language: %display_language).', array('%id' => $id, '%language' => $langcode, '%display_language' => $display_language)));
2870 }
2871 }
2872 }
2873
2874
2875
2876
2877 function testTranslatableFieldSaveLoad() {
2878
2879 field_test_entity_info_translatable('node', TRUE);
2880 $entity_info = entity_get_info('node');
2881 $this->assertTrue(count($entity_info['translation']), t('Nodes are translatable.'));
2882
2883
2884 field_test_entity_info_translatable('test_entity', TRUE);
2885 $eid = $evid = 1;
2886 $entity_type = 'test_entity';
2887 $entity = field_test_create_stub_entity($eid, $evid, $this->instance['bundle']);
2888 $field_translations = array();
2889 $available_languages = field_available_languages($entity_type, $this->field);
2890 $this->assertTrue(count($available_languages) > 1, t('Field is translatable.'));
2891 foreach ($available_languages as $langcode) {
2892 $field_translations[$langcode] = $this->_generateTestFieldValues($this->field['cardinality']);
2893 }
2894
2895
2896 $entity->{$this->field_name} = $field_translations;
2897 field_attach_insert($entity_type, $entity);
2898 unset($entity->{$this->field_name});
2899 field_attach_load($entity_type, array($eid => $entity));
2900
2901
2902 foreach ($field_translations as $langcode => $items) {
2903 $result = TRUE;
2904 foreach ($items as $delta => $item) {
2905 $result = $result && $item['value'] == $entity->{$this->field_name}[$langcode][$delta]['value'];
2906 }
2907 $this->assertTrue($result, t('%language translation correctly handled.', array('%language' => $langcode)));
2908 }
2909 }
2910
2911
2912
2913
2914 function testFieldDisplayLanguage() {
2915 $field_name = drupal_strtolower($this->randomName() . '_field_name');
2916 $entity_type = 'test_entity';
2917
2918
2919
2920 $field = array(
2921 'field_name' => $field_name,
2922 'type' => 'test_field',
2923 'cardinality' => 2,
2924 'translatable' => TRUE,
2925 );
2926 field_create_field($field);
2927
2928 $instance = array(
2929 'field_name' => $field['field_name'],
2930 'entity_type' => $entity_type,
2931 'bundle' => 'test_bundle',
2932 );
2933 field_create_instance($instance);
2934
2935 $entity = field_test_create_stub_entity(1, 1, $this->instance['bundle']);
2936 $instances = field_info_instances($entity_type, $this->instance['bundle']);
2937
2938 $enabled_languages = field_content_languages();
2939 $languages = array();
2940
2941
2942
2943 foreach ($instances as $instance) {
2944 $field_name = $instance['field_name'];
2945 $field = field_info_field($field_name);
2946 do {
2947
2948
2949 $langcode = $enabled_languages[mt_rand(1, count($enabled_languages) - 1)];
2950 }
2951 while (isset($languages[$l