Why does phpbb_handle_post_delete run twice?

Discussion forum for Extension Writers regarding Extension Development.
Post Reply
User avatar
Toxyy
Registered User
Posts: 938
Joined: Mon Oct 24, 2016 3:22 pm
Location: Namek
Contact:

Why does phpbb_handle_post_delete run twice?

Post by Toxyy »

So I'm fixing up deletion for my nested comments, and I've come across a pretty weird error. It seems when I delete a comment, it wants to run phpbb_handle_post_delete twice. In the event handle_post_delete_conditions, I say "if this post has a parent id, decrement it's total comment count by 1". Well, it decrements it. Twice. Very strange. I can't find anywhere else in the codebase where this should run more than once, but it does.

I would decrement the total comment count in the event delete_post_after, but I can't get the parent_id form the post_id's row as it's already been deleted. I just made a couple of pull requests and I'd rather not have to make another one for an event like delete_post_before, as then I'd have to decrement each parent's total comment count by 1, even if I'm deleting a ton of nested comments, and that's inefficient.

I could get around this by making 2 = 1, 3 = 2, etc for the total comment count but that seems like a silly workaround. I must be missing something here?
I am a web developer/administrator, specializing in forums. If you have work you need done or are too lazy to do, pm me!

Some of my extensions:
[3.3][BETA] Post Form Templates || [3.3][BETA] Anonymous Posts || [3.2][3.3][BETA] ACP Merge Child Forums || [3.2][BETA] Sticky Ad || [3.2][DEV] User Delete Topics || [3.3][DEV] Moderate While Searching || [3.3][RC] Short Number Twig Extension
User avatar
Ger
Registered User
Posts: 2107
Joined: Wed Jan 02, 2008 7:35 pm
Location: 192.168.1.100
Contact:

Re: Why does phpbb_handle_post_delete run twice?

Post by Ger »

You have some code to look at?
My extensions:
Simple CMS, Feed post bot, Avatar Resize, Modbreak, Magic OGP, Live topic update, Modern Quote, Quoted Where (GDPR) and Autoresponder.
Newest: FAQ manager for 3.2

Like my work? Buy me a coffee to keep it coming. :ugeek:

-Don't PM me for support-
User avatar
Toxyy
Registered User
Posts: 938
Joined: Mon Oct 24, 2016 3:22 pm
Location: Namek
Contact:

Re: Why does phpbb_handle_post_delete run twice?

Post by Toxyy »

Ger wrote: Tue Jul 17, 2018 7:07 am You have some code to look at?
Here you go:

