-
Notifications
You must be signed in to change notification settings - Fork 2
/
entity.test
1130 lines (959 loc) · 43.7 KB
/
entity.test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
// $Id$
/**
* @file
* Entity CRUD API tests.
*/
/**
* Test basic API.
*/
class EntityAPITestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Entity CRUD',
'description' => 'Tests basic CRUD API functionality.',
'group' => 'Entity API',
);
}
function setUp() {
parent::setUp('entity', 'entity_test');
}
/**
* Tests CRUD.
*/
function testCRUD() {
module_enable(array('entity_feature'));
$user1 = $this->drupalCreateUser();
// Create test entities for the user1 and unrelated to a user.
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => $user1->uid));
$entity->save();
$entity = entity_create('entity_test', array('name' => 'test2', 'uid' => $user1->uid));
$entity->save();
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => NULL));
$entity->save();
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test')));
$this->assertEqual($entities[0]->name, 'test', 'Created and loaded entity.');
$this->assertEqual($entities[1]->name, 'test', 'Created and loaded entity.');
$results = entity_test_load_multiple(array($entity->pid));
$loaded = array_pop($results);
$this->assertEqual($loaded->pid, $entity->pid, 'Loaded the entity unrelated to a user.');
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test2')));
$entities[0]->delete();
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test2')));
$this->assertEqual($entities, array(), 'Entity successfully deleted.');
$entity->save();
$this->assertEqual($entity->pid, $loaded->pid, 'Entity successfully updated.');
// Try deleting multiple test entities by deleting all.
$pids = array_keys(entity_test_load_multiple(FALSE));
entity_test_delete_multiple($pids);
}
/**
* Tests CRUD API functions: entity_(create|delete|save)
*/
function testCRUDAPIfunctions() {
module_enable(array('entity_feature'));
$user1 = $this->drupalCreateUser();
// Create test entities for the user1 and unrelated to a user.
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => $user1->uid));
entity_save('entity_test', $entity);
$entity = entity_create('entity_test', array('name' => 'test2', 'uid' => $user1->uid));
entity_save('entity_test', $entity);
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => NULL));
entity_save('entity_test', $entity);
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test')));
$this->assertEqual($entities[0]->name, 'test', 'Created and loaded entity.');
$this->assertEqual($entities[1]->name, 'test', 'Created and loaded entity.');
// Test getting the entity label, which is the used test-type's label.
$label = entity_label('entity_test', $entities[0]);
$this->assertEqual($label, 'label', 'Default label returned.');
$results = entity_test_load_multiple(array($entity->pid));
$loaded = array_pop($results);
$this->assertEqual($loaded->pid, $entity->pid, 'Loaded the entity unrelated to a user.');
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test2')));
entity_delete('entity_test', $entities[0]->pid);
$entities = array_values(entity_test_load_multiple(FALSE, array('name' => 'test2')));
$this->assertEqual($entities, array(), 'Entity successfully deleted.');
entity_save('entity_test', $entity);
$this->assertEqual($entity->pid, $loaded->pid, 'Entity successfully updated.');
// Try deleting multiple test entities by deleting all.
$pids = array_keys(entity_test_load_multiple(FALSE));
entity_delete_multiple('entity_test', $pids);
}
/**
* Test loading entities defined in code.
*/
function testExportables() {
module_enable(array('entity_feature'));
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'label', 'Default type loaded.');
$this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_IN_DB), 'Default type status is correct.');
// Test using a condition, which has to be applied on the defaults.
$types = entity_load('entity_test_type', FALSE, array('label' => 'label'));
$this->assertEqual($types['test']->label, 'label', 'Condition to default type applied.');
$types['test']->label = 'modified';
$types['test']->save();
// Ensure loading the changed entity works.
$types = entity_load('entity_test_type', FALSE, array('label' => 'modified'));
$this->assertEqual($types['test']->label, 'modified', 'Modified type loaded.');
// Clear the cache to simulate a new page load.
entity_get_controller('entity_test_type')->resetCache();
// Test loading using a condition again, now they default may not appear any
// more as it's overridden by an entity with another label.
$types = entity_load('entity_test_type', FALSE, array('label' => 'label'));
$this->assertTrue(empty($types), 'Conditions are applied to the overridden entity only.');
// But the overridden entity has to appear with another condition.
$types = entity_load('entity_test_type', FALSE, array('label' => 'modified'));
$this->assertEqual($types['test']->label, 'modified', 'Modified default type loaded by condition.');
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'modified', 'Modified default type loaded by id.');
$this->assertTrue($types['test']->status & ENTITY_IN_CODE && $types['test']->status & ENTITY_IN_DB, 'Status of modified type is correct.');
// Test loading an exportable by its numeric id.
$result = entity_load('entity_test_type', array($types['test']->id));
$this->assertTrue(isset($result['test']), 'Exportable entity loaded by the numeric id.');
// Test exporting an entity to JSON.
$serialized_string = $types['test']->export();
$data = drupal_json_decode($serialized_string);
$this->assertNotNull($data, 'Exported entity is valid JSON.');
$import = entity_import('entity_test_type', $serialized_string);
$this->assertTrue(get_class($import) == get_class($types['test']) && $types['test']->label == $import->label, 'Successfully exported entity to code.');
$this->assertTrue(!isset($import->status), 'Exportable status has not been exported to code.');
}
/**
* Tests hook_entity_enabled() and hook_entity_disabled().
*/
function testExportablesActivation() {
$_SESSION['entity_hook_test'] = array();
// Enabling the module should invoke the enabled hook for the other
// entities provided in code.
module_enable(array('entity_feature'));
$all = array('main', 'test', 'test2');
$this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all), 'Hook entity_enabled has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all), 'Hook entity_test_type_enabled has been invoked.');
// Add a new test entity in DB and make sure the hook is invoked too.
$test3 = entity_create('entity_test_type', array(
'name' => 'test3',
'label' => 'label',
'weight' => 0,
));
$test3->save();
$this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
// Now override the 'test' entity and make sure it doesn't invoke the
// enabling hook as it is already enabled. Then make sure it stays enabled
// when the feature module is disabled.
$result = entity_load('entity_test_type', array('test'));
$result['test']->label = 'modified';
$result['test']->save();
$this->assertTrue($_SESSION['entity_hook_test']['entity_enabled'] == array($all, array('test3')), 'Hook entity_enabled has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_enabled'] == array($all, array('test3')), 'Hook entity_test_type_enabled has been invoked.');
// 'test' has to remain enabled, as it has been overridden.
$all = array('main', 'test2');
module_disable(array('entity_feature'));
$this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all), 'Hook entity_disabled has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all), 'Hook entity_test_type_disabled has been invoked.');
// Now make sure 'test' is not overridden any more, but custom.
$result = entity_load('entity_test_type', array('test'));
$this->assertTrue(!entity_has_status('entity_test_type', $result['test'], ENTITY_OVERRIDDEN), 'Entity is not marked as overridden any more.');
// Test disabled hook for deleting the remaining entities from DB.
entity_delete_multiple('entity_test_type', array('test', 'test3'));
$all2 = array('test', 'test3');
$this->assertTrue($_SESSION['entity_hook_test']['entity_disabled'] == array($all, $all2), 'Hook entity_disabled has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_disabled'] == array($all, $all2), 'Hook entity_test_type_disabled has been invoked.');
}
/**
* Tests determining changes.
*/
function testChanges() {
module_enable(array('entity_feature'));
$types = entity_load('entity_test_type');
// Override the default entity, such it gets saved in the DB.
$types['test']->label ='test_changes';
$types['test']->save();
// Now test an update without applying any changes.
$types['test']->save();
$this->assertEqual($types['test']->label, 'test_changes', 'No changes have been determined.');
// Apply changes.
$types['test']->label = 'updated';
$types['test']->save();
// The hook implementations entity_test_entity_test_type_presave() and
// entity_test_entity_test_type_update() determine changes and change the
// label.
$this->assertEqual($types['test']->label, 'updated_presave_update', 'Changes have been determined.');
// Test the static load cache to be cleared.
$types = entity_load('entity_test_type');
$this->assertEqual($types['test']->label, 'updated_presave', 'Static cache has been cleared.');
}
/**
* Tests viewing entites.
*/
function testRendering() {
module_enable(array('entity_feature'));
$user1 = $this->drupalCreateUser();
// Create test entities for the user1 and unrelated to a user.
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => $user1->uid));
$render = $entity->view();
$output = drupal_render($render);
// The entity class adds the user name to the output. Verify it is there.
$this->assertTrue(strpos($output, format_username($user1)) !== FALSE, 'Entity has been rendered');
}
}
/**
* Test the generated Rules integration.
*/
class EntityAPIRulesIntegrationTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Entity CRUD Rules integration',
'description' => 'Tests the Rules integration provided by the Entity CRUD API.',
'group' => 'Entity API',
// Unfortunately the drupal.org testing bot doesn't pick that up yet, so
// this test is excluded from the automated tests. See #924090.
'dependencies' => array('rules'),
);
}
function setUp() {
parent::setUp('entity', 'entity_test', 'rules');
}
/**
* Test the events.
*/
function testEvents() {
$rule = rules_reaction_rule();
$rule->event('entity_test_presave');
$rule->event('entity_test_insert');
$rule->event('entity_test_update');
$rule->event('entity_test_delete');
$rule->action('drupal_message', array('message' => 'hello!'));
$rule->save();
rules_clear_cache(TRUE);
// Let the events occur.
$user1 = $this->drupalCreateUser();
$entity = entity_create('entity_test', array('name' => 'test', 'uid' => $user1->uid));
$entity->save();
$entity->name = 'update';
$entity->save();
$entity->delete();
// Now there should have been 5 events, 2 times presave and once insert,
// update and delete.
$count = substr_count(RulesLog::logger()->render(), '0 ms Reacting on event');
$this->assertTrue($count == 5, 'Events have been properly invoked.');
RulesLog::logger()->checkLog();
}
}
/**
* Tests metadata wrappers.
*/
class EntityMetadataTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Metadata Wrapper',
'description' => 'Makes sure metadata wrapper are working right.',
'group' => 'Entity API',
);
}
function setUp() {
parent::setUp('entity', 'entity_test');
// Create a field having 4 values for testing multiple value support.
$this->field_name = drupal_strtolower($this->randomName() . '_field_name');
$this->field = array('field_name' => $this->field_name, 'type' => 'text', 'cardinality' => 4);
$this->field = field_create_field($this->field);
$this->field_id = $this->field['id'];
$this->instance = array(
'field_name' => $this->field_name,
'entity_type' => 'node',
'bundle' => 'page',
'label' => $this->randomName() . '_label',
'description' => $this->randomName() . '_description',
'weight' => mt_rand(0, 127),
'settings' => array(
'text_processing' => FALSE,
),
'widget' => array(
'type' => 'text_textfield',
'label' => 'Test Field',
'settings' => array(
'size' => 64,
)
)
);
field_create_instance($this->instance);
}
/**
* Creates a user and a node, then tests getting the properties.
*/
function testEntityMetadataWrapper() {
$account = $this->drupalCreateUser();
// For testing sanitizing give the user a malicious user name
$account = user_save($account, array('name' => '<b>BadName</b>'));
$title = '<b>Is it bold?<b>';
$body[LANGUAGE_NONE][0] = array('value' => '<b>The body & nothing.</b>', 'summary' => '<b>The body.</b>');
$node = $this->drupalCreateNode(array('uid' => $account->uid, 'name' => $account->name, 'body' => $body, 'title' => $title, 'summary' => ''));
// First test without sanitizing.
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertEqual('<b>Is it bold?<b>', $wrapper->title->value(), 'Getting a field value.');
$this->assertEqual($node->title, $wrapper->title->raw(), 'Getting a raw property value.');
// Test chaining
$this->assertEqual($account->mail, $wrapper->author->mail->value(), 'Testing chained usage.');
$this->assertEqual($account->name, $wrapper->author->name->value(), 'Testing chained usage with callback and sanitizing.');
// Test sanitized output.
$options = array('sanitize' => TRUE);
$this->assertEqual(check_plain('<b>Is it bold?<b>'), $wrapper->title->value($options), 'Getting sanitized field.');
$this->assertEqual(filter_xss($node->name), $wrapper->author->name->value($options), 'Getting sanitized property with getter callback.');
// Test getting an not existing property
try {
echo $wrapper->dummy;
$this->fail('Getting an not existing property.');
}
catch (EntityMetadataWrapperException $e) {
$this->pass('Getting an not existing property.');
}
// Test setting.
$wrapper->author = 0;
$this->assertEqual(0, $wrapper->author->uid->value(), 'Setting a property.');
try {
$wrapper->url = 'dummy';
$this->fail('Setting an unsupported property.');
}
catch (EntityMetadataWrapperException $e) {
$this->pass('Setting an unsupported property.');
}
// Test value validation.
$this->assertFalse($wrapper->author->name->validate(array(3)), 'Validation correctly checks for valid data types.');
try {
$wrapper->author->mail = 'foo';
$this->fail('An invalid mail address has been set.');
}
catch (EntityMetadataWrapperException $e) {
$this->pass('Setting an invalid mail address throws exception.');
}
// Test setting a referenced entity by id.
$wrapper->author->set($GLOBALS['user']->uid);
$this->assertEqual($wrapper->author->getIdentifier(), $GLOBALS['user']->uid, 'Get the identifier of a referenced entity.');
$this->assertEqual($wrapper->author->uid->value(), $GLOBALS['user']->uid, 'Successfully set referenced entity using the identifier.');
// Set by object.
$wrapper->author->set($GLOBALS['user']);
$this->assertEqual($wrapper->author->uid->value(), $GLOBALS['user']->uid, 'Successfully set referenced entity using the entity.');
// Test getting by the field API processed values like the node body.
$body_value = $wrapper->body->value;
$this->assertEqual("<p>The body & nothing.</p>\n", $body_value->value(), "Getting processed value.");
$this->assertEqual("The body & nothing.\n", $body_value->value(array('decode' => TRUE)), "Decoded value.");
$this->assertEqual("<b>The body & nothing.</b>", $body_value->raw(), "Raw body returned.");
// Test getting the summary.
$this->assertEqual("<p>The body.</p>\n", $wrapper->body->summary->value(), "Getting body summary.");
$wrapper->body->set(array('value' => "<b>The second body.</b>"));
$this->assertEqual("<p>The second body.</p>\n", $wrapper->body->value->value(), "Setting a processed field value and reading it again.");
$this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], "<b>The second body.</b>", 'Update appears in the wrapped entity.');
$this->assert(isset($node->body[LANGUAGE_NONE][0]['safe_value']), 'Formatted text has been processed.');
// Test iterator.
$type_info = entity_get_property_info('node');
$this->assertFalse(array_diff_key($type_info['properties'], iterator_to_array($wrapper->getIterator())), 'Iterator is working.');
foreach ($wrapper as $property) {
$this->assertTrue($property instanceof EntityMetadataWrapper, 'Iterate over wrapper properties.');
}
// Test setting a new node.
$node->title = 'foo';
$wrapper->set($node);
$this->assertEqual($wrapper->title->value(), 'foo', 'Changed the wrapped node.');
// Test getting options lists.
$this->assertEqual($wrapper->type->optionsList(), node_type_get_names(), 'Options list returned.');
// Test saving and deleting.
$wrapper->save();
$wrapper->delete();
$return = node_load($wrapper->getIdentifier());
$this->assertFalse($return, "Node has been successfully deleted.");
}
/**
* Test supporting multi-valued fields.
*/
function testListMetadataWrappers() {
$property = $this->field_name;
$values = array();
$values[LANGUAGE_NONE][0] = array('value' => '<b>2009-09-05</b>');
$values[LANGUAGE_NONE][1] = array('value' => '2009-09-05');
$values[LANGUAGE_NONE][2] = array('value' => '2009-08-05');
$node = $this->drupalCreateNode(array('type' => 'page', $property => $values));
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertEqual('<b>2009-09-05</b>', $wrapper->{$property}[0]->value(), 'Getting array entry.');
$this->assertEqual('2009-09-05', $wrapper->{$property}->get(1)->value(), 'Getting array entry.');
$this->assertEqual(3, count($wrapper->{$property}->value()), 'Getting the whole array.');
// Test sanitizing
$this->assertEqual(check_plain('<b>2009-09-05</b>'), $wrapper->{$property}[0]->value(array('sanitize' => TRUE)), 'Getting array entry.');
// Test iterator
$this->assertEqual(array_keys(iterator_to_array($wrapper->$property->getIterator())), array_keys($wrapper->$property->value()), 'Iterator is working.');
foreach ($wrapper->$property as $p) {
$this->assertTrue($p instanceof EntityMetadataWrapper, 'Iterate over list wrapper properties.');
}
// Make sure changing the array changes the actual entity property.
$wrapper->{$property}[0] = '2009-10-05';
unset($wrapper->{$property}[1], $wrapper->{$property}[2]);
$this->assertEqual($wrapper->{$property}->value(), array('2009-10-05'), 'Setting multiple property values.');
// Test setting an arbitrary list item.
$list = array(0 => REQUEST_TIME);
$wrapper = entity_metadata_wrapper('list<date>', $list);
$wrapper[1] = strtotime('2009-09-05');
$this->assertEqual($wrapper->value(), array(REQUEST_TIME, strtotime('2009-09-05')), 'Setting a list item.');
$this->assertEqual($wrapper->count(), 2, 'List count is correct.');
// Test using a list wrapper without data.
$wrapper = entity_metadata_wrapper('list<date>');
$info = array();
foreach ($wrapper as $item) {
$info[] = $item->info();
}
$this->assertTrue($info[0]['type'] == 'date', 'Iterated over empty list wrapper.');
}
/**
* Tests using the wrapper without any data.
*/
function testWithoutData() {
$wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
$this->assertTrue(isset($wrapper->title), 'Bundle properties have been added.');
$info = $wrapper->author->mail->info();
$this->assertTrue(!empty($info) && is_array($info) && isset($info['label']), 'Property info returned.');
}
/**
* Test using access() method.
*/
function testAccess() {
// Test without data.
$account = $this->drupalCreateUser(array('bypass node access'));
$this->assertTrue(entity_access('view', 'node', NULL, $account), 'Access without data checked.');
// Test with actual data.
$values[LANGUAGE_NONE][0] = array('value' => '<b>2009-09-05</b>');
$values[LANGUAGE_NONE][1] = array('value' => '2009-09-05');
$node = $this->drupalCreateNode(array('type' => 'page', $this->field_name => $values));
$this->assertTrue(entity_access('delete', 'node', $node, $account), 'Access with data checked.');
// Test per property access without data.
$account2 = $this->drupalCreateUser(array('bypass node access', 'administer nodes'));
$wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
$this->assertTrue($wrapper->access('edit', $account), 'Access to node granted.');
$this->assertFalse($wrapper->status->access('edit', $account), 'Access for admin property denied.');
$this->assertTrue($wrapper->status->access('edit', $account2), 'Access for admin property allowed for the admin.');
// Test per property access with data.
$wrapper = entity_metadata_wrapper('node', $node, array('bundle' => 'page'));
$this->assertFalse($wrapper->status->access('edit', $account), 'Access for admin property denied.');
$this->assertTrue($wrapper->status->access('edit', $account2), 'Access for admin property allowed for the admin.');
// Test field level access.
$this->assertTrue($wrapper->{$this->field_name}->access('view'), 'Field access granted.');
}
/**
* Tests using a data structure with passed in metadata.
*/
function testDataStructureWrapper() {
$log_entry = array(
'type' => 'entity',
'message' => $this->randomName(8),
'variables' => array(),
'severity' => WATCHDOG_NOTICE,
'link' => '',
'user' => $GLOBALS['user'],
);
$info['property info'] = array(
'type' => array('type' => 'text', 'label' => 'The category to which this message belongs.'),
'message' => array('type' => 'text', 'label' => 'The log message.'),
'user' => array('type' => 'user', 'label' => 'The user causing the log entry.'),
);
$wrapper = entity_metadata_wrapper('log_entry', $log_entry, $info);
$this->assertEqual($wrapper->user->name->value(), $GLOBALS['user']->name, 'Wrapped custom entity.');
}
/**
* Tests using entity_property_query().
*/
function testEntityQuery() {
$title = '<b>Is it bold?<b>';
$values[LANGUAGE_NONE][0] = array('value' => 'foo');
$node = $this->drupalCreateNode(array($this->field_name => $values, 'title' => $title));
$results = entity_property_query('node', 'title', array($title, 'another title'));
$this->assertEqual($results, array($node->nid), 'Queried nodes with a given title.');
$results = entity_property_query('node', $this->field_name, 'foo');
$this->assertEqual($results, array($node->nid), 'Queried nodes with a given field value.');
}
/**
* Tests serializing data wrappers, in particular for EntityDrupalWrapper.
*/
function testWrapperSerialization() {
$node = $this->drupalCreateNode();
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertTrue($wrapper->value() == $node, 'Data correctly wrapped.');
// Test serializing and make sure only the node id is stored.
$this->assertTrue(strpos(serialize($wrapper), $node->title) === FALSE, 'Node has been correctly serialized.');
$this->assertEqual(unserialize(serialize($wrapper))->title->value(), $node->title, 'Serializing works right.');
$wrapper2 = unserialize(serialize($wrapper));
// Test serializing the unloaded wrapper.
$this->assertEqual(unserialize(serialize($wrapper2))->title->value(), $node->title, 'Serializing works right.');
// Test loading a not more existing node.
$s = serialize($wrapper2);
node_delete($node->nid);
$this->assertFalse(node_load($node->nid), 'Node deleted.');
try {
unserialize($s)->value();
$this->fail("Loading hasn't created an exception.");
}
catch (EntityMetadataWrapperException $e) {
$this->pass("Exception was thrown: ". $e->getMessage());
}
}
}
/**
* Tests provided entity property info of the core modules.
*/
class EntityTokenTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Entity tokens',
'description' => 'Tests provided tokens for entity properties.',
'group' => 'Entity API',
);
}
function setUp() {
parent::setUp('entity_token');
}
/**
* Tests whether token support is basically working.
*/
function testTokenSupport() {
$node = $this->drupalCreateNode(array('sticky' => TRUE, 'promote' => FALSE));
$text = "Sticky: [node:sticky] Promote: [node:promote] User: [site:current-user:name]";
$true = t('true');
$false = t('false');
$user_name = $GLOBALS['user']->name;
$target = "Sticky: $true Promote: $false User: $user_name";
$replace = token_replace($text, array('node' => $node));
$this->assertEqual($replace, $target, 'Provided tokens basically work.');
}
}
/**
* Tests provided entity property info of the core modules.
*/
class EntityMetadataIntegrationTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Property info core integration',
'description' => 'Tests using metadata wrapper for drupal core.',
'group' => 'Entity API',
);
}
function setUp() {
parent::setUp('entity', 'book', 'statistics');
}
protected function assertException($wrapper, $name, $text = NULL) {
$this->assertTrue(isset($wrapper->$name), 'Property wrapper ' . check_plain($name) . ' exists.');
$text = isset($text) ? $text : 'Getting the not existing property ' . $name . ' throws exception.';
try {
$wrapper->$name->value();
$this->fail($text);
}
catch (EntityMetadataWrapperException $e) {
$this->pass($text);
}
}
protected function assertEmpty($wrapper, $name) {
$this->assertTrue(isset($wrapper->$name), 'Property ' . check_plain($name) . ' exists.');
$this->assertTrue($wrapper->$name->value() === NULL, 'Property ' . check_plain($name) . ' is empty.');
}
protected function assertValue($wrapper, $key) {
$this->assertTrue($wrapper->$key->value() !== NULL, check_plain($key) . ' property returned.');
$info = $wrapper->$key->info();
if (!empty($info['raw getter callback'])) {
// Also test getting the raw value
$this->assertTrue($wrapper->$key->raw() !== NULL, check_plain($key) . ' raw value returned.');
}
}
/**
* Test book module integration.
*/
function testBookModule() {
$title = 'Book 1';
$node = $this->drupalCreateNode(array('title' => $title, 'type' => 'book'));
$node2 = $this->drupalCreateNode(array('type' => 'book', 'book' => array('bid' => $node->nid)));
$node3 = $this->drupalCreateNode(array('type' => 'page'));
// Test whether the properties work.
$wrapper = entity_metadata_wrapper('node', $node2);
$this->assertEqual("Book 1", $wrapper->book->title->value(), "Book title returned.");
$this->assertEqual($node->nid, $wrapper->book->nid->value(), "Book id returned.");
// Try using book properties for no book nodes.
$wrapper = entity_metadata_wrapper('node', $node3);
$this->assertException($wrapper, 'book');
}
/**
* Test properties of a comment.
*/
function testComments() {
$title = 'Node 1';
$node = $this->drupalCreateNode(array('title' => $title, 'type' => 'page'));
$account = $this->drupalCreateUser();
$comment = (object)array(
'subject' => 'topic',
'nid' => $node->nid,
'uid' => $account->uid,
'cid' => FALSE,
'pid' => 0,
'homepage' => '',
'language' => LANGUAGE_NONE,
'hostname' => ip_address(),
);
$comment->comment_body[LANGUAGE_NONE][0] = array('value' => 'text', 'format' => 0);
comment_save($comment);
$wrapper = entity_metadata_wrapper('comment', $comment);
foreach ($wrapper as $key => $value) {
if ($key != 'parent') {
$this->assertValue($wrapper, $key);
}
}
$this->assertException($wrapper, 'parent');
}
/**
* Test all properties of a node.
*/
function testNodeProperties() {
$title = 'Book 1';
$node = $this->drupalCreateNode(array('title' => $title, 'type' => 'page'));
$wrapper = entity_metadata_wrapper('node', $node);
foreach ($wrapper as $key => $value) {
if ($key != 'book' && $key != 'source') {
$this->assertValue($wrapper, $key);
}
}
$this->assertException($wrapper, 'book');
$this->assertEmpty($wrapper, 'source');
$this->assertException($wrapper->source, 'title');
}
/**
* Tests properties provided by the taxonomy module.
*/
function testTaxonomyProperties() {
$vocab = $this->createVocab();
$term_parent = entity_property_values_create_entity('taxonomy_term', array(
'name' => $this->randomName(),
'vocabulary' => $vocab,
))->save()->value();
$term_parent2 = entity_property_values_create_entity('taxonomy_term', array(
'name' => $this->randomName(),
'vocabulary' => $vocab,
))->save()->value();
$term = entity_property_values_create_entity('taxonomy_term', array(
'name' => $this->randomName(),
'vocabulary' => $vocab,
'description' => $this->randomString(),
'weight' => mt_rand(0, 10),
'parent' => array($term_parent->tid),
))->save()->value();
$wrapper = entity_metadata_wrapper('taxonomy_term', $term);
foreach ($wrapper as $key => $value) {
$this->assertValue($wrapper, $key);
}
// Test setting another parent using the full object.
$wrapper->parent[] = $term_parent2;
$this->assertEqual($wrapper->parent[1]->getIdentifier(), $term_parent2->tid, 'Term parent added.');
$parents = $wrapper->parent->value();
$tids = $term_parent->tid . ':' . $term_parent2->tid;
$this->assertEqual($parents[0]->tid . ':' . $parents[1]->tid, $tids, 'Parents returned.');
$this->assertEqual(implode(':', $wrapper->parent->value(array('identifier' => TRUE))), $tids, 'Parent ids returned.');
// Test vocabulary.
foreach ($wrapper->vocabulary as $key => $value) {
$this->assertValue($wrapper->vocabulary, $key);
}
// Test field integration.
$tags[LANGUAGE_NONE][0]['tid'] = $term->tid;
$node = $this->drupalCreateNode(array('title' => 'foo', 'type' => 'article', 'field_tags' => $tags));
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertEqual($wrapper->field_tags[0]->name->value(), $term->name, 'Get an associated tag of a node with the wrapper.');
$wrapper->field_tags[1] = $term_parent;
$tags = $wrapper->field_tags->value();
$this->assertEqual($tags[1]->tid, $term_parent->tid, 'Associated a new tag with a node.');
$this->assertEqual($tags[0]->tid, $term->tid, 'Previsous set association kept.');
// Test getting a list of identifiers.
$tags = $wrapper->field_tags->value(array('identifier' => TRUE));
$this->assertEqual($tags, array($term->tid, $term_parent->tid), 'List of referenced term identifiers returned.');
// Test setting tags by using ids.
$wrapper->field_tags->set(array(2));
$this->assertEqual($wrapper->field_tags[0]->tid->value(), 2, 'Specified tags by a list of term ids.');
}
/**
* Test all properties of a user.
*/
function testUserProperties() {
$account = $this->drupalCreateUser();
$wrapper = entity_metadata_wrapper('user', $account);
foreach ($wrapper as $key => $value) {
$this->assertValue($wrapper, $key);
}
}
/**
* Test properties provided by system module.
*/
function testSystemProperties() {
$wrapper = entity_metadata_site_wrapper();
foreach ($wrapper as $key => $value) {
$this->assertValue($wrapper, $key);
}
// Test files.
$file = $this->createFile();
$wrapper = entity_metadata_wrapper('file', $file);
foreach ($wrapper as $key => $value) {
$this->assertValue($wrapper, $key);
}
}
/**
* Runs some generic tests on each entity.
*/
function testCRUDfunctions() {
$info = entity_get_info();
foreach ($info as $entity_type => $entity_info) {
// Test using access callback.
entity_access('view', $entity_type);
entity_access('update', $entity_type);
entity_access('create', $entity_type);
entity_access('delete', $entity_type);
// Test creating the entity.
if (!isset($entity_info['creation callback'])) {
continue;
}
// Populate $values with all values that are setable. They will be set
// with an metadata wrapper, so we also test setting that way.
$values = array();
foreach (entity_metadata_wrapper($entity_type) as $name => $wrapper) {
$info = $wrapper->info();
if (!empty($info['setter callback'])) {
$info += array('type' => 'text');
$values[$name] = $this->createValue($info['type'], $info);
}
}
$entity = entity_property_values_create_entity($entity_type, $values)->value();
$this->assertTrue($entity, "Created $entity_type and set all setable values.");
// Save the new entity.
$return = entity_save($entity_type, $entity);
if ($return === FALSE) {
continue; // No support for saving.
}
$id = entity_metadata_wrapper($entity_type, $entity)->getIdentifier();
$this->assertTrue($id, "$entity_type has been successfully saved.");
// And delete it.
$return = entity_delete($entity_type, $id);
if ($return === FALSE) {
continue; // No support for deleting.
}
$return = entity_load($entity_type, array($id));
$this->assertFalse($return, "$entity_type has been successfully deleted.");
}
}
/**
* Test making use of a text fields.
*/
function testTextFields() {
// Create a simple text field without text processing.
$field = array(
'field_name' => 'field_text',
'type' => 'text',
'cardinality' => 2,
);
field_create_field($field);
$instance = array(
'field_name' => 'field_text',
'entity_type' => 'node',
'label' => 'test',
'bundle' => 'article',
'widget' => array(
'type' => 'text_textfield',
'weight' => -1,
),
);
field_create_instance($instance);
$node = $this->drupalCreateNode(array('type' => 'article'));
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_text[0] = 'the text';
// Try saving the node and make sure the information is still there after
// loading the node again, thus the correct data structure has been written.
node_save($node);
$node = node_load($node->nid, NULL, TRUE);
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertEqual('the text', $wrapper->field_text[0]->value(), 'Text has been specified.');
// Now activate text processing.
$instance['settings']['text_processing'] = 1;
field_update_instance($instance);
$node = $this->drupalCreateNode(array('type' => 'article'));
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_text[0]->set(array('value' => "<b>The second body.</b>"));
$this->assertEqual("<p>The second body.</p>\n", $wrapper->field_text[0]->value->value(), "Setting a processed text field value and reading it again.");
// Assert the summary property is correctly removed.
$this->assertFalse(isset($wrapper->field_text[0]->summary), 'Processed text has no summary.');
// Create a text field with summary but without text processing.
$field = array(
'field_name' => 'field_text2',
'type' => 'text_with_summary',
'cardinality' => 1,
);
field_create_field($field);
$instance = array(
'field_name' => 'field_text2',
'entity_type' => 'node',
'label' => 'test',
'bundle' => 'article',
'settings' => array('text_processing' => 0),
'widget' => array(
'type' => 'text_textarea_with_summary',
'weight' => -1,
),
);
field_create_instance($instance);
$node = $this->drupalCreateNode(array('type' => 'article'));
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_text2->summary = 'the summary';
$wrapper->field_text2->value = 'the text';
// Try saving the node and make sure the information is still there after
// loading the node again, thus the correct data structure has been written.
node_save($node);
$node = node_load($node->nid, NULL, TRUE);
$wrapper = entity_metadata_wrapper('node', $node);
$this->assertEqual('the text', $wrapper->field_text2->value->value(), 'Text has been specified.');
$this->assertEqual('the summary', $wrapper->field_text2->summary->value(), 'Summary has been specified.');
}
/**
* Test making use of a file field.
*/
function testFileFields() {
$file = $this->createFile();
// Create a file field.
$field = array(
'field_name' => 'field_file',
'type' => 'file',
'cardinality' => 2,
'settings' => array('display_field' => TRUE),
);
field_create_field($field);
$instance = array(
'field_name' => 'field_file',
'entity_type' => 'node',
'label' => 'File',
'bundle' => 'article',
'settings' => array('description_field' => TRUE),
'required' => FALSE,
'widget' => array(
'type' => 'file_generic',
'weight' => -1,
),
);
field_create_instance($instance);
$node = $this->drupalCreateNode(array('type' => 'article'));
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_file[0] = array('fid' => $file->fid, 'display' => FALSE);
$this->assertEqual($file->filename, $wrapper->field_file[0]->file->name->value(), 'File has been specified.');
$wrapper->field_file[0]->description = 'foo';
$wrapper->field_file[0]->display = TRUE;
$this->assertEqual($wrapper->field_file[0]->description->value(), 'foo', 'File description has been correctly set.');
// Try saving the node and make sure the information is still there after
// loading the node again, thus the correct data structure has been written.
node_save($node);
$node = node_load($node->nid, NULL, TRUE);
$wrapper = entity_metadata_wrapper('node', $node);