diff --git a/providers/class-two-factor-backup-codes.php b/providers/class-two-factor-backup-codes.php index d74592b3..158b3155 100644 --- a/providers/class-two-factor-backup-codes.php +++ b/providers/class-two-factor-backup-codes.php @@ -287,10 +287,10 @@ private function get_backup_code_length( $user ) { * * @since 0.11.0 * - * @param int $code_length Length of the backup code. Default 8. + * @param int $code_length Length of the backup code. Default is taken from the `two_factor_code_length` filter (which defaults to 8 if not filtered). * @param WP_User $user User object. */ - $code_length = (int) apply_filters( 'two_factor_backup_code_length', 8, $user ); + $code_length = (int) apply_filters( 'two_factor_backup_code_length', self::get_code_length(), $user ); return $code_length; } @@ -417,6 +417,18 @@ public function authentication_page( $user ) { $code_length = $this->get_backup_code_length( $user ); $code_placeholder = str_repeat( 'X', $code_length ); + /** + * Filters the `digits` dataset attribute of the backup code input field on the authentication screen. + * + * To disable autosubmit, set the digits to `0` via the core method `__return_zero`. + * + * @since 0.17.0 + * + * @param int $code_length The length of the backup code. + * @param Two_Factor_Provider $provider The two-factor provider instance. + */ + $code_length = apply_filters( 'two_factor_autosubmit_length', $code_length, $this ); + ?> get_token_length(); $token_placeholder = str_repeat( 'X', $token_length ); + /** This filter is documented in providers/class-two-factor-backup-codes.php */ + $token_length = apply_filters( 'two_factor_autosubmit_length', $token_length, $this ); + require_once ABSPATH . '/wp-admin/includes/template.php'; ?>
- +
provider->authentication_page( false ); + $default_output = ob_get_clean(); + $this->assertStringContainsString( 'data-digits="8"', $default_output ); + + // With filter: data-digits should be overridden to 0 (disables autosubmit). + add_filter( 'two_factor_autosubmit_length', '__return_zero' ); + ob_start(); + $this->provider->authentication_page( false ); + $filtered_output = ob_get_clean(); + remove_filter( 'two_factor_autosubmit_length', '__return_zero' ); + + $this->assertStringContainsString( 'data-digits="0"', $filtered_output ); + } } diff --git a/tests/providers/class-two-factor-provider.php b/tests/providers/class-two-factor-provider.php index 86a4bee3..138a0a8a 100644 --- a/tests/providers/class-two-factor-provider.php +++ b/tests/providers/class-two-factor-provider.php @@ -88,6 +88,54 @@ public function test_get_instance() { $this->assertSame( $instance_one, $instance_two ); } + /** + * Test that get_code_length() returns the default value when no filter is applied. + * + * @covers Two_Factor_Provider::get_code_length + */ + public function test_get_code_length_returns_default() { + $this->assertSame( 8, Two_Factor_Provider::get_code_length( 8 ) ); + $this->assertSame( 6, Two_Factor_Provider::get_code_length( 6 ) ); + } + + /** + * Test that the two_factor_code_length filter can override the default code length. + * + * @covers Two_Factor_Provider::get_code_length + */ + public function test_get_code_length_filter_overrides_default() { + $set_length_to_4 = function() { + return 4; + }; + add_filter( 'two_factor_code_length', $set_length_to_4 ); + $this->assertSame( 4, Two_Factor_Provider::get_code_length( 8 ) ); + remove_filter( 'two_factor_code_length', $set_length_to_4 ); + + $set_length_to_12 = function() { + return 12; + }; + add_filter( 'two_factor_code_length', $set_length_to_12 ); + $this->assertSame( 12, Two_Factor_Provider::get_code_length( 8 ) ); + remove_filter( 'two_factor_code_length', $set_length_to_12 ); + } + + /** + * Test that get_code( null ) uses the filtered code length from two_factor_code_length. + * + * @covers Two_Factor_Provider::get_code + * @covers Two_Factor_Provider::get_code_length + */ + public function test_get_code_with_null_uses_filtered_length() { + $set_length_to_5 = function() { + return 5; + }; + add_filter( 'two_factor_code_length', $set_length_to_5 ); + $code = Two_Factor_Provider::get_code( null ); + remove_filter( 'two_factor_code_length', $set_length_to_5 ); + + $this->assertSame( 5, strlen( $code ) ); + } + /** * Verify get_key() returns the provider's class name. *