Commit 58b0235a authored by Dries's avatar Dries

- Patch #324313 by catch et al: load multiple nodes and terms at once.

parent 0b06c68b
...@@ -32,6 +32,9 @@ Drupal 7.0, xxxx-xx-xx (development version) ...@@ -32,6 +32,9 @@ Drupal 7.0, xxxx-xx-xx (development version)
* Redesigned password strength validator. * Redesigned password strength validator.
* Redesigned the add content type screen. * Redesigned the add content type screen.
* Highlight duplicate URL aliases. * Highlight duplicate URL aliases.
- Performance:
* Improved performance on uncached page views by loading multiple core
objects in a single database query.
- Documentation: - Documentation:
* Hook API documentation now included in Drupal core. * Hook API documentation now included in Drupal core.
- News aggregator: - News aggregator:
......
...@@ -705,18 +705,13 @@ function book_build_active_trail($book_link) { ...@@ -705,18 +705,13 @@ function book_build_active_trail($book_link) {
/** /**
* Implementation of hook_nodeapi_load(). * Implementation of hook_nodeapi_load().
*/ */
function book_nodeapi_load(&$node, $teaser, $page) { function book_nodeapi_load($nodes, $types) {
// Note - we cannot use book_link_load() because it will call node_load(). $result = db_query("SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid IN (" . db_placeholders(array_keys($nodes)) . ")", array_keys($nodes), array('fetch' => PDO::FETCH_ASSOC));
$info['book'] = db_query('SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid = :nid', array( foreach ($result as $record) {
':nid' => $node->nid $nodes[$record['nid']]->book = $record;
))->fetchAssoc(); $nodes[$record['nid']]->book['href'] = $record['link_path'];
$nodes[$record['nid']]->book['title'] = $record['link_title'];
if ($info['book']) { $nodes[$record['nid']]->book['options'] = unserialize($record['options']);
$info['book']['href'] = $info['book']['link_path'];
$info['book']['title'] = $info['book']['link_title'];
$info['book']['options'] = unserialize($info['book']['options']);
return $info;
} }
} }
......
...@@ -146,7 +146,7 @@ class BookTestCase extends DrupalWebTestCase { ...@@ -146,7 +146,7 @@ class BookTestCase extends DrupalWebTestCase {
} }
// Check to make sure the book node was created. // Check to make sure the book node was created.
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertNotNull(($node === FALSE ? NULL : $node), t('Book node found in database.')); $this->assertNotNull(($node === FALSE ? NULL : $node), t('Book node found in database.'));
$number++; $number++;
......
...@@ -579,11 +579,32 @@ function comment_form_alter(&$form, $form_state, $form_id) { ...@@ -579,11 +579,32 @@ function comment_form_alter(&$form, $form_state, $form_id) {
/** /**
* Implementation of hook_nodeapi_load(). * Implementation of hook_nodeapi_load().
*/ */
function comment_nodeapi_load(&$node, $arg = 0) { function comment_nodeapi_load($nodes, $types) {
if ($node->comment != COMMENT_NODE_DISABLED) { $comments_enabled = array();
return db_query('SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = :nid', array(':nid' => $node->nid))->fetchAssoc();
// Check if comments are enabled for each node. If comments are disabled,
// assign values without hitting the database.
foreach ($nodes as $node) {
// Store whether comments are enabled for this node.
if ($node->comment != COMMENT_NODE_DISABLED) {
$comments_enabled[] = $node->nid;
}
else {
$node->last_comment_timestamp = $node->created;
$node->last_comment_name = '';
$node->comment_count = 0;
}
}
// For nodes with comments enabled, fetch information from the database.
if (!empty($comments_enabled)) {
$result = db_query('SELECT nid, last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid IN(' . db_placeholders($comments_enabled) . ')', $comments_enabled);
foreach ($result as $record) {
$nodes[$record->nid]->last_comment_timestamp = $record->last_comment_timestamp;
$nodes[$record->nid]->last_comment_name = $record->last_comment_name;
$nodes[$record->nid]->comment_count = $record->comment_count;
}
} }
return array('last_comment_timestamp' => $node->created, 'last_comment_name' => '', 'comment_count' => 0);
} }
/** /**
......
...@@ -262,7 +262,7 @@ class DBLogTestCase extends DrupalWebTestCase { ...@@ -262,7 +262,7 @@ class DBLogTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/' . $type, $edit, t('Save')); $this->drupalPost('node/add/' . $type, $edit, t('Save'));
$this->assertResponse(200); $this->assertResponse(200);
// Retrieve node object. // Retrieve node object.
$node = node_load(array('title' => $title)); $node = $this->drupalGetNodeByTitle($title);
$this->assertTrue($node != null, t('Node @title was loaded', array('@title' => $title))); $this->assertTrue($node != null, t('Node @title was loaded', array('@title' => $title)));
// Edit node. // Edit node.
$edit = $this->getContentUpdate($type); $edit = $this->getContentUpdate($type);
......
...@@ -114,7 +114,7 @@ class FilterAdminTestCase extends DrupalWebTestCase { ...@@ -114,7 +114,7 @@ class FilterAdminTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
$this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.')); $this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.'));
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue($node, t('Node found in database.')); $this->assertTrue($node, t('Node found in database.'));
$this->drupalGet('node/' . $node->nid); $this->drupalGet('node/' . $node->nid);
......
...@@ -341,11 +341,25 @@ function forum_nodeapi_delete(&$node, $teaser, $page) { ...@@ -341,11 +341,25 @@ function forum_nodeapi_delete(&$node, $teaser, $page) {
/** /**
* Implementation of hook_nodeapi_load(). * Implementation of hook_nodeapi_load().
*/ */
function forum_nodeapi_load(&$node, $teaser, $page) { function forum_nodeapi_load($nodes, $types) {
$vid = variable_get('forum_nav_vocabulary', ''); $vid = variable_get('forum_nav_vocabulary', '');
// If no forum vocabulary is set up, return.
if ($vid == '') {
return;
}
$vocabulary = taxonomy_vocabulary_load($vid); $vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
return db_fetch_array(db_query('SELECT tid AS forum_tid FROM {forum} WHERE vid = %d', $node->vid)); $node_vids = array();
foreach ($nodes as $node) {
if (isset($vocabulary->nodes[$node->type])) {
$node_vids[] = $node->vid;
}
}
if (!empty($node_vids)) {
$result = db_query('SELECT nid, tid FROM {forum} WHERE vid IN(' . db_placeholders($node_vids) . ')', $node_vids);
foreach ($result as $record) {
$nodes[$record->nid]->forum_tid = $record->tid;
}
} }
} }
...@@ -451,15 +465,6 @@ function forum_form_alter(&$form, $form_state, $form_id) { ...@@ -451,15 +465,6 @@ function forum_form_alter(&$form, $form_state, $form_id) {
} }
} }
/**
* Implementation of hook_load().
*/
function forum_load($node) {
$forum = db_fetch_object(db_query('SELECT * FROM {term_node} WHERE vid = %d', $node->vid));
return $forum;
}
/** /**
* Implementation of hook_block(). * Implementation of hook_block().
* *
......
...@@ -236,7 +236,7 @@ class ForumTestCase extends DrupalWebTestCase { ...@@ -236,7 +236,7 @@ class ForumTestCase extends DrupalWebTestCase {
} }
// Retrieve node object. // Retrieve node object.
$node = node_load(array('title' => $title), null, true); // Are these last two parameters necessary? $node = $this->drupalGetNodeByTitle($title);
$this->assertTrue($node != null, t('Node @title was loaded', array('@title' => $title))); $this->assertTrue($node != null, t('Node @title was loaded', array('@title' => $title)));
// View forum topic. // View forum topic.
......
...@@ -154,6 +154,39 @@ function hook_node_operations() { ...@@ -154,6 +154,39 @@ function hook_node_operations() {
return $operations; return $operations;
} }
/**
* Act on node objects when loaded.
*
* This hook allows you to add information to node objects when loaded from
* the database. It takes an array of nodes indexed by nid as its first
* parameter. For performance reasons, information for all available nodes
* should be loaded in a single query where possible.
*
* The types of all nodes being passed in are also available in the $types
* parameter. If your module keeps track of the node types it supports, this
* allows for an early return if nothing needs to be done.
*
* Due to the internal cache in node_load_multiple(), you should not use this
* hook to modify information returned from the {node} table itself, since
* this may affect the way nodes are returned from the cache in subsequent
* calls to the function.
*
* @see comment_nodeapi_load()
* @see taxonomy_nodeapi_load()
* @see forum_nodeapi_load()
*
* @param $nodes
* An array of node objects indexed by nid.
* @param $types
* An array containing the types of the nodes.
*/
function hook_nodeapi_load($nodes, $types) {
$result = db_query('SELECT nid, foo FROM {mytable} WHERE nid IN(' . db_placeholders(array_keys($nodes)) . ')', array_keys($nodes));
foreach ($result as $record) {
$nodes[$record->nid]->foo = $record->foo;
}
}
/** /**
* Act on nodes defined by other modules. * Act on nodes defined by other modules.
* *
...@@ -521,25 +554,22 @@ function hook_insert($node) { ...@@ -521,25 +554,22 @@ function hook_insert($node) {
* Load node-type-specific information. * Load node-type-specific information.
* *
* This is a hook used by node modules. It is called to allow the module * This is a hook used by node modules. It is called to allow the module
* a chance to load extra information that it stores about a node, or * a chance to load extra information that it stores about a node. The hook
* possibly replace already loaded information - which can be dangerous. * should not be used to replace information from the core {node} table since
* this may interfere with the way nodes are fetched from cache.
* *
* @param $node * @param $nodes
* The node being loaded. At call time, node.module has already loaded * An array of the nodes being loaded, keyed by nid. At call time,
* the basic information about the node, such as its node ID (nid), * node.module has already loaded the basic information about the nodes, such
* title, and body. * as node ID (nid), title, and body.
* @return
* An object containing properties of the node being loaded. This will
* be merged with the passed-in $node to result in an object containing
* a set of properties resulting from adding the extra properties to
* the passed-in ones, and overwriting the passed-in ones with the
* extra properties if they have the same name as passed-in properties.
* *
* For a detailed usage example, see node_example.module. * For a detailed usage example, see node_example.module.
*/ */
function hook_load($node) { function hook_load($nodes) {
$additions = db_fetch_object(db_query('SELECT * FROM {mytable} WHERE vid = %d', $node->vid)); $result = db_fetch_object(db_query('SELECT nid, foo FROM {mytable} WHERE nid IN (' . db_placeholders(array_keys($nodes)) . ')', array_keys($nodes)));
return $additions; foreach ($result as $record) {
$nodes[$record->nid]->foo = $record->foo;
}
} }
/** /**
......
This diff is collapsed.
<?php <?php
// $Id$ // $Id$
/**
* Test the node_load_multiple() function.
*/
class NodeLoadMultipleUnitTest extends DrupalWebTestCase {
function getInfo() {
return array(
'name' => t('Load multiple nodes'),
'description' => t('Test the loading of multiple nodes.'),
'group' => t('Node'),
);
}
function setUp() {
parent::setUp();
$web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
$this->drupalLogin($web_user);
}
/**
* Create four nodes and ensure they're loaded correctly.
*/
function testNodeMultipleLoad() {
$node1 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
$node2 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
$node3 = $this->drupalCreateNode(array('type' => 'article', 'promote' => 0));
$node4 = $this->drupalCreateNode(array('type' => 'page', 'promote' => 0));
// Confirm that promoted nodes appear in the default node listing.
$this->drupalGet('node');
$this->assertText($node1->title, t('Node title appears on the default listing.'));
$this->assertText($node2->title, t('Node title appears on the default listing.'));
$this->assertNoText($node3->title, t('Node title does not appear in the default listing.'));
$this->assertNoText($node4->title, t('Node title does not appear in the default listing.'));
// Load nodes with only a condition. Nodes 3 and 4 will be loaded.
$nodes = node_load_multiple(NULL, array('promote' => 0));
$this->assertEqual($node3->title, $nodes[$node3->nid]->title, t('Node was loaded.'));
$this->assertEqual($node4->title, $nodes[$node4->nid]->title, t('Node was loaded.'));
$count = count($nodes);
$this->assertTrue($count == 2, t('@count nodes loaded.', array('@count' => $count)));
// Load nodes by nid. Nodes 1, 2 and 4 will be loaded.
$nodes = node_load_multiple(array(1, 2, 4));
$count = count($nodes);
$this->assertTrue(count($nodes) == 3, t('@count nodes loaded', array('@count' => $count)));
$this->assertTrue(isset($nodes[$node1->nid]), t('Node is correctly keyed in the array'));
$this->assertTrue(isset($nodes[$node2->nid]), t('Node is correctly keyed in the array'));
$this->assertTrue(isset($nodes[$node4->nid]), t('Node is correctly keyed in the array'));
foreach ($nodes as $node) {
$this->assertTrue(is_object($node), t('Node is an object'));
}
// Load nodes by nid, where type = article. Nodes 1, 2 and 3 will be loaded.
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
$count = count($nodes);
$this->assertTrue($count == 3, t('@count nodes loaded', array('@count' => $count)));
$this->assertEqual($nodes[$node1->nid]->title, $node1->title, t('Node successfully loaded.'));
$this->assertEqual($nodes[$node2->nid]->title, $node2->title, t('Node successfully loaded.'));
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded.'));
$this->assertFalse(isset($nodes[$node4->nid]));
// Now that all nodes have been loaded into the static cache, ensure that
// they are loaded correctly again when a condition is passed.
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article'));
$count = count($nodes);
$this->assertTrue($count == 3, t('@count nodes loaded.', array('@count' => $count)));
$this->assertEqual($nodes[$node1->nid]->title, $node1->title, t('Node successfully loaded'));
$this->assertEqual($nodes[$node2->nid]->title, $node2->title, t('Node successfully loaded'));
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded'));
$this->assertFalse(isset($nodes[$node4->nid]), t('Node was not loaded'));
// Load nodes by nid, where type = article and promote = 0.
$nodes = node_load_multiple(array(1, 2, 3, 4), array('type' => 'article', 'promote' => 0));
$count = count($nodes);
$this->assertTrue($count == 1, t('@count node loaded', array('@count' => $count)));
$this->assertEqual($nodes[$node3->nid]->title, $node3->title, t('Node successfully loaded.'));
}
}
class NodeRevisionsTestCase extends DrupalWebTestCase { class NodeRevisionsTestCase extends DrupalWebTestCase {
protected $nodes; protected $nodes;
protected $logs; protected $logs;
...@@ -258,7 +338,7 @@ class PageEditTestCase extends DrupalWebTestCase { ...@@ -258,7 +338,7 @@ class PageEditTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
// Check that the node exists in the database. // Check that the node exists in the database.
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue($node, t('Node found in database.')); $this->assertTrue($node, t('Node found in database.'));
// Check that "edit" link points to correct page. // Check that "edit" link points to correct page.
...@@ -352,7 +432,7 @@ class PageCreationTestCase extends DrupalWebTestCase { ...@@ -352,7 +432,7 @@ class PageCreationTestCase extends DrupalWebTestCase {
$this->assertRaw(t('!post %title has been created.', array('!post' => 'Page', '%title' => $edit['title'])), t('Page created.')); $this->assertRaw(t('!post %title has been created.', array('!post' => 'Page', '%title' => $edit['title'])), t('Page created.'));
// Check that the node exists in the database. // Check that the node exists in the database.
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue($node, t('Node found in database.')); $this->assertTrue($node, t('Node found in database.'));
} }
} }
......
...@@ -135,12 +135,14 @@ function path_nodeapi_validate(&$node, $arg) { ...@@ -135,12 +135,14 @@ function path_nodeapi_validate(&$node, $arg) {
/** /**
* Implementation of hook_nodeapi_load(). * Implementation of hook_nodeapi_load().
*/ */
function path_nodeapi_load(&$node, $arg) { function path_nodeapi_load($nodes, $types) {
$language = isset($node->language) ? $node->language : ''; foreach ($nodes as $node) {
$path = 'node/' . $node->nid; $language = isset($node->language) ? $node->language : '';
$alias = drupal_get_path_alias($path, $language); $path = 'node/' . $node->nid;
if ($path != $alias) { $alias = drupal_get_path_alias($path, $language);
$node->path = $alias; if ($path != $alias) {
$node->path = $alias;
}
} }
} }
......
...@@ -131,7 +131,7 @@ class PathTestCase extends DrupalWebTestCase { ...@@ -131,7 +131,7 @@ class PathTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
// Check to make sure the node was created. // Check to make sure the node was created.
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertNotNull(($node === FALSE ? NULL : $node), 'Node found in database. %s'); $this->assertNotNull(($node === FALSE ? NULL : $node), 'Node found in database. %s');
...@@ -188,7 +188,7 @@ class PathLanguageTestCase extends DrupalWebTestCase { ...@@ -188,7 +188,7 @@ class PathLanguageTestCase extends DrupalWebTestCase {
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
// Check to make sure the node was created. // Check to make sure the node was created.
$english_node = node_load(array('title' => $edit['title'])); $english_node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue(($english_node), 'Node found in database.'); $this->assertTrue(($english_node), 'Node found in database.');
// Confirm that the alias works. // Confirm that the alias works.
...@@ -209,7 +209,7 @@ class PathLanguageTestCase extends DrupalWebTestCase { ...@@ -209,7 +209,7 @@ class PathLanguageTestCase extends DrupalWebTestCase {
// Ensure the node was created. // Ensure the node was created.
// Check to make sure the node was created. // Check to make sure the node was created.
$french_node = node_load(array('title' => $edit['title'])); $french_node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertTrue(($french_node), 'Node found in database.'); $this->assertTrue(($french_node), 'Node found in database.');
// Confirm that the alias works. // Confirm that the alias works.
......
...@@ -148,11 +148,9 @@ function poll_block($op = 'list', $delta = '') { ...@@ -148,11 +148,9 @@ function poll_block($op = 'list', $delta = '') {
} }
elseif ($op == 'view') { elseif ($op == 'view') {
// Retrieve the latest poll. // Retrieve the latest poll.
$sql = db_rewrite_sql("SELECT MAX(n.created) FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = 1 AND p.active = 1"); $record = db_query_range(db_rewrite_sql("SELECT n.nid FROM {node} n INNER JOIN {poll} p ON p.nid = n.nid WHERE n.status = :status AND p.active = :active ORDER BY n.created DESC"), array(':status' => 1, ':active' => 1), 0, 1)->fetch();
$timestamp = db_result(db_query($sql)); if ($record) {
if ($timestamp) { $poll = node_load($record->nid);
$poll = node_load(array('type' => 'poll', 'created' => $timestamp, 'status' => 1));
if ($poll->nid) { if ($poll->nid) {
$poll = poll_view($poll, TRUE, FALSE, TRUE); $poll = poll_view($poll, TRUE, FALSE, TRUE);
} }
...@@ -451,35 +449,35 @@ function poll_validate($node) { ...@@ -451,35 +449,35 @@ function poll_validate($node) {
/** /**
* Implementation of hook_load(). * Implementation of hook_load().
*/ */
function poll_load($node) { function poll_load($nodes) {
global $user; global $user;
foreach ($nodes as $node) {
$poll = db_query("SELECT runtime, active FROM {poll} WHERE nid = :nid", array(':nid' => $node->nid))->fetch();
$poll = db_fetch_object(db_query("SELECT runtime, active FROM {poll} WHERE nid = %d", $node->nid)); // Load the appropriate choices into the $poll object.
$poll->choice = db_query("SELECT chid, chtext, chvotes, weight FROM {poll_choice} WHERE nid = :nid ORDER BY weight", array(':nid' => $node->nid))->fetchAllAssoc('chid', PDO::FETCH_ASSOC);
// Load the appropriate choices into the $poll object.
$result = db_query("SELECT chid, chtext, chvotes, weight FROM {poll_choice} WHERE nid = %d ORDER BY weight", $node->nid);
while ($choice = db_fetch_array($result)) {
$poll->choice[$choice['chid']] = $choice;
}
// Determine whether or not this user is allowed to vote. // Determine whether or not this user is allowed to vote.
$poll->allowvotes = FALSE; $poll->allowvotes = FALSE;
if (user_access('vote on polls') && $poll->active) { if (user_access('vote on polls') && $poll->active) {
if ($user->uid) { if ($user->uid) {
$result = db_fetch_object(db_query('SELECT chid FROM {poll_vote} WHERE nid = %d AND uid = %d', $node->nid, $user->uid)); $result = db_query('SELECT chid FROM {poll_vote} WHERE nid = :nid AND uid = :uid', array(':nid' => $node->nid, ':uid' => $user->uid))->fetch();
} }
else { else {
$result = db_fetch_object(db_query("SELECT chid FROM {poll_vote} WHERE nid = %d AND hostname = '%s'", $node->nid, ip_address())); $result = db_query("SELECT chid FROM {poll_vote} WHERE nid = :nid AND hostname = :hostname", array(':nid' => $node->nid, ':hostname' => ip_address()))->fetch();
} }
if (isset($result->chid)) { if ($result) {
$poll->vote = $result->chid; $poll->vote = $result->chid;
}
else {
$poll->vote = -1;
$poll->allowvotes = TRUE;
}
} }
else { foreach ($poll as $key => $value) {
$poll->vote = -1; $nodes[$node->nid]->$key = $value;
$poll->allowvotes = TRUE;
} }
} }
return $poll;
} }
/** /**
......
...@@ -40,7 +40,7 @@ class PollTestCase extends DrupalWebTestCase { ...@@ -40,7 +40,7 @@ class PollTestCase extends DrupalWebTestCase {
} }
$this->drupalPost(NULL, $edit, t('Save')); $this->drupalPost(NULL, $edit, t('Save'));
$node = node_load(array('title' => $title)); $node = $this->drupalGetNodeByTitle($title);
$this->assertRaw(t('@type %title has been created.', array('@type' => node_get_types('name', 'poll'), '%title' => $title)), 'Poll has been created.'); $this->assertRaw(t('@type %title has been created.', array('@type' => node_get_types('name', 'poll'), '%title' => $title)), 'Poll has been created.');
$this->assertTrue($node->nid, t('Poll has been found in the database')); $this->assertTrue($node->nid, t('Poll has been found in the database'));
......
...@@ -446,6 +446,22 @@ protected function exceptionHandler($exception) { ...@@ -446,6 +446,22 @@ protected function exceptionHandler($exception) {
$this->error($exception->getMessage(), 'Uncaught exception', _drupal_get_last_caller($backtrace)); $this->error($exception->getMessage(), 'Uncaught exception', _drupal_get_last_caller($backtrace));
} }
/**
* Get a node from the database based on its title.
*
* @param title
* A node title, usually generated by $this->randomName().
*
* @return
* A node object matching $title.
*/
function drupalGetNodeByTitle($title) {
$nodes = node_load_multiple(array(), array('title' => $title));
// Load the first node returned from the database.
$returned_node = reset($nodes);
return $returned_node;
}
/** /**
* Creates a node based on default settings. * Creates a node based on default settings.
* *
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
/** /**
* Implementation of hook_taxonomy_term_load(). * Implementation of hook_taxonomy_term_load().
*/ */
function taxonomy_test_taxonomy_term_load($term) { function taxonomy_test_taxonomy_term_load(&$terms) {
$term->antonyms = taxonomy_test_get_antonyms($term->tid); foreach ($terms as $term) {
$term->antonyms = taxonomy_test_get_antonyms($term->tid);
}
} }
/** /**
......
...@@ -570,7 +570,7 @@ class PageTitleFiltering extends DrupalWebTestCase { ...@@ -570,7 +570,7 @@ class PageTitleFiltering extends DrupalWebTestCase {
// Create the node with HTML in the title. // Create the node with HTML in the title.
$this->drupalPost('node/add/page', $edit, t('Save')); $this->drupalPost('node/add/page', $edit, t('Save'));
$node = node_load(array('title' => $edit['title'])); $node = $this->drupalGetNodeByTitle($edit['title']);
$this->assertNotNull($node, 'Node created and found in database'); $this->assertNotNull($node, 'Node created and found in database');
$this->drupalGet("node/" . $node->nid); $this->drupalGet("node/" . $node->nid);
$this->assertText(check_plain($edit['title']), 'Check to make sure tags in the node title are converted.'); $this->assertText(check_plain($edit['title']), 'Check to make sure tags in the node title are converted.');
......
...@@ -74,12 +74,21 @@ function hook_taxonomy_vocabulary_delete($vocabulary) { ...@@ -74,12 +74,21 @@ function hook_taxonomy_vocabulary_delete($vocabulary) {
* *
* Modules implementing this hook can act on the term object returned by * Modules implementing this hook can act on the term object returned by
* taxonomy_term_load(). * taxonomy_term_load().
* For performance reasons, information to be added to term objects should be
* loaded in a single query for all terms where possible.
* *
* @param $term * Since terms are stored and retrieved from cache during a page request, avoid
* A taxonomy term object. * altering properties provided by the {term_data} table, since this may
* affect the way results are loaded from cache in subsequent calls.
*
* @param $terms
* An array of term objects, indexed by tid.
*/ */
function hook_taxonomy_term_load($term) { function hook_taxonomy_term_load($terms) {
$term->synonyms = taxonomy_get_synonyms($term->tid); $result = db_query('SELECT tid, foo FROM {mytable} WHERE tid IN (' . db_placeholders(array_keys($terms)) . ')', array_keys($terms));
foreach ($result as $record) {
$terms[$record->tid]->foo = $record->foo;
}