Skip to content

gw-custom-modifier-file-upload.php: Added snippet for custom filename modifier for file upload fields. #1144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

saifsultanc
Copy link
Contributor

Context

⛑️ Ticket(s): https://secure.helpscout.net/conversation/3025552109/87377

https://github.com/gravitywiz/gp-media-library/pull/35#issuecomment-3156459815

Summary

This snippet is an example of how to add custom modifiers to a Gravity Forms file upload field

Also dependent on GPML https://github.com/gravitywiz/gp-media-library/pull/35

Copy link

coderabbitai bot commented Aug 11, 2025

Walkthrough

Introduces a new Gravity Forms snippet that adds a "filename" merge tag modifier for file upload fields, handling single and multiple files, and integrates with GP Media Library to skip the modifier for images.

Changes

Cohort / File(s) Change Summary
Gravity Forms filename modifier snippet
gravity-forms/gw-filename-modifier-file-upload.php
New snippet hooking gform_merge_tag_filter to output basename(s) for file upload fields when using the :filename modifier; supports multi-file JSON values with
separators. Adds gpml_image_merge_tag_skip_modifiers to skip filename for images.

Sequence Diagram(s)

sequenceDiagram
  participant GF as Gravity Forms (merge tag render)
  participant Snippet as Filename Modifier Snippet
  participant GPML as GP Media Library

  GF->>Snippet: gform_merge_tag_filter(value, merge_tag, modifier, field, raw_value, format)
  alt modifier == 'filename' and field.type == fileupload
    alt multiple files
      Snippet->>GF: Join basenames with <br />
    else single file
      Snippet->>GF: basename(raw_value)
    end
  else
    Snippet->>GF: Return original value
  end

  GF->>GPML: gpml_image_merge_tag_skip_modifiers(mods, ...)
  GPML-->>GF: ['filename'] (skip for images)
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested reviewers

  • veryspry
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch saif/add/87377-add-custom-modifer-filename

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented Aug 11, 2025

Fails
🚫 gravity-forms/gw-filename-modifier-file-upload.php: it looks like this file does not have the appropriate snippet header.
Warnings
⚠️ When ready, don't forget to request reviews on this pull request from your fellow wizards.
Messages
📖 Merlin would give this scroll the highest of praises. Cheers for adding this new snippet to the library! 🪄

Generated by 🚫 dangerJS against 63c34fc

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
gravity-forms/gw-custom-modifier-file-upload.php (2)

11-23: Simplify control flow and add safe guards on $field

Early-return makes the intent clearer and avoids touching $field when it’s not an object.

-add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $modifier, $field, $raw_value, $format ) {
-	if ( $merge_tag != 'all_fields' && $field->type == 'fileupload' && ! empty( $raw_value ) && $modifier == 'filename' ) {
+add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $modifier, $field, $raw_value, $format ) {
+	if ( $merge_tag === 'all_fields' || empty( $raw_value ) || $modifier !== 'filename' || ! is_object( $field ) || $field->type !== 'fileupload' ) {
+		return $value;
+	}
+	if ( empty( $field->multipleFiles ) ) {
-		if ( ! $field->multipleFiles ) {
 			// ...
 		} else {
 			// ...
 		}
-	}
 	return $value;
 }, 10, 6 );

9-9: Nit: fix grammar in instructions

- * 1. Add to snippet to site. See https://gravitywiz.com/documentation/how-do-i-install-a-snippet/.
+ * 1. Add this snippet to the site. See https://gravitywiz.com/documentation/how-do-i-install-a-snippet/.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 453ad6a and 1de825a.

📒 Files selected for processing (1)
  • gravity-forms/gw-custom-modifier-file-upload.php (1 hunks)

