Skip to content

Consolidate get_post_types_names() into Settings - #776

Merged
ilicfilip merged 1 commit into
developfrom
filip/consolidate-post-types-names
Aug 25, 2026
Merged

Consolidate get_post_types_names() into Settings#776
ilicfilip merged 1 commit into
developfrom
filip/consolidate-post-types-names

Conversation

@ilicfilip

@ilicfilip ilicfilip commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Implements #433. Replaces #467, which had drifted ~2300 commits behind develop and conflicted in 6 of its 7 files.

The problem

Two copies of get_post_types_names() exist in develop, and callers were split roughly evenly between them (5 each):

  • classes/class-settings.php:119
  • classes/activities/class-content-helpers.php:22

Settings has become the canonical one — it's what the newer suggested-task and data-collector classes call, it carries the init-timing guard, and it's where the exclusion list has been maintained.

The Content_Helpers copy drifted behind. Its filtering logic differs in three ways:

  1. elementor_library — excluded by Settings, not by Content_Helpers. Elementor registers it as public + viewable, so it passes the Content_Helpers viewability check.
  2. The progress_planner_public_post_types filter — only honoured by Settings. Anything filtered out there still passes through Content_Helpers.
  3. Empty-case fallbackContent_Helpers returns a raw [ 'post', 'page' ] without checking those post types are still registered and public; Settings intersects against public types first.

Each copy holds its own static cache, warmed independently on first call. In a normal request both warm after init and agree, so the drift is latent rather than actively breaking sites — but it means two functions that are supposed to answer the same question no longer share filtering rules, and any future change to the exclusion list or the filter only lands in one of them.

The change

  • Point the six remaining Content_Helpers call sites at Settings.
  • Reduce Content_Helpers::get_post_types_names() to a deprecated one-line shim, so any external caller keeps working.

Net: 9 insertions, 16 deletions across 6 files. One cache and one set of filtering rules instead of two.

Note on direction

#467 consolidated the other way — deleting Settings::get_post_types_names() and moving it into Content_Helpers. Since that PR was opened, develop settled on Settings as the home (that's where the prpl_recommendations exclusion was added). Rebasing #467 would have meant reverting that decision, which is why this is a fresh change rather than a rebase.

Note on init ordering

All six migrated call sites run well after initshutdown, wp_insert_post, and admin widget rendering — so all CPTs are registered by the time they read. The shared cache is warmed by Tasks_Manager::init() at init priority 99, after the priority 0–10 where CPTs normally register. No call site is moved earlier by this PR.

Note on the null guards

