Skip to content

Commit

Permalink
[CMSP-994] Automatically update the default_ttl value if it was set…
Browse files Browse the repository at this point in the history
… to 600 (#269)

* add initial admin interface class
hook to mu-plugin > 1.4.0

* some more scaffolding

* require at least 6.4

* don't show notices if wp_admin_notice doesn't exist

* add notice if mu-plugin was not found

* add notice if the mu-plugin is old

* fix link and change decimal to string

* use spaces instead of line breaks

* add helper function to get current max age
this is either set in the mu-plugin or empty. if empty, it should default to 1 week

* add notice if less than 1 week but not == 600 seconds

* add docblock

* add translator comments

* update tested up to and requires at least values in readmes

* version bump

* bump composer deps

* don't display the warnings if we aren't on the pantheon cache admin page

* convert static class to a namespace
there's no reason to make this a class since we're not using any class features

* add a bootstrapper for namespace-only files

* lint

* escape the wp_die message

* use a helper for humanized time calculations

* we still need to test the current max age

* pass the current max age to the message, too
and be specific that we're talking about seconds

* use the filterable value for default max age
because it could be something different

* add a helper function for retrieving the default max age
this is helpful so we can always return the filtered value

* also display the seconds in the successful test

* rank the max age value
don't say it's "very low" unless that's actually accurate.

* add caching to the ranked compare

* make the color more severe if it's a bigger issue

* change the color of the admin notice based on the severity of the diff

* clear the transient when the option is updated

* break notice type into a variable

* fix the translator note

* keep the rank but hide it from the dom

* add unit tests

* add initial behat test
let's just see if we can assume this will work

* fix failing test

* specify the element where the notices are

* add site health check test

* actually save the changes

* remove max age check
only exists in an html comment anyway

* simplify the site health check

* add the message when you expand the accordion

* add other site health things

* change press to click?

* add "open the accordion" as a custom step

* move behat stuff around

* move stuff around again

* update the behat.yml

* remove custom context and try "when I follow"

* move to checking the text inside the elements

* target the hidden element

* use hidden='hidden'

* call it a div

* simplify the tests

* remove press
since we can't actually press

* it did actually find the right heading
maybe it will find the right text?

* add @\since tags

* add changelog and upgrade notice

* let's try checking for some of the hidden text

* period at the end of the sentence

* add the ranks back
this shows us that our ranking function is working

* add the messages

* remove age rank tests
because goutte doesn't natively interpret html comments

* add github testing badge
since phpunit is no longer run on circle

* add script to maybe skip behat tests if we don't need to run them

* add step to workflow

* do not run if the circle config changes

* also ignore if scripts (that aren't behat-related) have changed

* fix the logic (again)

* one more flippity flip

* remove the "ignoring" message
it's actually implied by the fact that is_ignored is checked

* use function to determine if a file should be ignored

Co-authored-by: Phil Tyler <[email protected]>

* update changelog to note mu-plugin updates

* add functionality to automatically set the default_ttl if it was set to 600

* trigger the setting change and display an admin notice informing users it was done
only show the notice to users who haven't already seen it and who can manage_options

* add unit tests for set_max_age_to_default

* move the max age update notice to the bootstrap

* remove the set_max_age_updated helper
this wasn't working and meant that we were needing to make multiple update options in a short space of time. we might have actually been running into race conditions where one update was overwriting the other one.

* use a new option for the updated flag

* add _notice to the user meta key so it's distinct from the new option

* update tests for new changes

* add translator note

* user notice about 600 second update is not dismissable
because it only appears once

* don't show seconds in updated notice

* pass the function into the apply_filter hook
so you can selectively disable specific notices

* add docblock

* add test for the notice

* return the value of disable_notices
rather than hard-coded "false"

* Add scenario to set max-age to 600 and auto-update to the default value

* here's a behat test that might not work
not sure if it will know what pantheon-cache[default-ttl] is without giving it an element to look at.

* fixed it based on upstream tests

* refresh the page

* go to instead of refresh
since refresh isn't a thing ¯\_(ツ)_/¯

* add additional test failure messaging

* break up tests

---------

Co-authored-by: Phil Tyler <[email protected]>
  • Loading branch information
jazzsequence and pwtyler authored May 17, 2024
1 parent 83df364 commit f1cfb46
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 3 deletions.
Empty file added assets/css/main.css
Empty file.
92 changes: 89 additions & 3 deletions inc/admin-interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
}

/**
Expand All @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 <a href="%2$s">Pantheon documentation</a>.', '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 );
}
8 changes: 8 additions & 0 deletions tests/behat/admin-interface.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
114 changes: 114 additions & 0 deletions tests/phpunit/test-admin-interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
}

Expand Down Expand Up @@ -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 ) );
}
}

0 comments on commit f1cfb46

Please sign in to comment.