Skip to content

Conversation

@KokkieH
Copy link
Contributor

@KokkieH KokkieH commented Nov 4, 2025

Submission Review Guidelines:

Changes proposed in this Pull Request:

At the moment, the My Subscriptions page shows an Install button for SaaS products, which don't have an installation file hosted on either WooCommerce.com or WordPress.org. We need to hide the button for those products, so we're not offering an action that's not possible.

Part of WCCOM-1896

Related WooCommerce.com PR: https://github.com/Automattic/woocommerce.com/pull/24640

How to test the changes in this Pull Request:

Using the WooCommerce Testing Instructions Guide, include your detailed testing instructions:

  1. Make sure the add/WCCOM-1896-has-changelog-prop branch is checked out on your WooCommerce.com dev environment, and that you have a user with an active SaaS/non-downloadable product (see test instructions for https://github.com/Automattic/woocommerce.com/pull/24640)
  2. Connect your WC Core site to your local WCCOM with docker network connect woocommerce.test <wc core container id>
  3. Log in and connect your local WCCOM account.
  4. Visit My Subscriptions. Confirm that your SaaS product is listed as active, but that the Install button doesn't appear next to it.
Extensions_‹_WooCommerce_‹_woocommerce

Testing that has already taken place:

Changelog entry

  • Automatically create a changelog entry from the details below.
  • This Pull Request does not require a changelog entry. (Comment required below)
Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Hide Install button for marketplace subscriptions that don't have anything to install

Changelog Entry Comment

Comment

@KokkieH KokkieH self-assigned this Nov 4, 2025
@KokkieH KokkieH added WCCOM/Marketplace Issues related to communication with woocommerce.com. Desire Woo Marketing and WooCommerce.com customer experience team: Desire labels Nov 4, 2025
@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Nov 4, 2025
@claude
Copy link

claude bot commented Nov 4, 2025

Claude finished @KokkieH's task —— View job


Backwards Compatibility Review ✅

Summary

Risk Level: None

This PR introduces a new optional property has_changelog to the internal Subscription TypeScript type and uses it to conditionally hide Install/Connect buttons for SaaS products. The changes are fully backwards compatible with no breaking changes detected.

Rationale:

  1. The new has_changelog: boolean property is added to an internal TypeScript interface that models data from the WooCommerce.com API
  2. The property is used defensively with strict equality checks (=== true), meaning undefined/missing values will safely prevent button rendering
  3. No public APIs are modified - changes are confined to internal UI rendering logic
  4. The data originates from WooCommerce.com's API (companion PR: https://github.com/Automattic/woocommerce.com/pull/24640), so this is a coordinated backend+frontend change
  5. No PHP APIs, REST endpoints, hooks, filters, or template files are modified

Detailed Analysis

TypeScript Interface Changes

File: plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts:36

Added property:

has_changelog: boolean;

BC Assessment:Safe

  • TypeScript interfaces are compile-time only and don't affect runtime behavior
  • The property is added to an internal type used only within the marketplace module (verified via grep: only 4 files import this type, all within /marketplace/)
  • No external extensions consume this type
  • The type models API response data, so the backend must provide this field (handled by companion WCCOM PR)
Conditional Rendering Logic Changes

File: plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx:390-402

Before:

} else if (
    subscription.local.installed === false &&
    subscription.subscription_installed === false
) {
    actionButton = <Install subscription={ subscription } />;
} else if (
    subscription.active === false &&
    subscription.subscription_available === true
) {
    actionButton = <ConnectButton subscription={ subscription } variant="link" />;
}

After:

} else if (
    subscription.local.installed === false &&
    subscription.subscription_installed === false &&
    subscription.has_changelog === true
) {
    actionButton = <Install subscription={ subscription } />;
} else if (
    subscription.active === false &&
    subscription.subscription_available === true &&
    subscription.has_changelog === true
) {
    actionButton = <ConnectButton subscription={ subscription } variant="link" />;
}

BC Assessment:Safe - Defensive Implementation

  • Uses strict equality (=== true), so undefined, null, or false values will prevent button rendering
  • If the backend doesn't provide has_changelog, buttons won't render (fail-safe behavior)
  • This is an additive guard - it only adds an additional condition to existing checks
  • No existing functionality is removed; the logic is more restrictive (which is the intended behavior)
Data Flow Analysis

The Subscription data flows from:

  1. PHP Backend: WC_Helper::get_subscription_list_data() in includes/admin/helper/class-wc-helper.php:1935
  2. REST API: /wc/v3/marketplace/subscriptions endpoint in class-wc-helper-subscriptions-api.php:45
  3. Frontend: Fetched via fetchSubscriptions() in utils/functions.tsx:265
  4. React Context: Stored in SubscriptionsContext and passed to components

BC Assessment:Safe

  • The PHP backend passes through data from WooCommerce.com's API without schema validation
  • The companion WCCOM PR adds the has_changelog field to API responses
  • No changes to REST endpoint schemas, parameters, or response structure
  • No changes to any WordPress hooks or filters

Ecosystem Impact Assessment

Payment Gateways: ✅ No impact

  • No payment gateway code is modified

WooCommerce Extensions (Subscriptions/Bookings/Memberships): ✅ No impact

  • Changes only affect marketplace UI for displaying WooCommerce.com subscriptions
  • No APIs that extensions depend on are modified
  • Extensions that are subscriptions themselves will simply have the new field in their data

Themes Customizing Templates: ✅ No impact

  • No template files modified
  • No HTML/CSS class names changed
  • Changes are React component-internal logic only

Custom Checkout Flows: ✅ No impact

  • No checkout-related code modified

Third-party Code Consuming Marketplace Data: ⚠️ Very Low Risk

  • If any third-party code reads subscription data via the REST API and uses TypeScript, they would see a new optional field
  • Impact: Cosmetic only - TypeScript may show type mismatches, but runtime behavior unchanged
  • Likelihood: Very low - the marketplace subscriptions API is intended for internal WooCommerce admin use only

Testing Focus

Primary Test Area: Marketplace My Subscriptions page (/wp-admin/admin.php?page=wc-admin&path=/extensions/subscriptions)

Regression Testing Steps:

  1. Traditional downloadable products:

    • Verify Install button still appears for uninstalled traditional extensions/plugins
    • Verify Connect button appears for available but inactive subscriptions
    • Test: Install a product and verify the button changes appropriately
  2. SaaS products (non-installable):

    • Verify Install button does NOT appear for SaaS products
    • Verify Connect button does NOT appear for SaaS products
    • Confirm SaaS products still display correctly in the list with other status badges
  3. Edge cases:

    • Expired subscriptions: Verify Renew button still appears (unchanged logic)
    • Products without subscriptions: Verify Subscribe button still appears (unchanged logic)
    • Auto-renewal disabled: Verify Auto-renew button still appears (unchanged logic)
  4. API compatibility:

    • Test with WooCommerce.com production API (if has_changelog is not yet deployed)
    • Verify graceful degradation if field is missing (buttons should not appear)

Expected Behavior:

  • Traditional downloadable products: Install/Connect buttons visible (when conditions met)
  • SaaS products (has_changelog: false or undefined): No Install/Connect buttons
  • No JavaScript errors in console
  • No PHP warnings/errors in debug log

Confidence

95% - High confidence in no breaking changes

Justification:

  • All changes are additive and internal to the marketplace module
  • No public APIs, hooks, filters, or REST schemas are modified
  • TypeScript type change is to an internal, non-exported interface
  • Rendering logic uses defensive checks with fail-safe behavior
  • The 5% uncertainty accounts for:
    • Potential undocumented third-party code consuming the subscriptions REST API
    • Unexpected interactions if WooCommerce.com API doesn't deploy the backend change
    • Edge case: TypeScript compilation in customizations that import this internal type

Migration/Deprecation Guidance

None required - This is a purely additive change with no deprecations.