Code: Select all

        // adjust parent comment count and topic posts approved if deleted post is a comment
        public function handle_post_delete_conditions(event $event)
        {
                $post_id = $event['post_id'];
                $topic_id = $event['topic_id'];
                $post_data = $event['post_data'];
                $parent_id = $post_data['parent_id'];
                
                // for some reason comments run this event twice, this failed attempt makes sure that on the second time we don't update the tables
                $select_from_closure = 'SELECT parent_id FROM ' . POSTS_TABLE . '
                                        WHERE post_id = ' . $post_id;

                $result = $parent_checker = array();
                $result = $this->db->sql_query($select_from_closure);

                while($row = $this->db->sql_fetchrow($result))
                {
                        $parent_checker = $row['parent_id'];
                }
                unset($result);
            
                if(($parent_id == $parent_checker) && $parent_id > 0)
                {       // decrement parent's comment count by 1
                        $parent_count_query = 'UPDATE ' . POSTS_TABLE . '
                                                SET post_comments = post_comments - 1
                                                WHERE post_id = ' . $parent_id;
                        $result = array();
                        $result = $this->db->sql_query($parent_count_query);
                        unset($result);
                        
                        $posts_approved_query = 'UPDATE ' . TOPICS_TABLE . '
                                                SET topic_posts_approved = topic_posts_approved + 1
                                                WHERE topic_id = ' . $topic_id;
                        $result = array();
                        $result = $this->db->sql_query($posts_approved_query);
                        unset($result);
                }
        }
        
        // delete nested posts when parent post is being deleted
        // adapted some from functions_posting.php if statemant at line 1406
        public function delete_post_after(event $event)
        {
                $data = $event['data'];
                $is_soft = $event['is_soft'];
                $post_id = $event['post_id'];
                $topic_id = $event['topic_id'];
                $forum_id = $event['forum_id'];
                $next_post_id = $event['next_post_id'];
                $softdelete_reason = $event['softdelete_reason'];
                
                // only way to transfer info from the recursive call I made in this event
                if(strlen($softdelete_reason) > 10)
                {
                        $delete_runner = substr($softdelete_reason, -10);
                        
                        // not sure how much use this is
                        $softdelete_reason = substr($softdelete_reason, 0, -10);
                }
                
                // delete_runner is an attempt to not have this if block ran on comments as the parent's call to this event is going to take care of all of this
                if(!$is_soft && $delete_runner != "DO~NOT~RUN")
                {       // get post ids of every post that will be deleted except this post
                        $select_from_closure = 'SELECT child_id FROM phpbb_posts_kinship
                                                WHERE child_id IN
                                                (       SELECT child_id
                                                        FROM phpbb_posts_kinship
                                                        WHERE ancestor_id = ' . $post_id . '
                                                        AND child_id != ' . $post_id . '
                                                )';

                        $result = $post_list = array();
                        $result = $this->db->sql_query($select_from_closure);
                        
                        while($row = $this->db->sql_fetchrow($result))
                        {
                                $post_list[] = $row['child_id'];
                        }
                        unset($result);
                        
                        $delete_from_closure = 'DELETE FROM phpbb_posts_kinship
                                                WHERE child_id IN
                                                (       SELECT * FROM
                                                        (       SELECT child_id
                                                                FROM phpbb_posts_kinship
                                                                WHERE ancestor_id = ' . $post_id . '
                                                        ) AS tmp
                                                )';
                        $result = array();
                        $result = $this->db->sql_query($delete_from_closure);
                        unset($result);
                        
                        // remove repeats, more efficient than array_unique (used to be array_flip(array_flip()) but that gave warnings)
                        $post_list = array_unique($post_list);
                        
                        $comment_count = count($post_list);
                        
                        // so the post we're deleting has comments...
                        if($comment_count > 0)
                        {
                                $post_data_query = 'SELECT post_visibility, post_reported, post_time, poster_id, post_postcount
                                                    FROM ' . POSTS_TABLE . '
                                                    WHERE post_id IN (' . implode(',', $post_list) . ')';

                                $result = $post_data = array();
                                $result = $this->db->sql_query($post_data_query);

                                while($row = $this->db->sql_fetchrow($result))
                                {
                                        $post_data['post_visibility'][] = $row['post_visibility'];
                                        $post_data['post_reported'][] = $row['post_reported'];
                                        $post_data['post_time'][] = $row['post_time'];
                                        $post_data['poster_id'][] = $row['poster_id'];
                                        $post_data['post_postcount'][] = $row['post_postcount'];
                                }
                                unset($result);
                                
                                // add the number of comments we're about to delete to topic_posts_approved since delete_post decrements it
                                $posts_approved_query = 'UPDATE ' . TOPICS_TABLE . '
                                                        SET topic_posts_approved = topic_posts_approved + ' . $comment_count . '
                                                        WHERE topic_id = ' . $topic_id;
                                $result = array();
                                $result = $this->db->sql_query($posts_approved_query);
                                unset($result);
                                
                                for($i = 0; $i < $comment_count; $i++)
                                {
                                        $data['post_visibility'] = $post_data['post_visibility'][$i];
                                        $data['post_reported'] = $post_data['post_reported'][$i];
                                        $data['post_time'] = $post_data['post_time'][$i];
                                        $data['poster_id'] = $post_data['poster_id'][$i];
                                        $data['post_postcount'] = $post_data['post_postcount'][$i];
                                        
                                        $next_post_id = delete_post($forum_id, $topic_id, $post_list[$i], $data, false, "~DO~NOT~RUN");
                                }
                        }
                }
                
                $event['data'] = $data;
                $event['next_post_id'] = $next_post_id;
                $event['softdelete_reason'] = $softdelete_reason;
        }
