diff --git a/.env b/.env index 63a8169f64..d393c9b324 100644 --- a/.env +++ b/.env @@ -59,6 +59,7 @@ LOCAL_WP_DEBUG_LOG=true LOCAL_WP_DEBUG_DISPLAY=true LOCAL_SCRIPT_DEBUG=true LOCAL_WP_ENVIRONMENT_TYPE=local +LOCAL_WP_DEVELOPMENT_MODE=core # The URL to use when running e2e tests. WP_BASE_URL=http://localhost:${LOCAL_PORT} diff --git a/src/wp-includes/default-constants.php b/src/wp-includes/default-constants.php index 61f02a3f60..871a79c729 100644 --- a/src/wp-includes/default-constants.php +++ b/src/wp-includes/default-constants.php @@ -77,9 +77,18 @@ function wp_initial_constants() { define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' ); // No trailing slash, full paths only - WP_CONTENT_URL is defined further down. } + /* + * Add define( 'WP_DEVELOPMENT_MODE', 'core' ) or define( 'WP_DEVELOPMENT_MODE', 'plugin' ) or + * define( 'WP_DEVELOPMENT_MODE', 'theme' ) to wp-config.php to signify development mode for WordPress core, a + * plugin, or a theme respectively. + */ + if ( ! defined( 'WP_DEVELOPMENT_MODE' ) ) { + define( 'WP_DEVELOPMENT_MODE', '' ); + } + // Add define( 'WP_DEBUG', true ); to wp-config.php to enable display of notices during development. if ( ! defined( 'WP_DEBUG' ) ) { - if ( 'development' === wp_get_environment_type() ) { + if ( wp_get_development_mode() || 'development' === wp_get_environment_type() ) { define( 'WP_DEBUG', true ); } else { define( 'WP_DEBUG', false ); diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index 84d775efb0..8c0f48b87a 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -66,12 +66,10 @@ function wp_get_global_settings( $path = array(), $context = array() ) { $cache_key = 'wp_get_global_settings_' . $origin; /* - * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme + * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme * developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. */ - $can_use_cached = ! WP_DEBUG; + $can_use_cached = wp_get_development_mode() !== 'theme'; $settings = false; if ( $can_use_cached ) { @@ -151,12 +149,10 @@ function wp_get_global_styles( $path = array(), $context = array() ) { */ function wp_get_global_stylesheet( $types = array() ) { /* - * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme + * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme * developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. */ - $can_use_cached = empty( $types ) && ! WP_DEBUG; + $can_use_cached = empty( $types ) && wp_get_development_mode() !== 'theme'; /* * By using the 'theme_json' group, this data is marked to be non-persistent across requests. @@ -252,12 +248,10 @@ function wp_get_global_styles_custom_css() { return ''; } /* - * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme + * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme * developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. */ - $can_use_cached = ! WP_DEBUG; + $can_use_cached = wp_get_development_mode() !== 'theme'; /* * By using the 'theme_json' group, this data is marked to be non-persistent across requests. @@ -303,12 +297,10 @@ function wp_get_global_styles_custom_css() { */ function wp_get_global_styles_svg_filters() { /* - * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme + * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme * developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. */ - $can_use_cached = ! WP_DEBUG; + $can_use_cached = wp_get_development_mode() !== 'theme'; $cache_group = 'theme_json'; $cache_key = 'wp_get_global_styles_svg_filters'; if ( $can_use_cached ) { @@ -402,12 +394,10 @@ function wp_theme_has_theme_json() { if ( null !== $theme_has_support && /* - * Ignore static cache when `WP_DEBUG` is enabled. Why? To avoid interfering with + * Ignore static cache when the development mode is set to 'theme', to avoid interfering with * the theme developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. */ - ! WP_DEBUG && + wp_get_development_mode() !== 'theme' && /* * Ignore cache when automated test suites are running. Why? To ensure * the static cache is reset between each test. diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index 268af02976..c0398cb4f9 100644 --- a/src/wp-includes/load.php +++ b/src/wp-includes/load.php @@ -261,6 +261,50 @@ function wp_get_environment_type() { return $current_env; } +/** + * Retrieves the current development mode. + * + * The development mode affects how certain parts of the WordPress application behave, which is relevant when + * developing for WordPress. + * + * Valid developer modes are 'core', 'plugin', 'theme', or an empty string to disable developer mode. + * + * Developer mode is considered separately from `WP_DEBUG` and {@see wp_get_environment_type()}. It does not affect + * debugging output, but rather functional nuances in WordPress. + * + * @since 6.3.0 + * + * @return string The current development mode. + */ +function wp_get_development_mode() { + static $current_mode = null; + + if ( ! defined( 'WP_RUN_CORE_TESTS' ) && null !== $current_mode ) { + return $current_mode; + } + + $development_mode = WP_DEVELOPMENT_MODE; + + // Exclusively for core tests, rely on a global `$_wp_tests_development_mode`. + if ( defined( 'WP_RUN_CORE_TESTS' ) && isset( $GLOBALS['_wp_tests_development_mode'] ) ) { + $development_mode = $GLOBALS['_wp_tests_development_mode']; + } + + $valid_modes = array( + 'core', + 'plugin', + 'theme', + '', + ); + if ( ! in_array( $development_mode, $valid_modes, true ) ) { + $development_mode = ''; + } + + $current_mode = $development_mode; + + return $current_mode; +} + /** * Don't load all of WordPress when handling a favicon.ico request. * diff --git a/tests/phpunit/tests/load/wpGetDevelopmentMode.php b/tests/phpunit/tests/load/wpGetDevelopmentMode.php new file mode 100644 index 0000000000..dac3bd7f95 --- /dev/null +++ b/tests/phpunit/tests/load/wpGetDevelopmentMode.php @@ -0,0 +1,46 @@ +assertSame( WP_DEVELOPMENT_MODE, wp_get_development_mode() ); + } + + /** + * Tests that `wp_get_development_mode()` allows test overrides. + * + * @ticket 57487 + */ + public function test_wp_get_development_mode_test_overrides() { + global $_wp_tests_development_mode; + + $_wp_tests_development_mode = 'plugin'; + $this->assertSame( 'plugin', wp_get_development_mode() ); + } + + /** + * Tests that `wp_get_development_mode()` ignores invalid filter values. + * + * @ticket 57487 + */ + public function test_wp_get_development_mode_filter_invalid_value() { + global $_wp_tests_development_mode; + + $_wp_tests_development_mode = 'invalid'; + $this->assertSame( '', wp_get_development_mode() ); + } +} diff --git a/tests/phpunit/tests/theme/wpGetGlobalStylesSvgFilters.php b/tests/phpunit/tests/theme/wpGetGlobalStylesSvgFilters.php index b1d23efb4d..bac3375b25 100644 --- a/tests/phpunit/tests/theme/wpGetGlobalStylesSvgFilters.php +++ b/tests/phpunit/tests/theme/wpGetGlobalStylesSvgFilters.php @@ -34,4 +34,29 @@ class Tests_Theme_wpGetGlobalStylesSvgFilters extends WP_UnitTestCase { $this->assertStringContainsString( 'assertNotSame( $svg_for_default_theme, $svg_for_block_theme, 'Cache value should have changed' ); } + + /** + * Tests that the function relies on the development mode for whether to use caching. + * + * @ticket 57487 + * + * @covers ::wp_get_global_styles_svg_filters + */ + public function test_caching_is_used_when_developing_theme() { + global $_wp_tests_development_mode; + + switch_theme( 'block-theme' ); + + // Store SVG in cache. + $svg = ''; + wp_cache_set( 'wp_get_global_styles_svg_filters', $svg, 'theme_json' ); + + // By default, caching should be used, so the above value will be returned. + $_wp_tests_development_mode = ''; + $this->assertSame( $svg, wp_get_global_styles_svg_filters(), 'Caching was not used despite development mode disabled' ); + + // When the development mode is set to 'theme', caching should not be used. + $_wp_tests_development_mode = 'theme'; + $this->assertNotSame( $svg, wp_get_global_styles_svg_filters(), 'Caching was used despite theme development mode' ); + } } diff --git a/tests/phpunit/tests/theme/wpGetGlobalStylesheet.php b/tests/phpunit/tests/theme/wpGetGlobalStylesheet.php index 6213a383e3..40d87940b4 100644 --- a/tests/phpunit/tests/theme/wpGetGlobalStylesheet.php +++ b/tests/phpunit/tests/theme/wpGetGlobalStylesheet.php @@ -220,6 +220,29 @@ class Tests_Theme_WpGetGlobalStylesheet extends WP_Theme_UnitTestCase { $this->assertStringContainsString( $expected, $stylesheet_for_block_theme, 'Custom font size (100px) should be present for block theme' ); } + /** + * Tests that the function relies on the development mode for whether to use caching. + * + * @ticket 57487 + */ + public function test_caching_is_used_when_developing_theme() { + global $_wp_tests_development_mode; + + $this->maybe_switch_theme( 'block-theme' ); + + // Store CSS in cache. + $css = '.my-class { display: block; }'; + wp_cache_set( 'wp_get_global_stylesheet', $css, 'theme_json' ); + + // By default, caching should be used, so the above value will be returned. + $_wp_tests_development_mode = ''; + $this->assertSame( $css, wp_get_global_stylesheet(), 'Caching was not used despite development mode disabled' ); + + // When the development mode is set to 'theme', caching should not be used. + $_wp_tests_development_mode = 'theme'; + $this->assertNotSame( $css, wp_get_global_stylesheet(), 'Caching was used despite theme development mode' ); + } + /** * Adds the 'editor-font-sizes' theme support with custom font sizes. * diff --git a/tools/local-env/scripts/install.js b/tools/local-env/scripts/install.js index c17bbce887..e8a448c8c9 100644 --- a/tools/local-env/scripts/install.js +++ b/tools/local-env/scripts/install.js @@ -16,6 +16,7 @@ wp_cli( `config set WP_DEBUG_LOG ${process.env.LOCAL_WP_DEBUG_LOG} --raw --type= wp_cli( `config set WP_DEBUG_DISPLAY ${process.env.LOCAL_WP_DEBUG_DISPLAY} --raw --type=constant` ); wp_cli( `config set SCRIPT_DEBUG ${process.env.LOCAL_SCRIPT_DEBUG} --raw --type=constant` ); wp_cli( `config set WP_ENVIRONMENT_TYPE ${process.env.LOCAL_WP_ENVIRONMENT_TYPE} --type=constant` ); +wp_cli( `config set WP_DEVELOPMENT_MODE ${process.env.LOCAL_WP_DEVELOPMENT_MODE} --type=constant` ); // Move wp-config.php to the base directory, so it doesn't get mixed up in the src or build directories. renameSync( 'src/wp-config.php', 'wp-config.php' );