Comment on lines 14 to 21
$value = basename( $raw_value );
} else {
$file_list = [];
foreach ( json_decode( $raw_value ) as $filepath ) {
$file_list[] = basename( $filepath );
}
$value = implode( '<br />', $file_list );
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Escape output, strip query strings, honor $format, and harden JSON handling

Avoid potential XSS by escaping HTML output, remove query strings from URLs, respect text vs HTML output via $format, and guard against invalid JSON for multi-file values.

-			$value = basename( $raw_value );
+			// Strip query string/fragment and escape for HTML when appropriate.
+			$path     = is_string( $raw_value ) ? parse_url( $raw_value, PHP_URL_PATH ) : '';
+			$filename = wp_basename( $path ? $path : (string) $raw_value );
+			$value    = ( $format === 'text' ) ? $filename : esc_html( $filename );
@@
-			$file_list = [];
-			foreach ( json_decode( $raw_value ) as $filepath ) {
-				$file_list[] = basename( $filepath );
-			}
-			$value = implode( '<br />', $file_list );
+			$file_list = [];
+			$decoded   = json_decode( $raw_value, true );
+			if ( is_array( $decoded ) ) {
+				foreach ( $decoded as $filepath ) {
+					$path        = parse_url( $filepath, PHP_URL_PATH );
+					$file_list[] = ( $format === 'text' ) ? wp_basename( $path ) : esc_html( wp_basename( $path ) );
+				}
+			} else {
+				// Fallback if the value isn't valid JSON.
+				$path        = is_string( $raw_value ) ? parse_url( $raw_value, PHP_URL_PATH ) : '';
+				$file_list[] = ( $format === 'text' ) ? wp_basename( $path ? $path : (string) $raw_value ) : esc_html( wp_basename( $path ? $path : (string) $raw_value ) );
+			}
+			$separator = ( $format === 'text' ) ? "\n" : '<br />';
+			$value     = implode( $separator, $file_list );
📝 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
$value = basename( $raw_value );
} else {
$file_list = [];
foreach ( json_decode( $raw_value ) as $filepath ) {
$file_list[] = basename( $filepath );
}
$value = implode( '<br />', $file_list );
}
// Strip query string/fragment and escape for HTML when appropriate.
$path = is_string( $raw_value ) ? parse_url( $raw_value, PHP_URL_PATH ) : '';
$filename = wp_basename( $path ? $path : (string) $raw_value );
$value = ( $format === 'text' ) ? $filename : esc_html( $filename );
} else {
$file_list = [];
$decoded = json_decode( $raw_value, true );
if ( is_array( $decoded ) ) {
foreach ( $decoded as $filepath ) {
$path = parse_url( $filepath, PHP_URL_PATH );
$file_list[] = ( $format === 'text' ) ? wp_basename( $path ) : esc_html( wp_basename( $path ) );
}
} else {
// Fallback if the value isn't valid JSON.
$path = is_string( $raw_value ) ? parse_url( $raw_value, PHP_URL_PATH ) : '';
$file_list[] = ( $format === 'text' )
? wp_basename( $path ? $path : (string) $raw_value )
: esc_html( wp_basename( $path ? $path : (string) $raw_value ) );
}
$separator = ( $format === 'text' ) ? "\n" : '<br />';
$value = implode( $separator, $file_list );
}
🤖 Prompt for AI Agents
In gravity-forms/gw-custom-modifier-file-upload.php around lines 14 to 21, the
code currently outputs raw basenames from $raw_value and multi-file JSON without
escaping, removing query strings, honoring the $format parameter, or validating
JSON; update it to: detect whether $raw_value is JSON and safely json_decode
with error checking, ensure the decoded value is an array before iterating,
strip any query string or params from each filepath (e.g. remove anything after
the first '?' or '#') before calling basename, escape the final output for HTML
when $format !== 'text' (and for text output return plain, newline-separated
values when $format === 'text'), and handle fallback to a single safe basename
when JSON is invalid — this will prevent XSS, respect $format, and harden JSON
handling.


// For GP Media Library
add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
return [ 'filename' ];
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Preserve other modifiers skipped by GPML

Don’t clobber existing $skip_modifiers; merge with them to remain compatible with other customizations.

-return [ 'filename' ];
+$skip_modifiers = is_array( $skip_modifiers ) ? $skip_modifiers : array();
+$skip_modifiers[] = 'filename';
+return array_values( array_unique( $skip_modifiers ) );
📝 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
return [ 'filename' ];
// Preserve any previously skipped modifiers, then add 'filename'
$skip_modifiers = is_array( $skip_modifiers ) ? $skip_modifiers : array();
$skip_modifiers[] = 'filename';
return array_values( array_unique( $skip_modifiers ) );
🤖 Prompt for AI Agents
In gravity-forms/gw-custom-modifier-file-upload.php around line 28, the function
currently returns [ 'filename' ] which clobbers any existing $skip_modifiers;
instead merge your modifier into the incoming $skip_modifiers and return the
combined set. Modify the code to add 'filename' to $skip_modifiers (e.g.
$skip_modifiers[] = 'filename' or $skip_modifiers = array_merge($skip_modifiers,
['filename'])), then ensure uniqueness/reset keys (e.g. return
array_values(array_unique($skip_modifiers))) so other GPML/custom modifiers are
preserved.

@spivurno
Copy link
Contributor

@saifsultanc I'd recommend making this snippet title specific to the :filename modifier. If we need to add more modifiers in the future we can either update the snippet then or create new ones.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
gravity-forms/gw-filename-modifier-file-upload.php (1)

3-10: Polish snippet header: brand, clarity, and title specificity

  • Use “Gravity Wiz” (singular) for branding.
  • Tighten wording and make the title explicitly about the :filename modifier, per the PR feedback.
- * Gravity Wizards // Gravity Forms // Filename Modifier for File Upload
+ * Gravity Wiz // Gravity Forms // :filename Modifier for File Upload fields
@@
- * This snippet is an example of how to add filename modifiers to a Gravity Forms file upload field.
+ * This snippet adds the :filename merge tag modifier for Gravity Forms File Upload fields.
@@
- * 1. Add to snippet to site. See https://gravitywiz.com/documentation/how-do-i-install-a-snippet/.
+ * 1. Add this snippet to your site. See https://gravitywiz.com/documentation/how-do-i-install-a-snippet/.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1de825a and 63c34fc.