I am a web developer/administrator, specializing in forums. If you have work you need done or are too lazy to do, pm me!

Some of my extensions:
[3.3][BETA] Post Form Templates || [3.3][BETA] Anonymous Posts || [3.2][3.3][BETA] ACP Merge Child Forums || [3.2][BETA] Sticky Ad || [3.2][DEV] User Delete Topics || [3.3][DEV] Moderate While Searching || [3.3][RC] Short Number Twig Extension
User avatar
Kailey
Community Team Leader
Community Team Leader
Posts: 3726
Joined: Mon Sep 01, 2014 1:00 am
Location: sudo rm -rf /
Name: Kailey Snay
Contact:

Re: Why does phpbb_handle_post_delete run twice?

Post by Kailey »

Probably not your issue, but event $event should be just $event.
Kailey Snay - Community Team Leader
Knowledge Base | Documentation | Community rules

If you have any questions about the rules/customs of this website, feel free to send me a PM.
User avatar
Ger
Registered User
Posts: 2107
Joined: Wed Jan 02, 2008 7:35 pm
Location: 192.168.1.100
Contact:

Re: Why does phpbb_handle_post_delete run twice?

Post by Ger »

You are calling delete_post in delete_post_after.
My extensions:
Simple CMS, Feed post bot, Avatar Resize, Modbreak, Magic OGP, Live topic update, Modern Quote, Quoted Where (GDPR) and Autoresponder.
Newest: FAQ manager for 3.2

Like my work? Buy me a coffee to keep it coming. :ugeek:

-Don't PM me for support-
User avatar
Toxyy
Registered User
Posts: 938
Joined: Mon Oct 24, 2016 3:22 pm
Location: Namek
Contact:

Re: Why does phpbb_handle_post_delete run twice?

Post by Toxyy »

Ger wrote: Thu Jul 19, 2018 6:53 am You are calling delete_post in delete_post_after.
I'm making an extension that allows you to make nested comments, think reddit. For permanently deleting posts, I want to remove parent P's whole comment tree, which I have to recursively call delete_post with on all of it's comment's post ids excluding the current post id, $post_list. I get parent P's whole comment tree list from the query $select_from_closure and store it in $post_list.

I filter $post_list for duplicates using array_unique, I was using array_flip_flip($post_list)) and it worked fine and benchmarks say it is a lot faster, but I was getting warnings that it has to be used with arrays of ints or strings, which they should be, but I decided to leave that be for now.

From this updated list, I count it and add that number to the topic approved posts count (as delete_post decrements it, and I don't count comments towards a thread's post total). Then I call delete_post on all of those post_ids. Haven't gotten around to making unapproved posts or anything compatible yet.

Everything works as intended so far, except the event handle_post_delete_conditions is called twice. I can tell because if the post I'm deleting is a comment itself, I decrement its parent's total comment count by 1. But if this post has comments itself, it runs the event twice for the original post_id that you're permanently deleting. I thought, if I pull the parent id from the posts table for the second call and check for it, it wouldn't matter. You can see my attempt at this in the code I provided. But it seems the event is called twice BEFORE the original parent_id is deleted.

/phpbb/posting.php - it is referenced twice in this file, but either one of the calls is failing, or they run so fast one after another that the first hasn't gotten to delete_post yet, or I'm wrong and have no idea.
kinerity wrote: Thu Jul 19, 2018 6:40 am Probably not your issue, but event $event should be just $event.
I saw it that way in some other extension, thank you for the tip :)
I am a web developer/administrator, specializing in forums. If you have work you need done or are too lazy to do, pm me!

Some of my extensions:
[3.3][BETA] Post Form Templates || [3.3][BETA] Anonymous Posts || [3.2][3.3][BETA] ACP Merge Child Forums || [3.2][BETA] Sticky Ad || [3.2][DEV] User Delete Topics || [3.3][DEV] Moderate While Searching || [3.3][RC] Short Number Twig Extension
Post Reply

Return to “Extension Writers Discussion”