Skip to content

Stop making useless casts#2626

Merged
Crabcyborg merged 2 commits into
masterfrom
stop_useless_casting
Dec 3, 2025
Merged

Stop making useless casts#2626
Crabcyborg merged 2 commits into
masterfrom
stop_useless_casting

Conversation

@Crabcyborg
Copy link
Copy Markdown
Contributor

@Crabcyborg Crabcyborg commented Dec 3, 2025

This removes an exception for a strict PHPStan rule.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 3, 2025

Walkthrough

Broadens PHPDoc type annotations across many files (e.g., int→int|string, array→array|object), removes several explicit casts ((array), (string)), and adds a small runtime guard in generate_xml; phpstan.neon removed its uselessCast override.

Changes

Cohort / File(s) Summary
**PHPDoc: int → int string**
classes/controllers/FrmDashboardController.php, classes/controllers/FrmFormsController.php, classes/models/FrmEntry.php, classes/models/FrmForm.php, classes/models/FrmStyle.php
PHPDoc: array/object / union widening
classes/controllers/FrmXMLController.php, classes/helpers/FrmAppHelper.php, classes/helpers/FrmStylesHelper.php, classes/helpers/FrmXMLHelper.php, classes/models/FrmDb.php, classes/models/FrmEntryMeta.php, classes/models/FrmFieldFormHtml.php, classes/models/fields/FrmFieldType.php
Docblocks changed to document `array
Removed explicit casts
classes/models/FrmAddon.php, classes/models/FrmMigrate.php, classes/models/FrmNotification.php, classes/models/FrmPersonalData.php, classes/models/FrmTableHTMLGenerator.php, classes/widgets/FrmShowForm.php
Removed (array)/(string) casts from loops, assignments, and parsing calls; variables are used directly.
Behavioral tweak (minor)
classes/models/FrmFieldOption.php
Changed check from '' !== (string) $this->saved_value to '' !== $this->saved_value, altering handling of null/false-like saved values when using value as label.
Small runtime guard
classes/controllers/FrmXMLController.php
Added an early return in generate_xml when $type is not an array (with docblock/type adjustments and a note about casting in prepare_types_array).
Formatting/docblock only
classes/helpers/FrmEntriesHelper.php, classes/helpers/FrmAppHelper.php, classes/models/FrmEntryMeta.php, classes/models/FrmFieldFormHtml.php, classes/helpers/FrmStylesHelper.php
Broadened PHPDoc types (e.g., arraymixed or `array
Configuration
phpstan.neon
Removed uselessCast: false from strictRules.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Focus review on:
    • classes/models/FrmFieldOption.php — changed comparison may change label output for null/false.
    • classes/models/FrmAddon.php — removed cast returning original truthy value; verify callers expect an array.
    • classes/controllers/FrmXMLController.php — new guard around $type and associated docblock changes.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Stop making useless casts' accurately summarizes the main objective of the changeset, which removes unnecessary type casts throughout the codebase and updates the phpstan.neon configuration.
Description check ✅ Passed The description 'This removes an exception for a strict PHPStan rule' is directly related to the changeset, which updates phpstan.neon by removing the uselessCast: false configuration entry.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stop_useless_casting

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49ce6de and 60d5173.

📒 Files selected for processing (1)
  • classes/controllers/FrmXMLController.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • classes/controllers/FrmXMLController.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: PHP 8 tests in WP trunk
  • GitHub Check: PHP 7.4 tests in WP trunk
  • GitHub Check: Cypress

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.

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: 2

Caution

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

⚠️ Outside diff range comments (1)
classes/controllers/FrmXMLController.php (1)

463-483: Psalm error: $type is now documented as array<string>|string, but foreach assumes array.

Widening the $type docblock to array<string>|string is reasonable given how this method is used, and prepare_types_array() correctly normalizes it with (array) $type. However, Psalm can’t see that the by‑ref call guarantees an array, so it flags foreach ( $type as $tb_type ) as “PossiblyInvalidIterator” (see the pipeline failure).

