From 0a3ed5aa31cd9ecb72d75379f898e0662d10f736 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 12 Jan 2026 16:29:26 -0400 Subject: [PATCH 1/4] Update readme for v6.27 --- changelog.txt | 17 +++++++++++++++++ readme.txt | 35 ++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/changelog.txt b/changelog.txt index b51c233b21..b1d29c7802 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,4 +1,21 @@ == Changelog == += 6.27 = +* New: Displaying payments is now handled by this plugin, instead of falling back to Stripe, Authorize.Net, and PayPal. In cases where these add-ons were active, the payments table should now appear more modern. +* New: A new coupons tab is available on the payments page. +* New: Required updates to support a new View-Specific CSS setting in the Visual Views add-on. +* New: The submit button will now be enabled when a Square postal code is successfully completed. This fixes issues where the submit button would never get enabled when a Square card field was auto-filled. +* New: Many references to old font icons have been removed, removing about 10KB of data from admin CSS. +* New: Several styles have been optimized in the generated formdiableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. +* Fix: Global custom CSS would incorrectly get added to the formidableforms.css more than once on some sites with multiple styles. +* Fix: The style-specific custom CSS setting would incorrectly get output in the formidableforms.css file as CSS variable data. +* Fix: The htaccess file included in this plugin is now automatically deleted when migrating to a new plugin version if a request to load CSS is blocked, fixing a conflict on some servers that are not configured to allow overwriting file permissions. +* Fix: A PHP warning would get logged when checking data for a rank field as spam. +* Fix: Add-on category counts were not always correct. +* Breaking: Many modern PHP functions are now being used including str_contains, str_starts_with, str_ends_with, array_key_last, and array_key_first. If you are using both a WordPress version older than 5.9, and a PHP version lower than 8.0, this will introduce fatal errors. Note that the minimum required WordPress version is already set to 6.3. +* Breaking: The deprecated functions FrmFieldCaptcha::captcha_size, FrmFormsHelper::should_use_pro_for_ajax_submit, FrmFormsController::add_form_style_tab_options, and FrmFieldType::get_select_atributes have been removed. +* Breaking: The deprecated FrmFormsHelper::actions_dropdown function and actions-dropdown.php view file have been removed. +* An unused FrmTransLiteSubscriptionsController::list_subscriptions_shortcode function and its related view file have been deprecated. + = 6.26.1 = * New: The cached data for license checks is now set to autoload to help reduce calls to the database, and an option check for a request lock has been moved so it only happens when the option data has expired. These changes should help with performance. * New: SVG icon updates have been made to avoid use of the deprecated xlink:href attribute. diff --git a/readme.txt b/readme.txt index c93fd459ac..0f50754f79 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Tags: forms, form builder, survey, payment form, custom form, contact form, form Requires at least: 6.3 Tested up to: 6.9 Requires PHP: 7.0 -Stable tag: 6.26.1 +Stable tag: 6.27 The most advanced WordPress forms plugin. Go beyond contact forms with our drag and drop form builder for surveys, quizzes, and more. @@ -372,6 +372,23 @@ Using our Zapier integration, you can easily connect your website with over 5,00 See all [Formidable Zapier Integrations](https://zapier.com/apps/formidable/integrations). == Changelog == += 6.27 = +* New: Displaying payments is now handled by this plugin, instead of falling back to Stripe, Authorize.Net, and PayPal. In cases where these add-ons were active, the payments table should now appear more modern. +* New: A new coupons tab is available on the payments page. +* New: Required updates to support a new View-Specific CSS setting in the Visual Views add-on. +* New: The submit button will now be enabled when a Square postal code is successfully completed. This fixes issues where the submit button would never get enabled when a Square card field was auto-filled. +* New: Many references to old font icons have been removed, removing about 10KB of data from admin CSS. +* New: Several styles have been optimized in the generated formdiableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. +* Fix: Global custom CSS would incorrectly get added to the formidableforms.css more than once on some sites with multiple styles. +* Fix: The style-specific custom CSS setting would incorrectly get output in the formidableforms.css file as CSS variable data. +* Fix: The htaccess file included in this plugin is now automatically deleted when migrating to a new plugin version if a request to load CSS is blocked, fixing a conflict on some servers that are not configured to allow overwriting file permissions. +* Fix: A PHP warning would get logged when checking data for a rank field as spam. +* Fix: Add-on category counts were not always correct. +* Breaking: Many modern PHP functions are now being used including str_contains, str_starts_with, str_ends_with, array_key_last, and array_key_first. If you are using both a WordPress version older than 5.9, and a PHP version lower than 8.0, this will introduce fatal errors. Note that the minimum required WordPress version is already set to 6.3. +* Breaking: The deprecated functions FrmFieldCaptcha::captcha_size, FrmFormsHelper::should_use_pro_for_ajax_submit, FrmFormsController::add_form_style_tab_options, and FrmFieldType::get_select_atributes have been removed. +* Breaking: The deprecated FrmFormsHelper::actions_dropdown function and actions-dropdown.php view file have been removed. +* An unused FrmTransLiteSubscriptionsController::list_subscriptions_shortcode function and its related view file have been deprecated. + = 6.26.1 = * New: The cached data for license checks is now set to autoload to help reduce calls to the database, and an option check for a request lock has been moved so it only happens when the option data has expired. These changes should help with performance. * New: SVG icon updates have been made to avoid use of the deprecated xlink:href attribute. @@ -405,22 +422,6 @@ See all [Formidable Zapier Integrations](https://zapier.com/apps/formidable/inte * Fix: Captcha labels would incorrectly use the same for attribute when multiple captchas were rendered, causing accessibility issues. * Fix: In some cases, new fields would get inserted below the submit button unexpectedly after saving and reloading. -= 6.25 = -* New: Style settings have been added to Email actions. -* New: reCAPTCHA and Turnstile now support a new frm_captcha_lang filter for modifying the captcha language. -* New: Square forms will now automatically enforce JavaScript validation before attempting to make the Square payment. -* New: Payment hooks like frm_payment_status_complete are now called even when no payments add-ons (Stripe or Authorize.Net) are active. -* Fix: An empty address will no longer be sent to Square when verifying the buyer to help reduce buyer verification issues. -* Fix: Square location IDs could be incorrectly set when connecting when another mode was active. -* Fix: Calculation settings would not properly load if the field was loaded using AJAX. -* Fix: Checkbox and radio button fields no longer include the aria-invalid attribute. Instead, this is applied to the group for better accessibility. -* Fix: Buttons could be cut off in an application pop-up when there was a lot of content in the description. -* Fix: Field unit dropdowns would lose its unit value. -* Fix: An Undefined property: stdClass::$item_key PHP warning when making Square payments has been fixed. -* Fix: The country code would not properly get sent to Square when using US as the address type. -* Fix: A Cannot access offset of type string on string fatal error that occurs when field options data is in an unexpected format has been fixed. -* Fix: Font sizes would not scale as expected after changing the base font size style setting for a second time. - [See changelog for all versions](https://raw.githubusercontent.com/Strategy11/formidable-forms/master/changelog.txt) == Upgrade Notice == From e17fd4883c2e0337998458d14a1c66fa08b6ade2 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 12 Jan 2026 18:05:50 -0400 Subject: [PATCH 2/4] Fix typo --- changelog.txt | 2 +- .../RedundantTruthyBeforeIdenticalSniff.php | 326 ++++++++++++++++++ phpcs.xml | 1 + 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php diff --git a/changelog.txt b/changelog.txt index b1d29c7802..c13bbb3f1c 100644 --- a/changelog.txt +++ b/changelog.txt @@ -5,7 +5,7 @@ * New: Required updates to support a new View-Specific CSS setting in the Visual Views add-on. * New: The submit button will now be enabled when a Square postal code is successfully completed. This fixes issues where the submit button would never get enabled when a Square card field was auto-filled. * New: Many references to old font icons have been removed, removing about 10KB of data from admin CSS. -* New: Several styles have been optimized in the generated formdiableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. +* New: Several styles have been optimized in the generated formidableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. * Fix: Global custom CSS would incorrectly get added to the formidableforms.css more than once on some sites with multiple styles. * Fix: The style-specific custom CSS setting would incorrectly get output in the formidableforms.css file as CSS variable data. * Fix: The htaccess file included in this plugin is now automatically deleted when migrating to a new plugin version if a request to load CSS is blocked, fixing a conflict on some servers that are not configured to allow overwriting file permissions. diff --git a/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php b/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php new file mode 100644 index 0000000000..ddcd400452 --- /dev/null +++ b/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php @@ -0,0 +1,326 @@ +getTokens(); + + // Find the variable before the &&. + $beforeAnd = $this->findExpressionBefore( $phpcsFile, $stackPtr ); + + if ( false === $beforeAnd ) { + return; + } + + // The expression before && should be a simple variable (truthy check). + if ( ! $this->isSimpleTruthyCheck( $phpcsFile, $beforeAnd ) ) { + return; + } + + $variableName = $this->getVariableName( $phpcsFile, $beforeAnd ); + + if ( false === $variableName ) { + return; + } + + // Find the expression after the &&. + $afterAnd = $this->findExpressionAfter( $phpcsFile, $stackPtr ); + + if ( false === $afterAnd ) { + return; + } + + // Check if the expression after && is an identical comparison using the same variable. + $comparisonInfo = $this->isIdenticalComparisonWithVariable( $phpcsFile, $afterAnd, $variableName ); + + if ( false === $comparisonInfo ) { + return; + } + + // We found a redundant pattern! + $fix = $phpcsFile->addFixableError( + 'Redundant truthy check before identical comparison. "%s && %s === ..." can be simplified to "%s === ..."', + $beforeAnd['start'], + 'RedundantTruthyCheck', + array( $variableName, $variableName, $variableName ) + ); + + if ( $fix ) { + $this->applyFix( $phpcsFile, $beforeAnd, $stackPtr ); + } + } + + /** + * Find the expression before the && operator. + * + * @param File $phpcsFile The file being scanned. + * @param int $andPtr The position of the && token. + * + * @return array|false Array with 'start' and 'end' positions, or false. + */ + private function findExpressionBefore( File $phpcsFile, $andPtr ) { + $tokens = $phpcsFile->getTokens(); + + // Find the first non-whitespace token before &&. + $end = $phpcsFile->findPrevious( T_WHITESPACE, $andPtr - 1, null, true ); + + if ( false === $end ) { + return false; + } + + // Walk backwards to find the start of this expression. + // Stop at ( or another && or ||. + $start = $end; + $parenDepth = 0; + $bracketDepth = 0; + + for ( $i = $end; $i >= 0; $i-- ) { + $code = $tokens[ $i ]['code']; + + // Track nested structures. + if ( $code === T_CLOSE_PARENTHESIS ) { + ++$parenDepth; + } elseif ( $code === T_OPEN_PARENTHESIS ) { + if ( $parenDepth === 0 ) { + // This is the opening paren of the if condition. + break; + } + --$parenDepth; + } elseif ( $code === T_CLOSE_SQUARE_BRACKET ) { + ++$bracketDepth; + } elseif ( $code === T_OPEN_SQUARE_BRACKET ) { + --$bracketDepth; + } + + // Stop at logical operators at depth 0. + if ( $parenDepth === 0 && $bracketDepth === 0 ) { + if ( in_array( $code, array( T_BOOLEAN_AND, T_BOOLEAN_OR, T_LOGICAL_AND, T_LOGICAL_OR ), true ) ) { + break; + } + } + + if ( $code !== T_WHITESPACE ) { + $start = $i; + } + } + + return array( + 'start' => $start, + 'end' => $end, + ); + } + + /** + * Find the expression after the && operator. + * + * @param File $phpcsFile The file being scanned. + * @param int $andPtr The position of the && token. + * + * @return array|false Array with 'start' and 'end' positions, or false. + */ + private function findExpressionAfter( File $phpcsFile, $andPtr ) { + $tokens = $phpcsFile->getTokens(); + + // Find the first non-whitespace token after &&. + $start = $phpcsFile->findNext( T_WHITESPACE, $andPtr + 1, null, true ); + + if ( false === $start ) { + return false; + } + + // Walk forward to find the end of this expression. + // Stop at ) or another && or ||. + $end = $start; + $parenDepth = 0; + $bracketDepth = 0; + + for ( $i = $start; $i < count( $tokens ); $i++ ) { + $code = $tokens[ $i ]['code']; + + // Track nested structures. + if ( $code === T_OPEN_PARENTHESIS ) { + ++$parenDepth; + } elseif ( $code === T_CLOSE_PARENTHESIS ) { + if ( $parenDepth === 0 ) { + // This is the closing paren of the if condition. + break; + } + --$parenDepth; + } elseif ( $code === T_OPEN_SQUARE_BRACKET ) { + ++$bracketDepth; + } elseif ( $code === T_CLOSE_SQUARE_BRACKET ) { + --$bracketDepth; + } + + // Stop at logical operators at depth 0. + if ( $parenDepth === 0 && $bracketDepth === 0 ) { + if ( in_array( $code, array( T_BOOLEAN_AND, T_BOOLEAN_OR, T_LOGICAL_AND, T_LOGICAL_OR ), true ) ) { + break; + } + } + + if ( $code !== T_WHITESPACE ) { + $end = $i; + } + } + + return array( + 'start' => $start, + 'end' => $end, + ); + } + + /** + * Check if the expression is a simple truthy check (just a variable). + * + * @param File $phpcsFile The file being scanned. + * @param array $expr The expression info with 'start' and 'end'. + * + * @return bool + */ + private function isSimpleTruthyCheck( File $phpcsFile, $expr ) { + $tokens = $phpcsFile->getTokens(); + + // Collect non-whitespace tokens in the expression. + $exprTokens = array(); + + for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { + if ( $tokens[ $i ]['code'] !== T_WHITESPACE ) { + $exprTokens[] = $tokens[ $i ]; + } + } + + // A simple truthy check is just a variable. + if ( count( $exprTokens ) === 1 && $exprTokens[0]['code'] === T_VARIABLE ) { + return true; + } + + return false; + } + + /** + * Get the variable name from a simple truthy check expression. + * + * @param File $phpcsFile The file being scanned. + * @param array $expr The expression info with 'start' and 'end'. + * + * @return string|false + */ + private function getVariableName( File $phpcsFile, $expr ) { + $tokens = $phpcsFile->getTokens(); + + for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { + if ( $tokens[ $i ]['code'] === T_VARIABLE ) { + return $tokens[ $i ]['content']; + } + } + + return false; + } + + /** + * Check if the expression is an identical comparison using the given variable. + * + * @param File $phpcsFile The file being scanned. + * @param array $expr The expression info with 'start' and 'end'. + * @param string $variableName The variable name to look for. + * + * @return bool + */ + private function isIdenticalComparisonWithVariable( File $phpcsFile, $expr, $variableName ) { + $tokens = $phpcsFile->getTokens(); + + // Look for === or == in the expression. + $hasIdentical = false; + $hasVariable = false; + + for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { + $code = $tokens[ $i ]['code']; + + if ( $code === T_IS_IDENTICAL || $code === T_IS_EQUAL ) { + $hasIdentical = true; + } + + if ( $code === T_VARIABLE && $tokens[ $i ]['content'] === $variableName ) { + $hasVariable = true; + } + } + + return $hasIdentical && $hasVariable; + } + + /** + * Apply the fix by removing the truthy check and the &&. + * + * @param File $phpcsFile The file being scanned. + * @param array $beforeAnd The expression before &&. + * @param int $andPtr The position of the && token. + * + * @return void + */ + private function applyFix( File $phpcsFile, $beforeAnd, $andPtr ) { + $tokens = $phpcsFile->getTokens(); + + $phpcsFile->fixer->beginChangeset(); + + // Remove the truthy check expression. + for ( $i = $beforeAnd['start']; $i <= $beforeAnd['end']; $i++ ) { + $phpcsFile->fixer->replaceToken( $i, '' ); + } + + // Remove the && and any whitespace around it. + $phpcsFile->fixer->replaceToken( $andPtr, '' ); + + // Remove whitespace between the truthy check and &&. + for ( $i = $beforeAnd['end'] + 1; $i < $andPtr; $i++ ) { + if ( $tokens[ $i ]['code'] === T_WHITESPACE ) { + $phpcsFile->fixer->replaceToken( $i, '' ); + } + } + + // Remove whitespace after &&. + $afterAnd = $andPtr + 1; + while ( isset( $tokens[ $afterAnd ] ) && $tokens[ $afterAnd ]['code'] === T_WHITESPACE ) { + $phpcsFile->fixer->replaceToken( $afterAnd, '' ); + ++$afterAnd; + } + + $phpcsFile->fixer->endChangeset(); + } +} diff --git a/phpcs.xml b/phpcs.xml index 5833e15d9e..68f651218b 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -249,4 +249,5 @@ + From 4796462fbc832124b1c9adac1f5e3e2d4ba15a13 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 12 Jan 2026 18:05:55 -0400 Subject: [PATCH 3/4] Fix typo --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 0f50754f79..39aa602ebe 100644 --- a/readme.txt +++ b/readme.txt @@ -378,7 +378,7 @@ See all [Formidable Zapier Integrations](https://zapier.com/apps/formidable/inte * New: Required updates to support a new View-Specific CSS setting in the Visual Views add-on. * New: The submit button will now be enabled when a Square postal code is successfully completed. This fixes issues where the submit button would never get enabled when a Square card field was auto-filled. * New: Many references to old font icons have been removed, removing about 10KB of data from admin CSS. -* New: Several styles have been optimized in the generated formdiableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. +* New: Several styles have been optimized in the generated formidableforms.css file when Pro is not active, helping to reduce file size by removing references to features that only exist in Pro. * Fix: Global custom CSS would incorrectly get added to the formidableforms.css more than once on some sites with multiple styles. * Fix: The style-specific custom CSS setting would incorrectly get output in the formidableforms.css file as CSS variable data. * Fix: The htaccess file included in this plugin is now automatically deleted when migrating to a new plugin version if a request to load CSS is blocked, fixing a conflict on some servers that are not configured to allow overwriting file permissions. From 31c8be12464819f88ad63814bc299f4128704d66 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Mon, 12 Jan 2026 18:13:59 -0400 Subject: [PATCH 4/4] Drop accidentally commited sniff --- .../RedundantTruthyBeforeIdenticalSniff.php | 326 ------------------ phpcs.xml | 1 - 2 files changed, 327 deletions(-) delete mode 100644 phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php diff --git a/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php b/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php deleted file mode 100644 index ddcd400452..0000000000 --- a/phpcs-sniffs/Formidable/Sniffs/CodeAnalysis/RedundantTruthyBeforeIdenticalSniff.php +++ /dev/null @@ -1,326 +0,0 @@ -getTokens(); - - // Find the variable before the &&. - $beforeAnd = $this->findExpressionBefore( $phpcsFile, $stackPtr ); - - if ( false === $beforeAnd ) { - return; - } - - // The expression before && should be a simple variable (truthy check). - if ( ! $this->isSimpleTruthyCheck( $phpcsFile, $beforeAnd ) ) { - return; - } - - $variableName = $this->getVariableName( $phpcsFile, $beforeAnd ); - - if ( false === $variableName ) { - return; - } - - // Find the expression after the &&. - $afterAnd = $this->findExpressionAfter( $phpcsFile, $stackPtr ); - - if ( false === $afterAnd ) { - return; - } - - // Check if the expression after && is an identical comparison using the same variable. - $comparisonInfo = $this->isIdenticalComparisonWithVariable( $phpcsFile, $afterAnd, $variableName ); - - if ( false === $comparisonInfo ) { - return; - } - - // We found a redundant pattern! - $fix = $phpcsFile->addFixableError( - 'Redundant truthy check before identical comparison. "%s && %s === ..." can be simplified to "%s === ..."', - $beforeAnd['start'], - 'RedundantTruthyCheck', - array( $variableName, $variableName, $variableName ) - ); - - if ( $fix ) { - $this->applyFix( $phpcsFile, $beforeAnd, $stackPtr ); - } - } - - /** - * Find the expression before the && operator. - * - * @param File $phpcsFile The file being scanned. - * @param int $andPtr The position of the && token. - * - * @return array|false Array with 'start' and 'end' positions, or false. - */ - private function findExpressionBefore( File $phpcsFile, $andPtr ) { - $tokens = $phpcsFile->getTokens(); - - // Find the first non-whitespace token before &&. - $end = $phpcsFile->findPrevious( T_WHITESPACE, $andPtr - 1, null, true ); - - if ( false === $end ) { - return false; - } - - // Walk backwards to find the start of this expression. - // Stop at ( or another && or ||. - $start = $end; - $parenDepth = 0; - $bracketDepth = 0; - - for ( $i = $end; $i >= 0; $i-- ) { - $code = $tokens[ $i ]['code']; - - // Track nested structures. - if ( $code === T_CLOSE_PARENTHESIS ) { - ++$parenDepth; - } elseif ( $code === T_OPEN_PARENTHESIS ) { - if ( $parenDepth === 0 ) { - // This is the opening paren of the if condition. - break; - } - --$parenDepth; - } elseif ( $code === T_CLOSE_SQUARE_BRACKET ) { - ++$bracketDepth; - } elseif ( $code === T_OPEN_SQUARE_BRACKET ) { - --$bracketDepth; - } - - // Stop at logical operators at depth 0. - if ( $parenDepth === 0 && $bracketDepth === 0 ) { - if ( in_array( $code, array( T_BOOLEAN_AND, T_BOOLEAN_OR, T_LOGICAL_AND, T_LOGICAL_OR ), true ) ) { - break; - } - } - - if ( $code !== T_WHITESPACE ) { - $start = $i; - } - } - - return array( - 'start' => $start, - 'end' => $end, - ); - } - - /** - * Find the expression after the && operator. - * - * @param File $phpcsFile The file being scanned. - * @param int $andPtr The position of the && token. - * - * @return array|false Array with 'start' and 'end' positions, or false. - */ - private function findExpressionAfter( File $phpcsFile, $andPtr ) { - $tokens = $phpcsFile->getTokens(); - - // Find the first non-whitespace token after &&. - $start = $phpcsFile->findNext( T_WHITESPACE, $andPtr + 1, null, true ); - - if ( false === $start ) { - return false; - } - - // Walk forward to find the end of this expression. - // Stop at ) or another && or ||. - $end = $start; - $parenDepth = 0; - $bracketDepth = 0; - - for ( $i = $start; $i < count( $tokens ); $i++ ) { - $code = $tokens[ $i ]['code']; - - // Track nested structures. - if ( $code === T_OPEN_PARENTHESIS ) { - ++$parenDepth; - } elseif ( $code === T_CLOSE_PARENTHESIS ) { - if ( $parenDepth === 0 ) { - // This is the closing paren of the if condition. - break; - } - --$parenDepth; - } elseif ( $code === T_OPEN_SQUARE_BRACKET ) { - ++$bracketDepth; - } elseif ( $code === T_CLOSE_SQUARE_BRACKET ) { - --$bracketDepth; - } - - // Stop at logical operators at depth 0. - if ( $parenDepth === 0 && $bracketDepth === 0 ) { - if ( in_array( $code, array( T_BOOLEAN_AND, T_BOOLEAN_OR, T_LOGICAL_AND, T_LOGICAL_OR ), true ) ) { - break; - } - } - - if ( $code !== T_WHITESPACE ) { - $end = $i; - } - } - - return array( - 'start' => $start, - 'end' => $end, - ); - } - - /** - * Check if the expression is a simple truthy check (just a variable). - * - * @param File $phpcsFile The file being scanned. - * @param array $expr The expression info with 'start' and 'end'. - * - * @return bool - */ - private function isSimpleTruthyCheck( File $phpcsFile, $expr ) { - $tokens = $phpcsFile->getTokens(); - - // Collect non-whitespace tokens in the expression. - $exprTokens = array(); - - for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { - if ( $tokens[ $i ]['code'] !== T_WHITESPACE ) { - $exprTokens[] = $tokens[ $i ]; - } - } - - // A simple truthy check is just a variable. - if ( count( $exprTokens ) === 1 && $exprTokens[0]['code'] === T_VARIABLE ) { - return true; - } - - return false; - } - - /** - * Get the variable name from a simple truthy check expression. - * - * @param File $phpcsFile The file being scanned. - * @param array $expr The expression info with 'start' and 'end'. - * - * @return string|false - */ - private function getVariableName( File $phpcsFile, $expr ) { - $tokens = $phpcsFile->getTokens(); - - for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { - if ( $tokens[ $i ]['code'] === T_VARIABLE ) { - return $tokens[ $i ]['content']; - } - } - - return false; - } - - /** - * Check if the expression is an identical comparison using the given variable. - * - * @param File $phpcsFile The file being scanned. - * @param array $expr The expression info with 'start' and 'end'. - * @param string $variableName The variable name to look for. - * - * @return bool - */ - private function isIdenticalComparisonWithVariable( File $phpcsFile, $expr, $variableName ) { - $tokens = $phpcsFile->getTokens(); - - // Look for === or == in the expression. - $hasIdentical = false; - $hasVariable = false; - - for ( $i = $expr['start']; $i <= $expr['end']; $i++ ) { - $code = $tokens[ $i ]['code']; - - if ( $code === T_IS_IDENTICAL || $code === T_IS_EQUAL ) { - $hasIdentical = true; - } - - if ( $code === T_VARIABLE && $tokens[ $i ]['content'] === $variableName ) { - $hasVariable = true; - } - } - - return $hasIdentical && $hasVariable; - } - - /** - * Apply the fix by removing the truthy check and the &&. - * - * @param File $phpcsFile The file being scanned. - * @param array $beforeAnd The expression before &&. - * @param int $andPtr The position of the && token. - * - * @return void - */ - private function applyFix( File $phpcsFile, $beforeAnd, $andPtr ) { - $tokens = $phpcsFile->getTokens(); - - $phpcsFile->fixer->beginChangeset(); - - // Remove the truthy check expression. - for ( $i = $beforeAnd['start']; $i <= $beforeAnd['end']; $i++ ) { - $phpcsFile->fixer->replaceToken( $i, '' ); - } - - // Remove the && and any whitespace around it. - $phpcsFile->fixer->replaceToken( $andPtr, '' ); - - // Remove whitespace between the truthy check and &&. - for ( $i = $beforeAnd['end'] + 1; $i < $andPtr; $i++ ) { - if ( $tokens[ $i ]['code'] === T_WHITESPACE ) { - $phpcsFile->fixer->replaceToken( $i, '' ); - } - } - - // Remove whitespace after &&. - $afterAnd = $andPtr + 1; - while ( isset( $tokens[ $afterAnd ] ) && $tokens[ $afterAnd ]['code'] === T_WHITESPACE ) { - $phpcsFile->fixer->replaceToken( $afterAnd, '' ); - ++$afterAnd; - } - - $phpcsFile->fixer->endChangeset(); - } -} diff --git a/phpcs.xml b/phpcs.xml index 68f651218b..5833e15d9e 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -249,5 +249,4 @@ -