📒 Files selected for processing (1)
  • gravity-forms/gw-filename-modifier-file-upload.php (1 hunks)

Comment on lines +11 to +24
add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $modifier, $field, $raw_value, $format ) {
if ( $merge_tag != 'all_fields' && $field->type == 'fileupload' && ! empty( $raw_value ) && $modifier == 'filename' ) {
if ( ! $field->multipleFiles ) {
$value = basename( $raw_value );
} else {
$file_list = [];
foreach ( json_decode( $raw_value ) as $filepath ) {
$file_list[] = basename( $filepath );
}
$value = implode( '<br />', $file_list );
}
}
return $value;
}, 10, 6 );
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Harden modifier handling, decoding, and output escaping (avoid warnings and potential XSS)

  • json_decode() may return null; foreach on null will warn. Normalize $raw_value robustly.
  • Strip query strings from URLs before basename().
  • Escape filenames for HTML output to avoid HTML injection if a filename includes special chars.
  • Honor stacked modifiers (e.g., {:filename:esc_html}) by checking substring presence.
  • Use strict comparisons and format-aware separators (
    vs newline).
-add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $modifier, $field, $raw_value, $format ) {
-	if ( $merge_tag != 'all_fields' && $field->type == 'fileupload' && ! empty( $raw_value ) && $modifier == 'filename' ) {
-		if ( ! $field->multipleFiles ) {
-			$value = basename( $raw_value );
-		} else {
-			$file_list = [];
-			foreach ( json_decode( $raw_value ) as $filepath ) {
-				$file_list[] = basename( $filepath );
-			}
-			$value = implode( '<br />', $file_list );
-		}
-	}
-	return $value;
-}, 10, 6 );
+add_filter( 'gform_merge_tag_filter', function ( $value, $merge_tag, $modifiers, $field, $raw_value, $format ) {
+	// Only handle file upload fields with the :filename modifier (supports stacked modifiers).
+	if ( $merge_tag === 'all_fields' || ! $field || $field->type !== 'fileupload' || empty( $raw_value ) || strpos( (string) $modifiers, 'filename' ) === false ) {
+		return $value;
+	}
+
+	$is_html = ( $format === 'html' );
+	$sep     = $is_html ? '<br />' : "\n";
+
+	// Normalize to an array of file paths/URLs.
+	if ( is_array( $raw_value ) ) {
+		$files = $raw_value;
+	} else {
+		$decoded = json_decode( $raw_value, true );
+		$files   = is_array( $decoded ) ? $decoded : array( $raw_value );
+	}
+
+	// Extract safe filenames (strip query strings; escape for HTML).
+	$filenames = array();
+	foreach ( $files as $path ) {
+		if ( ! is_string( $path ) || $path === '' ) {
+			continue;
+		}
+		$clean_path = parse_url( $path, PHP_URL_PATH );
+		$basename   = basename( $clean_path ?: $path );
+		$filenames[] = $is_html ? esc_html( $basename ) : $basename;
+	}
+
+	return implode( $sep, $filenames );
+}, 10, 6 );
🤖 Prompt for AI Agents
In gravity-forms/gw-filename-modifier-file-upload.php around lines 11 to 24, the
modifier handling should be hardened: treat $modifier as substring (use strpos)
so stacked modifiers like {:filename:esc_html} are honored; use strict
comparisons (=== / !==) when checking $merge_tag and $modifier; normalize
$raw_value to an array safely (if field is multipleFiles json_decode may return
null — default to an empty array or single-item array for a plain string) before
iterating to avoid warnings; strip query strings from file URLs before calling
basename (use parse_url or strtok on '?'); escape filenames for HTML output with
esc_html() and choose separator based on $format (use '<br />' for HTML and "\n"
for text); also guard access to $field->multipleFiles with isset/ property
check.

Comment on lines +27 to +29
add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
return [ 'filename' ];
}, 10, 4 );
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Don’t clobber existing GPML skip modifiers

Returning only ['filename'] discards previously skipped modifiers from other plugins/snippets. Append instead of replace.

-add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
-	return [ 'filename' ];
-}, 10, 4 );
+add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
+	$skip_modifiers[] = 'filename';
+	return array_values( array_unique( $skip_modifiers ) );
+}, 10, 4 );
📝 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
add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
return [ 'filename' ];
}, 10, 4 );
add_filter( 'gpml_image_merge_tag_skip_modifiers', function( $skip_modifiers, $modifiers, $input_id, $image_ids ) {
$skip_modifiers[] = 'filename';
return array_values( array_unique( $skip_modifiers ) );
}, 10, 4 );
🤖 Prompt for AI Agents
In gravity-forms/gw-filename-modifier-file-upload.php around lines 27 to 29, the
filter handler currently returns a fresh array ['filename'] which overwrites any
existing skip modifiers from other plugins; change it to append 'filename' to
the incoming $skip_modifiers and return the merged unique array (e.g., add
'filename' to $skip_modifiers and return array_unique($skip_modifiers)) so
existing modifiers are preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants