Make WordPress Core

Changeset 63357


Ignore:
Timestamp:
08/27/2026 03:45:40 AM (26 hours ago)
Author:
westonruter
Message:

Code Quality: Mark have_posts() and have_comments() as "impure" for PHPStan.

Both WP_Query::have_posts() and WP_Query::have_comments() advance the loop as a side effect, so two identical calls do not return the same value. PHPStan treated them as pure, concluded that a while ( have_posts() ) condition could never change, and reported the loops as always-true or always-false with the code past them unreachable. Marking those methods and their procedural wrappers in wp-includes/query.php as @phpstan-impure empties the while.alwaysTrue and while.alwaysFalse baselines, which are deleted along with their entries in phpstan.neon.dist, and trims deadCode.unreachable and if.alwaysTrue.

Two of the removed while.alwaysTrue entries were in Twenty_Fourteen_Ephemera_Widget::widget(), whose loop carries a real bug: $tmp_more was assigned inside the loop whose effects it exists to undo, so on every iteration after the first it captured the value the widget itself had just written, and the restore afterwards put back the secondary query's 0 rather than the caller's value. The assignment moves above the loop, while also guarding against the variable possibly being undefined.

Developed in https://github.com/WordPress/wordpress-develop/pull/13069.
Follow-up to r27124, r30085, r63023.

Props dpantazis, westonruter.
See #65817.

