diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 00000000..e69de29b diff --git a/inc/admin-interface.php b/inc/admin-interface.php index be6feae2..8e66f97a 100644 --- a/inc/admin-interface.php +++ b/inc/admin-interface.php @@ -34,6 +34,8 @@ function bootstrap() { add_filter( 'site_status_tests', __NAMESPACE__ . '\\default_cache_max_age_test' ); add_action( 'update_option_pantheon-cache', __NAMESPACE__ . '\\clear_max_age_compare_cache' ); + add_action( 'admin_init', __NAMESPACE__ . '\\set_max_age_to_default' ); + add_action( 'admin_notices', __NAMESPACE__ . '\\max_age_updated_admin_notice' ); } /** @@ -47,8 +49,9 @@ function admin_notice_no_mu_plugin() { * Allow disabling the admin notice. * * @param bool $disable_admin_notices Whether to disable the admin notice. + * @param string $callback The name of the current callback function. */ - if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) ) { + if ( apply_filters( 'pantheon_apc_disable_admin_notices', false, __FUNCTION__ ) ) { return; } @@ -71,7 +74,7 @@ function admin_notice_no_mu_plugin() { function admin_notice_old_mu_plugin() { $current_screen = get_current_screen(); - if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) || 'settings_page_pantheon-cache' !== $current_screen->id ) { + if ( apply_filters( 'pantheon_apc_disable_admin_notices', false, __FUNCTION__ ) || 'settings_page_pantheon-cache' !== $current_screen->id ) { return; } @@ -109,7 +112,7 @@ function admin_notice_old_mu_plugin() { function admin_notice_maybe_recommend_higher_max_age() { $current_screen = get_current_screen(); - if ( apply_filters( 'pantheon_apc_disable_admin_notices', false ) || 'settings_page_pantheon-cache' !== $current_screen->id ) { + if ( apply_filters( 'pantheon_apc_disable_admin_notices', false, __FUNCTION__ ) || 'settings_page_pantheon-cache' !== $current_screen->id ) { return; } @@ -317,3 +320,86 @@ function test_cache_max_age() { function clear_max_age_compare_cache() { delete_transient( 'papc_max_age_compare' ); } + +/** + * Set the default_ttl from the mu-plugin to WEEK_IN_SECONDS if it was saved as 600 seconds. + * + * @since 2.0.0 + * @return bool + */ +function set_max_age_to_default() { + $pantheon_cache = get_option( 'pantheon-cache', [] ); + $pantheon_max_age_updated = get_option( 'pantheon_max_age_updated', false ); + + // If we've already done this, bail. + if ( $pantheon_max_age_updated ) { + return; + } + + // If nothing is saved, bail. The default is used automatically. + if ( ! isset( $pantheon_cache['default_ttl'] ) ) { + return; + } + + // Everything beyond this point assumes the max age has been set manually or will be set to the default. + update_option( 'pantheon_max_age_updated', true ); + + // If the default_ttl is not 600, bail. + if ( 600 !== $pantheon_cache['default_ttl'] ) { + return; + } + + // Set the max age. At this point, we should only be here if it was set to 600. We're using the filter here in case someone has overridden the default. + $pantheon_cache['default_ttl'] = apply_filters( 'pantheon_cache_default_max_age', WEEK_IN_SECONDS ); + + // Update the option and set the max_age_updated flag and show the admin notice. + update_option( 'pantheon-cache', $pantheon_cache ); +} + +/** + * Display an admin notice if the max-age was updated. + * + * @since 2.0.0 + * @return void + */ +function max_age_updated_admin_notice() { + // Check if notices should be disabled. This includes if the user is using a version of WordPress that does not support wp_admin_notice. + if ( apply_filters( 'pantheon_apc_disable_admin_notices', false, __FUNCTION__ ) ) { + return; + } + + // Can the user manage options? If not, don't show the notice. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + // Check user meta to see if this user has seen this notice before. + $current_user_id = get_current_user_id(); + $dismissed = get_user_meta( $current_user_id, 'pantheon_max_age_updated_notice', true ); + if ( $dismissed ) { + return; + } + + // Check if the max-age was updated. + $max_age_updated = get_option( 'pantheon_max_age_updated', false ); + if ( ! $max_age_updated ) { + return; + } + + // If we got here, this is the _first time_ this user has seen this notice since the option was updated. Show the notice and update the user meta. + wp_admin_notice( + sprintf( + // translators: %1$s is the humanized max-age, %2$d is a link to the Pantheon documentation. + __( 'The Pantheon GCDN cache max-age has been updated. The previous value was 10 minutes. The new value is %1$s. For more information, refer to the Pantheon documentation.', 'pantheon-advanced-page-cache' ), + humanized_max_age(), + 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin' + ), + [ + 'type' => 'info', + 'dismissible' => false, + ] + ); + + // Update the user meta to prevent this notice from showing again after they've seen it once. + update_user_meta( $current_user_id, 'pantheon_max_age_updated_notice', true ); +} diff --git a/tests/behat/admin-interface.feature b/tests/behat/admin-interface.feature index 044f877f..7221b623 100644 --- a/tests/behat/admin-interface.feature +++ b/tests/behat/admin-interface.feature @@ -3,6 +3,14 @@ Feature: Adjust the Default Max Age setting Background: Given I log in as an admin +Scenario: Set max-age to 600 and auto-update to the default value + When I go to "/wp-admin/options-general.php?page=pantheon-cache" + And I fill in "pantheon-cache[default_ttl]" with "600" + And I press "Save Changes" + Then I should see "The Pantheon GCDN cache max-age has been updated. The previous value was 10 minutes. The new value is 1 week." + When I go to "/wp-admin/options-general.php?page=pantheon-cache" + Then the "pantheon-cache[default_ttl]" field should contain "604800" + Scenario: Change the cache max age When I go to "/wp-admin/options-general.php?page=pantheon-cache" And I fill in "pantheon-cache[default_ttl]" with "300" diff --git a/tests/phpunit/test-admin-interface.php b/tests/phpunit/test-admin-interface.php index 8da3f335..4f91f469 100644 --- a/tests/phpunit/test-admin-interface.php +++ b/tests/phpunit/test-admin-interface.php @@ -25,6 +25,7 @@ public function setUp(): void { public function tearDown(): void { parent::tearDown(); delete_option( 'pantheon-cache' ); + delete_option( 'pantheon_max_age_updated' ); delete_transient( 'papc_max_age_compare' ); } @@ -157,4 +158,117 @@ public function delete_transient_on_option_update_provider() { ]; } + /** + * Test running set_max_age_to_default when no option has been set. + */ + public function test_set_max_age_to_default_start() { + // Default start state. + delete_option( 'pantheon-cache' ); + set_max_age_to_default(); + $pantheon_cache = get_option( 'pantheon-cache' ); + $max_age_updated = get_option( 'pantheon_max_age_updated' ); + $this->assertFalse( isset( $pantheon_cache['default_ttl'] ), 'The default_ttl option should not be set.' ); + $this->assertFalse( $max_age_updated, 'The max age updated option should not be set.'); + } + + /** + * Test running set_max_age_to_default when the default_ttl is 600. + */ + public function test_set_max_age_to_default_600() { + // Cache max-age set to 600 and we haven't updated it since the notice. + $pantheon_cache = []; + $pantheon_cache['default_ttl'] = 600; + update_option( 'pantheon-cache', $pantheon_cache ); + $pantheon_cache = get_option( 'pantheon-cache' ); + // Validate that the option was set correctly. We'll only check this once. + $this->assertEquals( 600, $pantheon_cache['default_ttl'], 'The default_ttl option should be set to 600.' ); + set_max_age_to_default(); + $pantheon_cache = get_option( 'pantheon-cache' ); + $max_age_updated = get_option( 'pantheon_max_age_updated' ); + $this->assertEquals( WEEK_IN_SECONDS, $pantheon_cache['default_ttl'], 'The default_ttl option should be set to 1 week.'); + $this->assertTrue( $max_age_updated, 'The max age updated option should be true.'); + } + + /** + * Test running set_max_age_to_default when the default_ttl was manually reset to 600. + */ + public function test_set_max_age_to_default_600_reset() { + // Cache max-age set to 600 and we have updated it since the notice. + $pantheon_cache = []; + $pantheon_cache['default_ttl'] = 600; + update_option( 'pantheon-cache', $pantheon_cache ); + update_option( 'pantheon_max_age_updated', true ); + set_max_age_to_default(); + $pantheon_cache = get_option( 'pantheon-cache' ); + $this->assertEquals( 600, $pantheon_cache['default_ttl'], 'The default_ttl option should be set to 600.' ); + } + + /** + * Test running set_max_age_to_default when the default_ttl is 432000. + */ + public function test_set_max_age_to_default_432000() { + // Cache max-age set to anything else. We shouldn't ever see the notice. + delete_option( 'pantheon_max_age_updated' ); + $pantheon_cache = []; + $pantheon_cache['default_ttl'] = 432000; + update_option( 'pantheon-cache', $pantheon_cache ); + set_max_age_to_default(); + $pantheon_cache = get_option( 'pantheon-cache' ); + $max_age_updated = get_option( 'pantheon_max_age_updated' ); + $this->assertEquals( 432000, $pantheon_cache['default_ttl'], 'The default_ttl option should be set to 432000.' ); + $this->assertTrue( $max_age_updated, 'The max age updated option should be true.'); + } + + /** + * Test running set_max_age_to_default when the default_ttl is 600 and a filter is set. + */ + public function test_set_max_age_to_default_600_filter() { + // Use the filter to override the default. If a site had 600 set, we should still update it to the filtered value. + add_filter( 'pantheon_cache_default_max_age', function() { + return 3 * DAY_IN_SECONDS; + } ); + $pantheon_cache = []; + $pantheon_cache['default_ttl'] = 600; + update_option( 'pantheon-cache', $pantheon_cache ); + set_max_age_to_default(); + $pantheon_cache = []; + $pantheon_cache = get_option( 'pantheon-cache' ); + $max_age_updated = get_option( 'pantheon_max_age_updated' ); + $this->assertEquals( 3 * DAY_IN_SECONDS, $pantheon_cache['default_ttl'], 'The default_ttl option should be set to 3 days (the filtered value).' ); + $this->assertTrue( $max_age_updated, 'The max age updated option should be true.'); + } + + /** + * Test the admin notice for the max age being updated. + */ + function test_max_age_updated_admin_notice() { + // Switch to admin. + wp_set_current_user( 1 ); + + // We're testing notices but we don't want to display the "no mu plugin" notice. + add_filter( 'pantheon_apc_disable_admin_notices', function( $disable_notices, $callback ) { + if ( $callback === __NAMESPACE__ . '\\admin_notice_no_mu_plugin' ) { + return true; + } + return $disable_notices; + }, 10, 2 ); + + $current_user_id = get_current_user_id(); + + // Reset everything to start. + delete_option( 'pantheon-cache' ); + delete_user_meta( $current_user_id, 'pantheon_max_age_updated_notice' ); + + // Make sure the option says we've updated the max age. We're checking the notice, not the option. + update_option( 'pantheon_max_age_updated', true ); + + ob_start(); + max_age_updated_admin_notice(); + $notice = ob_get_clean(); + + // The notice that we're catching should be the one that the max-age was updated. + $this->assertStringContainsString( 'The Pantheon GCDN cache max-age has been updated. The previous value was 10 minutes. The new value is 1 week.', $notice ); + // The user meta should have been updated in the process. + $this->assertEquals( 1, get_user_meta( $current_user_id, 'pantheon_max_age_updated_notice', true ) ); + } }