Make WordPress Core

Changeset 61274 for branches/6.9


Ignore:
Timestamp:
11/20/2025 01:58:35 PM (10 months ago)
Author:
wildworks
Message:

Notes: trash (or delete) child notes when parent is deleted.

Ensure that when a top level note is trashed (or deleted), all of its replies (children) are also trashed or deleted. If EMPTY_TRASH_DAYS is 0, notes are deleted immediately; otherwise they are marked as trash for later cleanup.

Reviewed by wildworks.
Merges [61248] to the 6.9 branch.

Props adamsilverstein, desrosj, wildworks, mamaduka, karthickmurugan, jeffpaul, shailu25.
See #64240.

Location:
branches/6.9
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/6.9

  • branches/6.9/src/wp-includes/comment.php

    r61199 r61274  
    15751575 *
    15761576 * @since 2.9.0
     1577 * @since 6.9.0 Any child notes are deleted when deleting a note.
    15771578 *
    15781579 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.
     
    15811582function wp_trash_comment( $comment_id ) {
    15821583        if ( ! EMPTY_TRASH_DAYS ) {
    1583                 return wp_delete_comment( $comment_id, true );
     1584                $comment = get_comment( $comment_id );
     1585                $success = wp_delete_comment( $comment_id, true );
     1586
     1587                if ( ! $success ) {
     1588                        return false;
     1589                }
     1590
     1591                // Also delete children of top level 'note' type comments.
     1592                if ( $comment && 'note' === $comment->comment_type && 0 === (int) $comment->comment_parent ) {
     1593                        $children = $comment->get_children(
     1594                                array(
     1595                                        'fields' => 'ids',
     1596                                        'status' => 'all',
     1597                                        'type'   => 'note',
     1598                                )
     1599                        );
     1600
     1601                        foreach ( $children as $child_id ) {
     1602                                if ( ! wp_delete_comment( $child_id, true ) ) {
     1603                                        $success = false;
     1604                                }
     1605                        }
     1606                }
     1607
     1608                return $success;
    15841609        }
    15851610
     
    16161641                 */
    16171642                do_action( 'trashed_comment', $comment->comment_ID, $comment );
     1643
     1644                // For top level 'note' type comments, also trash children.
     1645                if ( 'note' === $comment->comment_type && 0 === (int) $comment->comment_parent ) {
     1646                        $children = $comment->get_children(
     1647                                array(
     1648                                        'fields' => 'ids',
     1649                                        'status' => 'all',
     1650                                        'type'   => 'note',
     1651                                )
     1652                        );
     1653
     1654                        $success = true;
     1655                        foreach ( $children as $child_id ) {
     1656                                if ( ! wp_trash_comment( $child_id ) ) {
     1657                                        $success = false;
     1658                                }
     1659                        }
     1660                        return $success;
     1661                }
    16181662
    16191663                return true;
  • branches/6.9/tests/phpunit/tests/comment.php

    r60486 r61274  
    16731673                $this->assertSame( '1', $comment->comment_approved );
    16741674        }
     1675
     1676        /**
     1677         * Tests that trashing a top-level note also trashes all direct child notes.
     1678         *
     1679         * @ticket 64240
     1680         * @covers ::wp_trash_comment
     1681         * @dataProvider data_comment_approved_statuses
     1682         */
     1683        public function test_wp_trash_comment_trashes_child_notes( $approved_status ) {
     1684                // Create a parent note (top-level, comment_parent=0).
     1685                $parent_note = self::factory()->comment->create(
     1686                        array(
     1687                                'comment_post_ID'  => self::$post_id,
     1688                                'comment_type'     => 'note',
     1689                                'comment_parent'   => 0,
     1690                                'comment_approved' => $approved_status,
     1691                        )
     1692                );
     1693
     1694                // Create child notes under the parent.
     1695                $child_note_1 = self::factory()->comment->create(
     1696                        array(
     1697                                'comment_post_ID'  => self::$post_id,
     1698                                'comment_type'     => 'note',
     1699                                'comment_parent'   => $parent_note,
     1700                                'comment_approved' => $approved_status,
     1701                        )
     1702                );
     1703
     1704                $child_note_2 = self::factory()->comment->create(
     1705                        array(
     1706                                'comment_post_ID'  => self::$post_id,
     1707                                'comment_type'     => 'note',
     1708                                'comment_parent'   => $parent_note,
     1709                                'comment_approved' => $approved_status,
     1710                        )
     1711                );
     1712
     1713                $child_note_3 = self::factory()->comment->create(
     1714                        array(
     1715                                'comment_post_ID'  => self::$post_id,
     1716                                'comment_type'     => 'note',
     1717                                'comment_parent'   => $parent_note,
     1718                                'comment_approved' => $approved_status,
     1719                        )
     1720                );
     1721
     1722                // Trash the parent note.
     1723                wp_trash_comment( $parent_note );
     1724
     1725                // Verify parent note is trashed.
     1726                $this->assertSame( 'trash', get_comment( $parent_note )->comment_approved );
     1727
     1728                // Verify all child notes are also trashed.
     1729                $this->assertSame( 'trash', get_comment( $child_note_1 )->comment_approved );
     1730                $this->assertSame( 'trash', get_comment( $child_note_2 )->comment_approved );
     1731                $this->assertSame( 'trash', get_comment( $child_note_3 )->comment_approved );
     1732        }
     1733
     1734        /**
     1735         * Data provider for test_wp_trash_comment_trashes_child_notes.
     1736         */
     1737        public function data_comment_approved_statuses() {
     1738                return array(
     1739                        array( '1' ),
     1740                        array( '0' ),
     1741                );
     1742        }
     1743
     1744        /**
     1745         * Tests that trashing a regular comment does NOT trash its children.
     1746         *
     1747         * @ticket 64240
     1748         * @covers ::wp_trash_comment
     1749         */
     1750        public function test_wp_trash_comment_does_not_trash_child_comments() {
     1751                // Create a parent comment (default type='comment').
     1752                $parent_comment = self::factory()->comment->create(
     1753                        array(
     1754                                'comment_post_ID'  => self::$post_id,
     1755                                'comment_type'     => 'comment',
     1756                                'comment_parent'   => 0,
     1757                                'comment_approved' => '1',
     1758                        )
     1759                );
     1760
     1761                // Create child comments under the parent.
     1762                $child_comment_1 = self::factory()->comment->create(
     1763                        array(
     1764                                'comment_post_ID'  => self::$post_id,
     1765                                'comment_type'     => 'comment',
     1766                                'comment_parent'   => $parent_comment,
     1767                                'comment_approved' => '1',
     1768                        )
     1769                );
     1770
     1771                $child_comment_2 = self::factory()->comment->create(
     1772                        array(
     1773                                'comment_post_ID'  => self::$post_id,
     1774                                'comment_type'     => 'comment',
     1775                                'comment_parent'   => $parent_comment,
     1776                                'comment_approved' => '1',
     1777                        )
     1778                );
     1779
     1780                // Trash the parent comment.
     1781                wp_trash_comment( $parent_comment );
     1782
     1783                // Verify parent comment is trashed.
     1784                $this->assertSame( 'trash', get_comment( $parent_comment )->comment_approved );
     1785
     1786                // Verify child comments are NOT trashed (maintaining existing behavior).
     1787                $this->assertSame( '1', get_comment( $child_comment_1 )->comment_approved );
     1788                $this->assertSame( '1', get_comment( $child_comment_2 )->comment_approved );
     1789        }
     1790
     1791        /**
     1792         * Tests that trashing a child note does not affect parent or siblings.
     1793         *
     1794         * @ticket 64240
     1795         * @covers ::wp_trash_comment
     1796         */
     1797        public function test_wp_trash_comment_child_note_does_not_affect_parent_or_siblings() {
     1798                // Create a parent note.
     1799                $parent_note = self::factory()->comment->create(
     1800                        array(
     1801                                'comment_post_ID'  => self::$post_id,
     1802                                'comment_type'     => 'note',
     1803                                'comment_parent'   => 0,
     1804                                'comment_approved' => '1',
     1805                        )
     1806                );
     1807
     1808                // Create multiple child notes.
     1809                $child_note_1 = self::factory()->comment->create(
     1810                        array(
     1811                                'comment_post_ID'  => self::$post_id,
     1812                                'comment_type'     => 'note',
     1813                                'comment_parent'   => $parent_note,
     1814                                'comment_approved' => '1',
     1815                        )
     1816                );
     1817
     1818                $child_note_2 = self::factory()->comment->create(
     1819                        array(
     1820                                'comment_post_ID'  => self::$post_id,
     1821                                'comment_type'     => 'note',
     1822                                'comment_parent'   => $parent_note,
     1823                                'comment_approved' => '1',
     1824                        )
     1825                );
     1826
     1827                $child_note_3 = self::factory()->comment->create(
     1828                        array(
     1829                                'comment_post_ID'  => self::$post_id,
     1830                                'comment_type'     => 'note',
     1831                                'comment_parent'   => $parent_note,
     1832                                'comment_approved' => '1',
     1833                        )
     1834                );
     1835
     1836                // Trash only one child note.
     1837                wp_trash_comment( $child_note_2 );
     1838
     1839                // Verify the parent note is still approved.
     1840                $this->assertSame( '1', get_comment( $parent_note )->comment_approved );
     1841
     1842                // Verify the trashed child is trashed.
     1843                $this->assertSame( 'trash', get_comment( $child_note_2 )->comment_approved );
     1844
     1845                // Verify sibling notes are still approved.
     1846                $this->assertSame( '1', get_comment( $child_note_1 )->comment_approved );
     1847                $this->assertSame( '1', get_comment( $child_note_3 )->comment_approved );
     1848        }
     1849
     1850        /**
     1851         * Tests that only top-level notes trigger child deletion.
     1852         *
     1853         * @ticket 64240
     1854         * @covers ::wp_trash_comment
     1855         */
     1856        public function test_wp_trash_comment_only_top_level_notes_trigger_child_deletion() {
     1857                // Create a parent note.
     1858                $parent_note = self::factory()->comment->create(
     1859                        array(
     1860                                'comment_post_ID'  => self::$post_id,
     1861                                'comment_type'     => 'note',
     1862                                'comment_parent'   => 0,
     1863                                'comment_approved' => '1',
     1864                        )
     1865                );
     1866
     1867                // Create a child note (not top-level, has comment_parent > 0).
     1868                $child_note = self::factory()->comment->create(
     1869                        array(
     1870                                'comment_post_ID'  => self::$post_id,
     1871                                'comment_type'     => 'note',
     1872                                'comment_parent'   => $parent_note,
     1873                                'comment_approved' => '1',
     1874                        )
     1875                );
     1876
     1877                // Create a sibling note (also not top-level).
     1878                $sibling_note = self::factory()->comment->create(
     1879                        array(
     1880                                'comment_post_ID'  => self::$post_id,
     1881                                'comment_type'     => 'note',
     1882                                'comment_parent'   => $parent_note,
     1883                                'comment_approved' => '1',
     1884                        )
     1885                );
     1886
     1887                // Trash the child note (which has comment_parent > 0).
     1888                wp_trash_comment( $child_note );
     1889
     1890                // Verify the child note is trashed.
     1891                $this->assertSame( 'trash', get_comment( $child_note )->comment_approved );
     1892
     1893                // Verify the parent note is NOT trashed.
     1894                $this->assertSame( '1', get_comment( $parent_note )->comment_approved );
     1895
     1896                // Verify the sibling note is NOT trashed (no cascade since child is not top-level).
     1897                $this->assertSame( '1', get_comment( $sibling_note )->comment_approved );
     1898        }
    16751899}
Note: See TracChangeset for help on using the changeset viewer.