Skip to content

New sniff to remove unecessary var declarations for used once vars#3045

Merged
Crabcyborg merged 16 commits into
masterfrom
new_sniff_to_remove_unnecessary_var_declartions_for_used_once_vars
Mar 26, 2026
Merged

New sniff to remove unecessary var declarations for used once vars#3045
Crabcyborg merged 16 commits into
masterfrom
new_sniff_to_remove_unnecessary_var_declartions_for_used_once_vars

Conversation

@Crabcyborg
Copy link
Copy Markdown
Contributor

@Crabcyborg Crabcyborg commented Mar 26, 2026

Summary by CodeRabbit

  • Chores
    • Improved code quality through refactoring and simplification of internal logic across multiple components.
    • Enhanced code standards tooling with new code analysis capabilities for maintaining consistency.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 26, 2026

Warning

Rate limit exceeded

@Crabcyborg has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 16 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 35f344d3-3676-4a7a-9080-c4959d1efcae

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff78d2 and 12e157d.

📒 Files selected for processing (4)
  • classes/helpers/FrmFormsHelper.php
  • classes/helpers/FrmListHelper.php
  • tests/phpunit/misc/test_FrmAppHelper.php
  • tests/phpunit/misc/test_FrmCSVExportHelper.php
📝 Walkthrough

Walkthrough

This pull request performs a widespread refactoring across the codebase to remove intermediate single-use variables and inline function calls at their point of usage. Additionally, a new PHPCS sniff is introduced to automatically detect and enforce this inlining pattern going forward.

Changes

Cohort / File(s) Summary
Controller Variable Inlining
classes/controllers/FrmAddonsController.php, FrmAppController.php, FrmCronController.php, FrmDashboardController.php, FrmEmailStylesController.php, FrmEntriesAJAXSubmitController.php, FrmEntriesController.php, FrmFormsController.php, FrmInboxController.php, FrmSMTPController.php, FrmStylesController.php, FrmWelcomeTourController.php
Removed intermediate variables and inlined function calls (e.g., get_current_user_id(), get_settings(), FrmForm::get_latest_form()) directly at usage sites within conditional checks, assignments, and function arguments. One controller (FrmFormsController) retained a variable with an added PHPCS ignore comment.
Helper Class Variable Inlining
classes/helpers/FrmAppHelper.php, FrmEntriesHelper.php, FrmEntriesListHelper.php, FrmFieldGdprHelper.php, FrmFieldGridHelper.php, FrmFieldsHelper.php, FrmShortcodeHelper.php, FrmStylesCardHelper.php, FrmXMLHelper.php, FrmFormsHelper.php, FrmListHelper.php
Eliminated temporary variables and inlined method/function calls (e.g., get_entry_statuses(), get_menu_name(), get_order_by(), get_contextual_shortcodes()) directly within loops, conditionals, and array operations, maintaining identical logic.
Model Variable Inlining
classes/models/FrmAddon.php, FrmCreateFile.php, FrmEntryMeta.php, FrmField.php, FrmFormState.php, FrmStyle.php, FrmStyleApi.php, FrmSolution.php
Removed intermediate assignments and directly inlined method results (e.g., get_license(), get_needed_dirs(), get_state_string(), get_defaults()) within constructor calls, array operations, and return statements.
Field Model Variable Inlining
classes/models/fields/FrmFieldCaptcha.php, FrmFieldName.php, FrmFieldType.php
Simplified field-type specific logic by inlining method results (e.g., api_url(), get_name_layout(), include_front_form_file()) directly in function arguments and conditionals.
Component & Helper Variable Inlining
classes/views/styles/components/FrmStyleComponent.php, square/helpers/FrmSquareLiteAppHelper.php, square/helpers/FrmSquareLiteConnectHelper.php, stripe/helpers/FrmStrpLiteAppHelper.php, stripe/helpers/FrmStrpLiteConnectApiAdapter.php, stripe/helpers/FrmStrpLiteConnectHelper.php, stripe/models/FrmTransLiteDb.php
Applied variable inlining pattern across payment gateway integrations and style components, removing temporary $settings, $plugin_version, $user_id, and $uuid variables by inlining their computed values directly.
Test Variable Inlining
tests/phpunit/base/FrmUnitTest.php, tests/phpunit/entries/test_FrmShowEntryShortcode.php, tests/phpunit/forms/test_FrmFormActionsController.php, tests/phpunit/misc/test_FrmAppController.php, tests/phpunit/misc/test_FrmAppHelper.php, tests/phpunit/misc/test_FrmCSVExportHelper.php, tests/phpunit/misc/test_FrmHooksController.php
Simplified test assertions and loops by inlining function calls (e.g., get_post_types(), go_to_new_post(), array_keys()) directly within assertions and loop constructs.
New PHPCS Sniff & Ruleset
phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php, phpcs-sniffs/Formidable/ruleset.xml
Introduced a comprehensive new PHPCS sniff (InlineSingleUseVariableSniff) that detects single-use variables assigned with function/method call results and enforces inlining via automated fixes. Includes guards for loops, complex usage contexts, compact() calls, string interpolation, and require/include statements. Registered sniff in the Formidable ruleset for CI/linting integration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hop, hop—variables gone!
Inline the calls, make code lean,
One swift sniff catches them all,
Single use? Not foreseen!
Cleaner forms, faster review—
What a delightful rabbit's debut!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing a PHPCS sniff to inline single-use variable declarations, which is the primary addition in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 96.97% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch new_sniff_to_remove_unnecessary_var_declartions_for_used_once_vars

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@deepsource-io
Copy link
Copy Markdown