You can keep the broader param type and fix the static analysis by asserting the post‑condition before the loop, e.g.:

 public static function generate_xml( $type, $args = array() ) {
     global $wpdb;

     self::prepare_types_array( $type );
+
+    /** @var array<string> $type */
+
     $tables = array(
         'items'   => $wpdb->prefix . 'frm_items',

This has no runtime effect but tells Psalm that $type is an array at that point. Alternatively, you could re-cast locally ($type = (array) $type;) if you prefer not to rely on the by‑ref helper.

♻️ Duplicate comments (2)
classes/models/FrmPersonalData.php (1)

120-120: Same verification needed as line 79.

This has the same concern regarding FrmDb::get_col() return type. The empty() check on line 114 provides protection, but verify the method always returns an array.

classes/controllers/FrmXMLController.php (1)

611-627: Docblock widening for $type in prepare_types_array is consistent with callers.

Allowing array<string>|string for $type in prepare_types_array() matches how generate_xml() now documents its own $type parameter and is safe given the explicit (array) $type normalization inside this helper. Once the Psalm concern above is addressed, this change should be non‑controversial.

🧹 Nitpick comments (3)
classes/models/FrmEntryMeta.php (1)

395-417: Return type mixed is accurate; optionally narrow to a union later

Changing the getAll docblock return from array to mixed better matches the current implementation, which can return different shapes depending on $limit and $stripslashes, via FrmDb::check_cache. No runtime behavior changes here.

If you want stricter static analysis in the future, you could consider documenting a more explicit union (e.g., array|object|null or similar) once the exact contract of FrmDb::check_cache is nailed down, but this is not required for this PR.

classes/models/FrmPersonalData.php (1)

141-141: Consider restoring "of" for clarity.

The updated PHPDoc "array Entry ids" is grammatically awkward compared to the previous "array of entry ids". While minor, the original phrasing was clearer.

Apply this diff to restore clarity:

-	 * @return array Entry ids
+	 * @return array of entry ids
classes/models/FrmFieldOption.php (1)

90-101: Cast removal is safe for documented types; only edge case is if $saved_value can be null.

Removing (string) from the '' !== (string) $this->saved_value check keeps behavior identical for the expected types (string / numeric string). The only behavior change would be if $saved_value were ever null or another non-string falsy value, in which case the label would now resolve to an empty string instead of FrmAppHelper::get_no_label_text(). If $saved_value is guaranteed to be a string per the class contract, this is fine; otherwise, consider normalizing it to a string when setting it, or keeping the cast.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0700b1 and 49ce6de.

📒 Files selected for processing (22)
  • classes/controllers/FrmDashboardController.php (2 hunks)
  • classes/controllers/FrmFormsController.php (1 hunks)
  • classes/controllers/FrmXMLController.php (2 hunks)
  • classes/helpers/FrmAppHelper.php (1 hunks)
  • classes/helpers/FrmEntriesHelper.php (1 hunks)
  • classes/helpers/FrmStylesHelper.php (1 hunks)
  • classes/helpers/FrmXMLHelper.php (1 hunks)
  • classes/models/FrmAddon.php (1 hunks)
  • classes/models/FrmDb.php (1 hunks)
  • classes/models/FrmEntry.php (5 hunks)
  • classes/models/FrmEntryMeta.php (1 hunks)
  • classes/models/FrmFieldFormHtml.php (1 hunks)
  • classes/models/FrmFieldOption.php (1 hunks)
  • classes/models/FrmForm.php (2 hunks)
  • classes/models/FrmMigrate.php (1 hunks)
  • classes/models/FrmNotification.php (1 hunks)
  • classes/models/FrmPersonalData.php (4 hunks)
  • classes/models/FrmStyle.php (1 hunks)
  • classes/models/FrmTableHTMLGenerator.php (1 hunks)
  • classes/models/fields/FrmFieldType.php (1 hunks)
  • classes/widgets/FrmShowForm.php (1 hunks)
  • phpstan.neon (0 hunks)
💤 Files with no reviewable changes (1)
  • phpstan.neon
🧰 Additional context used
🧬 Code graph analysis (3)
classes/models/FrmNotification.php (1)
classes/helpers/FrmAppHelper.php (2)
  • FrmAppHelper (6-5084)
  • kses (1059-1063)
classes/models/FrmFieldOption.php (1)
classes/helpers/FrmAppHelper.php (2)
  • FrmAppHelper (6-5084)
  • get_no_label_text (4005-4007)
classes/models/FrmForm.php (1)
classes/models/FrmDb.php (2)
  • FrmDb (6-870)
  • get_results (330-332)
🪛 GitHub Actions: Psalm Code Analysis
classes/controllers/FrmXMLController.php

[error] 495-495: Psalm: PossiblyInvalidIterator. Cannot iterate over string. See https://psalm.dev/165.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: PHP 7.4 tests in WP trunk
  • GitHub Check: PHP 8 tests in WP trunk
  • GitHub Check: Cypress
  • GitHub Check: Cypress
  • GitHub Check: PHP 7.4 tests in WP trunk
  • GitHub Check: PHP 8 tests in WP trunk
🔇 Additional comments (22)
classes/models/FrmMigrate.php (1)

555-569: Change is consistent with migrate_to_17; just confirm get_fields_with_size() always returns an array

Using foreach ( $fields as $f ) without the (array) cast brings migrate_to_86 in line with migrate_to_17, which already iterates the result of get_fields_with_size() without casting. Given the @return array docblock on get_fields_with_size(), this looks correct and removes a redundant cast.

The only thing to double‑check is that FrmDb::get_results() never returns null/false; otherwise this could start emitting “Invalid argument supplied for foreach()” notices where previously the cast would turn non‑arrays into an empty array.

If that contract is guaranteed, this change is good as‑is.

classes/models/FrmNotification.php (1)

72-72: LGTM! Unnecessary cast removed correctly.

The (array) cast on $temp was indeed useless since str_replace() returns an array when its subject parameter is an array (which $sent_to is guaranteed to be from lines 68-69).

classes/models/fields/FrmFieldType.php (1)

169-169: LGTM! Improved type documentation accuracy.

The broadened return type array|object|string more accurately reflects what this method can return. Since field columns can contain various data types including objects (nested configurations), arrays (options), or scalar values, this documentation improvement provides better type information.

classes/models/FrmAddon.php (1)

741-747: Removal of (array) cast in last_checked() is safe and keeps the return type invariant

Given the normalization block:

if ( $last_checked && ! is_array( $last_checked ) ) {
	$last_checked = array( 'time' => $last_checked );
}

any truthy $last_checked reaching the return is already an array, and falsy values still map to array(). The new:

return $last_checked ? $last_checked : array();

preserves the documented @return array contract and just drops a redundant cast. No behavior change for existing stored values or callers relying on an array.

classes/models/FrmTableHTMLGenerator.php (1)

97-97: No action required. All constructor call sites pass string literals ('entry' or 'shortcode'), confirming the cast removal is safe and not a breaking change. The PHPDoc annotations remain accurate.

classes/widgets/FrmShowForm.php (1)

66-66: The (array) cast removal is appropriate.

wp_parse_args() is designed to handle mixed input types and will normalize them to an array. Since FrmShowForm extends WordPress's WP_Widget class, the widget framework guarantees that form() receives $instance as an array from stored widget settings. The PHPDoc already declares the expected type as @param array $instance, making the explicit cast redundant. This change aligns with modern PHP practices and the removal is safe.

classes/models/FrmFieldFormHtml.php (1)

32-34: LGTM! PHPDoc accurately reflects the property's union type.

The change from @var array to @var array|object correctly documents that the $form property can be either type. This is validated by the necessary cast at line 360 ($form = (array) $this->form;), which ensures safe array access for subsequent operations. The default initialization as array() remains appropriate.

classes/models/FrmForm.php (2)

831-839: Docblock type for get_key_by_id now matches usage

Accepting int|string in the docblock aligns with the cast to (int) inside and common call patterns (numeric strings); no behavioral change introduced.


1002-1045: Removal of (array) cast around FrmDb::get_results is safe

FrmDb::get_results already returns an array of rows, so dropping the redundant cast in get_count() preserves behavior while satisfying the “no useless casts” objective.

classes/helpers/FrmXMLHelper.php (1)

771-781: Broadened $field doc type matches implementation

migrate_field_placeholder() already handles objects via (array) $field, so documenting array|object simply reflects reality and is correct.

classes/helpers/FrmEntriesHelper.php (1)

26-34: $fields docblock widened to mixed aligns with casting behavior

Since setup_new_vars() casts $fields to array before iteration, documenting it as mixed is more accurate and doesn’t change runtime behavior.

classes/models/FrmDb.php (1)

680-687: save_settings doc now matches the (array) cast

Allowing array|object in the docblock is consistent with casting $settings to array and accurately documents current behavior.

classes/controllers/FrmDashboardController.php (1)

470-493: get_youtube_embed_video docblock matches actual usage

Documenting $entries_count as int|string is consistent with the internal (int) casts and common numeric-string inputs; logic and return behavior remain unchanged.

classes/helpers/FrmStylesHelper.php (1)

762-769: Docblock for get_base_font_size_scale updated to reflect real inputs

Allowing int|string for $value matches how callers pass font sizes and how the function casts to (int) internally; behavior is unaffected.

classes/helpers/FrmAppHelper.php (1)

2895-2898: Docblock type now correctly matches actual usage of $fields.

Allowing array|string in the docblock for $fields reflects existing behavior (default '' and arrays) and matches the (array) $fields cast in the implementation, with no runtime change.

classes/controllers/FrmFormsController.php (1)

1294-1299: Docblock widening for $value matches how screen options are passed.

Annotating $value as int|string aligns with WordPress screen options behavior and the explicit (int) cast in save_per_page, without changing runtime semantics.

classes/models/FrmStyle.php (1)

847-852: Allowing int|string for $style_id is consistent with current usage.

The docblock now reflects that callers may pass either an int or a string ID, and the method already normalizes via (int) $style_id, so there is no behavioral impact.

classes/models/FrmEntry.php (5)

724-724: PHPDoc type broadening looks correct.

The parameter type change from int to int|string accurately reflects that this method accepts both types at runtime, with the code safely casting to int on Line 730.


1055-1055: PHPDoc type broadening is accurate.

The change from int to int|string correctly documents that this method accepts both types, with the code safely casting to int on Line 1066 before storing in the array.


1074-1075: PHPDoc update aligns with runtime behavior.

The parameter type broadening for $entry_id from int to int|string is consistent with how the parameter is used—passed to other methods and cast to int when needed on Line 1084.


1173-1175: PHPDoc accurately reflects parameter usage.

The broadening of $id from int to int|string correctly documents the method's actual behavior—accepting both types and casting to int on Line 1184 when needed for comparison.


1242-1245: PHPDoc changes are consistent and accurate.

The parameter type broadening for $id from int to int|string appropriately documents the method's runtime behavior, with safe casting to int on Line 1260 where needed.

Comment thread classes/models/FrmPersonalData.php
Comment thread classes/models/FrmPersonalData.php
@Crabcyborg Crabcyborg added this to the 6.26 milestone Dec 3, 2025
@Crabcyborg Crabcyborg merged commit 2001d51 into master Dec 3, 2025
16 checks passed
@Crabcyborg Crabcyborg deleted the stop_useless_casting branch December 3, 2025 18:47
stephywells pushed a commit that referenced this pull request Apr 4, 2026
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