-
Notifications
You must be signed in to change notification settings - Fork 93
gwpc-post-image-subfields.php
: Added snippet to enable word count for Post Image subfields.
#1148
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
base: master
Are you sure you want to change the base?
Conversation
…or Post Image subfields.
WalkthroughAdds a new PHP module implementing per-subfield word-count enforcement for Gravity Forms Post Image fields. It registers a singleton class that enqueues a word-count script on relevant forms, initializes textarea counters for configured subfields, and validates min/max word counts server-side during submission. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Browser
participant WP as WordPress
participant GF as Gravity Forms
participant GW as GW_Post_Image_Word_Count
Note over WP,GW: Page render
WP->>GW: init()
GW->>GF: hook gform_enqueue_scripts / gform_register_init_scripts
GF->>GW: enqueue_scripts(form)
alt Form has configured post_image fields
GW->>Browser: enqueue GP Word Count JS
GF->>GW: enqueue_textarea_counter(form)
GW->>Browser: register textareaCounter init (per subfield with min/max)
else No relevant fields
Note over GW: No-op
end
sequenceDiagram
autonumber
participant User
participant Browser
participant GF as Gravity Forms
participant GW as GW_Post_Image_Word_Count
Note over Browser: Client-side typing
Browser->>Browser: textareaCounter enforces/indicates counts
Note over GF,GW: Submission
User->>GF: Submit form
GF->>GW: validate_word_count(result)
loop For each configured post_image subfield
GW->>GW: count words, compare min/max
alt Outside limits
GW-->>GF: set field validation failed + message
else Within limits
GW-->>GF: validation ok
end
end
GF-->>User: Success or error per subfield
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (7)
gp-word-count/gwpc-post-image-subfields.php (7)
27-37
: Make the class truly singleton and avoid duplicate hook registrations across multiple configurationsCreating multiple instances with
new GW_Post_Image_Word_Count( ... )
registers the hooks multiple times, which can enqueue/validate repeatedly. Promote the first instance to the singleton and only register hooks once; subsequent instantiations should only append config.This also fixes the PHPCS error at Line 32 (missing trailing comma).
Apply this diff:
public function __construct( $config = array() ) { - - $this->_configs[] = array_merge( array( - 'form_id' => false, - 'field_id' => false, - 'limits' => array() - ), $config ); - - add_action( 'init', array( $this, 'init' ) ); - - } + // Promote first instance to singleton and register hooks once. + if ( self::$_instance instanceof self ) { + self::$_instance->_configs[] = array_merge( array( + 'form_id' => false, + 'field_id' => false, + 'limits' => array(), + ), $config ); + return; + } + + self::$_instance = $this; + + $this->_configs[] = array_merge( array( + 'form_id' => false, + 'field_id' => false, + 'limits' => array(), + ), $config ); + + add_action( 'init', array( $this, 'init' ) ); + + }
57-63
: Reformat subfield map to meet WPCS for multi-line associative arraysPHPCS flagged Lines 58–61: “When a multi-item array uses associative keys, each value should start on a new line.”
Apply this diff:
public function get_subfields() { - return array( - 'caption' => array( 'suffix' => '4', 'label' => __( 'Caption', 'gravityforms' ) ), - 'description' => array( 'suffix' => '7', 'label' => __( 'Description', 'gravityforms' ) ), - 'alt' => array( 'suffix' => '2', 'label' => __( 'Alt Text', 'gravityforms' ) ), - 'title' => array( 'suffix' => '1', 'label' => __( 'Title', 'gravityforms' ) ), - ); + return array( + 'caption' => array( + 'suffix' => '4', + 'label' => __( 'Caption', 'gravityforms' ), + ), + 'description' => array( + 'suffix' => '7', + 'label' => __( 'Description', 'gravityforms' ), + ), + 'alt' => array( + 'suffix' => '2', + 'label' => __( 'Alt Text', 'gravityforms' ), + ), + 'title' => array( + 'suffix' => '1', + 'label' => __( 'Title', 'gravityforms' ), + ), + ); }
105-121
: Add translators comments for placeholders and remove an unnecessary sprintfPHPCS flagged many lines here for missing “translators:” comments. Also, Line 115 calls
sprintf()
without a placeholder in the string.Apply this diff:
$args = array( 'formId' => $form_id, 'limit' => $max, 'min' => $min, 'truncate' => true, - 'defaultLabel' => sprintf( __( 'Max: %s words', 'gp-word-count' ), '{limit}' ), - 'defaultLabelSingular' => sprintf( __( 'Max: %s word', 'gp-word-count' ), '{limit}' ), - 'counterLabel' => sprintf( __( '%s words left', 'gp-word-count' ), '{remaining}' ), - 'counterLabelSingular' => sprintf( __( '%s word left', 'gp-word-count' ), '{remaining}' ), - 'limitReachedLabel' => '<span class="gwwc-max-reached" style="font-weight:bold;">' . sprintf( __( '%s words left', 'gp-word-count' ), '{remaining}' ) . '</span>', - 'limitExceededLabel' => '<span class="gwwc-max-exceeded" style="font-weight:bold;color:#c0392b;">' . sprintf( __( 'Limit exceeded!', 'gp-word-count' ), '{remaining}' ) . '</span>', - 'minCounterLabel' => sprintf( __( '%s more words required', 'gp-word-count' ), '{remaining}' ), - 'minCounterLabelSingular' => sprintf( __( '%s more word required', 'gp-word-count' ), '{remaining}' ), + /* translators: %s: maximum number of words allowed */ + 'defaultLabel' => sprintf( __( 'Max: %s words', 'gp-word-count' ), '{limit}' ), + /* translators: %s: maximum number of words allowed */ + 'defaultLabelSingular' => sprintf( __( 'Max: %s word', 'gp-word-count' ), '{limit}' ), + /* translators: %s: remaining words allowed before reaching the limit */ + 'counterLabel' => sprintf( __( '%s words left', 'gp-word-count' ), '{remaining}' ), + /* translators: %s: remaining words allowed before reaching the limit */ + 'counterLabelSingular' => sprintf( __( '%s word left', 'gp-word-count' ), '{remaining}' ), + /* translators: %s: remaining words allowed before reaching the limit */ + 'limitReachedLabel' => '<span class="gwwc-max-reached" style="font-weight:bold;">' . sprintf( __( '%s words left', 'gp-word-count' ), '{remaining}' ) . '</span>', + 'limitExceededLabel' => '<span class="gwwc-max-exceeded" style="font-weight:bold;color:#c0392b;">' . __( 'Limit exceeded!', 'gp-word-count' ) . '</span>', + /* translators: %s: remaining words needed to meet the minimum */ + 'minCounterLabel' => sprintf( __( '%s more words required', 'gp-word-count' ), '{remaining}' ), + /* translators: %s: remaining words needed to meet the minimum */ + 'minCounterLabelSingular' => sprintf( __( '%s more word required', 'gp-word-count' ), '{remaining}' ), 'minReachedLabel' => '<span class="gwwc-min-reached" style="font-weight:bold;color:#27ae60">' . __( 'Minimum word count met.', 'gp-word-count' ) . '</span>', - 'minDefaultLabel' => sprintf( __( 'Min: %s words', 'gp-word-count' ), '{min}' ), - 'minDefaultLabelSingular' => sprintf( __( 'Min: %s word', 'gp-word-count' ), '{min}' ), + /* translators: %s: minimum number of words required */ + 'minDefaultLabel' => sprintf( __( 'Min: %s words', 'gp-word-count' ), '{min}' ), + /* translators: %s: minimum number of words required */ + 'minDefaultLabelSingular' => sprintf( __( 'Min: %s word', 'gp-word-count' ), '{min}' ), );
123-126
: Use wp_json_encode for safe JSON in inline JS
wp_json_encode()
sets sane defaults and handles encoding more safely for inline scripts. Minor, but recommended.Apply this diff:
- $args_json = json_encode( $args ); + $args_json = wp_json_encode( $args ); $input_id = "input_{$form_id}_{$field_id}_{$suffix}"; $script = "jQuery('#{$input_id}').textareaCounter({$args_json});";
162-176
: Order placeholders in translatable strings to satisfy WPCS and translatorsPHPCS flagged Lines 165 and 174: multiple placeholders should be ordered. Use numbered placeholders and add translators comments.
Apply this diff:
- if ( $min && $word_count < $min ) { + if ( $min && $word_count < $min ) { $field->failed_validation = true; - $field->validation_message = sprintf( - _n( '%s must be at least %s word.', '%s must be at least %s words.', $min, 'gp-word-count' ), - $label, $min - ); + /* translators: 1: subfield label, 2: minimum word count */ + $field->validation_message = sprintf( + _n( '%1$s must be at least %2$s word.', '%1$s must be at least %2$s words.', $min, 'gp-word-count' ), + $label, + $min + ); $result['is_valid'] = false; } - if ( $max && $word_count > $max ) { + if ( $max && $word_count > $max ) { $field->failed_validation = true; - $field->validation_message = sprintf( - _n( '%s may only be %s word.', '%s may only be %s words.', $max, 'gp-word-count' ), - $label, $max - ); + /* translators: 1: subfield label, 2: maximum word count */ + $field->validation_message = sprintf( + _n( '%1$s may only be %2$s word.', '%1$s may only be %2$s words.', $max, 'gp-word-count' ), + $label, + $max + ); $result['is_valid'] = false; }
17-18
: Align assignments or disable the sniff locallyPHPCS warning (Line 18): “Equals sign not aligned with surrounding assignments.” If you prefer not aligning, you can either align these two properties or add a local phpcs:ignore for
Generic.Formatting.MultipleStatementAlignment
to keep your preferred style.Would you like me to add a scoped
// phpcs:ignore
?
194-205
: Fix tab alignment in configuration and keep style consistentPHPCS flagged Line 199 for using a tab for mid-line alignment. Replace with spaces. Also normalize commented examples for consistency.
Apply this diff:
'limits' => array( - 'caption' => array( 'min' => 3, 'max' => 10 ), + 'caption' => array( 'min' => 3, 'max' => 10 ), 'description' => array( 'min' => 2, 'max' => 20 ), - // 'alt' => array( 'min' => 1, 'max' => 5 ), - // 'title' => array( 'min' => 1, 'max' => 5 ), + // 'alt' => array( 'min' => 1, 'max' => 5 ), + // 'title' => array( 'min' => 1, 'max' => 5 ), ),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
gp-word-count/gwpc-post-image-subfields.php
(1 hunks)
🧰 Additional context used
🪛 GitHub Check: PHPCS (Files Changed)
gp-word-count/gwpc-post-image-subfields.php
[failure] 199-199:
Spaces must be used for mid-line alignment; tabs are not allowed
[failure] 174-174:
Multiple placeholders should be ordered. Expected '%1$s, %2$s', but got %s, %s.
[failure] 174-174:
Multiple placeholders should be ordered. Expected '%1$s, %2$s', but got %s, %s.
[failure] 165-165:
Multiple placeholders should be ordered. Expected '%1$s, %2$s', but got %s, %s.
[failure] 165-165:
Multiple placeholders should be ordered. Expected '%1$s, %2$s', but got %s, %s.
[warning] 119-119:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 117-117:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 116-116:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 114-114:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 113-113:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 112-112:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 111-111:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 110-110:
A gettext call containing placeholders was found, but was not accompanied by a "translators:" comment on the line above to clarify the meaning of the placeholders.
[warning] 106-106:
Array double arrow not aligned correctly; expected 18 space(s) between "'formId'" and double arrow, but found 17.
[failure] 61-61:
When a multi-item array uses associative keys, each value should start on a new line.
[failure] 60-60:
When a multi-item array uses associative keys, each value should start on a new line.
[failure] 59-59:
When a multi-item array uses associative keys, each value should start on a new line.
[failure] 58-58:
When a multi-item array uses associative keys, each value should start on a new line.
[failure] 32-32:
Each array item in a multi-line array declaration must end in a comma
[warning] 18-18:
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space
🪛 GitHub Actions: PHP Lint (PR)
gp-word-count/gwpc-post-image-subfields.php
[warning] 18-18: PHPCS (thenabeel/action-phpcs@v8): Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space. (Generic.Formatting.MultipleStatementAlignment.NotSameWarning)
[error] 32-32: PHPCS (thenabeel/action-phpcs@v8): Each array item in a multi-line array declaration must end in a comma. (WordPress.Arrays.CommaAfterArrayItem.NoComma)
🔇 Additional comments (4)
gp-word-count/gwpc-post-image-subfields.php (4)
65-78
: Confirm the script handle and plugin basename for GP Word CountLine 72 enqueues the script by building a URL with
plugins_url( 'scripts/jquery.textareaCounter.js', 'gwwordcount/gwwordcount.php' )
. Please verify:
- The handle you want to use is indeed
gp-word-count
(matches GP Word Count).- The plugin basename
'gwwordcount/gwwordcount.php'
is correct for GP Word Count in your environment. If the slug isgp-word-count/gp-word-count.php
, this URL will 404.Optionally, prefer enqueuing the registered handle when available:
if ( wp_script_is( 'gp-word-count', 'registered' ) ) { wp_enqueue_script( 'gp-word-count' ); } else { wp_enqueue_script( 'gp-word-count', plugins_url( 'scripts/jquery.textareaCounter.js', 'gp-word-count/gp-word-count.php' ), array( 'jquery' ), null, true ); }
80-131
: Verify textareaCounter works on non-textareas (Title/Alt are text inputs)Caption and Description may be textareas, but Title and Alt are often inputs. The GP Word Count
jquery.textareaCounter
generally operates on inputs as well, but please confirm it behaves correctly for input[type="text"] on your form, especially withtruncate => true
.
58-62
: Double-check subfield suffixes against your GF versionThe suffixes used here (Title 1, Alt 2, Caption 4, Description 7) match common Post Image input IDs. Gravity Forms has tweaked internal indexing across versions in the past.
Please confirm these match the rendered input IDs in your environment (inspect the DOM for the Post Image field). If they differ, consider deriving suffixes dynamically from
$field->inputs
by label to make this robust across versions.
1-14
: Solid addition; scope and intent are clearThe snippet’s purpose, hooks used, and server-side validation approach look good. Nice job mapping per-subfield limits and keeping the UX consistent with GP Word Count labels.
$suffix = $subfields[ $subfield ]['suffix']; | ||
$label = $subfields[ $subfield ]['label']; | ||
$input_name = "input_{$field->id}_{$suffix}"; | ||
$value = rgpost( $input_name ); | ||
$word_count = preg_match_all( '/\S+/', trim( $value ) ); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid PHP 8.1+ deprecation/warnings: ensure trim() gets a string
If the subfield isn’t present, rgpost()
may return null. trim(null)
is deprecated. Cast before trimming and handle the empty case.
Apply this diff:
- $input_name = "input_{$field->id}_{$suffix}";
- $value = rgpost( $input_name );
- $word_count = preg_match_all( '/\S+/', trim( $value ) );
+ $input_name = "input_{$field->id}_{$suffix}";
+ $value = trim( (string) rgpost( $input_name ) );
+ $word_count = $value === '' ? 0 : preg_match_all( '/\S+/', $value );
📝 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.
$suffix = $subfields[ $subfield ]['suffix']; | |
$label = $subfields[ $subfield ]['label']; | |
$input_name = "input_{$field->id}_{$suffix}"; | |
$value = rgpost( $input_name ); | |
$word_count = preg_match_all( '/\S+/', trim( $value ) ); | |
$suffix = $subfields[ $subfield ]['suffix']; | |
$label = $subfields[ $subfield ]['label']; | |
$input_name = "input_{$field->id}_{$suffix}"; | |
$value = trim( (string) rgpost( $input_name ) ); | |
$word_count = $value === '' ? 0 : preg_match_all( '/\S+/', $value ); |
🤖 Prompt for AI Agents
In gp-word-count/gwpc-post-image-subfields.php around lines 153 to 158, rgpost()
can return null so calling trim() directly can trigger PHP 8.1+ deprecation
warnings; ensure you coerce the value to a string or default to an empty string
before trimming and then only call preg_match_all if the trimmed string is
non-empty (otherwise set word_count to 0). Replace the direct trim($value) usage
with a safe string cast or null coalescing to '' and handle the empty case to
avoid warnings and produce a correct 0 word count.
Context
⛑️ Ticket(s): https://secure.helpscout.net/conversation/3033697344/87708
Summary
Use GP Word Count to count the words entered in the subfields (caption, description, alt text, title) of a Post Image field.
Loom:
https://www.loom.com/share/005eda834a6348f9a874a5e6cdd85461