【问题标题】:Hook called before to delete a node删除节点之前调用的钩子
【发布时间】:2010-07-25 11:01:43
【问题描述】:

我正在编写一个自定义模块,我想在删除节点之前做一些检查。是否有一个钩子会在节点被删除之前触发?有没有办法以某种方式防止删除?顺便说一句,我正在使用 drupal6

【问题讨论】:

    标签: drupal drupal-6 hook drupal-modules


    【解决方案1】:

    您可以使用 hook_menu_alter 将菜单回调 node/%node/delete 指向您自己的函数。您的函数可以执行您想要的任何检查,然后在检查通过时显示node_delete_confirm 表单。

    【讨论】:

    • 它适用于我的情况,因为它是一个封闭系统,但它存在安全漏洞,但对我的情况无关紧要。
    • 这不会保护节点不被使用视图批量操作删除。
    【解决方案2】:

    这将删除删除按钮并添加您自己的按钮和操作。这不会阻止用户使用 URL /node/[nid]/delete 删除节点,请使用权限设置。

    function my_module_form_alter(&$form, &$form_state, $form_id) {
      if($form_id == "allocation_node_form") {
        if (isset($form['#node']->nid))  {
                $form['buttons']['my_remove'] = array(
                                            '#type' => 'submit',
                                            '#value' => 'Remove',
                                            '#weight' => 15,
                                            '#submit' => array('allocation_remove_submit'),
                                            );
    
                if($user->uid != 1) {
                  unset($form['buttons']['delete']);
                  $form['buttons']['#suffix'] = "<br>".t("<b>Remove</b> will...");
                }else{
                  $form['buttons']['#suffix'] = t("<b>Delete</b> only if ...");
                }
            }
      }
    
    }
    
    
    function allocation_remove_submit($form, &$form_state) {
        if (is_numeric($form_state['values']['field_a_team'][0]['nid'])) {
            //my actions
    
            //Clear forms cache
            $cid = 'content:'. $form_state['values']['nid'].':'. $form_state['values']['vid'];
            cache_clear_all($cid, 'cache_content', TRUE);
    
            //Redirect
            drupal_goto("node/".$form_state['values']['field_a_team'][0]['nid']);        
        }else{
            drupal_set_message(t("Need all values to be set"), "warning");
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用hook_nodeapi op 删除。

      尝试停止删除节点可能是个坏主意,因为您不知道其他模块做了什么,例如删除 cck 字段值等。

      在删除节点之前,没有可用于执行操作的挂钩。以上是你能来的最接近的。

      【讨论】:

      • 重点是我希望在节点上发生任何删除“之前”访问。我很清楚这个钩子,但据我所知并没有帮助我
      【解决方案4】:

      如果满足您的条件,请使用 form_alter 并删除删除按钮。 像这样的。

      function xxx_contact_form_alter(&$form, $form_state, $form_id) {
        global $user;
      
        if (strstr($form_id, 'xxx_node_form')) {
          // Stop deletion of xxx users unless you are an admin
          if (($form['#node']->uid) == 0 && ($user->uid != 1)) {
            unset($form['actions']['delete']);
          }
        }
      }
      

      【讨论】:

        【解决方案5】:

        此自定义模块代码适用于 Drupal 7,但我确信类似的概念也适用于 Drupal 6。此外,到目前为止,您很可能正在寻找 Drupal 7 的解决方案。

        此代码将在删除节点“之前”运行,因此您可以运行所需的检查,然后可选择隐藏删除按钮以防止节点被删除。查看函数的 cmets 了解更多信息。

        这是展示最终结果的屏幕截图:

        这是使用的自定义代码:

        <?php
        
        /**
         * Implements hook_form_FORM_ID_alter() to conditionally prevent node deletion.
         * 
         * We check if the current node has child menu items and, if yes, we prevent
         * this node's deletion and also show a message explaining the situation and 
         * links to the child nodes so that the user can easily delete them first
         * or move them to another parent menu item.
         * 
         * This can be useful in many cases especially if you count on the paths of 
         * the child items being derived from their parent item path, for example.
         */
        function sk_form_node_delete_confirm_alter(&$form, $form_state) {
            //Check if we have a node id and stop if not
            if(empty($form['nid']['#value'])) {
                return;
            }
        
            //Load the node from the form
            $node = node_load($form['nid']['#value']);
        
            //Check if node properly loaded and stop if not
            //Empty checks for both $node being not empty and also for its property nid
            if(empty($node->nid)) {
                return;
            }
        
            //Get child menu items array for this node
            $children_nids = sk_get_all_menu_node_children_ids('node/' . $node->nid);
            $children_count = count($children_nids);
        
            //If we have children, do set a warning and disable delete button and such
            //so that this node cannot be deleted by the user.
            //Note: we are not 100% that this prevents the user from deleting it through
            //views bulk operations for example or by faking a post request, but for our
            //needs, this is adequate as we trust the editors on our websites.
            if(!empty($children_nids)) {
                //Construct explanatory message
                $msg = '';
        
                $t1 = '';
                $t1 .= '%title is part of a menu and has %count child menu items. ';
                $t1 .= 'If you delete it, the URL paths of its children will no longer work.';
                $msg .= '<p>';
                $msg .= t($t1, array('%title' => $node->title, '%count' => $children_count));
                $msg .= '</p>';
        
                $t2 = 'Please check the %count child menu items below and delete them first.';
                $msg .= '<p>';
                $msg .= t($t2, array('%count' => $children_count));
                $msg .= '</p>';
        
                $msg .= '<ol>';        
                $children_nodes = node_load_multiple($children_nids);
                if(!empty($children_nodes)) {
                    foreach($children_nodes as $child_node) {
                        if(!empty($child_node->nid)) {
                            $msg .= '<li>';
                            $msg .= '<a href="' . url('node/' . $child_node->nid) . '">';
                            $msg .= $child_node->title;
                            $msg .= '</a>';
                            $msg .= '</li>';
                        }
                    }
                }
                $msg .= '</ol>';
        
                //Set explanatory message
                $form['sk_children_exist_warning'] = array(
                    '#markup' => $msg,
                    '#weight' => -10,
                );
        
                //Remove the 'This action cannot be undone' message
                unset($form['description']);
        
                //Remove the delete button
                unset($form['actions']['submit']);
            }
        }
        

        有关更多信息,请查看有关 conditionally preventing node deletion in Drupal 7 的详细博客文章。它包含有关整个过程的详细信息以及资源链接,包括如何轻松创建自定义模块,您可以在其中复制/粘贴上述代码以使其正常工作。

        祝你好运。

        【讨论】:

          【解决方案6】:

          在删除节点之前不会调用挂钩,但 Drupal 会检查 node_access 以查看是否允许用户在继续删除之前删除节点。

          您可以将节点访问权限设置为不允许用户删除节点:如果用户是用户 1 或具有管理节点权限,这将无济于事,因此不要将这些权限授予不受信任的用户(即删除节点的人)。这也是 Drupal 防止无故删除节点的方式。

          【讨论】:

            【解决方案7】:

            如果 op == delete,您可以使用 hook_access 和 put 条件。如果您的条件已满,则返回 True,否则返回 false。如果为 false,您的节点将不会被删除。

            请记住,管理员不会触发此操作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-12-25
              • 1970-01-01
              • 2011-02-09
              • 1970-01-01
              • 2013-11-09
              • 1970-01-01
              相关资源
              最近更新 更多