Skip to content

Headline Testing settings endpoint stores site-level settings as unprefixed user meta #4555

Description

@acicovic

Summary

Endpoint_Headline_Testing_Settings stores site-level Headline Testing settings as per-user meta, under an unprefixed meta key, and nothing reads what it writes.

Current state

Headline Testing is configured site-wide. The settings page writes them into the parsely plugin option (src/UI/class-settings-page.php:556 onwards), and the feature reads them from there:

// src/class-headline-testing.php:69
return true === $options['headline_testing']['enabled'] && …

// src/class-headline-testing.php:83
$headline_testing_options = $options['headline_testing'];

Separately, Endpoint_Headline_Testing_Settings registers a REST settings endpoint whose get_subvalues_specs() mirrors those same six settings exactly — enabled, installation_method, enable_flicker_control, enable_live_updates, live_update_timeout, allow_after_content_load, with the same defaults as Parsely::OPTIONS_DEFAULTS['headline_testing'] (src/class-parsely.php:158-165). But it is a Base_Settings_Endpoint, so it persists to user meta:

// src/rest-api/settings/class-endpoint-headline-testing-settings.php:41-43
protected function get_meta_key(): string {
    return 'headline_testing';
}

Three issues follow:

1. Wrong storage layer. Site-level settings are written per-user. Base_Settings_Endpoint::is_available_to_current_user() allows current_user_can( 'edit_user', $current_user_id ), so any logged-in user can PUT to /wp-parsely/v2/settings/headline-testing and store e.g. enabled: true in their own meta. Harmless today because nothing reads it, but the endpoint's shape implies it controls a site feature.

2. The meta key is unprefixed. headline_testing risks colliding with another plugin's or theme's user meta. Every other user meta key this plugin writes is prefixed (parsely_content_helper_settings_*, and the now-dead wp_parsely_page).

3. No consumer. Nothing PUTs or GETs this route — no JS references settings/headline-testing, and no Content Intelligence feature declares it as a $settings_route for the Base_Settings_Endpoint injection in src/content-helper/common/class-content-helper-feature.php:161-168. The only get_user_meta() calls in src/ are inside Base_Settings_Endpoint itself.

For contrast, Endpoint_Traffic_Boost_Settings returning array() from get_subvalues_specs() is not part of this issue — that is deliberate scaffolding, emptied on purpose in cf941d0 ("Do not return Traffic Boost sample settings") when its Setting1 => 'Hello World!' placeholder was removed.

Desired state

A decision on the endpoint, then follow through:

  • If Headline Testing settings are meant to stay site-level, the endpoint should be removed, or reworked to read/write the plugin option with an appropriate capability check rather than per-user meta.
  • If per-user overrides are genuinely wanted, the meta key should be prefixed (e.g. parsely_content_helper_settings_headline_testing), the feature should actually read them, and the capability model should be revisited.

Either way it should gain integration test coverage — there is currently none for this endpoint.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugTicket that is a bug report

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions