Podcast: gate the Episodes dashboard tab on Premium product access (PODS-145)#48704
Podcast: gate the Episodes dashboard tab on Premium product access (PODS-145)#48704robertbpugh wants to merge 10 commits into
Conversation
Adds `Podcast_Gate::has_product_access()` as the single entry point downstream gates (dashboard tab, stats endpoint, episode block, AI shownotes) will call. Two ways to pass: the `podcasting-grandfathered` blog sticker, or `Current_Plan::supports( 'podcasting' )` — which short-circuits to `wpcom_site_has_feature` on Simple/Atomic and falls through to cached plan data on self-hosted Jetpack, so the same helper is correct on every host.
* Drop @phan-suppress-next-line PhanUndeclaredClassMethod on the two Atomic-only branches in class-tracks (Current_Plan::get, Tracking::tracks_record_event). Adding automattic/jetpack-plans to the package require pulls in the connection package transitively, so phan now resolves both classes and the suppressions are unused. * Regenerate the three plugin composer.locks (jetpack, mu-wpcom-plugin, wpcomsh) that reference automattic/jetpack-podcast, picking up the new jetpack-plans dep.
Matches sibling changelog entries in projects/packages/podcast/changelog (add-podcast-tracks, add-podcast-settings, add-podcast-package) which all use `minor` for new added surface area.
Required by the pre-push changelog check now that the previous commit touched jetpack/mu-wpcom-plugin/wpcomsh composer.lock files.
Inject `podcast.has_product_access` via `jetpack_admin_js_script_data` and branch the Episodes tab on it. Treat a missing flag as access-granted so a deploy race never locks grandfathered users out. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
AGENTS.md says not to prefix changelog text with the package name. Switch to "Dashboard:" to match `add-podcast-ui` convention. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Replace the hand-rolled upsell card with `UpsellBanner` from `@automattic/jetpack-components`. - Build the checkout URL with `getProductCheckoutUrl`, which adds `redirect_to`, `unlinked`, and `site` query params for free. - Add `dashboard/declarations.d.ts` so `JetpackScriptData` carries the `podcast.has_product_access` field, removing the `as unknown as` cast on `getScriptData()`. - Rename the helper to `hasProductAccess`; the flag is product-level, not Episodes-tab-specific. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖 Follow this PR Review Process:
If you have questions about anything, reach out in #jetpack-developers for guidance! Jetpack plugin: The Jetpack plugin has different release cadences depending on the platform:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Mu Wpcom plugin:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Wpcomsh plugin:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. |
Code Coverage SummaryThis PR did not change code coverage! That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷 |
There was a problem hiding this comment.
Pull request overview
This PR introduces a Premium-access gate for the Jetpack Podcast “Episodes” dashboard tab by surfacing a server-computed access flag into JetpackScriptData and rendering an upsell experience when access is denied.
Changes:
- Add
Podcast_Gate::has_product_access()(with PHPUnit coverage) and wire it into admin script data asJetpackScriptData.podcast.has_product_access. - Gate the Episodes tab UI: show the existing Episodes experience when allowed, otherwise show a new
UpsellBannerwith a Premium checkout CTA. - Add
jetpack-plansas a dependency (and update downstreamcomposer.lockfiles) to support plan-based gating.
Reviewed changes
Copilot reviewed 13 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| projects/plugins/wpcomsh/composer.lock | Updates locked deps for the podcast package to include jetpack-plans. |
| projects/plugins/wpcomsh/changelog/pods-141-add-gate | Notes the lockfile update for wpcomsh. |
| projects/plugins/mu-wpcom-plugin/composer.lock | Updates locked deps for the podcast package to include jetpack-plans. |
| projects/plugins/mu-wpcom-plugin/changelog/pods-141-add-gate | Notes the lockfile update for mu-wpcom-plugin. |
| projects/plugins/jetpack/composer.lock | Updates locked deps for the podcast package to include jetpack-plans. |
| projects/plugins/jetpack/changelog/pods-141-add-gate | Adds a Jetpack plugin changelog entry indicating no plugin-level behavior change. |
| projects/packages/podcast/tests/php/Podcast_Gate_Test.php | Adds unit tests for the product-access gate logic. |
| projects/packages/podcast/tests/php/bootstrap.php | Adds a test stub for wpcom_has_blog_sticker used by the gate. |
| projects/packages/podcast/src/dashboard/upsell/index.tsx | Introduces the upsell UI using UpsellBanner and getProductCheckoutUrl. |
| projects/packages/podcast/src/dashboard/index.tsx | Reads JetpackScriptData.podcast.has_product_access and conditionally renders Episodes vs upsell. |
| projects/packages/podcast/src/dashboard/declarations.d.ts | Module-augments JetpackScriptData typing to include podcast.has_product_access. |
| projects/packages/podcast/src/class-tracks.php | Removes now-unneeded Phan suppressions around plan/tracks calls. |
| projects/packages/podcast/src/class-podcast-gate.php | Adds the Podcast_Gate helper implementing sticker/plan access checks. |
| projects/packages/podcast/src/class-admin-page.php | Injects podcast.has_product_access into jetpack_admin_js_script_data for the podcast admin request. |
| projects/packages/podcast/composer.json | Adds automattic/jetpack-plans dependency. |
| projects/packages/podcast/changelog/pods-145-gate-episode-dashboard-tab-on-premium-product-access | Adds a changelog entry for gating Episodes tab UI. |
| projects/packages/podcast/changelog/pods-141-add-gate | Adds a changelog entry for introducing the product-access gate helper. |
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/Automattic/jetpack/sessions/f2e086e7-020d-48a9-94d8-a7e9094cb83d Co-authored-by: robertbpugh <52668747+robertbpugh@users.noreply.github.com>
Applied the requested review-thread fixes in 53bac59: moved the Jetpack changelog Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Per AGENTS.md, changelog entries within a package should not repeat the package name. Restored sub-area label. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fixes PODS-145.
Proposed changes
class-admin-page.phpadds ajetpack_admin_js_script_datafilter that injectspodcast.has_product_accessintowindow.JetpackScriptData. The hook fires frommaybe_load_wp_build(), so it only runs on the podcast admin request.dashboard/index.tsxreads the flag viagetScriptData()and branches the Episodes tab content only. Settings and Distribution render normally. Welcome onboarding stays the same.dashboard/upsell/index.tsx(new): usesUpsellBannerfrom@automattic/jetpack-componentsandgetProductCheckoutUrlfor the CTA target.dashboard/declarations.d.ts(new): module-augmentsJetpackScriptDatawith thepodcastfield, so the helper is typed without a cast.Related product discussion/links
Does this pull request change what data or activity we track or use?
No.
Testing instructions
On a site with
jetpack_podcast_untanglefiltered to true and the podcast package built:Jetpack > Podcast > Episodes. Expect the upsell banner with an "Upgrade to Premium" CTA that links towordpress.com/checkout/<your-site>/premium?redirect_to=<episodes-url>&site=<your-site>.podcasting-grandfatheredsticker to the blog. Episodes tab shows the episode list.add_filterline inmaybe_load_wp_build(). Episodes still renders (no upsell), since a missing flag means access-granted.Codex and simplify review notes
I ran Codex review and the simplify skill before opening. Three findings applied in the second commit:
Card+VStack+Buttonupsell withUpsellBannerfrom@automattic/jetpack-components(already a workspace dep).getProductCheckoutUrl, which addsredirect_toandsitequery params.declarations.d.tssoJetpackScriptDatacarries thepodcastfield, removing theas unknown ascast.🤖 Generated with Claude Code