Location:
trunk
Files:
1 added
2 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/phpstan.neon.dist

    r63351 r63357  
    8686        - tests/phpstan/baselines/varTag.noVariable.neon
    8787        - tests/phpstan/baselines/variable.undefined.neon
    88         - tests/phpstan/baselines/while.alwaysFalse.neon
    89         - tests/phpstan/baselines/while.alwaysTrue.neon
    9088        # phpstan:baselines end
    9189
  • trunk/src/wp-content/themes/twentyfourteen/inc/widgets.php

    r62893 r63357  
    138138                        $tmp_content_width        = $GLOBALS['content_width'];
    139139                        $GLOBALS['content_width'] = 306;
     140                        // The global is unset until a loop has run, so this may be reached before it exists.
     141                        $tmp_more = $GLOBALS['more'] ?? null;
    140142
    141143                        echo $args['before_widget'];
     
    149151                                while ( $ephemera->have_posts() ) :
    150152                                        $ephemera->the_post();
    151                                         $tmp_more        = $GLOBALS['more'];
    152153                                        $GLOBALS['more'] = 0;
    153154                                        ?>
  • trunk/src/wp-includes/class-wp-query.php

    r62956 r63357  
    38403840         * @since 1.5.0
    38413841         *
     3842         * @phpstan-impure
     3843         *
    38423844         * @return bool True if posts are available, false if end of the loop.
    38433845         */
     
    39293931         *
    39303932         * @since 2.2.0
     3933         *
     3934         * @phpstan-impure
    39313935         *
    39323936         * @return bool True if comments are available, false if no more comments.
  • trunk/src/wp-includes/query.php

    r62664 r63357  
    957957 * @global WP_Query $wp_query WordPress Query object.
    958958 *
     959 * @phpstan-impure
     960 *
    959961 * @return bool True if posts are available, false if end of the loop.
    960962 */
     
    10361038 *
    10371039 * @global WP_Query $wp_query WordPress Query object.
     1040 *
     1041 * @phpstan-impure
    10381042 *
    10391043 * @return bool True if comments are available, false if no more comments.
  • trunk/tests/phpstan/baselines/deadCode.unreachable.neon

    r63301 r63357  
    4343                        identifier: deadCode.unreachable
    4444                        count: 2
    45                         path: ../../../src/wp-admin/includes/dashboard.php
    46                 -
    47                         message: '#^Unreachable statement \- code above always terminates\.$#'
    48                         identifier: deadCode.unreachable
    49                         count: 2
    5045                        path: ../../../src/wp-admin/post.php
    51                 -
    52                         message: '#^Unreachable statement \- code above always terminates\.$#'
    53                         identifier: deadCode.unreachable
    54                         count: 1
    55                         path: ../../../src/wp-content/themes/twentyeleven/archive.php
    56                 -
    57                         message: '#^Unreachable statement \- code above always terminates\.$#'
    58                         identifier: deadCode.unreachable
    59                         count: 1
    60                         path: ../../../src/wp-content/themes/twentyeleven/author.php
    61                 -
    62                         message: '#^Unreachable statement \- code above always terminates\.$#'
    63                         identifier: deadCode.unreachable
    64                         count: 1
    65                         path: ../../../src/wp-content/themes/twentyeleven/category.php
    66                 -
    67                         message: '#^Unreachable statement \- code above always terminates\.$#'
    68                         identifier: deadCode.unreachable
    69                         count: 1
    70                         path: ../../../src/wp-content/themes/twentyeleven/inc/widgets.php
    71                 -
    72                         message: '#^Unreachable statement \- code above always terminates\.$#'
    73                         identifier: deadCode.unreachable
    74                         count: 1
    75                         path: ../../../src/wp-content/themes/twentyeleven/index.php
    76                 -
    77                         message: '#^Unreachable statement \- code above always terminates\.$#'
    78                         identifier: deadCode.unreachable
    79                         count: 1
    80                         path: ../../../src/wp-content/themes/twentyeleven/search.php
    81                 -
    82                         message: '#^Unreachable statement \- code above always terminates\.$#'
    83                         identifier: deadCode.unreachable
    84                         count: 1
    85                         path: ../../../src/wp-content/themes/twentyeleven/showcase.php
    86                 -
    87                         message: '#^Unreachable statement \- code above always terminates\.$#'
    88                         identifier: deadCode.unreachable
    89                         count: 1
    90                         path: ../../../src/wp-content/themes/twentyeleven/tag.php
    91                 -
    92                         message: '#^Unreachable statement \- code above always terminates\.$#'
    93                         identifier: deadCode.unreachable
    94                         count: 1
    95                         path: ../../../src/wp-content/themes/twentyfifteen/archive.php
    96                 -
    97                         message: '#^Unreachable statement \- code above always terminates\.$#'
    98                         identifier: deadCode.unreachable
    99                         count: 1
    100                         path: ../../../src/wp-content/themes/twentyfifteen/index.php
    101                 -
    102                         message: '#^Unreachable statement \- code above always terminates\.$#'
    103                         identifier: deadCode.unreachable
    104                         count: 1
    105                         path: ../../../src/wp-content/themes/twentyfifteen/search.php
    106                 -
    107                         message: '#^Unreachable statement \- code above always terminates\.$#'
    108                         identifier: deadCode.unreachable
    109                         count: 1
    110                         path: ../../../src/wp-content/themes/twentyfourteen/archive.php
    111                 -
    112                         message: '#^Unreachable statement \- code above always terminates\.$#'
    113                         identifier: deadCode.unreachable
    114                         count: 1
    115                         path: ../../../src/wp-content/themes/twentyfourteen/author.php
    116                 -
    117                         message: '#^Unreachable statement \- code above always terminates\.$#'
    118                         identifier: deadCode.unreachable
    119                         count: 1
    120                         path: ../../../src/wp-content/themes/twentyfourteen/category.php
    121                 -
    122                         message: '#^Unreachable statement \- code above always terminates\.$#'
    123                         identifier: deadCode.unreachable
    124                         count: 1
    125                         path: ../../../src/wp-content/themes/twentyfourteen/inc/widgets.php
    126                 -
    127                         message: '#^Unreachable statement \- code above always terminates\.$#'
    128                         identifier: deadCode.unreachable
    129                         count: 1
    130                         path: ../../../src/wp-content/themes/twentyfourteen/index.php
    131                 -
    132                         message: '#^Unreachable statement \- code above always terminates\.$#'
    133                         identifier: deadCode.unreachable
    134                         count: 1
    135                         path: ../../../src/wp-content/themes/twentyfourteen/search.php
    136                 -
    137                         message: '#^Unreachable statement \- code above always terminates\.$#'
    138                         identifier: deadCode.unreachable
    139                         count: 1
    140                         path: ../../../src/wp-content/themes/twentyfourteen/tag.php
    141                 -
    142                         message: '#^Unreachable statement \- code above always terminates\.$#'
    143                         identifier: deadCode.unreachable
    144                         count: 1
    145                         path: ../../../src/wp-content/themes/twentyfourteen/taxonomy-post_format.php
    146                 -
    147                         message: '#^Unreachable statement \- code above always terminates\.$#'
    148                         identifier: deadCode.unreachable
    149                         count: 1
    150                         path: ../../../src/wp-content/themes/twentynineteen/archive.php
    151                 -
    152                         message: '#^Unreachable statement \- code above always terminates\.$#'
    153                         identifier: deadCode.unreachable
    154                         count: 1
    155                         path: ../../../src/wp-content/themes/twentynineteen/index.php
    156                 -
    157                         message: '#^Unreachable statement \- code above always terminates\.$#'
    158                         identifier: deadCode.unreachable
    159                         count: 1
    160                         path: ../../../src/wp-content/themes/twentynineteen/search.php
    161                 -
    162                         message: '#^Unreachable statement \- code above always terminates\.$#'
    163                         identifier: deadCode.unreachable
    164                         count: 1
    165                         path: ../../../src/wp-content/themes/twentyseventeen/archive.php
    166                 -
    167                         message: '#^Unreachable statement \- code above always terminates\.$#'
    168                         identifier: deadCode.unreachable
    169                         count: 1
    170                         path: ../../../src/wp-content/themes/twentyseventeen/index.php
    171                 -
    172                         message: '#^Unreachable statement \- code above always terminates\.$#'
    173                         identifier: deadCode.unreachable
    174                         count: 1
    175                         path: ../../../src/wp-content/themes/twentyseventeen/search.php
    176                 -
    177                         message: '#^Unreachable statement \- code above always terminates\.$#'
    178                         identifier: deadCode.unreachable
    179                         count: 1
    180                         path: ../../../src/wp-content/themes/twentyseventeen/template-parts/page/content-front-page-panels.php
    181                 -
    182                         message: '#^Unreachable statement \- code above always terminates\.$#'
    183                         identifier: deadCode.unreachable
    184                         count: 1
    185                         path: ../../../src/wp-content/themes/twentysixteen/archive.php
    186                 -
    187                         message: '#^Unreachable statement \- code above always terminates\.$#'
    188                         identifier: deadCode.unreachable
    189                         count: 1
    190                         path: ../../../src/wp-content/themes/twentysixteen/index.php
    191                 -
    192                         message: '#^Unreachable statement \- code above always terminates\.$#'
    193                         identifier: deadCode.unreachable
    194                         count: 1
    195                         path: ../../../src/wp-content/themes/twentysixteen/search.php
    196                 -
    197                         message: '#^Unreachable statement \- code above always terminates\.$#'
    198                         identifier: deadCode.unreachable
    199                         count: 1
    200                         path: ../../../src/wp-content/themes/twentythirteen/archive.php
    201                 -
    202                         message: '#^Unreachable statement \- code above always terminates\.$#'
    203                         identifier: deadCode.unreachable
    204                         count: 1
    205                         path: ../../../src/wp-content/themes/twentythirteen/author.php
    206                 -
    207                         message: '#^Unreachable statement \- code above always terminates\.$#'
    208                         identifier: deadCode.unreachable
    209                         count: 1
    210                         path: ../../../src/wp-content/themes/twentythirteen/category.php
    211                 -
    212                         message: '#^Unreachable statement \- code above always terminates\.$#'
    213                         identifier: deadCode.unreachable
    214                         count: 1
    215                         path: ../../../src/wp-content/themes/twentythirteen/index.php
    216                 -
    217                         message: '#^Unreachable statement \- code above always terminates\.$#'
    218                         identifier: deadCode.unreachable
    219                         count: 1
    220                         path: ../../../src/wp-content/themes/twentythirteen/search.php
    221                 -
    222                         message: '#^Unreachable statement \- code above always terminates\.$#'
    223                         identifier: deadCode.unreachable
    224                         count: 1
    225                         path: ../../../src/wp-content/themes/twentythirteen/tag.php
    226                 -
    227                         message: '#^Unreachable statement \- code above always terminates\.$#'
    228                         identifier: deadCode.unreachable
    229                         count: 1
    230                         path: ../../../src/wp-content/themes/twentythirteen/taxonomy-post_format.php
    231                 -
    232                         message: '#^Unreachable statement \- code above always terminates\.$#'
    233                         identifier: deadCode.unreachable
    234                         count: 1
    235                         path: ../../../src/wp-content/themes/twentytwelve/archive.php
    236                 -
    237                         message: '#^Unreachable statement \- code above always terminates\.$#'
    238                         identifier: deadCode.unreachable
    239                         count: 1
    240                         path: ../../../src/wp-content/themes/twentytwelve/author.php
    241                 -
    242                         message: '#^Unreachable statement \- code above always terminates\.$#'
    243                         identifier: deadCode.unreachable
    244                         count: 1
    245                         path: ../../../src/wp-content/themes/twentytwelve/category.php
    246                 -
    247                         message: '#^Unreachable statement \- code above always terminates\.$#'
    248                         identifier: deadCode.unreachable
    249                         count: 1
    250                         path: ../../../src/wp-content/themes/twentytwelve/index.php
    251                 -
    252                         message: '#^Unreachable statement \- code above always terminates\.$#'
    253                         identifier: deadCode.unreachable
    254                         count: 1
    255                         path: ../../../src/wp-content/themes/twentytwelve/search.php
    256                 -
    257                         message: '#^Unreachable statement \- code above always terminates\.$#'
    258                         identifier: deadCode.unreachable
    259                         count: 1
    260                         path: ../../../src/wp-content/themes/twentytwelve/tag.php
    261                 -
    262                         message: '#^Unreachable statement \- code above always terminates\.$#'
    263                         identifier: deadCode.unreachable
    264                         count: 1
    265                         path: ../../../src/wp-content/themes/twentytwentyone/archive.php
    266                 -
    267                         message: '#^Unreachable statement \- code above always terminates\.$#'
    268                         identifier: deadCode.unreachable
    269                         count: 1
    270                         path: ../../../src/wp-content/themes/twentytwentyone/index.php
    271                 -
    272                         message: '#^Unreachable statement \- code above always terminates\.$#'
    273                         identifier: deadCode.unreachable
    274                         count: 1
    275                         path: ../../../src/wp-content/themes/twentytwentyone/search.php
    27646                -
    27747                        message: '#^Unreachable statement \- code above always terminates\.$#'
  • trunk/tests/phpstan/baselines/if.alwaysTrue.neon

    r63023 r63357  
    3333                        identifier: if.alwaysTrue
    3434                        count: 1
    35                         path: ../../../src/wp-content/themes/twentynineteen/comments.php
    36                 -
    37                         message: '#^If condition is always true\.$#'
    38                         identifier: if.alwaysTrue
    39                         count: 1
    4035                        path: ../../../src/wp-content/themes/twentynineteen/template-parts/footer/footer-widgets.php
    4136                -
Note: See TracChangeset for help on using the changeset viewer.