Commit 87567f89 authored by Dries's avatar Dries

- Patch #310212 by justinrandell: killed in _node hook, as well as twelve sable tooth tigers.

parent 026af5df
......@@ -221,7 +221,7 @@ function blogapi_blogger_new_post($appkey, $blogid, $username, $password, $conte
$edit['date'] = format_date(REQUEST_TIME, 'custom', 'Y-m-d H:i:s O');
}
node_invoke_nodeapi($edit, 'blogapi new');
node_invoke_nodeapi($edit, 'blogapi_new');
node_validate($edit);
if ($errors = form_get_errors()) {
......@@ -273,7 +273,7 @@ function blogapi_blogger_edit_post($appkey, $postid, $username, $password, $cont
$node->body = $content;
}
node_invoke_nodeapi($node, 'blogapi edit');
node_invoke_nodeapi($node, 'blogapi_edit');
node_validate($node);
if ($errors = form_get_errors()) {
......
......@@ -668,110 +668,132 @@ function book_build_active_trail($book_link) {
}
/**
* Implementation of hook_nodeapi().
*
* Appends book navigation to all nodes in the book, and handles book outline
* insertions and updates via the node form.
* Implementation of hook_nodeapi_load().
*/
function book_nodeapi(&$node, $op, $teaser, $page) {
switch ($op) {
case 'load':
// Note - we cannot use book_link_load() because it will call node_load().
$info['book'] = db_fetch_array(db_query('SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid = %d', $node->nid));
function book_nodeapi_load(&$node, $teaser, $page) {
// Note - we cannot use book_link_load() because it will call node_load().
$info['book'] = db_fetch_array(db_query('SELECT * FROM {book} b INNER JOIN {menu_links} ml ON b.mlid = ml.mlid WHERE b.nid = %d', $node->nid));
if ($info['book']) {
$info['book']['href'] = $info['book']['link_path'];
$info['book']['title'] = $info['book']['link_title'];
$info['book']['options'] = unserialize($info['book']['options']);
return $info;
}
break;
if ($info['book']) {
$info['book']['href'] = $info['book']['link_path'];
$info['book']['title'] = $info['book']['link_title'];
$info['book']['options'] = unserialize($info['book']['options']);
case 'view':
if (!$teaser) {
if (!empty($node->book['bid']) && $node->build_mode == NODE_BUILD_NORMAL) {
$node->content['book_navigation'] = array(
'#markup' => theme('book_navigation', $node->book),
'#weight' => 100,
);
if ($page) {
menu_set_active_trail(book_build_active_trail($node->book));
menu_set_active_menu_name($node->book['menu_name']);
}
}
}
break;
return $info;
}
}
case 'presave':
// Always save a revision for non-administrators.
if (!empty($node->book['bid']) && !user_access('administer nodes')) {
$node->revision = 1;
}
// Make sure a new node gets a new menu link.
if (empty($node->nid)) {
$node->book['mlid'] = NULL;
}
break;
/**
* Implementation of hook_nodeapi_view().
*/
function book_nodeapi_view(&$node, $teaser, $page) {
if (!$teaser) {
if (!empty($node->book['bid']) && $node->build_mode == NODE_BUILD_NORMAL) {
$node->content['book_navigation'] = array(
'#markup' => theme('book_navigation', $node->book),
'#weight' => 100,
);
case 'insert':
case 'update':
if (!empty($node->book['bid'])) {
if ($node->book['bid'] == 'new') {
// New nodes that are their own book.
$node->book['bid'] = $node->nid;
}
$node->book['nid'] = $node->nid;
$node->book['menu_name'] = book_menu_name($node->book['bid']);
_book_update_outline($node);
if ($page) {
menu_set_active_trail(book_build_active_trail($node->book));
menu_set_active_menu_name($node->book['menu_name']);
}
break;
}
}
}
case 'delete':
if (!empty($node->book['bid'])) {
if ($node->nid == $node->book['bid']) {
// Handle deletion of a top-level post.
$result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = %d", $node->book['mlid']);
while ($child = db_fetch_array($result)) {
$child_node = node_load($child['nid']);
$child_node->book['bid'] = $child_node->nid;
_book_update_outline($child_node);
}
}
menu_link_delete($node->book['mlid']);
db_query('DELETE FROM {book} WHERE mlid = %d', $node->book['mlid']);
}
break;
/**
* Implementation of hook_nodeapi_presave().
*/
function book_nodeapi_presave(&$node, $teaser, $page) {
// Always save a revision for non-administrators.
if (!empty($node->book['bid']) && !user_access('administer nodes')) {
$node->revision = 1;
}
// Make sure a new node gets a new menu link.
if (empty($node->nid)) {
$node->book['mlid'] = NULL;
}
}
case 'prepare':
// Prepare defaults for the add/edit form.
if (empty($node->book) && (user_access('add content to books') || user_access('administer book outlines'))) {
$node->book = array();
/**
* Implementation of hook_nodeapi_insert().
*/
function book_nodeapi_insert(&$node, $teaser, $page) {
if (!empty($node->book['bid'])) {
if ($node->book['bid'] == 'new') {
// New nodes that are their own book.
$node->book['bid'] = $node->nid;
}
$node->book['nid'] = $node->nid;
$node->book['menu_name'] = book_menu_name($node->book['bid']);
_book_update_outline($node);
}
}
if (empty($node->nid) && isset($_GET['parent']) && is_numeric($_GET['parent'])) {
// Handle "Add child page" links:
$parent = book_link_load($_GET['parent']);
/**
* Implementation of hook_nodeapi_update().
*/
function book_nodeapi_update(&$node, $teaser, $page) {
if (!empty($node->book['bid'])) {
if ($node->book['bid'] == 'new') {
// New nodes that are their own book.
$node->book['bid'] = $node->nid;
}
$node->book['nid'] = $node->nid;
$node->book['menu_name'] = book_menu_name($node->book['bid']);
_book_update_outline($node);
}
}
if ($parent && $parent['access']) {
$node->book['bid'] = $parent['bid'];
$node->book['plid'] = $parent['mlid'];
$node->book['menu_name'] = $parent['menu_name'];
}
}
// Set defaults.
$node->book += _book_link_defaults(!empty($node->nid) ? $node->nid : 'new');
}
else {
if (isset($node->book['bid']) && !isset($node->book['original_bid'])) {
$node->book['original_bid'] = $node->book['bid'];
}
/**
* Implementation of hook_nodeapi_delete().
*/
function book_nodeapi_delete(&$node, $teaser, $page) {
if (!empty($node->book['bid'])) {
if ($node->nid == $node->book['bid']) {
// Handle deletion of a top-level post.
$result = db_query("SELECT b.nid FROM {menu_links} ml INNER JOIN {book} b on b.mlid = ml.mlid WHERE ml.plid = %d", $node->book['mlid']);
while ($child = db_fetch_array($result)) {
$child_node = node_load($child['nid']);
$child_node->book['bid'] = $child_node->nid;
_book_update_outline($child_node);
}
// Find the depth limit for the parent select.
if (isset($node->book['bid']) && !isset($node->book['parent_depth_limit'])) {
$node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book);
}
menu_link_delete($node->book['mlid']);
db_query('DELETE FROM {book} WHERE mlid = %d', $node->book['mlid']);
}
}
/**
* Implementation of hook_nodeapi_prepare().
*/
function book_nodeapi_prepare(&$node, $teaser, $page) {
// Prepare defaults for the add/edit form.
if (empty($node->book) && (user_access('add content to books') || user_access('administer book outlines'))) {
$node->book = array();
if (empty($node->nid) && isset($_GET['parent']) && is_numeric($_GET['parent'])) {
// Handle "Add child page" links:
$parent = book_link_load($_GET['parent']);
if ($parent && $parent['access']) {
$node->book['bid'] = $parent['bid'];
$node->book['plid'] = $parent['mlid'];
$node->book['menu_name'] = $parent['menu_name'];
}
break;
}
// Set defaults.
$node->book += _book_link_defaults(!empty($node->nid) ? $node->nid : 'new');
}
else {
if (isset($node->book['bid']) && !isset($node->book['original_bid'])) {
$node->book['original_bid'] = $node->book['bid'];
}
}
// Find the depth limit for the parent select.
if (isset($node->book['bid']) && !isset($node->book['parent_depth_limit'])) {
$node->book['parent_depth_limit'] = _book_parent_depth_limit($node->book);
}
}
......
......@@ -552,50 +552,68 @@ function comment_form_alter(&$form, $form_state, $form_id) {
}
/**
* Implementation of hook_nodeapi().
* Implementation of hook_nodeapi_load().
*/
function comment_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'load':
if ($node->comment != COMMENT_NODE_DISABLED) {
return db_fetch_array(db_query("SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = %d", $node->nid));
}
return array('last_comment_timestamp' => $node->created, 'last_comment_name' => '', 'comment_count' => 0);
function comment_nodeapi_load(&$node, $arg = 0) {
if ($node->comment != COMMENT_NODE_DISABLED) {
return db_fetch_array(db_query("SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = %d", $node->nid));
}
return array('last_comment_timestamp' => $node->created, 'last_comment_name' => '', 'comment_count' => 0);
}
case 'prepare':
if (!isset($node->comment)) {
$node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
}
break;
/**
* Implementation of hook_nodeapi_prepare().
*/
function comment_nodeapi_prepare(&$node, $arg = 0) {
if (!isset($node->comment)) {
$node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
}
}
case 'insert':
db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid);
break;
/**
* Implementation of hook_nodeapi_insert().
*/
function comment_nodeapi_insert(&$node, $arg = 0) {
db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid);
}
case 'delete':
db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
break;
/**
* Implementation of hook_nodeapi_delete().
*/
function comment_nodeapi_delete(&$node, $arg = 0) {
db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
}
case 'update index':
$text = '';
$comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED);
while ($comment = db_fetch_object($comments)) {
$text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, FALSE);
}
return $text;
/**
* Implementation of hook_nodeapi_update_index().
*/
function comment_nodeapi_update_index(&$node, $arg = 0) {
$text = '';
$comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED);
while ($comment = db_fetch_object($comments)) {
$text .= '<h2>' . check_plain($comment->subject) . '</h2>' . check_markup($comment->comment, $comment->format, FALSE);
}
return $text;
}
case 'search result':
$comments = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $node->nid));
return format_plural($comments, '1 comment', '@count comments');
/**
* Implementation of hook_nodeapi_search_result().
*/
function comment_nodeapi_search_result(&$node, $arg = 0) {
$comments = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $node->nid));
return format_plural($comments, '1 comment', '@count comments');
}
case 'rss item':
if ($node->comment != COMMENT_NODE_DISABLED) {
return array(array('key' => 'comments', 'value' => url('node/' . $node->nid, array('fragment' => 'comments', 'absolute' => TRUE))));
}
else {
return array();
}
/**
* Implementation of hook_nodeapi_rss_item().
*/
function comment_nodeapi_rss_item(&$node, $arg = 0) {
if ($node->comment != COMMENT_NODE_DISABLED) {
return array(array('key' => 'comments', 'value' => url('node/' . $node->nid, array('fragment' => 'comments', 'absolute' => TRUE))));
}
else {
return array();
}
}
......
......@@ -156,133 +156,197 @@ function forum_init() {
}
/**
* Implementation of hook_nodeapi().
* _forum_nodeapi_check_node_type
*
* @param mixed $node
* @param mixed $vocabulary
* @access protected
* @return bool
*/
function forum_nodeapi(&$node, $op, $teaser, $page) {
function _forum_nodeapi_check_node_type($node, $vocabulary) {
// We are going to return if $node->type is not one of the node
// types assigned to the forum vocabulary. If forum_nav_vocabulary
// is undefined or the vocabulary does not exist, it clearly cannot
// be assigned to $node->type, so return to avoid E_ALL warnings.
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (empty($vocabulary)) {
return;
return FALSE;
}
// Operate only on node types assigned for the forum vocabulary.
if (!in_array($node->type, $vocabulary->nodes)) {
return;
return FALSE;
}
switch ($op) {
case 'view':
if ($page && taxonomy_node_get_terms_by_vocabulary($node, $vid) && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id => $term) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
}
}
// Breadcrumb navigation
$breadcrumb[] = l(t('Home'), NULL);
$breadcrumb[] = l($vocabulary->name, 'forum');
if ($parents = taxonomy_get_parents_all($node->tid)) {
$parents = array_reverse($parents);
foreach ($parents as $p) {
$breadcrumb[] = l($p->name, 'forum/' . $p->tid);
}
}
drupal_set_breadcrumb($breadcrumb);
return TRUE;
}
if (!$teaser) {
$node->content['forum_navigation'] = array(
'#markup' => theme('forum_topic_navigation', $node),
'#weight' => 100,
);
/**
* Implementation of hook_nodeapi_view().
*/
function forum_nodeapi_view(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
if ($page && taxonomy_node_get_terms_by_vocabulary($node, $vid) && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id => $term) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
}
}
break;
case 'prepare':
if (empty($node->nid)) {
// New topic
$node->taxonomy[arg(3)]->vid = $vid;
$node->taxonomy[arg(3)]->tid = arg(3);
// Breadcrumb navigation
$breadcrumb[] = l(t('Home'), NULL);
$breadcrumb[] = l($vocabulary->name, 'forum');
if ($parents = taxonomy_get_parents_all($node->tid)) {
$parents = array_reverse($parents);
foreach ($parents as $p) {
$breadcrumb[] = l($p->name, 'forum/' . $p->tid);
}
}
break;
drupal_set_breadcrumb($breadcrumb);
// Check in particular that only a "leaf" term in the associated taxonomy
// vocabulary is selected, not a "container" term.
case 'validate':
if ($node->taxonomy) {
// Extract the node's proper topic ID.
$vocabulary = $vid;
$containers = variable_get('forum_containers', array());
foreach ($node->taxonomy as $term) {
if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
if (in_array($term, $containers)) {
$term = taxonomy_term_load($term);
form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name)));
}
}
}
if (!$teaser) {
$node->content['forum_navigation'] = array(
'#markup' => theme('forum_topic_navigation', $node),
'#weight' => 100,
);
}
break;
}
}
}
// Assign forum taxonomy when adding a topic from within a forum.
case 'presave':
// Make sure all fields are set properly:
$node->icon = !empty($node->icon) ? $node->icon : '';
/**
* Implementation of hook_nodeapi_prepare().
*/
function forum_nodeapi_prepare(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
if (empty($node->nid)) {
// New topic
$node->taxonomy[arg(3)]->vid = $vid;
$node->taxonomy[arg(3)]->tid = arg(3);
}
}
}
if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree if we have a taxonomy.
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
/**
* Implementation of hook_nodeapi_validate().
*
* Check in particular that only a "leaf" term in the associated taxonomy.
*/
function forum_nodeapi_validate(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
// vocabulary is selected, not a "container" term.
if ($node->taxonomy) {
// Extract the node's proper topic ID.
$vocabulary = $vid;
$containers = variable_get('forum_containers', array());
foreach ($node->taxonomy as $term) {
if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
if (in_array($term, $containers)) {
$term = taxonomy_term_load($term);
form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name)));
}
}
$old_tid = db_result(db_query_range("SELECT t.tid FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.nid = %d ORDER BY t.vid DESC", $node->nid, 0, 1));
if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) {
// A shadow copy needs to be created. Retain new term and add old term.
$node->taxonomy[] = $old_tid;
}
}
break;
}
}
}
case 'update':
if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) {
if (!empty($node->tid)) {
db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid);
}
// The node is removed from the forum.
else {
db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
/**
* Implementation of hook_nodeapi_presave().
*
* Assign forum taxonomy when adding a topic from within a forum.
*/
function forum_nodeapi_presave(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
// Make sure all fields are set properly:
$node->icon = !empty($node->icon) ? $node->icon : '';
if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree if we have a taxonomy.
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
}
break;
}
// Deliberate no break -- for new revisions and for previously unassigned terms we need an insert.
$old_tid = db_result(db_query_range("SELECT t.tid FROM {term_node} t INNER JOIN {node} n ON t.vid = n.vid WHERE n.nid = %d ORDER BY t.vid DESC", $node->nid, 0, 1));
if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) {
// A shadow copy needs to be created. Retain new term and add old term.
$node->taxonomy[] = $old_tid;
}
}
}
}
case 'insert':
/**
* Implementation of hook_nodeapi_update().
*/
function forum_nodeapi_update(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
if (empty($node->revision) && db_result(db_query('SELECT tid FROM {forum} WHERE nid=%d', $node->nid))) {
if (!empty($node->tid)) {
db_query('UPDATE {forum} SET tid = %d WHERE vid = %d', $node->tid, $node->vid);
}
// The node is removed from the forum.
else {
db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
}
}
else {
if (!empty($node->tid)) {
db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid);
}
break;
}
}
}
case 'delete':
db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
break;
/**
* Implementation of hook_nodeapi_insert().
*/
function forum_nodeapi_insert(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
if (!empty($node->tid)) {
db_query('INSERT INTO {forum} (tid, vid, nid) VALUES (%d, %d, %d)', $node->tid, $node->vid, $node->nid);
}
}
}
case 'load':
return db_fetch_array(db_query('SELECT tid AS forum_tid FROM {forum} WHERE vid = %d', $node->vid));
/**
* Implementation of hook_nodeapi_delete().
*/
function forum_nodeapi_delete(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_nodeapi_check_node_type($node, $vocabulary)) {
db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
}
}
return;
/**
* Implementation of hook_nodeapi_load().
*/
function forum_nodeapi_load(&$node, $teaser, $page) {
$vid = variable_get('forum_nav_vocabulary', '');
$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));
}
}
/**
......
......@@ -277,65 +277,90 @@ function menu_block($op = 'list', $delta = '') {
}
/**
* Implementation of hook_nodeapi().
* Implementation of hook_nodeapi_insert().
*/
function menu_nodeapi(&$node, $op) {
switch ($op) {
case 'insert':
case 'update':
if (isset($node->menu)) {
$item = $node->menu;
if (!empty($item['delete'])) {
menu_link_delete($item['mlid']);
}
elseif (trim($item['link_title'])) {
$item['link_title'] = trim(