For Extension Developers: No action needed. If you have custom code that:

  • Consumes /wc/v3/marketplace/subscriptions REST endpoint: The new has_changelog field will appear in responses (safe to ignore)
  • Uses TypeScript and imports marketplace types: Update your local types or ignore the new field (it's internal to WooCommerce core)

Conclusion

No breaking changes detected. This PR safely hides Install/Connect buttons for SaaS products that don't have downloadable files, improving the user experience by removing non-functional UI elements. The implementation is defensive, backwards-compatible, and properly coordinated with backend changes.

@KokkieH KokkieH requested review from a team, bor0 and gedex November 4, 2025 11:56
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

📝 Walkthrough

Walkthrough

This pull request adds a conditional guard to prevent displaying the Install and ConnectButton actions for marketplace subscriptions without a changelog. A new boolean field has_changelog is introduced to the Subscription type and used in the action selection logic.

Changes

Cohort / File(s) Summary
Changelog documentation
plugins/woocommerce/changelog/61797-update-WCCOM-1896-hide-install-button-for-saas-products
Added changelog entry documenting the hiding of the Install button for SaaS products without installables. Marked as minor/tweak.
Type definition
plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts
Added has_changelog: boolean field to the Subscription type.
Action selection logic
plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx
Added has_changelog === true condition guard to two branches in actions() that determine when Install and ConnectButton actions are presented.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • The changes are straightforward: adding a single boolean field and applying a simple conditional guard in two locations
  • All modifications follow a consistent pattern with minimal logic complexity
  • Changelog entry is purely descriptive documentation

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: hiding the Install/Connect button for SaaS products without installation files.
Description check ✅ Passed The description comprehensively explains the change, rationale, testing instructions, and includes a relevant changelog entry directly related to the changeset.
✨ 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 update/WCCOM-1896-hide-install-button-for-saas-products

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
Contributor

github-actions bot commented Nov 4, 2025

Size Change: +16 B (0%)

Total Size: 6.03 MB

compressed-size-action

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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx (1)

395-402: Guard against undefined has_changelog for backwards compatibility.

Same issue as the Install button above: the strict equality check subscription.has_changelog === true may break existing ConnectButton functionality if the API doesn't provide has_changelog for all subscriptions.

Apply similar defensive coding as suggested for the Install button:

 } else if (
 	subscription.active === false &&
 	subscription.subscription_available === true &&
-	subscription.has_changelog === true
+	( subscription.has_changelog ?? true ) === true
 ) {

Based on coding guidelines

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9ab88e and 16c5693.

📒 Files selected for processing (3)
  • plugins/woocommerce/changelog/61797-update-WCCOM-1896-hide-install-button-for-saas-products (1 hunks)
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx (1 hunks)
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{php,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/code-quality.mdc)

**/*.{php,js,jsx,ts,tsx}: Guard against unexpected inputs
Sanitize and validate any potentially dangerous inputs
Ensure code is backwards compatible
Write code that is readable and intuitive
Ensure code has unit or E2E tests where applicable

Files:

  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx
**/*.{php,js,jsx,tsx,ts}

📄 CodeRabbit inference engine (.cursor/rules/avoid-regex.mdc)

**/*.{php,js,jsx,tsx,ts}: Avoid using regular expressions unless absolutely necessary to favor readability and maintainability
Only consider regex when no built-in language alternative (string/array APIs) fits the need
Only use regex when performance is critical and faster than alternatives, with measurements to justify
Use regex for complex pattern matching only if the pattern is well-documented and thoroughly tested
Allow regex when maintaining legacy code where an existing, correct pattern is being modified
If regex is necessary, document the pattern extensively to explain what it matches
If regex is necessary, add comprehensive tests covering edge cases and potential security issues
Use named capture groups in regex to improve readability when supported
Validate input before applying regex to ensure it is safe
Assess and mitigate security risks when using regex, including ReDoS and injection vulnerabilities
Avoid regex patterns that can cause catastrophic backtracking (ReDoS)
Do not construct regex from untrusted input to prevent injection attacks
Ensure regex patterns do not overmatch and unintentionally capture unexpected inputs

Files:

  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx
**/*.{php,js,ts,jsx,tsx}

⚙️ CodeRabbit configuration file

**/*.{php,js,ts,jsx,tsx}: Don't trust that extension developers will follow the best practices, make sure the code:

  • Guards against unexpected inputs.
  • Sanitizes and validates any potentially dangerous inputs.
  • Is backwards compatible.
  • Is readable and intuitive.
  • Has unit or E2E tests where applicable.
    When making any changes to code that deletes or modifies orders/products/customer data, make sure that there are
    sufficient checks in place to prevent accidental data loss. As an example, if deleting a draft order, check that
    the order status is indeed draft or checkout-draft. Also think about whether race conditions could occur and
    delete orders that don't belong to the current customer. When in doubt, ask for clarification in the PR comments.

Files:

  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: jorgeatorres
Repo: woocommerce/woocommerce PR: 59675
File: .github/workflows/release-bump-as-requirement.yml:48-65
Timestamp: 2025-07-15T15:39:21.856Z
Learning: In WooCommerce core repository, changelog entries for all PRs live in `plugins/woocommerce/changelog/` directory and are processed during releases, not at the repository root level.
Learnt from: annemirasol
Repo: woocommerce/woocommerce PR: 60578
File: plugins/woocommerce/includes/gateways/paypal/includes/settings-paypal.php:104-113
Timestamp: 2025-09-03T17:16:04.109Z
Learning: For the PayPal WPS migration project in WooCommerce, legacy settings (marked with 'is_legacy' => true in settings-paypal.php) should not be modified as part of the migration work. Changes to legacy settings should be handled in separate PRs to maintain focused scope on the WPS migration functionality.
Learnt from: jamesckemp
Repo: woocommerce/woocommerce PR: 60816
File: plugins/woocommerce/includes/class-wc-post-types.php:485-492
Timestamp: 2025-09-12T13:24:41.207Z
Learning: In WooCommerce PR #60816, the shop_order post type registration correctly uses 'show_in_menu' => true to create a top-level Orders menu, moving away from the previous submenu structure under WooCommerce. This is intentional and aligns with the PR goal of promoting Orders to top-level navigation.
📚 Learning: 2025-07-15T15:39:21.856Z
Learnt from: jorgeatorres
Repo: woocommerce/woocommerce PR: 59675
File: .github/workflows/release-bump-as-requirement.yml:48-65
Timestamp: 2025-07-15T15:39:21.856Z
Learning: In WooCommerce core repository, changelog entries for all PRs live in `plugins/woocommerce/changelog/` directory and are processed during releases, not at the repository root level.

Applied to files:

  • plugins/woocommerce/changelog/61797-update-WCCOM-1896-hide-install-button-for-saas-products
📚 Learning: 2025-07-24T05:37:00.907Z
Learnt from: dinhtungdu
Repo: woocommerce/woocommerce PR: 59900
File: plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/inner-blocks/attribute-filter/inspector.tsx:0-0
Timestamp: 2025-07-24T05:37:00.907Z
Learning: The DisplayStyleSwitcher component in plugins/woocommerce/client/blocks/assets/js/blocks/product-filters/components/display-style-switcher/index.tsx has been updated so that its onChange prop accepts only a string type (not string | number | undefined), eliminating the need for type assertions when using this component.

Applied to files:

  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts
  • plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/table/rows/functions.tsx
🔇 Additional comments (2)
plugins/woocommerce/changelog/61797-update-WCCOM-1896-hide-install-button-for-saas-products (1)

1-4: LGTM!

The changelog entry follows the correct format and clearly describes the UI change.

plugins/woocommerce/client/admin/client/marketplace/components/my-subscriptions/types.ts (1)

36-36: Naming concern remains valid; manual verification of field usage required.

The search reveals has_changelog is newly added to the Subscription type but no component usage was found in the marketplace directory yet. The type definition also shows several installable-related fields:

  • subscription_available (product can be installed)
  • is_installable (line 33)
  • has_changelog (line 36, new)
  • SubscriptionLocal.installable (separate context)

The semantic naming concern stands: has_changelog suggests changelog documentation rather than installable files/download packages. The relationship between is_installable and has_changelog remains unclear.

Please verify:

  1. How has_changelog is actually used in component rendering logic (likely outside the marketplace directory)
  2. Whether is_installable and has_changelog serve distinct purposes or should be consolidated
  3. Consider renaming to has_download, has_installation_package, or similar if the field gates the Install button

@github-actions
Copy link
Contributor

github-actions bot commented Nov 4, 2025

Testing Guidelines

Hi @gedex @bor0 @woocommerce/desire,

Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

Reminder: PR reviewers are required to document testing performed. This includes:

  • 🖼️ Screenshots or screen recordings.
  • 📝 List of functionality tested / steps followed.
  • 🌐 Site details (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
  • 🔍 Any analysis performed, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 4, 2025

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Test this pull request with WordPress Playground.

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Desire Woo Marketing and WooCommerce.com customer experience plugin: woocommerce Issues related to the WooCommerce Core plugin. team: Desire WCCOM/Marketplace Issues related to communication with woocommerce.com.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants