Skip to content

Pass $post to the get_the_excerpt filter - #641

Merged
galbus merged 2 commits into
mainfrom
claude/excerpt-filter-post-arg
Sep 24, 2026
Merged

galbus merged 2 commits into
mainfrom
claude/excerpt-filter-post-arg

Conversation

@galbus

@galbus galbus commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Summary

A publisher reported that audio generation failed for some posts, and traced it to Content::get_post_summary() in src/post/class-content.php. We call:

apply_filters( 'get_the_excerpt', $summary );

WordPress core has passed the post as a second argument since 4.5 (apply_filters( 'get_the_excerpt', $post->post_excerpt, $post )), so callbacks written against core's signature can rely on it:

  • A callback registered for both arguments with a required $post throws ArgumentCountError on PHP 8. That aborts content aggregation, so no audio is generated.
  • A callback with an optional $post falls back to the global post. In the cron and REST contexts generation runs in, that global is empty or a different post, so the summary can be built from the wrong post.

The fix passes $post:

apply_filters( 'get_the_excerpt', $summary, $post );

The misplaced phpcs:ignore above it is also re-indented from spaces to tabs.

Risk and blast radius

This only affected a narrow set of publishers. All three conditions must hold:

  1. The "Prepend excerpt" setting (beyondwords_prepend_excerpt) is enabled. It is off by default.
  2. The post has a manual excerpt. Posts without one never reach this code.
  3. The site runs a third-party get_the_excerpt callback that uses the second argument. WordPress's own callback (wp_trim_excerpt) makes $post optional and returns an existing excerpt unchanged, so sites without such a plugin or theme were unaffected.

The same call has been in the plugin since at least 6.3, so this is a long-standing edge case, not a 7.x regression. The change only adds an argument that core itself always supplies, so existing callbacks that ignore it behave exactly as before.

Test plan

Written test-first. Both tests go through Content::get_content_body():

  • get_content_body_with_summary_supports_excerpt_callbacks_requiring_post: registers a callback with a required $post. Before the fix it failed with ArgumentCountError: Too few arguments … 1 passed … exactly 2 expected, the reported crash. It passes after the fix.
  • get_content_body_with_summary_passes_the_processed_post_to_excerpt_callbacks: sets the global $post to a different post, as in cron or REST, and asserts the callback receives the post being processed. It fails without the fix, because the callback read the other post, and passes with it.
  • Full PHPUnit suite: 821 tests, 1 skipped.
  • phpcs (WordPress-VIP-Go) clean.

🤖 Generated with Claude Code

galbus and others added 2 commits September 24, 2026 18:04
Content::get_post_summary() applied get_the_excerpt with only the
excerpt, but core has passed the post as a second argument since
WordPress 4.5. A callback registered for both arguments with a
required $post threw ArgumentCountError on PHP 8, failing content
aggregation; one with an optional $post fell back to the global post,
which is wrong or empty in the cron and REST contexts generation runs
in.

Only reached when "prepend excerpt" is on and the post has an excerpt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


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

@gouravkhunger gouravkhunger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@galbus This is an automated PR review.

Soft score: Approve.
Minimal fix that matches core's get_the_excerpt contract, and both regression tests fail without it.

Full review

Summary

Content::get_post_summary() now calls apply_filters( 'get_the_excerpt', $summary, $post ), which matches the signature core has used since WordPress 4.5. The misindented phpcs:ignore line is re-tabbed. Two regression tests and a changelog bullet are added.

Affected subsystems

  • Only src/post/class-content.php, the content aggregation step of audio generation.
  • The change only matters when the "Prepend excerpt" setting is on and the post has a manual excerpt.

Dependency graph changes

None. No new classes, imports or wiring in Plugin::init().

Risky files

  • src/post/class-content.php:137: low risk. $post is already normalized with get_post() and checked with instanceof \WP_Post before this call, so callbacks always get a WP_Post, never an int. A callback type-hinted \WP_Post is safe.
  • Callbacks registered with the default $accepted_args = 1 still get one argument, so nothing changes for them.

Public API changes

The get_the_excerpt filter now receives a second argument. This is additive and matches core's contract, so there's no breaking change.

DB changes

None. The tests set beyondwords_prepend_excerpt and delete it again in finally.

Auth/security changes

None. The excerpt is still passed through htmlentities() before the filter runs, same as before.

Deployment/config changes

None. The changelog entry is in the unreleased block of readme.txt under Fixes, as AGENTS.md rule 5 requires.

Tests

  • Test 1 registers a callback with a required $post. Before the fix it reproduced the ArgumentCountError.
  • Test 2 sets the global $post to a different post, as happens in cron or REST, and asserts the callback reads the post being processed.
  • Both tests clean up in finally, so a failure doesn't leak state into other tests.

Pre-existing (not blocking)

Callbacks receive an HTML-entity-encoded excerpt, while core passes the raw post_excerpt. That behaviour predates this PR. It could be looked at separately if third-party filters misbehave on the encoded text.

Review priority

  1. src/post/class-content.php
  2. tests/phpunit/post/test-content.php
  3. readme.txt

Verdict: Approve. Small, correct fix that matches core's contract, covered by tests that fail without it.

@galbus
galbus merged commit d74d22d into main Sep 24, 2026
13 checks passed
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.

2 participants