Skip to content

Fix template validation failing when addon product is selected#347

Merged
superdav42 merged 2 commits intomainfrom
fix/template-validation-addon-merge
Feb 27, 2026
Merged

Fix template validation failing when addon product is selected#347
superdav42 merged 2 commits intomainfrom
fix/template-validation-addon-merge

Conversation

@superdav42
Copy link
Collaborator

@superdav42 superdav42 commented Feb 27, 2026

Summary

  • Bug: Customers selecting a plan + addon product at checkout got "The selected template is not available for this product" when choosing a template
  • Root cause: merge_recursive in additive mode allowed null values from addon products' site_templates.limit to overwrite the plan's template list, causing get_available_site_templates() to return an empty array
  • Fix 1: merge_recursive now skips null values in additive mode (consistent with existing 0/'' unlimited handling)
  • Fix 2: get_empty() now returns proper default states in to_array(), so non-plan products only store actual differences from defaults rather than all modules

Test plan

  • All 2879 existing tests pass (1 pre-existing failure in Site_Duplicator unrelated to this change)
  • 4 new regression tests added covering:
    • Null limit not overwriting template list in additive merge
    • Null limit still overwriting in override mode (correct behavior preserved)
    • get_empty()->to_array() returning proper default states
    • Full checkout scenario: plan + addon product preserving templates
  • Manual test: create a plan with template restrictions, create a package/service product, go to checkout selecting both, verify template selection works

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where null values from addons could overwrite existing plan limits in additive merges; merging now preserves prior limits and avoids duplicate assignments.
  • Enhancements

    • Search/query handling now combines caller-provided parameters with internal query construction, improving result accuracy across model searches.
  • Tests

    • Added tests covering limit merging (additive vs override), default empty-state behavior, and combined plan+addon scenarios.

…ckout

When merging product limitations during checkout, addon products with
site_templates.limit = null would overwrite the plan's template list
in additive mode, causing get_available_site_templates() to return an
empty array. This made the validation rule reject all template selections
with "The selected template is not available for this product."

Two fixes:
- merge_recursive now skips null values in additive mode, consistent
  with existing behavior for 0 and '' (unlimited) values
- get_empty() now returns proper default module states in to_array(),
  so non-plan products only store actual differences from defaults

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc627fb and f2efe3f.

📒 Files selected for processing (1)
  • inc/class-ajax.php

📝 Walkthrough

Walkthrough

Refactors Limitations merging to prevent nulls from overwriting existing additive values, consolidates merge assignment, batch-initializes default module states, adds tests for these behaviors, adds a void return type to a PSR logger setter, and merges caller query params into the local query in AJAX model search.

Changes

Cohort / File(s) Summary
Limitations logic
inc/objects/class-limitations.php
Updated merge_recursive to preserve existing values when additive and incoming value is null; removed duplicate per-key assignment; refactored get_empty to batch-initialize module default states via default_state() rather than lazy property population.
Tests for Limitations
tests/WP_Ultimo/Objects/Limitations_Test.php
Added four tests: preserve templates when merging null additive limits, null overwrites in override mode, get_empty()->to_array() returns expected default keys, and checkout plan+addon merge behavior including templates and additive disk_space.
AJAX search query merging
inc/class-ajax.php
In search_models, merged caller-provided args['query'] into the locally-built $query before model dispatch, ensuring combined query parameters are used for model retrieval and fallback searches.
PSR logger trait
patches/mpdf-mpdf-psr-log-aware-trait-void-return.patch
Added : void return type to setLogger(LoggerInterface $logger) in src/PsrLogAwareTrait.php (signature-only change).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled through code, so neat and small,

I guarded limits from a nully fall.
Merged queries now shake paws and play,
Logger says "void" — tidy all the way.
Tests hop in to keep bugs at bay 🥕✨

🚥 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 bug fix: template validation errors when addon products are selected during checkout, which is the primary issue addressed across all file changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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 docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/template-validation-addon-merge

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.

@github-actions
Copy link

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

Copy link
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.

🧹 Nitpick comments (2)
tests/WP_Ultimo/Objects/Limitations_Test.php (2)

819-820: Consider using string keys in assertions for consistency.

The limit array uses string keys ('2', '3'), and get_available_site_templates() returns $site_id which preserves the string type. Depending on PHPUnit version and strict mode settings, comparing integer 2 against string '2' may behave unexpectedly.

🔧 Suggested fix
-		$this->assertContains(2, $available, 'Template 2 should still be available after merging addon with null limit');
-		$this->assertContains(3, $available, 'Template 3 should still be available after merging addon with null limit');
+		$this->assertContains('2', $available, 'Template 2 should still be available after merging addon with null limit');
+		$this->assertContains('3', $available, 'Template 3 should still be available after merging addon with null limit');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/WP_Ultimo/Objects/Limitations_Test.php` around lines 819 - 820, The
assertions use integer literals (2, 3) while the `limit` array and
`get_available_site_templates()` preserve string keys, which can cause mismatch;
update the two assertions in Limitations_Test (the lines calling
`$this->assertContains(2, $available, ...)` and `$this->assertContains(3,
$available, ...)`) to assert against string keys ('2' and '3') so the types
match the returned `$site_id` strings from `get_available_site_templates()`.

907-908: Same type consideration as earlier test.

Similar to the earlier test, consider using string keys ('5', '7') in assertions to match the array key types in the limit configuration.

🔧 Suggested fix
-		$this->assertContains(5, $available, 'Template 5 should be available');
-		$this->assertContains(7, $available, 'Template 7 should be available');
+		$this->assertContains('5', $available, 'Template 5 should be available');
+		$this->assertContains('7', $available, 'Template 7 should be available');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/WP_Ultimo/Objects/Limitations_Test.php` around lines 907 - 908, The
test is asserting numeric keys but the limit configuration uses string keys;
update the assertions that check $available to use string keys ('5' and '7')
instead of integers so the types match (i.e., change the two calls using
$this->assertContains(5, $available, ...) and $this->assertContains(7,
$available, ...) to $this->assertContains('5', $available, ...) and
$this->assertContains('7', $available, ...)); alternatively you can replace them
with $this->assertArrayHasKey('5', $available, ...) and
$this->assertArrayHasKey('7', $available, ...) to explicitly assert keys exist.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/WP_Ultimo/Objects/Limitations_Test.php`:
- Around line 819-820: The assertions use integer literals (2, 3) while the
`limit` array and `get_available_site_templates()` preserve string keys, which
can cause mismatch; update the two assertions in Limitations_Test (the lines
calling `$this->assertContains(2, $available, ...)` and
`$this->assertContains(3, $available, ...)`) to assert against string keys ('2'
and '3') so the types match the returned `$site_id` strings from
`get_available_site_templates()`.
- Around line 907-908: The test is asserting numeric keys but the limit
configuration uses string keys; update the assertions that check $available to
use string keys ('5' and '7') instead of integers so the types match (i.e.,
change the two calls using $this->assertContains(5, $available, ...) and
$this->assertContains(7, $available, ...) to $this->assertContains('5',
$available, ...) and $this->assertContains('7', $available, ...)); alternatively
you can replace them with $this->assertArrayHasKey('5', $available, ...) and
$this->assertArrayHasKey('7', $available, ...) to explicitly assert keys exist.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2ee2b5 and cc627fb.

📒 Files selected for processing (3)
  • inc/objects/class-limitations.php
  • patches/mpdf-mpdf-psr-log-aware-trait-void-return.patch
  • tests/WP_Ultimo/Objects/Limitations_Test.php

The $query variable was built from exclude/include params but never merged
with $args['query'] which contains the search term. This caused server-side
search filtering to silently fail (selectize.js client-side filtering masked it).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42 superdav42 merged commit 92c64b0 into main Feb 27, 2026
8 of 9 checks passed
@superdav42 superdav42 deleted the fix/template-validation-addon-merge branch February 27, 2026 20:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant