Newer
Older
Wolfgang Ziegler
committed
<?php
// $Id$
/**
* @file
* Entity CRUD API tests.
Wolfgang Ziegler
committed
*/
/**
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
* 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.');
Wolfgang Ziegler
committed
$this->assertTrue($types['test']->status & ENTITY_IN_CODE && !($types['test']->status & ENTITY_CUSTOM), 'Default type status is correct.');
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
// 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.');
Wolfgang Ziegler
committed
$this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
// Test rebuilding the defaults and make sure overridden entities stay.
entity_defaults_rebuild();
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'modified', 'Overridden entity is still overridden.');
$this->assertTrue(entity_has_status('entity_test_type', $types['test'], ENTITY_OVERRIDDEN), 'Status of overridden type is correct.');
// Test reverting.
$types['test']->delete();
$types = entity_load('entity_test_type', array('test', 'test2'));
$this->assertEqual($types['test']->label, 'label', 'Entity has been reverted.');
// 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.');
}
/**
Wolfgang Ziegler
committed
* Make sure insert() and update() hooks for exportables are invoked.
*/
Wolfgang Ziegler
committed
function testExportableHooks() {
$_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'));
Wolfgang Ziegler
committed
$insert = array('main', 'test', 'test2');
$this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert 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();
Wolfgang Ziegler
committed
$insert[] = 'test3';
$this->assertTrue($_SESSION['entity_hook_test']['entity_insert'] == $insert, 'Hook entity_insert has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_insert'] == $insert, 'Hook entity_test_type_insert has been invoked.');
// Now override the 'test' entity and make sure it invokes the update hook.
$result = entity_load('entity_test_type', array('test'));
$result['test']->label = 'modified';
$result['test']->save();
Wolfgang Ziegler
committed
$this->assertTrue($_SESSION['entity_hook_test']['entity_update'] == array('test'), 'Hook entity_update has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_update'] == array('test'), 'Hook entity_test_type_update has been invoked.');
// 'test' has to remain enabled, as it has been overridden.
Wolfgang Ziegler
committed
$delete = array('main', 'test2');
module_disable(array('entity_feature'));
Wolfgang Ziegler
committed
$this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
// Now make sure 'test' is not overridden any more, but custom.
$result = entity_load('entity_test_type', array('test'));
Wolfgang Ziegler
committed
$this->assertTrue(!$result['test']->hasStatus(ENTITY_OVERRIDDEN), 'Entity is not marked as overridden any more.');
Wolfgang Ziegler
committed
$this->assertTrue(entity_has_status('entity_test_type', $result['test'], ENTITY_CUSTOM), 'Entity is marked as custom.');
Wolfgang Ziegler
committed
// Test deleting the remaining entities from DB.
entity_delete_multiple('entity_test_type', array('test', 'test3'));
Wolfgang Ziegler
committed
$delete[] = 'test';
$delete[] = 'test3';
$this->assertTrue($_SESSION['entity_hook_test']['entity_delete'] == $delete, 'Hook entity_deleted has been invoked.');
$this->assertTrue($_SESSION['entity_hook_test']['entity_test_type_delete'] == $delete, 'Hook entity_test_type_deleted has been invoked.');
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
}
/**
* 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',
'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.
Wolfgang Ziegler
committed
*/
class EntityMetadataTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Metadata Wrapper',
'description' => 'Makes sure metadata wrapper are working right.',
'group' => 'Entity API',
Wolfgang Ziegler
committed
);
}
function setUp() {
parent::setUp('entity', 'entity_test', 'locale');
Wolfgang Ziegler
committed
// 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,
Wolfgang Ziegler
committed
'entity_type' => 'node',
Wolfgang Ziegler
committed
'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>';
Wolfgang Ziegler
committed
$body[LANGUAGE_NONE][0] = array('value' => '<b>The body & nothing.</b>', 'summary' => '<b>The body.</b>');
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
// 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.');
Wolfgang Ziegler
committed
try {
Wolfgang Ziegler
committed
$wrapper->url = 'dummy';
Wolfgang Ziegler
committed
$this->fail('Setting an unsupported property.');
}
catch (EntityMetadataWrapperException $e) {
$this->pass('Setting an unsupported property.');
}
Wolfgang Ziegler
committed
// 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.');
Wolfgang Ziegler
committed
// Test getting by the field API processed values like the node body.
Wolfgang Ziegler
committed
$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.");
Wolfgang Ziegler
committed
Wolfgang Ziegler
committed
// Test getting the summary.
$this->assertEqual("<p>The body.</p>\n", $wrapper->body->summary->value(), "Getting body summary.");
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
$this->assert(isset($node->body[LANGUAGE_NONE][0]['safe_value']), 'Formatted text has been processed.');
Wolfgang Ziegler
committed
// Test translating the body.
locale_add_language('de');
$wrapper->language('de');
$languages = language_list();
$this->assertEqual($wrapper->getPropertyLanguage(), $languages['de'], 'Wrapper language has been set to German');
$this->assertEqual($wrapper->body->value->value(), "<p>The second body.</p>\n", 'Language fallback on neutral language.');
// Set a German text using the wrapper.
$wrapper->body->set(array('value' => "<b>Der zweite Text.</b>"));
$this->assertEqual($wrapper->body->value->value(), "<p>Der zweite Text.</p>\n", 'German body set and retrieved.');
$wrapper->language(NULL);
$this->assertEqual($wrapper->body->value->value(), "<p>The second body.</p>\n", 'Language neutral text is still there.');
Wolfgang Ziegler
committed
// Test iterator.
$type_info = entity_get_property_info('node');
Wolfgang Ziegler
committed
$this->assertFalse(array_diff_key($type_info['properties'], iterator_to_array($wrapper->getIterator())), 'Iterator is working.');
Wolfgang Ziegler
committed
foreach ($wrapper as $property) {
$this->assertTrue($property instanceof EntityMetadataWrapper, 'Iterate over wrapper properties.');
}
Wolfgang Ziegler
committed
// Test setting a new node.
Wolfgang Ziegler
committed
$node->title = 'foo';
Wolfgang Ziegler
committed
$wrapper->set($node);
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
Wolfgang Ziegler
committed
// Test making use of a generic 'entity' reference property the
// 'entity_test' module provides. The property defaults to the node author.
$this->assertEqual($wrapper->reference->uid->value(), $wrapper->author->getIdentifier(), 'Used generic entity reference property.');
// For testing, just point the reference to the node itself now.
$wrapper->reference->set($wrapper);
$this->assertEqual($wrapper->reference->nid->value(), $wrapper->getIdentifier(), 'Correctly updated the generic entity referenced property.');
Wolfgang Ziegler
committed
// Test saving and deleting.
$wrapper->save();
$wrapper->delete();
$return = node_load($wrapper->getIdentifier());
$this->assertFalse($return, "Node has been successfully deleted.");
Wolfgang Ziegler
committed
}
/**
* Test supporting multi-valued fields.
*/
function testListMetadataWrappers() {
Wolfgang Ziegler
committed
$property = $this->field_name;
Wolfgang Ziegler
committed
$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');
Wolfgang Ziegler
committed
$node = $this->drupalCreateNode(array('type' => 'page', $property => $values));
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
// Test sanitizing
$this->assertEqual(check_plain('<b>2009-09-05</b>'), $wrapper->{$property}[0]->value(array('sanitize' => TRUE)), 'Getting array entry.');
Wolfgang Ziegler
committed
// Test iterator
Wolfgang Ziegler
committed
$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.');
}
Wolfgang Ziegler
committed
// 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.');
Wolfgang Ziegler
committed
// Test setting an arbitrary list item.
Wolfgang Ziegler
committed
$list = array(0 => REQUEST_TIME);
$wrapper = entity_metadata_wrapper('list<date>', $list);
Wolfgang Ziegler
committed
$wrapper[1] = strtotime('2009-09-05');
$this->assertEqual($wrapper->value(), array(REQUEST_TIME, strtotime('2009-09-05')), 'Setting a list item.');
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
}
/**
* Tests using the wrapper without any data.
*/
function testWithoutData() {
Wolfgang Ziegler
committed
$wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
Wolfgang Ziegler
committed
$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'));
Wolfgang Ziegler
committed
$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));
Wolfgang Ziegler
committed
$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'));
Wolfgang Ziegler
committed
$wrapper = entity_metadata_wrapper('node', NULL, array('bundle' => 'page'));
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
/**
* Tests using a data structure with passed in metadata.
Wolfgang Ziegler
committed
*/
function testDataStructureWrapper() {
Wolfgang Ziegler
committed
$log_entry = array(
'type' => 'entity',
'message' => $this->randomName(8),
'variables' => array(),
'severity' => WATCHDOG_NOTICE,
'link' => '',
'user' => $GLOBALS['user'],
);
Wolfgang Ziegler
committed
'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.');
}
Wolfgang Ziegler
committed
/**
Wolfgang Ziegler
committed
* Tests using entity_property_query().
Wolfgang Ziegler
committed
*/
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));
Wolfgang Ziegler
committed
$results = entity_property_query('node', 'title', $title);
$this->assertEqual($results, array($node->nid), 'Queried nodes with a given title.');
Wolfgang Ziegler
committed
$results = entity_property_query('node', $this->field_name, 'foo');
$this->assertEqual($results, array($node->nid), 'Queried nodes with a given field value.');
}
Wolfgang Ziegler
committed
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
/**
* 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());
Wolfgang Ziegler
committed
}
}
}
/**
* 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');
}
Wolfgang Ziegler
committed
/**
* Tests whether token support is basically working.
*/
function testTokenSupport() {
$node = $this->drupalCreateNode(array('sticky' => TRUE, 'promote' => FALSE));
Wolfgang Ziegler
committed
$text = "Sticky: [node:sticky] Promote: [node:promote] User: [site:current-user:name]";
Wolfgang Ziegler
committed
$true = t('true');
$false = t('false');
Wolfgang Ziegler
committed
$user_name = $GLOBALS['user']->name;
$target = "Sticky: $true Promote: $false User: $user_name";
Wolfgang Ziegler
committed
$replace = token_replace($text, array('node' => $node));
$this->assertEqual($replace, $target, 'Provided tokens basically work.');
}
Wolfgang Ziegler
committed
}
/**
* Tests provided entity property info of the core modules.
Wolfgang Ziegler
committed
*/
Wolfgang Ziegler
committed
class EntityMetadataIntegrationTestCase extends DrupalWebTestCase {
Wolfgang Ziegler
committed
public static function getInfo() {
return array(
'name' => 'Property info core integration',
'description' => 'Tests using metadata wrapper for drupal core.',
'group' => 'Entity API',
Wolfgang Ziegler
committed
);
}
function setUp() {
parent::setUp('entity', 'book', 'statistics');
Wolfgang Ziegler
committed
}
protected function assertException($wrapper, $name, $text = NULL) {
Wolfgang Ziegler
committed
$this->assertTrue(isset($wrapper->$name), 'Property wrapper ' . check_plain($name) . ' exists.');
$text = isset($text) ? $text : 'Getting the not existing property ' . $name . ' throws exception.';
Wolfgang Ziegler
committed
try {
$wrapper->$name->value();
$this->fail($text);
}
catch (EntityMetadataWrapperException $e) {
$this->pass($text);
}
}
Wolfgang Ziegler
committed
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.');
}
Wolfgang Ziegler
committed
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';
Wolfgang Ziegler
committed
$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.");
Wolfgang Ziegler
committed
// 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';
Wolfgang Ziegler
committed
$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);
Wolfgang Ziegler
committed
comment_save($comment);
$wrapper = entity_metadata_wrapper('comment', $comment);
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
Wolfgang Ziegler
committed
if ($key != 'parent') {
$this->assertValue($wrapper, $key);
}
}
$this->assertException($wrapper, 'parent');
}
/**
* Test all properties of a node.
*/
function testNodeProperties() {
$title = 'Book 1';
Wolfgang Ziegler
committed
$node = $this->drupalCreateNode(array('title' => $title, 'type' => 'page'));
$wrapper = entity_metadata_wrapper('node', $node);
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
if ($key != 'book' && $key != 'source') {
Wolfgang Ziegler
committed
$this->assertValue($wrapper, $key);
}
}
$this->assertException($wrapper, 'book');
Wolfgang Ziegler
committed
$this->assertEmpty($wrapper, 'source');
$this->assertException($wrapper->source, 'title');
Wolfgang Ziegler
committed
}
/**
* Tests properties provided by the taxonomy module.
*/
function testTaxonomyProperties() {
Wolfgang Ziegler
committed
$vocab = $this->createVocab();
Wolfgang Ziegler
committed
$term_parent = entity_property_values_create_entity('taxonomy_term', array(
Wolfgang Ziegler
committed
'name' => $this->randomName(),
'vocabulary' => $vocab,
Wolfgang Ziegler
committed
))->save()->value();
Wolfgang Ziegler
committed
$term_parent2 = entity_property_values_create_entity('taxonomy_term', array(
Wolfgang Ziegler
committed
'name' => $this->randomName(),
'vocabulary' => $vocab,
Wolfgang Ziegler
committed
))->save()->value();
Wolfgang Ziegler
committed
$term = entity_property_values_create_entity('taxonomy_term', array(
Wolfgang Ziegler
committed
'name' => $this->randomName(),
'vocabulary' => $vocab,
'description' => $this->randomString(),
'weight' => mt_rand(0, 10),
Wolfgang Ziegler
committed
'parent' => array($term_parent->tid),
Wolfgang Ziegler
committed
))->save()->value();
Wolfgang Ziegler
committed
$wrapper = entity_metadata_wrapper('taxonomy_term', $term);
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
Wolfgang Ziegler
committed
$this->assertValue($wrapper, $key);
}
Wolfgang Ziegler
committed
// Test setting another parent using the full object.
$wrapper->parent[] = $term_parent2;
$this->assertEqual($wrapper->parent[1]->getIdentifier(), $term_parent2->tid, 'Term parent added.');
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
// Test vocabulary.
Wolfgang Ziegler
committed
foreach ($wrapper->vocabulary as $key => $value) {
Wolfgang Ziegler
committed
$this->assertValue($wrapper->vocabulary, $key);
}
// Test field integration.
$tags[LANGUAGE_NONE][0]['tid'] = $term->tid;
Wolfgang Ziegler
committed
$node = $this->drupalCreateNode(array('title' => 'foo', 'type' => 'article', 'field_tags' => $tags));
$wrapper = entity_metadata_wrapper('node', $node);
Wolfgang Ziegler
committed
$this->assertEqual($wrapper->field_tags[0]->name->value(), $term->name, 'Get an associated tag of a node with the wrapper.');
Wolfgang Ziegler
committed
Wolfgang Ziegler
committed
$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.');
Wolfgang Ziegler
committed
// Test getting a list of identifiers.
Wolfgang Ziegler
committed
$tags = $wrapper->field_tags->value(array('identifier' => TRUE));
Wolfgang Ziegler
committed
$this->assertEqual($tags, array($term->tid, $term_parent->tid), 'List of referenced term identifiers returned.');
// Test setting tags by using ids.
Wolfgang Ziegler
committed
$wrapper->field_tags->set(array(2));
$this->assertEqual($wrapper->field_tags[0]->tid->value(), 2, 'Specified tags by a list of term ids.');
Wolfgang Ziegler
committed
}
/**
* Test all properties of a user.
*/
function testUserProperties() {
$account = $this->drupalCreateUser();
Wolfgang Ziegler
committed
$account->login = time();
Wolfgang Ziegler
committed
$wrapper = entity_metadata_wrapper('user', $account);
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
Wolfgang Ziegler
committed
$this->assertValue($wrapper, $key);
}
}
/**
* Test properties provided by system module.
*/
function testSystemProperties() {
Wolfgang Ziegler
committed
$wrapper = entity_metadata_site_wrapper();
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
Wolfgang Ziegler
committed
$this->assertValue($wrapper, $key);
}
// Test files.
$file = $this->createFile();
Wolfgang Ziegler
committed
$wrapper = entity_metadata_wrapper('file', $file);
Wolfgang Ziegler
committed
foreach ($wrapper as $key => $value) {
Wolfgang Ziegler
committed
$this->assertValue($wrapper, $key);
}
}
Wolfgang Ziegler
committed
/**
* 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);
Wolfgang Ziegler
committed
// 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();
Wolfgang Ziegler
committed
foreach (entity_metadata_wrapper($entity_type) as $name => $wrapper) {
$info = $wrapper->info();
Wolfgang Ziegler
committed
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();
Wolfgang Ziegler
committed
$this->assertTrue($entity, "Created $entity_type and set all setable values.");
// Save the new entity.
$return = entity_save($entity_type, $entity);
Wolfgang Ziegler
committed
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);
Wolfgang Ziegler
committed
if ($return === FALSE) {
continue; // No support for deleting.
Wolfgang Ziegler
committed
}
$return = entity_load($entity_type, array($id));
$this->assertFalse($return, "$entity_type has been successfully deleted.");
}
}
Wolfgang Ziegler
committed
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
/**
* 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,