deepsource-io Bot commented Mar 26, 2026

DeepSource Code Review

We reviewed changes in 6a50dcf...12e157d on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Mar 26, 2026 2:21p.m. Review ↗
JavaScript Mar 26, 2026 2:21p.m. Review ↗

Copy link
Copy Markdown
Contributor

@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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
stripe/helpers/FrmTransLiteListHelper.php (1)

230-254: ⚠️ Potential issue | 🔴 Critical

Critical bug: $form_ids is undefined when used by compact().

The refactoring removed $form_ids = $this->get_form_ids() but line 234 still uses compact('form_ids', ...), which requires the variable to exist. This causes:

  1. PHP E_NOTICE for undefined variable
  2. form_ids key missing from $args array
  3. get_form_id_column() always returns empty string (form column broken)

The $form_ids variable cannot be inlined here because compact() needs the variable name to exist in scope.

🐛 Proposed fix to restore the required variable
 public function display_rows() {
     $date_format = FrmAppHelper::get_date_format();
     $gateways    = FrmTransLiteAppHelper::get_gateways();
     $alt         = 0;
+    $form_ids    = $this->get_form_ids();
     $args        = compact( 'form_ids', 'date_format', 'gateways' );
-    // $form_ids is indexed by entry ID.
-    $this->valid_entry_ids = array_keys( $this->get_form_ids() );
+    $this->valid_entry_ids = array_keys( $form_ids );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@stripe/helpers/FrmTransLiteListHelper.php` around lines 230 - 254, In
display_rows(), compact('form_ids', 'date_format', 'gateways') references an
undefined $form_ids (causing notices and a missing form_ids arg); fix by
restoring a local $form_ids variable (assign $form_ids = $this->get_form_ids()
before building $args) or otherwise ensure $args includes a 'form_ids' key
populated from $this->get_form_ids(); this will restore correct behavior for
get_form_id_column() and display_columns().
classes/controllers/FrmFormsController.php (1)

3043-3066: ⚠️ Potential issue | 🔴 Critical

Keep $doing_ajax as a local for the JS redirect fallback.

Line 3066 passes compact( 'success_url', 'doing_ajax' ) but there is no $doing_ajax assignment in the method scope. This breaks AJAX submissions reaching redirect_after_submit_using_js() and causes a Psalm UndefinedVariable error since the method checks $args['doing_ajax'] at line 3187. Add the assignment before the first condition and reuse it instead of calling FrmAppHelper::doing_ajax() twice:

$doing_ajax = FrmAppHelper::doing_ajax();

Then replace FrmAppHelper::doing_ajax() in the condition with $doing_ajax.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@classes/controllers/FrmFormsController.php` around lines 3043 - 3066, The
method in FrmFormsController uses FrmAppHelper::doing_ajax() inline and later
calls redirect_after_submit_using_js( $args + compact( 'success_url',
'doing_ajax' ) ) without a local $doing_ajax variable, causing an undefined
variable and incorrect args; fix by declaring a local $doing_ajax =
FrmAppHelper::doing_ajax(); before the first conditional, replace subsequent
FrmAppHelper::doing_ajax() checks with $doing_ajax, ensure
get_ajax_redirect_response_data and redirect_after_submit_using_js receive $args
+ compact('success_url','doing_ajax') so $args['doing_ajax'] is set for
redirect_after_submit_using_js.
🧹 Nitpick comments (8)
classes/models/FrmSettings.php (1)

624-630: Consider eliminating the unused $details variable.

The $details variable is destructured from get_editable_roles() but never used within the loop. Only the role names are needed for the capability checks.

♻️ Optional refactor to eliminate unused variable
-			foreach ( get_editable_roles() as $role => $details ) {
+			foreach ( array_keys( get_editable_roles() ) as $role ) {
 				if ( in_array( $role, $this->$frm_role, true ) ) {
 					$wp_roles->add_cap( $role, $frm_role );
 				} else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@classes/models/FrmSettings.php` around lines 624 - 630, The foreach currently
destructures get_editable_roles() into $role and an unused $details; remove the
unused variable by iterating only the role keys (e.g. use foreach
(array_keys(get_editable_roles()) as $role) { ... }) so the loop keeps checking
$this->$frm_role and calling $wp_roles->add_cap / remove_cap without the unused
$details variable.
classes/helpers/FrmEntriesListHelper.php (1)

365-369: Method called inside loop, consider caching.

$this->get_action_columns() is called on each iteration until $action_col is set. While the method returns a small static array and the short-circuit logic limits calls, caching it before the loop would be more efficient.

This is a minor concern given the small array size and early exit.

🔧 Suggested fix
 list( $columns, $hidden, , $primary ) = $this->get_column_info();
 $action_col                           = false;
+$action_columns                       = $this->get_action_columns();

 foreach ( $columns as $column_name => $column_display_name ) {
     // ...
     if ( in_array( $column_name, $hidden, true ) ) {
         $class .= ' frm_hidden';
-    } elseif ( ! $action_col && ! in_array( $column_name, $this->get_action_columns(), true ) ) {
+    } elseif ( ! $action_col && ! in_array( $column_name, $action_columns, true ) ) {
         $action_col = $column_name;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@classes/helpers/FrmEntriesListHelper.php` around lines 365 - 369, Cache the
result of $this->get_action_columns() before the loop and use that cached array
inside the loop instead of calling get_action_columns() repeatedly; update the
in_array check that currently uses $this->get_action_columns() to use the cached
$action_columns variable while keeping the existing short-circuit logic that
sets $action_col when not already set and adds ' frm_hidden' when $column_name
is in $hidden.
classes/controllers/FrmCronController.php (1)

63-69: Unused $recurrence variable in loop.

The static analysis tool correctly identifies that $recurrence is never used within this loop body. Since only the event name is needed here, consider using array_keys() instead.

🔧 Suggested fix
 public static function remove_crons() {
-	foreach ( self::get_events() as $event => $recurrence ) {
+	foreach ( array_keys( self::get_events() ) as $event ) {
 		$timestamp = wp_next_scheduled( $event );

 		if ( false !== $timestamp ) {
 			wp_unschedule_event( $timestamp, $event );
 		}
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@classes/controllers/FrmCronController.php` around lines 63 - 69, The foreach
in FrmCronController::get_events() iteration declares an unused $recurrence
variable; change the loop to iterate only event names (e.g. foreach
(array_keys(self::get_events()) as $event)) so you remove the unused $recurrence
and keep the existing calls to wp_next_scheduled($event) and
wp_unschedule_event($timestamp, $event); this eliminates the unused variable
while preserving behavior.
tests/phpunit/misc/test_FrmCSVExportHelper.php (1)

28-30: array_keys() called repeatedly inside loop.

The previous code likely had $keys = array_keys($headings) computed once before the loop. Now array_keys($headings) is called on every iteration, which is the opposite of the optimization pattern this PR aims to achieve.

While this is test code and performance isn't critical, consider keeping the cached variable here for consistency:

🔧 Suggested fix
+		$keys = array_keys( $headings );
 		foreach ( $expected as $key => $label ) {
-			$this->assertContains( $key, array_keys( $headings ), "{$label} is not present in CSV Headings" );
+			$this->assertContains( $key, $keys, "{$label} is not present in CSV Headings" );
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/phpunit/misc/test_FrmCSVExportHelper.php` around lines 28 - 30, The
loop calls array_keys($headings) on every iteration; compute and cache the keys
once before the foreach (e.g., $keys = array_keys($headings)) and then use that
cached $keys inside the loop with $this->assertContains($key, $keys, ...) to
avoid repeated calls while keeping the test semantics the same (references:
$expected, $headings, array_keys, $this->assertContains).
phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php (4)

276-283: Empty if-block with only a comment is a code smell.

The condition is evaluated but no action is taken. Consider restructuring to make the intent clearer—either invert the condition and return early if invalid, or remove the conditional entirely if it's purely informational.

♻️ Proposed fix: Remove the empty block
 	$afterClose = $phpcsFile->findNext( T_WHITESPACE, $closeParen + 1, $end + 1, true );

-	if ( false !== $afterClose && $afterClose !== $end ) {
-		// There's something after the function call before the semicolon.
-		// This could be a chained call, array access, etc.
-		// Still valid but we use the full expression as the "call".
-	}
+	// Note: If there's something after the function call before the semicolon
+	// (chained call, array access, etc.), we still use the full expression as the "call".

 	// Extract just the function/method name (last meaningful part).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 276 - 283, The if statement checking the result of
$phpcsFile->findNext (using $afterClose, $closeParen and $end) contains only
comments and no behavior; remove this empty conditional block to avoid the code
smell and leave the surrounding logic as-is in the InlineSingleUseVariableSniff
class (InlineSingleUseVariableSniff::process or the enclosing method where
$afterClose is computed) so the subsequent code uses $afterClose directly; if
early-return logic is actually required, invert the condition to return early
instead of leaving an empty block.

335-345: Unused parameter $phpcsFile.

The $phpcsFile parameter is never used in this method. You could remove it and update the call site at line 117.

♻️ Proposed fix
-private function hasRequireOrInclude( File $phpcsFile, array $tokens, $functionOpener, $functionCloser ) {
+private function hasRequireOrInclude( array $tokens, $functionOpener, $functionCloser ) {
 	$includeTokens = array( T_REQUIRE, T_REQUIRE_ONCE, T_INCLUDE, T_INCLUDE_ONCE );

 	for ( $i = $functionOpener + 1; $i < $functionCloser; $i++ ) {

And at line 117:

-if ( $this->hasRequireOrInclude( $phpcsFile, $tokens, $functionOpener, $functionCloser ) ) {
+if ( $this->hasRequireOrInclude( $tokens, $functionOpener, $functionCloser ) ) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 335 - 345, Remove the unused $phpcsFile parameter from the
hasRequireOrInclude method signature and update all call sites to stop passing
that argument: change "private function hasRequireOrInclude( File $phpcsFile,
array $tokens, $functionOpener, $functionCloser )" to "private function
hasRequireOrInclude( array $tokens, $functionOpener, $functionCloser )" and
adjust any callers (the place that currently invokes hasRequireOrInclude(...)
with a File object and tokens) to call hasRequireOrInclude($tokens,
$functionOpener, $functionCloser) instead; ensure parameter order matches the
new signature and run tests/static analysis to confirm no other references
remain.

237-257: Remove unused variable $lastNameToken.

The variable $lastNameToken is assigned at line 246 but never used anywhere in the method. This was flagged by static analysis (PHPMD).

♻️ Proposed fix
 	// Collect the function/method name parts.
 	$nameParts     = array();
-	$lastNameToken = $current;

 	while ( $current < $end ) {
 		$code = $tokens[ $current ]['code'];

 		if ( in_array( $code, array( T_STRING, T_VARIABLE, T_SELF, T_STATIC, T_PARENT ), true ) ) {
 			$nameParts[]  = $tokens[ $current ]['content'];
-			$lastNameToken = $current;
 		} elseif ( in_array( $code, array( T_DOUBLE_COLON, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR ), true ) ) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 237 - 257, In the InlineSingleUseVariableSniff method that collects
function/method name parts, remove the unused variable $lastNameToken: delete
its initial declaration/assignment ($lastNameToken = $current) and the in-loop
update (++$lastNameToken = $current) so only $nameParts, $tokens, $current and
$end remain; ensure there are no other references to $lastNameToken in the
method before committing the change.

566-573: Consider handling Windows line endings (\r\n).

The check strpos( $wsContent, "\n" ) === 0 handles Unix line endings but not Windows-style \r\n, where the newline character is at position 1, not 0. This could leave a stray \r character.

♻️ Proposed fix
 // Remove the newline after the semicolon.
 if ( isset( $tokens[ $assignmentEnd + 1 ] ) && $tokens[ $assignmentEnd + 1 ]['code'] === T_WHITESPACE ) {
 	$wsContent = $tokens[ $assignmentEnd + 1 ]['content'];

-	if ( strpos( $wsContent, "\n" ) === 0 ) {
-		$phpcsFile->fixer->replaceToken( $assignmentEnd + 1, substr( $wsContent, 1 ) );
+	if ( strpos( $wsContent, "\r\n" ) === 0 ) {
+		$phpcsFile->fixer->replaceToken( $assignmentEnd + 1, substr( $wsContent, 2 ) );
+	} elseif ( strpos( $wsContent, "\n" ) === 0 ) {
+		$phpcsFile->fixer->replaceToken( $assignmentEnd + 1, substr( $wsContent, 1 ) );
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 566 - 573, The current check only strips a leading "\n" from
$wsContent after $assignmentEnd, missing Windows "\r\n" and leaving a stray
"\r"; update InlineSingleUseVariableSniff to detect and handle CRLF by checking
$wsContent for a leading "\r\n" (remove first two characters) else for a leading
"\n" or "\r" (remove first character) before calling
$phpcsFile->fixer->replaceToken($assignmentEnd + 1, ...); use $assignmentEnd,
$wsContent and $phpcsFile->fixer->replaceToken to locate and apply the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@classes/controllers/FrmFormsController.php`:
- Around line 268-275: The current code calls FrmForm::update($id, $_POST)
before checking antispam state, so antispam_was_on($id) reads the post-update
state; capture the previous antispam setting into a variable (e.g.,
$old_antispam = self::antispam_was_on($id)) before calling FrmForm::update, then
compute $antispam_is_on from $_POST and compare $antispam_is_on !==
$old_antispam to decide whether to call FrmAntiSpam::clear_caches(); ensure you
reference the existing methods FrmForm::update, self::antispam_was_on, and
FrmAntiSpam::clear_caches when making the change.
- Around line 3426-3431: The else branch in front_head() uses $suffix but
$suffix is never defined, causing an undefined variable notice; define $suffix
by assigning FrmAppHelper::js_suffix() near the start of the function (e.g.,
before the if) and then use that $suffix in the wp_register_script fallback line
that registers "formidable" (the line calling wp_register_script with
"/js/formidable{$suffix}.js"), keeping the existing condition that calls
self::has_combo_js_file() and the primary registration of 'formidable' with
frm.min.js.

In `@classes/controllers/FrmWelcomeTourController.php`:
- Around line 625-627: The loop is iterating the wrapper returned by
self::get_steps() (which contains keys like 'keys' and 'steps') instead of the
actual step IDs, causing wrong usage-tracking keys; change the iteration to loop
over the real steps array (e.g., the 'steps' element returned by
self::get_steps()) and then use each step's ID/key when building
$usage_data['completed_step_'.$key]; update the foreach in
FrmWelcomeTourController to pull the steps array from self::get_steps() (and
guard that $option['completed_steps'] exists) so the correct step IDs are used
for usage tracking.

In `@classes/controllers/FrmXMLController.php`:
- Around line 768-772: Cache the result of FrmField::no_save_fields() before
iterating $csv_fields to avoid calling the method on every loop iteration; e.g.
assign $no_save_fields = FrmField::no_save_fields() once prior to the foreach in
FrmXMLController and replace in_array($f->type, FrmField::no_save_fields(),
true) with in_array($f->type, $no_save_fields, true) so the lookup uses the
cached array.

In
`@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`:
- Around line 378-412: The isComplexUsage function misses
pre-increment/pre-decrement because it only inspects tokens after the variable;
update it to also look at the token immediately before $usagePtr (skipping
whitespace) and treat T_INC or T_DEC there as complex usage. Use
$phpcsFile->findPrevious to find the previous non-whitespace token and check
$tokens[ $prevPtr ]['code'] with in_array for T_INC and T_DEC (same strict check
as post-check) so ++$var/--$var are correctly classified as complex in
isComplexUsage.

In `@tests/phpunit/misc/test_FrmAppHelper.php`:
- Around line 408-409: The test reads the query var via
FrmAppHelper::get_query_var('', 'p') before setting up the new post context with
go_to_new_post(), causing a stale value; swap the operations so go_to_new_post()
(the call that sets the new post context) runs first and then capture the result
of FrmAppHelper::get_query_var('', 'p') into $get_post_id and assert it equals
the value returned by go_to_new_post().

---

Outside diff comments:
In `@classes/controllers/FrmFormsController.php`:
- Around line 3043-3066: The method in FrmFormsController uses
FrmAppHelper::doing_ajax() inline and later calls
redirect_after_submit_using_js( $args + compact( 'success_url', 'doing_ajax' ) )
without a local $doing_ajax variable, causing an undefined variable and
incorrect args; fix by declaring a local $doing_ajax =
FrmAppHelper::doing_ajax(); before the first conditional, replace subsequent
FrmAppHelper::doing_ajax() checks with $doing_ajax, ensure
get_ajax_redirect_response_data and redirect_after_submit_using_js receive $args
+ compact('success_url','doing_ajax') so $args['doing_ajax'] is set for
redirect_after_submit_using_js.

In `@stripe/helpers/FrmTransLiteListHelper.php`:
- Around line 230-254: In display_rows(), compact('form_ids', 'date_format',
'gateways') references an undefined $form_ids (causing notices and a missing
form_ids arg); fix by restoring a local $form_ids variable (assign $form_ids =
$this->get_form_ids() before building $args) or otherwise ensure $args includes
a 'form_ids' key populated from $this->get_form_ids(); this will restore correct
behavior for get_form_id_column() and display_columns().

---

Nitpick comments:
In `@classes/controllers/FrmCronController.php`:
- Around line 63-69: The foreach in FrmCronController::get_events() iteration
declares an unused $recurrence variable; change the loop to iterate only event
names (e.g. foreach (array_keys(self::get_events()) as $event)) so you remove
the unused $recurrence and keep the existing calls to wp_next_scheduled($event)
and wp_unschedule_event($timestamp, $event); this eliminates the unused variable
while preserving behavior.

In `@classes/helpers/FrmEntriesListHelper.php`:
- Around line 365-369: Cache the result of $this->get_action_columns() before
the loop and use that cached array inside the loop instead of calling
get_action_columns() repeatedly; update the in_array check that currently uses
$this->get_action_columns() to use the cached $action_columns variable while
keeping the existing short-circuit logic that sets $action_col when not already
set and adds ' frm_hidden' when $column_name is in $hidden.

In `@classes/models/FrmSettings.php`:
- Around line 624-630: The foreach currently destructures get_editable_roles()
into $role and an unused $details; remove the unused variable by iterating only
the role keys (e.g. use foreach (array_keys(get_editable_roles()) as $role) {
... }) so the loop keeps checking $this->$frm_role and calling
$wp_roles->add_cap / remove_cap without the unused $details variable.

In
`@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`:
- Around line 276-283: The if statement checking the result of
$phpcsFile->findNext (using $afterClose, $closeParen and $end) contains only
comments and no behavior; remove this empty conditional block to avoid the code
smell and leave the surrounding logic as-is in the InlineSingleUseVariableSniff
class (InlineSingleUseVariableSniff::process or the enclosing method where
$afterClose is computed) so the subsequent code uses $afterClose directly; if
early-return logic is actually required, invert the condition to return early
instead of leaving an empty block.
- Around line 335-345: Remove the unused $phpcsFile parameter from the
hasRequireOrInclude method signature and update all call sites to stop passing
that argument: change "private function hasRequireOrInclude( File $phpcsFile,
array $tokens, $functionOpener, $functionCloser )" to "private function
hasRequireOrInclude( array $tokens, $functionOpener, $functionCloser )" and
adjust any callers (the place that currently invokes hasRequireOrInclude(...)
with a File object and tokens) to call hasRequireOrInclude($tokens,
$functionOpener, $functionCloser) instead; ensure parameter order matches the
new signature and run tests/static analysis to confirm no other references
remain.
- Around line 237-257: In the InlineSingleUseVariableSniff method that collects
function/method name parts, remove the unused variable $lastNameToken: delete
its initial declaration/assignment ($lastNameToken = $current) and the in-loop
update (++$lastNameToken = $current) so only $nameParts, $tokens, $current and
$end remain; ensure there are no other references to $lastNameToken in the
method before committing the change.
- Around line 566-573: The current check only strips a leading "\n" from
$wsContent after $assignmentEnd, missing Windows "\r\n" and leaving a stray
"\r"; update InlineSingleUseVariableSniff to detect and handle CRLF by checking
$wsContent for a leading "\r\n" (remove first two characters) else for a leading
"\n" or "\r" (remove first character) before calling
$phpcsFile->fixer->replaceToken($assignmentEnd + 1, ...); use $assignmentEnd,
$wsContent and $phpcsFile->fixer->replaceToken to locate and apply the fix.

In `@tests/phpunit/misc/test_FrmCSVExportHelper.php`:
- Around line 28-30: The loop calls array_keys($headings) on every iteration;
compute and cache the keys once before the foreach (e.g., $keys =
array_keys($headings)) and then use that cached $keys inside the loop with
$this->assertContains($key, $keys, ...) to avoid repeated calls while keeping
the test semantics the same (references: $expected, $headings, array_keys,
$this->assertContains).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3b220963-49c1-46b6-aeaf-555f190d4c8b

📥 Commits

Reviewing files that changed from the base of the PR and between 6a50dcf and 8d4788b.

📒 Files selected for processing (51)
  • classes/controllers/FrmAddonsController.php
  • classes/controllers/FrmAppController.php
  • classes/controllers/FrmCronController.php
  • classes/controllers/FrmDashboardController.php
  • classes/controllers/FrmEmailStylesController.php
  • classes/controllers/FrmEntriesAJAXSubmitController.php
  • classes/controllers/FrmEntriesController.php
  • classes/controllers/FrmFormsController.php
  • classes/controllers/FrmInboxController.php
  • classes/controllers/FrmSMTPController.php
  • classes/controllers/FrmStylesController.php
  • classes/controllers/FrmWelcomeTourController.php
  • classes/controllers/FrmXMLController.php
  • classes/helpers/FrmAppHelper.php
  • classes/helpers/FrmEntriesHelper.php
  • classes/helpers/FrmEntriesListHelper.php
  • classes/helpers/FrmFieldGdprHelper.php
  • classes/helpers/FrmFieldGridHelper.php
  • classes/helpers/FrmFieldsHelper.php
  • classes/helpers/FrmShortcodeHelper.php
  • classes/helpers/FrmStylesCardHelper.php
  • classes/helpers/FrmXMLHelper.php
  • classes/models/FrmAddon.php
  • classes/models/FrmCreateFile.php
  • classes/models/FrmEntryMeta.php
  • classes/models/FrmField.php
  • classes/models/FrmFormState.php
  • classes/models/FrmInbox.php
  • classes/models/FrmSettings.php
  • classes/models/FrmStyle.php
  • classes/models/FrmStyleApi.php
  • classes/models/fields/FrmFieldCaptcha.php
  • classes/models/fields/FrmFieldName.php
  • classes/models/fields/FrmFieldType.php
  • classes/views/styles/components/FrmStyleComponent.php
  • phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php
  • phpcs-sniffs/Formidable/ruleset.xml
  • square/helpers/FrmSquareLiteAppHelper.php
  • square/helpers/FrmSquareLiteConnectHelper.php
  • stripe/helpers/FrmStrpLiteAppHelper.php
  • stripe/helpers/FrmStrpLiteConnectApiAdapter.php
  • stripe/helpers/FrmStrpLiteConnectHelper.php
  • stripe/helpers/FrmTransLiteListHelper.php
  • stripe/models/FrmTransLiteDb.php
  • tests/phpunit/base/FrmUnitTest.php
  • tests/phpunit/entries/test_FrmShowEntryShortcode.php
  • tests/phpunit/forms/test_FrmFormActionsController.php
  • tests/phpunit/misc/test_FrmAppController.php
  • tests/phpunit/misc/test_FrmAppHelper.php
  • tests/phpunit/misc/test_FrmCSVExportHelper.php
  • tests/phpunit/misc/test_FrmHooksController.php

Comment thread classes/controllers/FrmFormsController.php
Comment thread classes/controllers/FrmFormsController.php
Comment thread classes/controllers/FrmWelcomeTourController.php
Comment thread classes/controllers/FrmXMLController.php
Comment thread tests/phpunit/misc/test_FrmAppHelper.php Outdated
Copy link
Copy Markdown
Contributor

@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: 3

♻️ Duplicate comments (1)
phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php (1)

503-536: ⚠️ Potential issue | 🔴 Critical

isComplexUsage() is still too narrow for an autofix.

It still misses prefix ++$var / --$var, and it also treats dereference usages like $result[0] or $result->id as safe even though the injected RHS is not parenthesized. That can yield invalid rewrites like ++get_count() or precedence changes like get_result() ?: array()[0].

🐛 Conservative guard
 private function isComplexUsage( File $phpcsFile, array $tokens, $usagePtr ) {
+	$beforeUsage = $phpcsFile->findPrevious( T_WHITESPACE, $usagePtr - 1, null, true );
+
+	if ( false !== $beforeUsage && in_array( $tokens[ $beforeUsage ]['code'], array( T_INC, T_DEC ), true ) ) {
+		return true;
+	}
+
 	$afterUsage = $phpcsFile->findNext( T_WHITESPACE, $usagePtr + 1, null, true );
@@
 	if ( in_array( $tokens[ $afterUsage ]['code'], array( T_INC, T_DEC ), true ) ) {
 		return true;
 	}
+
+	if ( in_array( $tokens[ $afterUsage ]['code'], array( T_OPEN_SQUARE_BRACKET, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR ), true ) ) {
+		return true;
+	}
 
 	return false;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 503 - 536, The isComplexUsage() check must be expanded: detect
prefix increments/decrements by checking the previous non-whitespace token
before $usagePtr for T_INC or T_DEC and treat that as complex, and treat any
dereference/prop access as complex by also checking the token immediately after
the variable (skipping whitespace) for bracket/property operators
(T_OPEN_SQUARE_BRACKET, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR, and
similar tokens like T_DOUBLE_COLON if relevant) so that usages like ++$var,
--$var, $result[0], $result->id, or $result?->id are considered complex and
prevented from autofix; update isComplexUsage() to include these additional
token checks (refer to function isComplexUsage, $usagePtr, $afterUsage and the
token codes named above).
🧹 Nitpick comments (1)
phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php (1)

255-263: Remove the dead $lastNameToken state.

It’s assigned here but never read, so PHPMD will keep flagging this helper until it’s dropped.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`
around lines 255 - 263, Remove the dead state variable $lastNameToken: it is
assigned inside the loop but never read elsewhere, so delete its declaration and
all assignments to it (the initial "$lastNameToken = $current;" and the
"$lastNameToken = $current;" inside the loop) in InlineSingleUseVariableSniff
(the loop that iterates using $current, $end and $tokens while collecting
$nameParts); keep the rest of the logic that builds $nameParts unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@classes/helpers/FrmListHelper.php`:
- Line 831: The foreach loop is declaring an unused variable $column_name in the
context of FrmListHelper; change the loop that currently reads foreach (
$this->get_columns() as $col => $column_name ) to only capture the used key
(e.g., foreach ( $this->get_columns() as $col ) ), removing $column_name and
ensuring no other references to $column_name exist in the surrounding code or
methods like get_columns(); keep behavior identical while eliminating the unused
variable.

In
`@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`:
- Around line 153-157: The current guard in InlineSingleUseVariableSniff (the
isUsedInsideLoop check using $tokens, $stackPtr, $usagePtr) is too narrow;
instead ensure the assignment and the usage remain in the same execution context
before offering an autofix: locate the nearest common AST/block/container for
$stackPtr and $usagePtr (not just loop bodies), and reject fixes if they have
different parent statements/blocks, if either sits inside a conditional
predicate, loop predicate, ternary, or different control-structure header, or if
either is inside an expression that could change evaluation frequency or be
skipped (e.g. for/while conditions, if/elseif/else headers, ternary,
boolean-short-circuit contexts). Update the logic that currently calls
isUsedInsideLoop to perform this common-ancestor/same-context check (or add a
new helper method referenced from InlineSingleUseVariableSniff) and return
without autofix when contexts differ.
- Around line 676-689: The fixer currently sets $lineStart by walking back to
the start of the source line and then removes everything through $assignmentEnd,
which can delete unrelated code when other statements share the same line;
modify the logic to anchor deletion to the assignment statement itself by either
(a) finding an $assignmentStart token (search backwards from $varStart for a
statement boundary such as a previous semicolon/closer or the token that begins
the assignment) and use that as the deletion start instead of $lineStart, or (b)
detect if any non-whitespace/comment tokens exist between $lineStart and
$varStart and, if so, skip the autofix (do not call
$phpcsFile->fixer->replaceToken) to avoid removing preceding code; update the
block that computes $lineStart and the removal loop that uses $assignmentEnd
accordingly (references: $varStart, $lineStart, $assignmentEnd, the fixer
replaceToken loop).

---

Duplicate comments:
In
`@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`:
- Around line 503-536: The isComplexUsage() check must be expanded: detect
prefix increments/decrements by checking the previous non-whitespace token
before $usagePtr for T_INC or T_DEC and treat that as complex, and treat any
dereference/prop access as complex by also checking the token immediately after
the variable (skipping whitespace) for bracket/property operators
(T_OPEN_SQUARE_BRACKET, T_OBJECT_OPERATOR, T_NULLSAFE_OBJECT_OPERATOR, and
similar tokens like T_DOUBLE_COLON if relevant) so that usages like ++$var,
--$var, $result[0], $result->id, or $result?->id are considered complex and
prevented from autofix; update isComplexUsage() to include these additional
token checks (refer to function isComplexUsage, $usagePtr, $afterUsage and the
token codes named above).

---

Nitpick comments:
In
`@phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php`:
- Around line 255-263: Remove the dead state variable $lastNameToken: it is
assigned inside the loop but never read elsewhere, so delete its declaration and
all assignments to it (the initial "$lastNameToken = $current;" and the
"$lastNameToken = $current;" inside the loop) in InlineSingleUseVariableSniff
(the loop that iterates using $current, $end and $tokens while collecting
$nameParts); keep the rest of the logic that builds $nameParts unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3198b973-39ed-45ec-a10f-e0945a0efa42

📥 Commits

Reviewing files that changed from the base of the PR and between 8d4788b and 51e7f23.

📒 Files selected for processing (5)
  • classes/controllers/FrmFormsController.php
  • classes/helpers/FrmFormsHelper.php
  • classes/helpers/FrmListHelper.php
  • classes/models/FrmSolution.php
  • phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/InlineSingleUseVariableSniff.php
✅ Files skipped from review due to trivial changes (3)
  • classes/models/FrmSolution.php
  • classes/helpers/FrmFormsHelper.php
  • classes/controllers/FrmFormsController.php

Comment thread classes/helpers/FrmListHelper.php
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 26.66667% with 55 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.61%. Comparing base (b2a47e3) to head (12e157d).
⚠️ Report is 27 commits behind head on master.

Files with missing lines Patch % Lines
classes/controllers/FrmStylesController.php 0.00% 6 Missing ⚠️
classes/controllers/FrmDashboardController.php 0.00% 5 Missing ⚠️
classes/controllers/FrmFormsController.php 0.00% 5 Missing ⚠️
classes/helpers/FrmListHelper.php 0.00% 5 Missing ⚠️
classes/controllers/FrmAppController.php 0.00% 3 Missing ⚠️
classes/helpers/FrmAppHelper.php 40.00% 3 Missing ⚠️
classes/controllers/FrmAddonsController.php 0.00% 2 Missing ⚠️
classes/controllers/FrmWelcomeTourController.php 0.00% 2 Missing ⚠️
classes/helpers/FrmEntriesHelper.php 33.33% 2 Missing ⚠️
classes/helpers/FrmFieldsHelper.php 0.00% 2 Missing ⚠️
... and 18 more
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3045      +/-   ##
============================================
- Coverage     26.62%   26.61%   -0.02%     
- Complexity     8915     8917       +2     
============================================
  Files           145      145              
  Lines         30074    30020      -54     
============================================
- Hits           8007     7989      -18     
+ Misses        22067    22031      -36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Crabcyborg Crabcyborg merged commit 9f8a105 into master Mar 26, 2026
22 of 24 checks passed
@Crabcyborg Crabcyborg deleted the new_sniff_to_remove_unnecessary_var_declartions_for_used_once_vars branch March 26, 2026 14:29
stephywells pushed a commit that referenced this pull request Apr 4, 2026
…ary_var_declartions_for_used_once_vars

New sniff to remove unecessary var declarations for used once vars
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant