Skip to content

feat(access-control): advanced settings for RSS content restriction#4613

Open
dkoo wants to merge 11 commits intotrunkfrom
feat/access-control-advanced-settings
Open

feat(access-control): advanced settings for RSS content restriction#4613
dkoo wants to merge 11 commits intotrunkfrom
feat/access-control-advanced-settings

Conversation

@dkoo
Copy link
Copy Markdown
Contributor

@dkoo dkoo commented Mar 30, 2026

All Submissions:

Changes proposed in this Pull Request:

Adds an Advanced Settings modal in the Access Control wizard page to contain options that don't fit into any other UI views or components. Implements the following options:

  • Restrict content in feeds - Truncate restricted content in RSS feeds. Enabled by default.
  • Hide Everlit in restricted content - Prevents Everlit audio embed blocks from rendering in restricted content. Enabled by default. Note: we've removed this option as this should be handled by the Everlit plugin, not here.

Closes NPPD-1035.

How to test the changes in this Pull Request:

  1. In Audience > Access Control, confirm that the "Advanced settings" item in the dropdown menu next to the page title is no longer disabled:
Screenshot 2026-03-31 at 3 35 24 PM
  1. Click it and confirm it shows the new modal:
Screenshot 2026-03-31 at 2 55 55 PM
  1. Toggle off the option, save, refresh, and confirm that the saved settings persist.
  2. Test the "undo" link in the snackbar after saving and confirm that it undoes the most recent save.
  3. Leave the option toggled off and save.
  4. Publish a content gate that applies to all posts with Registered and Paid Access enabled + metering.
  5. Visit your RSS feed (https://sitedomain/feed) and confirm that all restricted articles show their full content.
  6. Toggle on the option and save.
  7. Repeat steps 7-8 and confirm that the feed shows truncated content for restricted posts unless logged into a user account that has full access

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@dkoo dkoo self-assigned this Mar 31, 2026
@dkoo dkoo added the [Status] Needs Review The issue or pull request needs to be reviewed label Mar 31, 2026
@dkoo dkoo marked this pull request as ready for review March 31, 2026 21:45
@dkoo dkoo requested a review from a team as a code owner March 31, 2026 21:45
Copilot AI review requested due to automatic review settings March 31, 2026 21:45
@dkoo dkoo requested a review from thomasguillot March 31, 2026 21:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds “Advanced settings” support to the Audience → Access Control wizard, introducing backend-stored toggles to (1) truncate restricted posts in RSS feeds and (2) optionally hide Everlit embeds in restricted content.

Changes:

  • Adds an Advanced Settings modal to the Access Control wizard UI and wires it to a new wizard settings REST endpoint.
  • Introduces a new Content_Gate_Settings backend class to enforce feed truncation and Everlit block stripping based on saved options.
  • Adds unit tests covering feed truncation behavior and Everlit stripping behavior.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/unit-tests/content-gate/test-advanced-settings.php Adds unit tests for feed truncation and Everlit stripping behavior.
src/wizards/audience/views/content-gates/types/index.d.ts Adds TS types for advanced_settings returned in wizard config.
src/wizards/audience/views/content-gates/content-gates.tsx Enables “Advanced settings” menu item and mounts the new modal component.
src/wizards/audience/views/content-gates/advanced-settings.tsx Implements the Advanced Settings modal UI and saving/undo via REST.
includes/wizards/audience/class-audience-content-gates.php Adds REST endpoint to update advanced settings and exposes settings in wizard config.
includes/content-gate/class-content-gate.php Ensures the new settings class is loaded during Content Gate initialization.
includes/content-gate/class-content-gate-settings.php New settings class: option storage + feed truncation + Everlit block stripping hooks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@thomasguillot
Copy link
Copy Markdown
Contributor

@dkoo — Thomas has reviewed these changes and will be marking this PR as design approved.

Changes pushed in the latest commit:

  • Moved modal action buttons inside the VStack for correct layout flow
  • Switched Institutions menu item from href: '#/institutions' to history.push('/institutions') via the router proxy, for consistent SPA navigation
  • Fixed AdvancedSettingsConfig type — restrict_content_feeds was a typo; renamed to restrict_feeds to match the PHP and component code

@dkoo dkoo changed the title feat(access-control): advanced settings feat(access-control): advanced settings for RSS content restriction Apr 2, 2026
Copy link
Copy Markdown
Member

@miguelpeixe miguelpeixe left a comment

Choose a reason for hiding this comment

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

Tested well! Left a couple of non-blocking suggestions and a small issue.

/**
* Main class.
*/
class Content_Gate_Settings {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not to be confused with the component at src/wizards/audience/views/content-gates/content-gate-settings.tsx

Non-blocking suggestion: we could make this class just about the RSS feed handling. It is already by implementing the feed restriction on top of the settings, just need to make it official with the docblocks and class name 😄

I can see a year from now, this class having 1000+ lines of small features and patches mixed together...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I see your point, but this class is kind of where I envision we'll add additional "global" settings beyond just this RSS option, hence why it originally also owned the Everlit option. What if we renamed it to Content_Gate_Advanced_Settings or Content_Gate_Global_Settings?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think Content_Gate_Advanced_Settings is better.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

00d01c4 renames the class to Content_Gate_Global_Settings (and the test class too) to hopefully make the intention a bit clearer.

Comment on lines +13 to +16
/**
* Tests for RSS feed content restriction.
*/
class Test_Advanced_Settings extends \WP_UnitTestCase {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also non-blocking, but I think we can have this either for RSS Feed restriction control alone or just additional tests within tests/unit-tests/content-gate/content-gates.php. "Advanced settings" is just a UI layer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

00d01c4 renames this to Test_Global_Settings to match the renamed class it tests.

const wizardData = useWizardData( AUDIENCE_CONTENT_GATES_WIZARD_SLUG ) as WizardData;
const { wizardApiFetch, isFetching, resetError, setError } = useWizardApiFetch( AUDIENCE_CONTENT_GATES_WIZARD_SLUG );
const { addNotice, resetNotices, updateWizardSettings } = useDispatch( WIZARD_STORE_NAMESPACE );
const [ config, setConfig ] = useState< AdvancedSettingsConfig >( ( wizardData?.config?.advanced_settings as AdvancedSettingsConfig ) || {} );
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The AdvancedSettings component is always mounted, so changing config, closing, and re-opening the modal will show stale data. I don't think we need to introduce a dirty state confirmation modal, but might be a good idea to reset on close here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The component always being mounted is intentional, as this is what allows the Undo button in the Snackbar component that appears after saving to function (otherwise the prior state in the ref is lost when the component unmounts). The internal config state is updated after a successful save in tandem with the wizard store, using the same data, so it's not likely to get out of sync. If you're worried about this being possibly too fragile we could do away with the "Undo" button so the component can be unmounted when the modal isn't visible. But so far I haven't run into any trouble with the component state and store data getting out of sync. 🤷

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see... I had a different UX perception for this. When I open something in a modal, make changes, and close without clicking the Save button, I'd not expect that state to be preserved. I'd also not expect that closed modal state to be persisted if I click save somewhere else.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's a valid point. b748566 fixes that issue, so that the local state is reset upon closing the modal. Also applies the same fix to the Premium Newsletters advanced settings modal, which uses the same component pattern (maybe we could combine these into one reusable component in the future).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If I save the new value, opening the modal again will render the state from page load.

@github-actions github-actions bot added the [Status] Needs Changes or Feedback The issue or pull request needs action from the original creator label Apr 2, 2026
@dkoo dkoo requested a review from miguelpeixe April 2, 2026 17:21
@dkoo
Copy link
Copy Markdown
Contributor Author

dkoo commented Apr 2, 2026

@miguelpeixe thanks for the feedback! Happy to discuss further if you feel the changes aren't enough

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

Labels

[Status] Design Approved [Status] Needs Changes or Feedback The issue or pull request needs action from the original creator [Status] Needs Review The issue or pull request needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants