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
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,48 @@
*/
class GravityView_Plugin_Hooks_Gravity_Forms extends GravityView_Plugin_and_Theme_Hooks {

/**
* The query arg to identify the view.
*
* @since TODO
*
* @var string
*/
const QUERY_ARG_VIEW_ID = 'gvid';

/**
* The nonce query arg.
*
* @since TODO
*
* @var string
*/
const QUERY_ARG_NONCE = 'gvnonce';

/**
* The nonce action.
*
* @since TODO
*
* @var string
*/
const NONCE_ACTION = 'gvdownload';

/**
* @inheritDoc
*
* @since TODO
*
* @var string
*/
public $class_name = 'GFForms';

/**
* @inheritDoc
*
* @since 1.15.2
*
* @var array
*/
protected $style_handles = array(
'gform_tooltip',
Expand All @@ -32,13 +69,104 @@ class GravityView_Plugin_Hooks_Gravity_Forms extends GravityView_Plugin_and_Them

/**
* @inheritDoc
*
* @since 1.15.2
*
* @var array
*/
protected $script_handles = array(
'gform_tooltip_init',
'gform_field_filter',
'gform_forms',
);

/**
* @inheritDoc
*
* @since TODO
*/
public function __construct() {
parent::__construct();

if ( self::is_gf_gv_download() ) {
add_filter( 'nocache_headers', [ $this, 'remove_nocache_headers_from_gf_download' ], 1000 );
}
}

/**
* @inheritDoc
*
* @since TODO
*/
public function add_hooks() {
parent::add_hooks();

add_action( 'gravityview/template/before', [ $this, 'add_query_arg_to_gf_download_url' ] );
}

/**
* Checks if the current request is a Gravity Forms download coming from GravityView.
*
* @since TODO
*
* @return bool
*/
private static function is_gf_gv_download() {

$is_download = ! empty( $_GET['gf-download'] );
$nonce = \GV\Utils::get( $_GET, self::QUERY_ARG_NONCE, '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$is_nonce_valid = $nonce && wp_verify_nonce( $nonce, self::NONCE_ACTION );

return $is_download && $is_nonce_valid;
}

/**
* Adds a query arg to the Gravity Forms download URL to identify the View.
*
* This allows us to only remove the cache headers for GravityView embedded files.
*
* @param \GV\Template_Context $context The context object.
*
* @since TODO
*/
public function add_query_arg_to_gf_download_url() {
/**
* Adds the View ID to the Gravity Forms download URL.
*
* @param string $url The existing Gravity Forms download URL.
*
* @return string The new Gravity Forms download URL, with the View ID added.
*/
add_filter( 'gform_secure_file_download_url', function( $url ) {
return wp_nonce_url( $url, self::NONCE_ACTION, self::QUERY_ARG_NONCE );
} );
}

/**
* Remove cache headers for Gravity Forms downloads.
*
* @param array $headers
*
* @since TODO
*
* @return array
*/
public static function remove_nocache_headers_from_gf_download( $headers ) {
// Sanity check (this shouldn't be called if it's not already a GF download from GV).
if ( ! self::is_gf_gv_download() ) {
return $headers;
}

// Nonces are valid for 24-48 hours.
$max_age = DAY_IN_SECONDS * 2;

// Add caching headers to allow caching for as long as the nonce is valid.
$headers['Cache-Control'] = 'max-age=' . $max_age . ', public, immutable';
$headers['Expires'] = gmdate( 'D, d M Y H:i:s', time() + $max_age ) . ' GMT';

return $headers;
}
Comment on lines +154 to +168
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove conflicting nocache headers before setting cache headers.

The method adds cache headers but doesn't remove existing nocache headers that might conflict. This could lead to inconsistent caching behavior.

 	public static function remove_nocache_headers_from_gf_download( $headers ) {
 		// Sanity check (this shouldn't be called if it's not already a GF download from GV).
 		if ( ! self::is_gf_gv_download() ) {
 			return $headers;
 		}
 
+		// Remove conflicting nocache headers
+		unset( $headers['Cache-Control'] );
+		unset( $headers['Expires'] );
+		unset( $headers['Pragma'] );
+
 		// Nonces are valid for 24-48 hours.
 		$max_age = DAY_IN_SECONDS * 2;
 
 		// Add caching headers to allow caching for as long as the nonce is valid.
 		$headers['Cache-Control'] = 'max-age=' . $max_age . ', public, immutable';
 		$headers['Expires'] = gmdate( 'D, d M Y H:i:s', time() + $max_age ) . ' GMT';
 
 		return $headers;
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function remove_nocache_headers_from_gf_download( $headers ) {
// Sanity check (this shouldn't be called if it's not already a GF download from GV).
if ( ! self::is_gf_gv_download() ) {
return $headers;
}
// Nonces are valid for 24-48 hours.
$max_age = DAY_IN_SECONDS * 2;
// Add caching headers to allow caching for as long as the nonce is valid.
$headers['Cache-Control'] = 'max-age=' . $max_age . ', public, immutable';
$headers['Expires'] = gmdate( 'D, d M Y H:i:s', time() + $max_age ) . ' GMT';
return $headers;
}
public static function remove_nocache_headers_from_gf_download( $headers ) {
// Sanity check (this shouldn't be called if it's not already a GF download from GV).
if ( ! self::is_gf_gv_download() ) {
return $headers;
}
// Remove conflicting nocache headers
unset( $headers['Cache-Control'] );
unset( $headers['Expires'] );
unset( $headers['Pragma'] );
// Nonces are valid for 24-48 hours.
$max_age = DAY_IN_SECONDS * 2;
// Add caching headers to allow caching for as long as the nonce is valid.
$headers['Cache-Control'] = 'max-age=' . $max_age . ', public, immutable';
$headers['Expires'] = gmdate( 'D, d M Y H:i:s', time() + $max_age ) . ' GMT';
return $headers;
}
🤖 Prompt for AI Agents
In
includes/plugin-and-theme-hooks/class-gravityview-plugin-hooks-gravity-forms.php
around lines 155 to 169, the method sets cache headers but does not remove
existing nocache headers that can conflict and cause inconsistent caching. To
fix this, identify and remove any nocache-related headers such as 'Pragma',
'Cache-Control' with no-cache directives, and 'Expires' before setting the new
cache headers. This ensures no conflicting headers remain and caching behavior
is consistent.


}

new GravityView_Plugin_Hooks_Gravity_Forms();
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Beautifully display your Gravity Forms entries. Learn more on [gravitykit.com](h
= develop =

* Added compatibility for Views embedded in Jetpack CRM Client Portal Pro pages.
* Improved performance of Gravity Forms secure embedded file image downloads embedded in Views by adding caching, while also maintaining security.

= 2.42.2 on July 17, 2025 =

Expand Down