Skip to content

Commit

Permalink
[BUGS-8452] add callback info to filtered message (#292)
Browse files Browse the repository at this point in the history
* add a new function that will get the filter callback name
this way it's easier to debug because we can show people where they've added the filter

* alter the filtered message with the filter callback name(s)
if it's in an anonymous function, we note that.

* handle the anonymous function string early
so we don't need to reset it to the string we want to output later

* if one callaback, wrap in code tags or just output as plaintext (if anonymous)

* drop handling the 'an anonymous function' transform

* add test filter callbacks

* add tests

* adjust linting

* remove $priority
not used

* bump tested-up-to

* apparently this is a gutenberg thing

* WP 6.7 changes the output of human_time_diff

* strip out alpha, beta, rc, etc tags from version
these aren't valid versions, so version_compare freaks out and (incorrectly) flags 6.7-alpha-whatever as less than 6.7 🤦‍♂️
  • Loading branch information
jazzsequence authored Aug 6, 2024
1 parent b2b358b commit 8ef69e1
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**Contributors:** [getpantheon](https://profiles.wordpress.org/getpantheon), [danielbachhuber](https://profiles.wordpress.org/danielbachhuber), [kporras07](https://profiles.wordpress.org/kporras07), [jspellman](https://profiles.wordpress.org/jspellman/), [jazzs3quence](https://profiles.wordpress.org/jazzs3quence/), [ryanshoover](https://profiles.wordpress.org/ryanshoover/), [rwagner00](https://profiles.wordpress.org/rwagner00/), [pwtyler](https://profiles.wordpress.org/pwtyler)
**Tags:** pantheon, cdn, cache
**Requires at least:** 6.4
**Tested up to:** 6.5.3
**Tested up to:** 6.6.1
**Stable tag:** 2.0.1-dev
**License:** GPLv2 or later
**License URI:** http://www.gnu.org/licenses/gpl-2.0.html
Expand Down
71 changes: 66 additions & 5 deletions inc/admin-interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,55 @@ function add_max_age_setting_header() {
return ob_get_clean();
}

/**
* Get the callback(s) hooked to pantheon_cache_default_max_age, if one exists.
*
* @since 2.1.0
* @return string
*/
function get_pantheon_cache_filter_callback() {
global $wp_filter;
$hook = 'pantheon_cache_default_max_age';
$output = '';

if ( ! has_filter( $hook ) ) {
return $output;
}

$callback_functions = [];
if ( isset( $wp_filter[ $hook ] ) ) {
foreach ( $wp_filter[ $hook ]->callbacks as $callbacks ) {
foreach ( $callbacks as $callback ) {
if ( is_string( $callback['function'] ) ) {
// Function name.
$callback_functions[] = $callback['function'];
} elseif ( is_array( $callback['function'] ) ) {
// Method call.
$class = is_object( $callback['function'][0] ) ? get_class( $callback['function'][0] ) : $callback['function'][0];
$method = $callback['function'][1];
$callback_functions[] = "$class::$method";
} else {
$callback_functions[] = __( 'an anonymous function', 'pantheon-advanced-page-cache' );
}
}
}
}

// Count the callbacks and if there's only one, return the name (if able).
$callbacks_count = count( $callback_functions );
if ( $callbacks_count === 1 ) {
return stripos( $callback_functions[0], 'an anonymous function' ) === false ? "<code>{$callback_functions[0]}<code>" : $callback_functions[0];
}

// If there are multiple callbacks, format the output.
foreach ( $callback_functions as $index => $callback ) {
$callback = stripos( $callback, 'anonymous' ) !== false ? $callback : "<code>$callback</code>";
$output .= $index === $callbacks_count - 1 ? __( 'and', 'pantheon-advanced-page-cache' ) . ' ' . $callback : $callback . ', ';
}

return $output;
}

/**
* Add a description to the max-age setting field.
*
Expand All @@ -94,15 +143,27 @@ function add_max_age_setting_header() {
*/
function add_max_age_setting_description() {
$is_filtered = has_filter( 'pantheon_cache_default_max_age' );
$filter_callback = get_pantheon_cache_filter_callback();
$filtered_message = '';
$above_recommended_message = __( 'Your cache maximum age is currently <strong>above</strong> the recommended value.', 'pantheon-advanced-page-cache' );
$below_recommended_message = __( 'Your cache maximum age is currently <strong>below</strong> the recommended value.', 'pantheon-advanced-page-cache' );
$recommended_message = __( 'Your cache maximum age is currently set to the recommended value.', 'pantheon-advanced-page-cache' );
$recommendation_message = get_current_max_age() > WEEK_IN_SECONDS ? $above_recommended_message : ( get_current_max_age() < WEEK_IN_SECONDS ? $below_recommended_message : $recommended_message );
$filtered_message = $is_filtered ? sprintf(
// translators: %s is the humanized max-age.
__( 'This value has been hardcoded to %s via a filter.', 'pantheon-advanced-page-cache' ),
'<strong>' . humanized_max_age() . '</strong>'
) : '';

if ( $is_filtered ) {
// Set the message to name the callback(s).
$filtered_message = ! empty( $filter_callback ) ? sprintf(
// translators: %1$s is the humanized max-age, %2$s is the callback function(s).
__( 'This value has been hardcoded to %1$s via a filter hooked to %2$s in your code.', 'pantheon-advanced-page-cache' ),
'<strong>' . humanized_max_age() . '</strong>',
$filter_callback
) : sprintf(
// translators: %s is the humanized max-age.
__( 'This value has been hardcoded to %s via a filter.', 'pantheon-advanced-page-cache' ),
'<strong>' . humanized_max_age() . '</strong>'
); // If there's no callback, we'll just note that it's been hardcoded. This shouldn't ever happen.
}

$pantheon_cache = get_option( 'pantheon-cache', [] );
$has_custom_ttl = isset( $pantheon_cache['default_ttl'] ) && ! array_key_exists( $pantheon_cache['default_ttl'], max_age_options() );
$filtered_message .= $has_custom_ttl && ! $is_filtered ? '<br />' . __( '<strong>Warning:</strong>The cache max age is not one of the recommended values. If this is not intentional, you should remove this custom value and save the settings, then select one of the options from the dropdown.', 'pantheon-advanced-page-cache' ) : '';
Expand Down
2 changes: 1 addition & 1 deletion readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Contributors: getpantheon, danielbachhuber, kporras07, jspellman, jazzs3quence, ryanshoover, rwagner00, pwtyler
Tags: pantheon, cdn, cache
Requires at least: 6.4
Tested up to: 6.5.3
Tested up to: 6.6.1
Stable tag: 2.0.1-dev
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Expand Down
50 changes: 46 additions & 4 deletions tests/phpunit/test-admin-interface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@
* Tests for the admin interface namespace..
*/
class Admin_Interface_Functions extends \Pantheon_Advanced_Page_Cache_Testcase {
/**
* Get the WordPress version-compatible string for "5 minutes".
*/
private function get_five_minutes() {
$wp_version = get_bloginfo( 'version' );

// If the version contains a string like -alpha, -beta, etc., strip it.
$wp_version = preg_replace( '/-.*/', '', $wp_version );

// WordPress 6.7 changed the string for "5 mins" to "5 minutes".
$five_mins = version_compare( $wp_version, '6.7', '<' ) ? '5 mins' : '5 minutes';
return $five_mins;
}

/**
* Set up tests.
*/
Expand Down Expand Up @@ -46,14 +60,16 @@ public function test_get_max_age() {
*/
public function test_site_health_tests_300_seconds() {
$tests = apply_filters( 'site_status_tests', [] );
$five_mins = $this->get_five_minutes();

$this->assertContains( 'pantheon_edge_cache', array_keys( $tests['direct'] ) );

// Base test with 300 second max-age.
$test_results = test_cache_max_age();
$this->assertEquals( 'recommended', $test_results['status'] );
$this->assertEquals( 'red',$test_results['badge']['color'] );
$this->assertStringContainsString( '5 mins', $test_results['description'] );

$this->assertStringContainsString( $five_mins, $test_results['description'] );
$this->assertStringContainsString( 'We recommend increasing to 1 week', $test_results['description'] );
}

Expand Down Expand Up @@ -99,8 +115,10 @@ public function test_humanized_max_age( $max_age, $expected ) {
* @return array
*/
public function humanized_max_age_provider() {
$five_mins = $this->get_five_minutes();
var_dump( $five_mins );
return [
[ 300, '5 mins' ], // 300 seconds is humanized to 5 mins.
[ 300, $five_mins ], // 300 seconds is humanized to 5 mins.
[ 5 * DAY_IN_SECONDS, '5 days' ],
[ WEEK_IN_SECONDS, '1 week' ],
];
Expand Down Expand Up @@ -328,6 +346,14 @@ public function test_add_max_age_setting_description( $max_age, $expected ) {
add_filter( 'pantheon_cache_default_max_age', function() {
return 10 * DAY_IN_SECONDS;
} );
} elseif ( $max_age === 'multiple-filters-below' ) {
add_filter( 'pantheon_cache_default_max_age', [ $this, 'reset_cache_max_age' ] );
add_filter( 'pantheon_cache_default_max_age', [ $this, 'another_function' ] );
add_filter( 'pantheon_cache_default_max_age', function() {
return 3 * DAY_IN_SECONDS;
} );
} elseif ( $max_age === 'just-named-filters' ) {
add_filter( 'pantheon_cache_default_max_age', [ $this, 'reset_cache_max_age' ] );
} else {
update_option( 'pantheon-cache', [ 'default_ttl' => $max_age ] );
}
Expand All @@ -343,15 +369,31 @@ public function test_add_max_age_setting_description( $max_age, $expected ) {
*/
public function add_max_age_setting_description_provider() {
return [
[ 'filter-below', 'Your cache maximum age is currently <strong>below</strong> the recommended value. This value has been hardcoded to <strong>3 days</strong> via a filter.' ],
[ 'filter-above', 'Your cache maximum age is currently <strong>above</strong> the recommended value. This value has been hardcoded to <strong>1 week</strong> via a filter.' ],
[ 'filter-below', 'Your cache maximum age is currently <strong>below</strong> the recommended value. This value has been hardcoded to <strong>3 days</strong> via a filter hooked to an anonymous function in your code.' ],
[ 'filter-above', 'Your cache maximum age is currently <strong>above</strong> the recommended value. This value has been hardcoded to <strong>1 week</strong> via a filter hooked to an anonymous function in your code.' ],
[ 'multiple-filters-below', 'Your cache maximum age is currently <strong>below</strong> the recommended value. This value has been hardcoded to <strong>3 days</strong> via a filter hooked to <code>Pantheon_Advanced_Page_Cache\Admin_Interface\Admin_Interface_Functions::reset_cache_max_age</code>, <code>Pantheon_Advanced_Page_Cache\Admin_Interface\Admin_Interface_Functions::another_function</code>, and an anonymous function in your code.' ],
[ 'just-named-filters', 'Your cache maximum age is currently <strong>below</strong> the recommended value. This value has been hardcoded to <strong>1 second</strong> via a filter hooked to <code>Pantheon_Advanced_Page_Cache\Admin_Interface\Admin_Interface_Functions::reset_cache_max_age<code> in your code.' ],
[ 600, 'Your cache maximum age is currently <strong>below</strong> the recommended value. <br /><strong>Warning:</strong>The cache max age is not one of the recommended values.' ],
[ WEEK_IN_SECONDS, 'Your cache maximum age is currently set to the recommended value.' ],
[ MONTH_IN_SECONDS, 'Your cache maximum age is currently <strong>above</strong> the recommended value.' ],
[ YEAR_IN_SECONDS, 'Your cache maximum age is currently <strong>above</strong> the recommended value.' ],
];
}

/**
* Filter callback for testing pantheon_cache_default_max_age.
*/
public function reset_cache_max_age() {
return 0;
}

/**
* Filter callback for testing pantheon_cache_default_max_age.
*/
public function another_function() {
return 42;
}

/**
* Test the update_default_ttl_input function. Check the input type if the max age has been filtered.
*
Expand Down

0 comments on commit 8ef69e1

Please sign in to comment.