The null === $content_helpers guards in Content_Scan and Content are deliberately left in place — they still protect the get_activity_from_post() calls in those methods. In Content_Scan::get_total_pages() the guard no longer covers any $content_helpers usage, but it doubles as an intentional circuit-breaker returning 0 to halt the scan during plugin updates (added in #743), so removing it would change update-time behaviour beyond this PR's scope.

Verification

  • composer check-cs -- --warning-severity=6 — clean (exit 0)
  • composer phpstan — no errors
  • composer test — OK (398 tests, 1203 assertions)

Note that the test suite has no existing coverage of get_post_types_names(), so the suite passing is not by itself evidence for this change. I additionally ran a throwaway differential harness comparing the old Content_Helpers implementation against the new delegate across 10 scenarios (public CPT, non-public CPT, elementor_library, attachment, the progress_planner_public_post_types filter, unregistered post types, empty settings) and confirmed both entry points return identical results. That harness was not committed.

The two wpdberror lines that appear in the test output are pre-existing; they reproduce identically on unmodified develop.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Test merged PR on Playground
Test this pull request on the Playground
or download the zip

@github-actions

Copy link
Copy Markdown
Contributor

✅ Code Coverage Report

Metric Value
Total Coverage 31.75% 📉
Base Coverage 31.76%
Difference 📉 -0.01%

⚠️ Coverage below recommended 40% threshold

📊 File-level Coverage Changes (1 files)

📈 Coverage Improved

Class Before After Change
Progress_Planner\Activities\Content_Helpers 62.50% 87.50% +25.00%
ℹ️ About this report
  • All tests run in a single job with Xdebug coverage
  • Security tests excluded from coverage to prevent output issues
  • Coverage calculated from line coverage percentages

@github-actions

Copy link
Copy Markdown
Contributor

🔍 WordPress Plugin Check Report

⚠️ Status: Passed with warnings

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
10 0 10

⚠️ Warnings (10)

📁 classes/suggested-tasks/providers/class-content-review.php (4 warnings)
📍 Line 🔖 Check 💬 Message
232 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
377 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
381 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
388 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
📁 classes/suggested-tasks/data-collector/class-unpublished-content.php (1 warning)
📍 Line 🔖 Check 💬 Message
103 WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_post__not_in Using exclusionary parameters, like post__not_in, in calls to get_posts() should be done with caution, see https://docs.wpvip.com/databases/optimize-queries/using-post__not_in/ for more information.
📁 classes/suggested-tasks/data-collector/class-yoast-orphaned-content.php (1 warning)
📍 Line 🔖 Check 💬 Message
111 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_row()\n$query assigned unsafely at line 98.
📁 classes/suggested-tasks/data-collector/class-terms-without-description.php (1 warning)
📍 Line 🔖 Check 💬 Message
108 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_results()\n$query assigned unsafely at line 106.
📁 classes/suggested-tasks/data-collector/class-terms-without-posts.php (1 warning)
📍 Line 🔖 Check 💬 Message
120 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $query used in $wpdb->get_results()\n$query assigned unsafely at line 118.
📁 classes/activities/class-query.php (2 warnings)
📍 Line 🔖 Check 💬 Message
71 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $table_name used in $wpdb->query()\n$table_name assigned unsafely at line 58.
163 PluginCheck.Security.DirectDB.UnescapedDBParameter Unescaped parameter $where_args used in $wpdb->get_results()\n$where_args assigned unsafely at line 153.

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Two copies of get_post_types_names() existed:
Settings::get_post_types_names() and
Content_Helpers::get_post_types_names().

The Settings version has become the canonical one -- it is what the
newer suggested-task and data-collector classes call, it carries the
init-timing guard, and it is where the exclusion list is maintained.

The Content_Helpers copy had drifted behind, and its filtering logic
differs in three ways:

- It does not exclude elementor_library, which Elementor registers as
  public + viewable, so it passes the viewability check.
- It does not honour the progress_planner_public_post_types filter.
- Its empty-case fallback returns a raw [ 'post', 'page' ] without
  checking those post types are still registered and public.

Each copy holds its own static cache, warmed independently on first
call. In a normal request both warm after init and agree, so the drift
is latent rather than actively breaking sites -- but two functions
answering the same question no longer share filtering rules, and any
future change to the exclusion list or the filter lands in only one.

Point the six remaining Content_Helpers call sites at Settings and
reduce Content_Helpers::get_post_types_names() to a deprecated shim so
external callers keep working. All six run well after init (shutdown,
wp_insert_post, admin widget rendering), so no call site is moved
earlier by this change.

The null guards in Content_Scan and Content are left in place: they
still protect the get_activity_from_post() calls in those methods, and
in Content_Scan::get_total_pages() the guard doubles as a deliberate
circuit-breaker that halts the scan during plugin updates.

Implements #433.
@ilicfilip
ilicfilip force-pushed the filip/consolidate-post-types-names branch from d01c6e2 to 714cdbc Compare August 25, 2026 12:28
@ilicfilip
ilicfilip marked this pull request as ready for review August 25, 2026 12:34
@ilicfilip
ilicfilip merged commit 9466fe4 into develop Aug 25, 2026
22 checks passed
@ilicfilip
ilicfilip deleted the filip/consolidate-post-types-names branch August 25, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant