I have a number of children nodes that are associated to a parent node by using node reference in CCK. I would like to auto delete all of the children nodes when its parent is deleted.

That's my end goal but I can't even seem to solve deleting all nodes of a certain type (my children nodes) when its author has deleted the parent node.

Here's what I have:


function MYMODULE_nodeapi(&$node, $op) {
  if ($node->type =='parent_node_type' && $op=='delete') {

  db_query("DELETE * from {node} where type='children_node_type' AND uid=%d",$node->uid);

}

This does not seem to work however. What am I doing wrong?
Thanks for any help with this.

Comments

nevets’s picture

First off you need call node_delete(), nodes use more than one table.

So you need a list of nodes that refer to the parent.

You could use a node referrer field in the parent, in this case you could use that field to find the children.

Otherwise you will need to know which table the node reference field is in and find all rows where the field references the parent.

fallsemo’s picture

Thanks nevets!

I looked at node_delete and reworked a snippet of code to solve my issue.
It now looks like this


function MYMODULE_nodeapi(&$node, $op) {
    
  if ($node->type =='parent_node_type' && $op=='delete') {
  
    // Delete all the "Add to Tracker" Nodes attached to the author deleting this Weight Tracker
    $attQuery = db_query("SELECT n.nid FROM {node} n WHERE n.type = 'child_node_type' AND n.uid = $node->uid");
    $deleted_count = 0;
    
    //While loop to delete them
    while ($n = db_fetch_object($attQuery)) {
      set_time_limit(5);
      node_delete($n->nid);
      $deleted_count += 1;
    }
  }
}

nevets’s picture

A couple of comments

1) Unless a user can only have one node of type parent_node_type using n.uid = $node->uid could delete more nodes than you expect. (It deletes all nodes of type child_node_type belonging the the parents owner, not just the ones associated with the parent.

2) set_time_limit(5); could lead to problems. I realize the purpose is to avoid a timeout if lots of children, but there is likely code that runs after your function and its constrained by the last call to set_time_limit(5). You may want to add a set_time_limit(30) after the while loop to be safe.

fallsemo’s picture

Thanks for the comments

Regarding 1) In my case a user has access to create only one parent node - so it works.

I will do add set_time_limit(30) after the while loop. Thanks for that!

tajindersingh’s picture

The hook_nodeapi code will fail in case user deleting the referred node [e.g. Article] doesn't have delete access on referring node [e.g. Article Review] as node_delete function first checks for node_access('delete', $node);

The other solution is to set referring node's referred nid field [e.g. content_type_journax_response] to NULL as below on delete:

function mymodule_nodeapi(&$node, $op, $params = NULL, $page = NULL) {
  switch ($op) {
    case 'delete':
      if ($node->type == 'article') {
        db_query("UPDATE {content_type_review} SET field_review_for_nid = NULL WHERE field_review_for_nid  = %d", $node->nid);
      }
    break;
  }
}

Then further using hook_cron, delete all the referring nodes [Reviews] having referred nid [Article NID] as NULL.

function mymodule_cron() {
  $orphan_reviews = db_query("SELECT nid FROM {content_type_review} WHERE field_review_for_nid IS NULL");
  
  while ($orphan_review = db_fetch_object($orphan_reviews)) {
    node_delete($orphan_review->nid);
  }
}

Best Regards,

Tajinder Singh Namdhari
https://TajinderSinghNamdhari.com

mhtran’s picture

Hi i'm new in Drupal. I want to make a similar functionality for the website of my school, but i don't know where i can use that code.
I create content type with CCK and using node reference (like you).