Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 90 additions & 16 deletions inc/pantheon-page-cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@

add_action( 'admin_post_pantheon_cache_flush_site', [ $this, 'flush_site' ] );

add_action( 'send_headers', [ $this, 'cache_add_headers' ] );
add_filter( 'rest_post_dispatch', [ $this, 'filter_rest_post_dispatch_send_cache_control' ], 10, 2 );
add_filter( 'nocache_headers', [ $this, 'filter_nocache_headers' ] );
add_filter( 'wp_headers', [ $this, 'filter_wp_headers' ] );
add_filter( 'rest_post_dispatch', [ $this, 'filter_rest_post_dispatch_send_cache_control' ] );

add_action( 'admin_notices', function () {
global $wp_object_cache;
Expand Down Expand Up @@ -417,54 +418,127 @@
/**
* Get the cache-control header value.
*
* This removes "max-age=0" which could hypothetically be used by
* Varnish on an immediate subsequent request.
*
* @return string
* @return non-empty-string Header value.
*/
private function get_cache_control_header_value() {
private function get_cache_control_header_value(): string {

Check warning on line 423 in inc/pantheon-page-cache.php

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

inc/pantheon-page-cache.php#L423

get_cache_control_header_value accesses the super-global variable $_ENV.
Comment thread
jazzsequence marked this conversation as resolved.
if ( ! is_admin() && ! is_user_logged_in() ) {
$ttl = apply_filters( 'pantheon_cache_default_max_age', absint( $this->options['default_ttl'] ) );
$ttl = (int) apply_filters( 'pantheon_cache_default_max_age', absint( $this->options['default_ttl'] ) );
if ( $ttl < 60 && isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && 'live' === $_ENV['PANTHEON_ENVIRONMENT'] ) {
$ttl = 60;
}

return sprintf( 'public, max-age=%d', $ttl );
$directives = [ 'public', "max-age={$ttl}" ];
} else {
return 'no-cache, no-store, must-revalidate';
$nocache_headers = wp_get_nocache_headers();
if ( isset( $nocache_headers['Cache-Control'] ) && is_string( $nocache_headers['Cache-Control'] ) ) {
$directives = array_diff(
(array) preg_split( '/\s*,\s*/', $nocache_headers['Cache-Control'] ),
[ 'max-age=0' ]
);
} else {
// Note that `no-store` is intentionally omitted to enable bfcache per <https://core.trac.wordpress.org/ticket/63636>.
$directives = [ 'no-cache', 'must-revalidate', 'private' ];
}
}

return implode( ', ', $directives );
}

/**
* Add the cache-control header.
* Determines whether the Cache-Control header should be sent.
*
* @return void
* @return bool Whether the Cache-Control header should be sent.
*/
public function cache_add_headers() {
private function should_skip_cache_control_header(): bool {
Comment thread
jazzsequence marked this conversation as resolved.
/**
* Filter to skip the cache control header.
*
* @param bool $skip_cache_control Whether to skip the cache control header.
* @see https://github.com/pantheon-systems/pantheon-mu-plugin/issues/37
* @return bool
*/
$skip_cache_control = apply_filters( 'pantheon_skip_cache_control', false );
return (bool) apply_filters( 'pantheon_skip_cache_control', false );
}

if ( $skip_cache_control ) {
/**
* Add the cache-control header.
*
* @deprecated
* @return void
*/
public function cache_add_headers() {
if ( $this->should_skip_cache_control_header() ) {
return;
}

header( sprintf( 'cache-control: %s', $this->get_cache_control_header_value() ) );
}

/**
* Filters nocache_headers so that max-age=0 is omitted.
*
* This removes "max-age=0" which could hypothetically be used by
* Varnish on an immediate subsequent request.
*
* @param array<string, string>|mixed $headers Nocache headers.
* @return array<string, string> Filtered nocache headers.
*/
public function filter_nocache_headers( $headers ): array {
Comment thread
westonruter marked this conversation as resolved.
if ( ! is_array( $headers ) ) {
$headers = [];
}

if ( $this->should_skip_cache_control_header() ) {
return $headers;
}

if ( isset( $headers['Cache-Control'] ) && is_string( $headers['Cache-Control'] ) ) {
$headers['Cache-Control'] = implode(
', ',
array_diff(
(array) preg_split( '/\s*,\s*/', $headers['Cache-Control'] ),
[ 'max-age=0' ]
)
);
}

return $headers;
}

/**
* Filters wp_headers to add Cache-Control directives.
*
* @param array<string, string>|mixed $headers Headers to send.
* @return array<string, string> Modified headers to send.
*/
public function filter_wp_headers( $headers ): array {
Comment thread
westonruter marked this conversation as resolved.
if ( ! is_array( $headers ) ) {
$headers = [];
}

if ( $this->should_skip_cache_control_header() ) {
return $headers;
}

$headers['Cache-Control'] = $this->get_cache_control_header_value();
return $headers;
}

/**
* Send the cache control header for REST API requests
*
* This will be overridden when a user is logged in and the REST API {@see \WP_REST_Server::serve_request()} is
* sending nocache headers already. In this case, it is important to rely on filtering `nocache_headers` to add
* any critical Cache-Control directives. So this method is primarily relevant for public REST API responses,
* unless `rest_send_nocache_headers` has been filtered to be false.
*
* @param WP_REST_Response $response Response.
* @return WP_REST_Response Response.
*/
public function filter_rest_post_dispatch_send_cache_control( $response ) {
$response->header( 'Cache-Control', $this->get_cache_control_header_value() );
if ( ! $this->should_skip_cache_control_header() ) {
$response->header( 'Cache-Control', $this->get_cache_control_header_value() );
}
return $response;
}

Expand Down
8 changes: 5 additions & 3 deletions inc/pantheon-updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ function _pantheon_upstream_update_notice() {
$div_style = esc_attr( 'display: table;' );
$paragraph_style = esc_attr( 'font-size: 14px; font-weight: bold; margin: 0 0 0.5em 0;' );

// If WP core is out of date, alter the message and show the nag everywhere.
if ( ! _pantheon_is_wordpress_core_latest() ) {
// If WP core is out of date, alter the message and show the nag everywhere.
// Translators: %s is a URL to the user's Pantheon Dashboard.
$notice_message = sprintf( __( 'A new WordPress update is available! Please update from <a href="%s">your Pantheon dashboard</a>.', 'pantheon-systems' ), 'https://dashboard.pantheon.io/sites/' . $_ENV['PANTHEON_SITE'] );
}
Expand Down Expand Up @@ -157,8 +157,10 @@ function _pantheon_disable_wp_updates(): object {
];
}

// In the Test and Live environments, clear plugin/theme update notifications.
// Users must check a dev or multidev environment for updates.
/**
* In the Test and Live environments, clear plugin/theme update notifications.
* Users must check a dev or multidev environment for updates.
*/
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], [ 'test', 'live' ], true ) && ( php_sapi_name() !== 'cli' ) ) {

// Disable Plugin Updates.
Expand Down
7 changes: 5 additions & 2 deletions pantheon.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@
*/
define( 'FS_METHOD', 'direct' );
}
// When developing a WordPress Multisite locally, ensure that this constant is set.
// This will set the Multisite variable in all Pantheon environments.
/**
* When developing a WordPress Multisite locally, ensure that this constant
* is set. This will set the Multisite variable in all Pantheon
* environments.
*/
if ( getenv( 'FRAMEWORK' ) === 'wordpress_network' && ! defined( 'WP_ALLOW_MULTISITE' ) ) {
define( 'WP_ALLOW_MULTISITE', true );
}
Expand Down
5 changes: 5 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,10 @@
<exclude name="Generic.Commenting.DocComment.MissingShort">
<exclude-pattern>inc/pantheon-page-cache.php</exclude-pattern>
</exclude>

<!-- Ignore long lines in includes-network.php -->
<exclude name="Pantheon_WP.Commenting.DisallowMultilineSlashComment.LongLine">
<exclude-pattern>inc/network/includes-network.php</exclude-pattern>
</exclude>
</rule>
</ruleset>