From e76dd3270538169e02fbffc6e975ebbcce81d821 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Mon, 21 Mar 2022 11:33:34 -0700 Subject: [PATCH] Ensure default modules setting value is always used regardless of setting registration. --- load.php | 44 +++++++++++++++++++++++++++++++------------- tests/load-tests.php | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/load.php b/load.php index 0d0f8cf8c1..4da3996da6 100644 --- a/load.php +++ b/load.php @@ -26,29 +26,44 @@ * @since 1.0.0 */ function perflab_register_modules_setting() { - // To set the default value for which modules are enabled, rely on this generated file. - $default_enabled_modules = require plugin_dir_path( __FILE__ ) . 'default-enabled-modules.php'; - $default_option = array_reduce( - $default_enabled_modules, - function( $module_settings, $module_dir ) { - $module_settings[ $module_dir ] = array( 'enabled' => true ); - return $module_settings; - }, - array() - ); - register_setting( PERFLAB_MODULES_SCREEN, PERFLAB_MODULES_SETTING, array( 'type' => 'object', 'sanitize_callback' => 'perflab_sanitize_modules_setting', - 'default' => $default_option, + 'default' => perflab_get_modules_setting_default(), ) ); } add_action( 'init', 'perflab_register_modules_setting' ); +/** + * Gets the default value for the performance modules setting. + * + * @since n.e.x.t + */ +function perflab_get_modules_setting_default() { + // Since the default relies on some minimal logic that includes requiring an additional file, + // the result is "cached" in a static variable. + static $default_option = null; + + if ( null === $default_option ) { + // To set the default value for which modules are enabled, rely on this generated file. + $default_enabled_modules = require plugin_dir_path( __FILE__ ) . 'default-enabled-modules.php'; + $default_option = array_reduce( + $default_enabled_modules, + function( $module_settings, $module_dir ) { + $module_settings[ $module_dir ] = array( 'enabled' => true ); + return $module_settings; + }, + array() + ); + } + + return $default_option; +} + /** * Sanitizes the performance modules setting. * @@ -87,7 +102,10 @@ function( $module_settings ) { * @return array Associative array of module settings keyed by module slug. */ function perflab_get_module_settings() { - return (array) get_option( PERFLAB_MODULES_SETTING ); + // Even though a default value is registered for this setting, the default must be explicitly + // passed here, to support scenarios where this function is called before the 'init' action, + // for example when loading the active modules. + return (array) get_option( PERFLAB_MODULES_SETTING, perflab_get_modules_setting_default() ); } /** diff --git a/tests/load-tests.php b/tests/load-tests.php index db3388363c..9c81353d24 100644 --- a/tests/load-tests.php +++ b/tests/load-tests.php @@ -28,7 +28,7 @@ public function test_perflab_register_modules_setting() { } // Assert that registered default works correctly. - $this->assertSame( $this->get_expected_default_option(), get_option( PERFLAB_MODULES_SETTING ) ); + $this->assertSame( perflab_get_modules_setting_default(), get_option( PERFLAB_MODULES_SETTING ) ); // Assert that most basic sanitization works correctly (an array is required). update_option( PERFLAB_MODULES_SETTING, 'invalid' ); @@ -56,10 +56,39 @@ public function test_perflab_sanitize_modules_setting() { $this->assertSame( array( 'my-module' => array( 'enabled' => false ) ), $sanitized ); } + public function test_perflab_get_modules_setting_default() { + $default_enabled_modules = require plugin_dir_path( PERFLAB_MAIN_FILE ) . 'default-enabled-modules.php'; + $expected = array(); + foreach ( $default_enabled_modules as $default_enabled_module ) { + $expected[ $default_enabled_module ] = array( 'enabled' => true ); + } + + $this->assertSame( $expected, perflab_get_modules_setting_default() ); + } + public function test_perflab_get_module_settings() { - // Assert that by default the settings are an empty array. + // Assert that by default the settings are using the same value as the registered default. + $settings = perflab_get_module_settings(); + $this->assertSame( perflab_get_modules_setting_default(), $settings ); + + // More specifically though, assert that the default is also passed through to the + // get_option() call, to support scenarios where the function is called before 'init'. + // Unhook the registered default logic to verify the default comes from the passed value. + remove_all_filters( 'default_option_' . PERFLAB_MODULES_SETTING ); + $has_passed_default = false; + add_filter( + 'default_option_' . PERFLAB_MODULES_SETTING, + function( $default, $option, $passed_default ) use ( &$has_passed_default ) { + // This callback just records whether there is a default value being passed. + $has_passed_default = $passed_default; + return $default; + }, + 10, + 3 + ); $settings = perflab_get_module_settings(); - $this->assertSame( $this->get_expected_default_option(), $settings ); + $this->assertTrue( $has_passed_default ); + $this->assertSame( perflab_get_modules_setting_default(), $settings ); // Assert that option updates are reflected in the settings correctly. $new_value = array( 'my-module' => array( 'enabled' => true ) ); @@ -73,7 +102,7 @@ public function test_perflab_get_active_modules() { $active_modules = perflab_get_active_modules(); $expected_active_modules = array_keys( array_filter( - $this->get_expected_default_option(), + perflab_get_modules_setting_default(), function( $module_settings ) { return $module_settings['enabled']; }