2

I'm trying to delete all translations when deleting a node using default language?

For that purpose, I am using the hook_node_delete, but I am not able to invoke node_delete() from it. It cause a fatal error and the process can't terminate. Even the first node I am deleting isn't deleted preoperly.

 function hook_node_delete($node){
        $translation_list = translation_node_get_translations($node->tnid);
        $default_language = language_default()->language;

        if($translation_list!=""){
           foreach($translation_list as $translation_list_item){    
              if ($translation_list_item->language!=$default_language){
                  node_delete($translation_list_item->nid);
              }
           };
        };
    }

So I am forced to simply unpublish the translations by doing something like that:

 function hook_node_delete($node){
                $translation_list = translation_node_get_translations($node->tnid);
                $default_language = language_default()->language;

                if($translation_list!=""){
                   foreach($translation_list as $translation_list_item){    
                      if ($translation_list_item->language!=$default_language){
                          $node_translated = node_load($translation_list_item->nid);
                          $node_translated->status = 0;
                          node_save($node_translated);
                      }
                   };
                };
            }

Why can I not invoke node_delete() from hook_node_delete()??

3

you first have to remove the nodes from the translation set before you can delete them. So do something like this:

function hook_node_delete($node){
    $all = translation_node_get_translations($node->tnid);

    foreach($all as $del){
        if($node->nid != $del->nid){
            translation_remove_from_set(node_load($del->nid));
            node_delete($del->nid);
        }
    }
}
2

The answer provided by 118218 doesn't work for me because if you are deleting the source node (first node created of the translation set) the function translation_node_get_translations will return null, since the tnid of the other nodes of this translation set will be updated before the execution of hook_node_delete.

The solution for me was to overwrite the node/%node/delete menu item like this:

/**
 * Implements hook_menu_alter().
 */
function my_module_menu_alter(&$items)
{
    $items['node/%node/delete']['page arguments'] = array('my_module_custom_node_delete', 1);
    $items['node/%node/delete']['file path'] = drupal_get_path('module', 'my_module');
    $items['node/%node/delete']['file'] = 'my_module.module';
}

and then implement the delete confirmation form and submit function creating a callback before the node deletion like this:

function my_module_custom_node_delete($form, &$form_state, $node) {
    $form['#node'] = $node;
    // Always provide entity id in the same form key as in the entity edit form.
    $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
    return confirm_form($form,
        t('Are you sure you want to delete %title?', array('%title' => $node->title)),
        'node/' . $node->nid,
        t('This action cannot be undone.'),
        t('Delete'),
        t('Cancel')
    );
}

function my_module_custom_node_delete_submit($form, &$form_state) {
    if ($form_state['values']['confirm']) {
        $node = node_load($form_state['values']['nid']);
        drupal_alter('before_node_delete', clone $node);
        node_delete($form_state['values']['nid']);
        watchdog('content', '@type: deleted %title.', array('@type' => $node->type, '%title' => $node->title));
        drupal_set_message(t('@type %title has been deleted.', array('@type' => node_type_get_name($node), '%title' => $node->title)));
    }
    $form_state['redirect'] = '<front>';
}

implement the deletion of the other nodes:

function my_module_delete_child_nodes($node) {
    if($node->language == SOURCE_NODE_LANGUAGE) {
        $all = translation_node_get_translations($node->tnid);
        if(isset($all[SOURCE_NODE_LANGUAGE]))
            unset($all[SOURCE_NODE_LANGUAGE]);
        if(count($all) > 0) {
            $nids = array();
            foreach($all as $t) {
                $nids[] = $t->nid;
            }
            node_delete_multiple($nids);
        }
    }
}

and finally, you can call the deletion function from any module you want just implementing the hook MODULE_NAME_before_node_delete_alter($node)

/**
 * Implements hook_before_node_delete_alter().
 */
function MODULE_NAME_before_node_delete_alter($node)
{
        my_module_delete_child_nodes($node);
}
1

As "filipedelmonte" answer says, if the source node of the translation set is deleted, then the function translation_node_get_translations will return null since the tnid of the other nodes of the translation set will be updated before the execution of hook_node_delete. However, his approach is too complicated. So I improved "Gert van den buijs" answer to work in all cases. The idea is to preload the translation set in all nodes:

/**
 * Implements hook_node_load().
 */
function hook_node_load($nodes, $types) {
  if (!is_array($nodes)) {
    return;
  }
  foreach ($nodes as $node) {
    $node->translation_set = translation_node_get_translations($node->tnid);
  }
}

/**
 * Implements hook_node_delete().
 */
function hook_node_delete($node) {
  if (is_array($node->translation_set)) {
    foreach ($node->translation_set as $del) {
      if ($node->nid != $del->nid) {
        translation_remove_from_set(node_load($del->nid));
        node_delete($del->nid);
      }
    }
  }
}
0

The "Gert van den buijs" answer doesn't work for me. So I managed to do it by deleting the content directly with db_delete. I'm not sure it's the best way to do it but at least it works.

Like that, hook_node_delete isn't called recursively and the function can terminate properly.

function hook_node_delete($node){
   $all = translation_node_get_translations($node->tnid);
     unset($all[$node->language]);
     if(isset($all)){
            foreach($all as $del){
                    if($node->nid != $del->nid){
                        $nids[] = $del->nid; 
                            db_delete('node')
                                ->condition('nid', $nids, 'IN')
                                ->execute();
                            db_delete('node_revision')
                                ->condition('nid', $nids, 'IN')
                                ->execute();
                            db_delete('history')
                                ->condition('nid', $nids, 'IN')
                                ->execute();
                            db_delete('node_access')
                             ->condition('nid', $nids, 'IN')
                             ->execute();
                    }
            }
     }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.