Opened 8 years ago
Last modified 4 months ago
#41179 new enhancement
Adding get_the_content-filter
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | 4.8 |
| Component: | Themes | Keywords: | needs-codex dev-feedback |
| Focuses: | docs, template | Cc: |
Description
Hey there,
atm I cannot replace the content by a custom on, because of missing filter for get_the_content().
Attached a patch for this.
Attachments (1)
Change History (10)
This ticket was mentioned in Slack in #themereview by nikolam. View the logs.
8 years ago
#4
@
8 years ago
- Keywords has-patch removed
This patch does not match the ticket description. The patch adds parameters to the the_content filter, which would break all kinds of themes, plugins, and core.
Why do you think get_the_content() needs a filter? I thought the whole point of it was that it was returning the actual content, unfiltered. It is a reliable source of actual content.
#5
@
8 years ago
Why it would break all kinds of themes, plugins or core? It does not replace params. Also atm plugins, themes and core just uses add_filter( 'the_content', 'yourfunction', PRIORITY )
, no admin is using here the param $accepted_args, because not needed. If used, they have to use 1. So it's not breaking anything. The other params are optional.
get_the_content()-filter is needed for plugins to change content in themes. The params $more_link_text
& $strip_teaser can then be used by plugins e.g. to readd the $more_link_text after changing content.
#6
@
8 years ago
Ooops, my mistake of thinking the parameters backwardly. Sorry.
I still think get_the_content() is better left unfiltered.
#7
@
8 years ago
Why get_the_content() is better unfiltered but the_content() already has an filter? If someone wants to have raw content, he can use $post->post_content.
#9
@
4 months ago
Hello @joyously , I just coming here and a little bit shocked if this idea has been patched 8 years ago and still not considered if that's useful, I hope my use case can help you to understand why we need it. At the moment, I'm working on a plugin that extend a revision system, I asked AI for help me to explain it, I hope it can explains everything
===========================
WordPress Trac Ticket Proposal: Add Filter Hook for get_the_content() Function
Summary
Request to add a filter hook to the get_the_content() function to allow plugins to modify post content when accessed directly, similar to how the_content filter works for the_content() function.
Problem Description
Current Limitation
The get_the_content() function in WordPress core does not provide any filter hooks, making it impossible for plugins to modify content when it's accessed directly. This creates an inconsistency with the_content() function which applies the the_content filter.
Real-World Use Case: Advanced Revision System
We are developing an advanced revision system plugin that allows users to preview specific revisions of posts on the frontend. Our system works by:
- Revision Storage: Storing complete post revisions with content, title, and metadata
- Frontend Preview: Generating secure URLs with nonce verification to preview revisions
- Content Filtering: Intercepting content display to show revision content instead of published content
The Problem
Our revision system successfully filters content when themes use the_content() via the the_content filter. However, many plugins and themes call get_the_content() directly, bypassing our content filtering entirely.
Detailed Example: qi-blocks Plugin Global Styles System
The qi-blocks plugin (a Gutenberg blocks framework) has a global styles system that needs to analyze post content to:
- Generate Dynamic CSS: Create inline styles based on block configurations
- Process Reusable Blocks: Expand reusable block references to get their actual content
- Font Loading Optimization: Detect which fonts are actually used in content
- Style Cleanup: Remove unused styles from the database when blocks are deleted
Here's the problematic code from add_page_inline_style() method from qi-blocks plugin https://wordpress.org/plugins/qi-blocks/ at file class-qi-blocks.php :
public function add_page_inline_style() {
$global_styles = get_option( 'qi_blocks_global_styles' );
if ( ! empty( $global_styles ) ) {
$page_id = apply_filters( 'qi_blocks_filter_page_inline_style_page_id', get_queried_object_id() );
$styles = array();
$fonts = array(
'family' => array(),
'weight' => array(),
'style' => array(),
);
$update = false;
$include_italic_fonts = false;
$templates_selector = 'body ';
// Post blocks.
if ( isset( $global_styles['posts'][ $page_id ] ) && ! empty( $global_styles['posts'][ $page_id ] ) ) {
$get_page_content = trim( get_the_content( null, false, $page_id ) );
// Check if the content contains reusable blocks and expand the page content with the real reusable content.
preg_match_all( '({[\s]?[\'\"]ref[\'\"]:(.*?)[\s]?})', $get_page_content, $reusable_matches );
if ( ! empty( $reusable_matches ) && isset( $reusable_matches[1] ) && ! empty( $reusable_matches[1] ) ) {
$usable_content = '';
if ( is_array( $reusable_matches[1] ) ) {
foreach ( $reusable_matches[1] as $reusable_match_item ) {
$usable_content .= get_the_content( null, false, intval( $reusable_match_item ) );
}
} else {
$usable_content = get_the_content( null, false, intval( $reusable_matches[1] ) );
}
if ( ! empty( $usable_content ) ) {
$get_page_content .= $usable_content;
}
}
// Check if the content contains italic html selector and include corresponding font weights and styles for it.
if ( strpos( $get_page_content, '<em>' ) !== false ) {
$include_italic_fonts = true;
}
foreach ( $global_styles['posts'][ $page_id ] as $block_index => $block_style ) {
$block_style_fonts = (array) $block_style->fonts;
foreach ( array_keys( $fonts ) as $font_key ) {
if ( array_key_exists( $font_key, $block_style_fonts ) ) {
$fonts[ $font_key ] = array_merge( $fonts[ $font_key ], $block_style_fonts[ $font_key ] );
}
}
// Remove unnecessary styles from the database if IDS not match or values are empty, because Gutenberg can change the block ID.
if ( ! empty( $get_page_content ) && property_exists( $block_style, 'key' ) ) {
$blocks_removed = false;
if ( empty( $block_style->values ) ) {
$blocks_removed = true;
} elseif ( ! empty( $block_style->key ) && strpos( $get_page_content, $block_style->key ) === false ) {
$blocks_removed = true;
}
if ( $blocks_removed ) {
unset( $global_styles['posts'][ $page_id ][ $block_index ] );
$update = true;
}
}
foreach ( $block_style->values as $block_element ) {
if ( ! empty( $block_element->styles ) ) {
$styles[] = $block_element->selector . '{' . $block_element->styles . '}';
}
if ( isset( $block_element->tablet_styles ) && ! empty( $block_element->tablet_styles ) ) {
$styles[] = '@media (max-width: 1024px) { ' . $block_element->selector . '{' . $block_element->tablet_styles . '} }';
}
if ( isset( $block_element->mobile_styles ) && ! empty( $block_element->mobile_styles ) ) {
$styles[] = '@media (max-width: 680px) { ' . $block_element->selector . '{' . $block_element->mobile_styles . '} }';
}
if ( isset( $block_element->custom_styles ) && ! empty( $block_element->custom_styles ) ) {
foreach ( $block_element->custom_styles as $custom_style ) {
if ( isset( $custom_style->value ) && ! empty( $custom_style->value ) ) {
$styles[] = '@media (max-width: ' . $custom_style->key . 'px) { ' . $block_element->selector . '{' . $custom_style->value . '} }';
}
}
}
}
}
// Update global options indexes.
if ( $update ) {
$global_styles['posts'][ $page_id ] = array_values( $global_styles['posts'][ $page_id ] );
}
}
// Enqueue Google Fonts.
if ( isset( $fonts['family'] ) && ! empty( $fonts['family'] ) ) {
$this->include_google_fonts( $fonts, $include_italic_fonts );
}
// Update global options.
if ( $update ) {
update_option( 'qi_blocks_global_styles', $global_styles );
}
// Load styles.
if ( ! empty( $styles ) ) {
wp_add_inline_style( 'qi-blocks-main', implode( ' ', $styles ) );
}
}
}
Why This Breaks Our Revision System:
When a user previews a revision via our system:
- URL:
example.com/post-name/?revision=123&_wpnonce=abc123 - Our
the_contentfilter correctly shows revision content in the main post area - But qi-blocks calls
get_the_content()directly, getting the published content instead of revision content - This creates inconsistency: main content shows revision, but styles are generated from published content
- Result: Broken layout, missing styles, or incorrect styling for the revision preview
Current Workarounds and Their Limitations
We've attempted several workarounds:
the_postsFilter: Modifying post objects before they're processed- Issue: Doesn't reliably intercept
get_the_content()calls - Timing: Filter may run too early or late in the process
- Issue: Doesn't reliably intercept
- Global
$postObject Modification: Directly modifying the global post- Issue: Risky and can cause conflicts with other plugins
- Scope: May affect unintended parts of the application
- Function Override: Attempting to override
get_the_content()- Issue: Not possible without modifying core files
- Maintenance: Would break on WordPress updates
Proposed Solution
Add a filter hook to the get_the_content() function, similar to existing patterns in WordPress:
Suggested Implementation
function get_the_content( $more_link_text = null, $strip_teaser = false, $post = null ) {
// ... existing code ...
// Before returning content, apply filter
$content = apply_filters( 'get_the_content', $content, $more_link_text, $strip_teaser, $post );
return $content;
}
Alternative Filter Names
pre_get_the_content- Applied before content processingthe_content_raw- Applied to raw content before formattingget_the_content_filter- Explicit naming
Benefits
1. Plugin Compatibility
- Allows content modification plugins to work with all content access methods
- Ensures consistent behavior between
the_content()andget_the_content() - Enables advanced features like revision previews, content translation, A/B testing
2. Developer Experience
- Provides expected filtering capability that developers assume exists
- Maintains consistency with WordPress filter patterns
- Reduces need for complex workarounds
3. Backward Compatibility
- Adding a filter hook is non-breaking
- Existing code continues to work unchanged
- Optional for developers who don't need it
Use Cases Beyond Revision Systems
- Content Translation Plugins: Modify content based on user language
- A/B Testing Plugins: Serve different content variations
- Content Security Plugins: Filter or sanitize content before display
- SEO Plugins: Modify content for search engine optimization
- Personalization Plugins: Customize content based on user preferences
- Content Caching Plugins: Implement custom caching strategies
Technical Considerations
Performance Impact
- Minimal: Filter only runs when
get_the_content()is called - Optional: No performance impact if no filters are registered
- Consistent: Same pattern as existing WordPress filters
Implementation Location
- File:
wp-includes/post-template.php - Function:
get_the_content() - Line: ~380 (before return statement)
Filter Parameters
apply_filters( 'get_the_content', $content, $more_link_text, $strip_teaser, $post )
$content(string): The post content$more_link_text(string): More link text$strip_teaser(bool): Whether to strip teaser$post(WP_Post|null): Post object
Conclusion
Adding a filter hook to get_the_content() would:
- Solve real-world plugin compatibility issues
- Maintain consistency with WordPress patterns
- Enable advanced content management features
- Require minimal code changes with zero breaking changes
This enhancement would benefit the entire WordPress ecosystem by providing developers with the filtering capabilities they need for modern content management requirements.
Related Functions That Have Filters
the_content()- appliesthe_contentfilterthe_title()- appliesthe_titlefilterthe_excerpt()- appliesthe_excerptfilterget_the_excerpt()- appliesget_the_excerptfilter
The absence of a filter in get_the_content() is an inconsistency that should be addressed.
BTW the function get_the_content() and the_content() seems too much inconsistent compared with e.g. get_the_excerpt() and the_excerpt(). Also it looks too much complex (job could surely be done in an easier way). May it needs a complete refactoring.
Pro:
Contra:
PS: I hope for WP 5.0 you're planning some refactoring, e.g. media lib and code cleanup / consistency.