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.
Summary
Endpoint_Headline_Testing_Settingsstores 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
parselyplugin option (src/UI/class-settings-page.php:556onwards), and the feature reads them from there:Separately,
Endpoint_Headline_Testing_Settingsregisters a REST settings endpoint whoseget_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 asParsely::OPTIONS_DEFAULTS['headline_testing'](src/class-parsely.php:158-165). But it is aBase_Settings_Endpoint, so it persists to user meta:Three issues follow:
1. Wrong storage layer. Site-level settings are written per-user.
Base_Settings_Endpoint::is_available_to_current_user()allowscurrent_user_can( 'edit_user', $current_user_id ), so any logged-in user can PUT to/wp-parsely/v2/settings/headline-testingand store e.g.enabled: truein 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_testingrisks 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-deadwp_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_routefor theBase_Settings_Endpointinjection insrc/content-helper/common/class-content-helper-feature.php:161-168. The onlyget_user_meta()calls insrc/are insideBase_Settings_Endpointitself.For contrast,
Endpoint_Traffic_Boost_Settingsreturningarray()fromget_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 itsSetting1 => 'Hello World!'placeholder was removed.Desired state
A decision on the endpoint, then follow through:
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.