Skip to content

Fix AI features rendered twice on user profile page#23218

Merged
pls78 merged 2 commits intotrunkfrom
2972-trivial-ai-features-displayed-two-times-at-user-settings
May 4, 2026
Merged

Fix AI features rendered twice on user profile page#23218
pls78 merged 2 commits intotrunkfrom
2972-trivial-ai-features-displayed-two-times-at-user-settings

Conversation

@thijsoo
Copy link
Copy Markdown
Contributor

@thijsoo thijsoo commented Apr 30, 2026

Context

  • The AI module was duplicated into a legacy tree (src/ai-*) and a new onion-architecture tree (src/ai/*) so that older Premium versions can keep referencing the legacy namespaces. Both trees register identical hooks at the same priority, so both fire on every profile page load.
  • The migration to the new tree shipped in Yoast SEO Premium 27.5, which is the natural cut-off for choosing which tree to load.

Summary

This PR can be summarized in the following changelog entry:

  • Fixes a bug where the AI features section was rendered twice on the user profile page.

Relevant technical choices:

  • The DI container is compiled at build time and cannot know which Premium version (if any) is installed, so the gating happens at the runtime conditional layer instead — Loader::conditionals_are_met() evaluates conditionals on init, where Premium's WPSEO_PREMIUM_VERSION constant is reachable via Product_Helper.

  • Resulting matrix — exactly one tree active per environment:

    Environment OLD src/ai-* NEW src/ai/*
    Free only (no Premium) bail run
    Premium < 27.5-RC0 run bail
    Premium >= 27.5-RC0 bail run
  • When Premium < 27.5 support is eventually dropped, the entire src/ai-* tree and Old_Premium_AI_Conditional can be deleted in one go without affecting Free or new-Premium users.

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:

  • Make sure you can switch between three setups: (a) Free only, (b) Free + Premium < 27.5 (e.g. 27.4), and (c) Free + Premium >= 27.5.
  • In each of the three setups, log in as an editor or administrator and visit /wp-admin/profile.php.
  • Scroll to the AI features section. Verify it appears exactly once in every setup — not zero times, not twice.
  • In each setup, click the AI features consent toggle and confirm the toggle saves (refresh the page; the toggle state is persisted).
  • Open a post in the block editor, open the Yoast sidebar, and click Generate on the title or meta description suggestion. Confirm a suggestion is returned in all three setups (this exercises the AI generator routes, which are also gated by the new conditionals).

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

  • The AI features consent UI on the user profile page.
  • The AI generator modal in the post/term/Elementor editors.
  • The AI-related REST routes under /yoast/v1/ai_generator/* and /yoast/v1/ai/free_sparks (consent, suggestions, usage, subscription-cache busting, free sparks, OAuth callbacks).
  • The interaction with Yoast SEO Premium across the 27.5 boundary — both the legacy-Premium path and the new-Premium path must keep working.

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and committed the results, if my PR introduces or edits images or SVGs.

Innovation

  • No innovation project is applicable for this PR.
  • This PR falls under an innovation project. I have attached the innovation label.
  • I have added my hours to the WBSO document.

The AI module was duplicated into src/ai-* (legacy) and src/ai/* (new
onion structure) so older Premium versions can keep referencing the
legacy namespaces. Both trees registered identical hooks at the same
priority, which rendered the "AI features" section twice on the user
profile page in 27.6-RC2.

Add two version-aware conditionals that key off the Premium 27.5 AI
restructure:

- Old_Premium_AI_Conditional: true when Premium is active and
  predates 27.5-RC0; gates every src/ai-* integration and route.
- New_Premium_Or_Free_AI_Conditional: true when Premium is absent
  or at least 27.5-RC0; gates every src/ai/* integration and route.

The conditionals are runtime-evaluated in Loader::conditionals_are_met,
so the DI container does not need to know which Premium is installed
at compile time. Free users and Premium >=27.5 see the new tree;
Premium <27.5 keeps using the legacy tree; only one tree is ever
active at a time.

Also drops a redundant No_Conditionals trait usage in both
Get_Suggestions_Route classes; the explicit get_conditionals()
already overrides it.

Refs #2972.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thijsoo thijsoo added the changelog: bugfix Needs to be included in the 'Bugfixes' category in the changelog label Apr 30, 2026
@coveralls
Copy link
Copy Markdown

coveralls commented Apr 30, 2026

Coverage Report for CI Build 8

Coverage decreased (-0.6%) to 52.936%

Details

  • Coverage decreased (-0.6%) from the base build.
  • Patch coverage: 8 uncovered changes across 8 files (26 of 34 lines covered, 76.47%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
src/ai-authorization/user-interface/abstract-callback-route.php 1 0 0.0%
src/ai-consent/user-interface/ai-consent-integration.php 1 0 0.0%
src/ai-consent/user-interface/consent-route.php 1 0 0.0%
src/ai-free-sparks/user-interface/free-sparks-route.php 1 0 0.0%
src/ai-generator/user-interface/ai-generator-integration.php 1 0 0.0%
src/ai-generator/user-interface/bust-subscription-cache-route.php 1 0 0.0%
src/ai-generator/user-interface/get-suggestions-route.php 1 0 0.0%
src/ai-generator/user-interface/get-usage-route.php 1 0 0.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 65309
Covered Lines: 34531
Line Coverage: 52.87%
Relevant Branches: 16414
Covered Branches: 8730
Branch Coverage: 53.19%
Branches in Coverage %: Yes
Coverage Strength: 46059.31 hits per line

💛 - Coveralls

@thijsoo thijsoo marked this pull request as ready for review April 30, 2026 07:57
…972-trivial-ai-features-displayed-two-times-at-user-settings
@pls78 pls78 modified the milestones: 27.7, 27.6 May 4, 2026
Copy link
Copy Markdown
Member

@pls78 pls78 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CR && Acc: ✅

@pls78 pls78 merged commit 6007e22 into trunk May 4, 2026
31 checks passed
@pls78 pls78 deleted the 2972-trivial-ai-features-displayed-two-times-at-user-settings branch May 4, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: bugfix Needs to be included in the 'Bugfixes' category in the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants