diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 3e4b36f256d96..1416704909f34 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -85,8 +85,6 @@ includes: - tests/phpstan/baselines/ternary.alwaysTrue.neon - tests/phpstan/baselines/varTag.noVariable.neon - tests/phpstan/baselines/variable.undefined.neon - - tests/phpstan/baselines/while.alwaysFalse.neon - - tests/phpstan/baselines/while.alwaysTrue.neon # phpstan:baselines end parameters: diff --git a/src/wp-content/themes/twentyfourteen/inc/widgets.php b/src/wp-content/themes/twentyfourteen/inc/widgets.php index 36846daa84860..b375113b308b5 100644 --- a/src/wp-content/themes/twentyfourteen/inc/widgets.php +++ b/src/wp-content/themes/twentyfourteen/inc/widgets.php @@ -137,6 +137,8 @@ public function widget( $args, $instance ) { if ( $ephemera->have_posts() ) : $tmp_content_width = $GLOBALS['content_width']; $GLOBALS['content_width'] = 306; + // The global is unset until a loop has run, so this may be reached before it exists. + $tmp_more = $GLOBALS['more'] ?? null; echo $args['before_widget']; ?> @@ -148,7 +150,6 @@ public function widget( $args, $instance ) { have_posts() ) : $ephemera->the_post(); - $tmp_more = $GLOBALS['more']; $GLOBALS['more'] = 0; ?>
  • diff --git a/src/wp-includes/class-wp-query.php b/src/wp-includes/class-wp-query.php index 228691d26d12b..906cca0905e1a 100644 --- a/src/wp-includes/class-wp-query.php +++ b/src/wp-includes/class-wp-query.php @@ -3839,6 +3839,8 @@ function ( $carry, $post ) { * * @since 1.5.0 * + * @phpstan-impure + * * @return bool True if posts are available, false if end of the loop. */ public function have_posts() { @@ -3929,6 +3931,8 @@ public function the_comment() { * * @since 2.2.0 * + * @phpstan-impure + * * @return bool True if comments are available, false if no more comments. */ public function have_comments() { diff --git a/src/wp-includes/query.php b/src/wp-includes/query.php index 60571c01cb880..42592002c1cab 100644 --- a/src/wp-includes/query.php +++ b/src/wp-includes/query.php @@ -956,6 +956,8 @@ function is_main_query() { * * @global WP_Query $wp_query WordPress Query object. * + * @phpstan-impure + * * @return bool True if posts are available, false if end of the loop. */ function have_posts() { @@ -1036,6 +1038,8 @@ function the_post() { * * @global WP_Query $wp_query WordPress Query object. * + * @phpstan-impure + * * @return bool True if comments are available, false if no more comments. */ function have_comments() { diff --git a/tests/phpstan/baselines/deadCode.unreachable.neon b/tests/phpstan/baselines/deadCode.unreachable.neon index 0bd31fe524a9a..8a4288bc40c43 100644 --- a/tests/phpstan/baselines/deadCode.unreachable.neon +++ b/tests/phpstan/baselines/deadCode.unreachable.neon @@ -38,241 +38,11 @@ parameters: identifier: deadCode.unreachable count: 1 path: ../../../src/wp-admin/includes/class-wp-internal-pointers.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 2 - path: ../../../src/wp-admin/includes/dashboard.php - message: '#^Unreachable statement \- code above always terminates\.$#' identifier: deadCode.unreachable count: 2 path: ../../../src/wp-admin/post.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/author.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/category.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/inc/widgets.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/showcase.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/tag.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/author.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/category.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/inc/widgets.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/tag.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/taxonomy-post_format.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/template-parts/page/content-front-page-panels.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/author.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/category.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/tag.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/taxonomy-post_format.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/author.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/category.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/search.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/tag.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/archive.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/index.php - - - message: '#^Unreachable statement \- code above always terminates\.$#' - identifier: deadCode.unreachable - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/search.php - message: '#^Unreachable statement \- code above always terminates\.$#' identifier: deadCode.unreachable diff --git a/tests/phpstan/baselines/if.alwaysTrue.neon b/tests/phpstan/baselines/if.alwaysTrue.neon index f049efde2d19d..6888b9780b5f9 100644 --- a/tests/phpstan/baselines/if.alwaysTrue.neon +++ b/tests/phpstan/baselines/if.alwaysTrue.neon @@ -28,11 +28,6 @@ parameters: identifier: if.alwaysTrue count: 2 path: ../../../src/wp-admin/upload.php - - - message: '#^If condition is always true\.$#' - identifier: if.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/comments.php - message: '#^If condition is always true\.$#' identifier: if.alwaysTrue diff --git a/tests/phpstan/baselines/while.alwaysFalse.neon b/tests/phpstan/baselines/while.alwaysFalse.neon deleted file mode 100644 index 3c924003ea783..0000000000000 --- a/tests/phpstan/baselines/while.alwaysFalse.neon +++ /dev/null @@ -1,25 +0,0 @@ -# PHPStan baseline for the `while.alwaysFalse` errors in WordPress core. -# -# https://phpstan.org/error-identifiers/while.alwaysFalse -# -# Each entry is scoped to a single file and carries an exact occurrence count, -# so that a new instance is reported as a new error rather than being absorbed -# silently. Fixing an occurrence therefore means decrementing or removing its -# entry here as part of the same change. -# -# The goal is to empty this file and delete it, along with the `includes` entry -# for it in phpstan.neon.dist. -# -# Generated by `composer phpstan:baselines`. Do not edit by hand; regenerate with -# -# composer phpstan:baselines -- --identifier=while.alwaysFalse -# -# which reruns the analysis with this file suppressed so the errors surface again. - -parameters: - ignoreErrors: - - - message: '#^While loop condition is always false\.$#' - identifier: while.alwaysFalse - count: 1 - path: ../../../src/wp-includes/feed-rdf.php diff --git a/tests/phpstan/baselines/while.alwaysTrue.neon b/tests/phpstan/baselines/while.alwaysTrue.neon deleted file mode 100644 index 5da6550e89cc0..0000000000000 --- a/tests/phpstan/baselines/while.alwaysTrue.neon +++ /dev/null @@ -1,300 +0,0 @@ -# PHPStan baseline for the `while.alwaysTrue` errors in WordPress core. -# -# https://phpstan.org/error-identifiers/while.alwaysTrue -# -# Each entry is scoped to a single file and carries an exact occurrence count, -# so that a new instance is reported as a new error rather than being absorbed -# silently. Fixing an occurrence therefore means decrementing or removing its -# entry here as part of the same change. -# -# The goal is to empty this file and delete it, along with the `includes` entry -# for it in phpstan.neon.dist. -# -# Generated by `composer phpstan:baselines`. Do not edit by hand; regenerate with -# -# composer phpstan:baselines -- --identifier=while.alwaysTrue -# -# which reruns the analysis with this file suppressed so the errors surface again. - -parameters: - ignoreErrors: - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-admin/includes/dashboard.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-admin/includes/nav-menu.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/author.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/category.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/inc/widgets.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/showcase.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyeleven/tag.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfifteen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/author.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/category.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/inc/widgets.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/tag.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyfourteen/taxonomy-post_format.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentynineteen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/front-page.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyseventeen/template-parts/page/content-front-page-panels.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentysixteen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyten/loop-attachment.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyten/loop-page.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentyten/loop-single.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/author.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/category.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/tag.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentythirteen/taxonomy-post_format.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/author.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/category.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwelve/tag.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwenty/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwenty/singular.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwenty/templates/template-cover.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/archive.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/index.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-content/themes/twentytwentyone/search.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-includes/block-template.php - - - message: '#^While loop condition is always true\.$#' - identifier: while.alwaysTrue - count: 1 - path: ../../../src/wp-includes/theme-compat/embed.php diff --git a/tests/phpunit/tests/theme/twentyFourteenEphemeraWidget.php b/tests/phpunit/tests/theme/twentyFourteenEphemeraWidget.php new file mode 100644 index 0000000000000..c2442ef18ec7e --- /dev/null +++ b/tests/phpunit/tests/theme/twentyFourteenEphemeraWidget.php @@ -0,0 +1,134 @@ + + */ + private array $original_globals = array(); + + public function set_up() { + parent::set_up(); + + /* + * `backupGlobals` is disabled for the suite, so these have to be restored by hand + * to keep later tests in the process from inheriting them. Capture them before the + * skip below, which still runs `tear_down()`. + */ + foreach ( $this->global_names as $global_name ) { + if ( array_key_exists( $global_name, $GLOBALS ) ) { + $this->original_globals[ $global_name ] = $GLOBALS[ $global_name ]; + } + } + + $widgets = WP_CONTENT_DIR . '/themes/twentyfourteen/inc/widgets.php'; + if ( ! file_exists( $widgets ) ) { + $this->markTestSkipped( 'The Twenty Fourteen theme is not installed.' ); + } + require_once $widgets; + } + + public function tear_down() { + foreach ( $this->global_names as $global_name ) { + if ( array_key_exists( $global_name, $this->original_globals ) ) { + $GLOBALS[ $global_name ] = $this->original_globals[ $global_name ]; + } else { + unset( $GLOBALS[ $global_name ] ); + } + } + + parent::tear_down(); + } + + /** + * The widget must restore the original `$more` global, which `WP_Query::setup_postdata()` + * zeroes out for each post the widget's secondary loop renders. + */ + public function test_widget_restores_more_global() { + $post_id = self::factory()->post->create( + array( + 'post_content' => 'I want ice cream!', + ) + ); + $this->assertIsInt( $post_id ); + set_post_format( $post_id, 'aside' ); + + // Sentinel value for the restore assertion below; it does not affect what the widget renders. + $GLOBALS['more'] = 1; + $GLOBALS['content_width'] = 474; + + $widget = new Twenty_Fourteen_Ephemera_Widget(); + + $output = get_echo( + array( $widget, 'widget' ), + array( + array( + 'before_widget' => '', + 'after_widget' => '', + ), + array( 'format' => 'aside' ), + ) + ); + + $this->assertNotEmpty( $output, 'The widget content.' ); + $processor = new WP_HTML_Tag_Processor( $output ); + $more_link_count = 0; + while ( $processor->next_tag( array( 'class_name' => 'more-link' ) ) ) { + ++$more_link_count; + } + $this->assertSame( 1, $more_link_count, 'Expected there to be one more link.' ); + $this->assertSame( 1, $GLOBALS['more'], 'The $more global was not restored to its original value.' ); // @phpstan-ignore method.alreadyNarrowedType (The global variable is modified by Twenty_Fourteen_Ephemera_Widget::widget().) + $this->assertSame( 474, $GLOBALS['content_width'], 'The $content_width global was not restored to its original value.' ); + } + + /** + * The `$more` global is only defined once a loop has run, so the widget must not + * assume it exists. It can render before any loop on a 404, an empty search, or an + * empty archive, as well as outside the template entirely. + */ + public function test_widget_when_more_global_is_undefined() { + $post_id = self::factory()->post->create( + array( + 'post_content' => 'I want ice cream!', + ) + ); + $this->assertIsInt( $post_id ); + set_post_format( $post_id, 'aside' ); + + unset( $GLOBALS['more'] ); + $GLOBALS['content_width'] = 474; + + $widget = new Twenty_Fourteen_Ephemera_Widget(); + + $output = get_echo( + array( $widget, 'widget' ), + array( + array( + 'before_widget' => '', + 'after_widget' => '', + ), + array( 'format' => 'aside' ), + ) + ); + + $this->assertNotEmpty( $output, 'The widget content.' ); + $this->assertNull( $GLOBALS['more'], 'The $more global was not restored to a falsey value.' ); // @phpstan-ignore offsetAccess.notFound (The global variable is set by Twenty_Fourteen_Ephemera_Widget::widget().) + } +}