admin管理员组文章数量:1125742
NOTE: The issue I'm encountering is specific to Block Themes; I understand how to filter the text returned from the_excerpt
in a Classic Theme.
What I would like to only show read more text when when wp:post-excerpt
meets excerptLength
. However, when I use, for example,
<!-- wp:post-excerpt {"moreText":"Read More","excerptLength":40, "showMoreOnNewLine":false} /-->
in a template/pattern, all posts on the pages that use this template/pattern have a "Read More" link, even if the except text length had not met the value excerptLength
(shows even if there is no excerpt).
Referencing the source for Excerpt linked to from , I see an easy fix: move the except_more
filter logic into the if ( isset( $excerpt_length )
conditional. I suppose then my question is more of a general one: how would I go about overriding function render_block_core_post_excerpt
(source: .php)? Add logic in functions.php
that checks for the existence of function render_block_core_post_excerpt
, deregister it, then redefine and register the override? Would the action hook be init
?
To be perfectly clear, I already have a excerpt_more
filter in functions.php
that works as expected in a Classic Theme style query loop that calls the_excerpt
. It does not affect the results of <!-- wp:post-excerpt -->
.
EDIT: For anyone curious, following from WordPress Buddha's answer, the override function I ended up using is as follows,
// Source: .php
function render_block_core_post_excerpt_override($attributes, $content, $block)
{
if (! isset($block->context['postId'])) {
return '';
}
/*
* The purpose of the excerpt length setting is to limit the length of both
* automatically generated and user-created excerpts.
* Because the excerpt_length filter only applies to auto generated excerpts,
* wp_trim_words is used instead.
*/
$excerpt_length = $attributes['excerptLength'];
$excerpt = get_the_excerpt($block->context['postId']);
if (isset($excerpt_length) && (str_word_count($excerpt) > $excerpt_length)) {
$excerpt = wp_trim_words($excerpt, $excerpt_length);
$more_text = ! empty($attributes['moreText']) ? '<a class="wp-block-post-excerpt__more-link" href="' . esc_url(get_the_permalink($block->context['postId'])) . '">' . wp_kses_post($attributes['moreText']) . '</a>' : '';
$filter_excerpt_more = static function ($more) use ($more_text) {
return empty($more_text) ? $more : '';
};
/**
* Some themes might use `excerpt_more` filter to handle the
* `more` link displayed after a trimmed excerpt. Since the
* block has a `more text` attribute we have to check and
* override if needed the return value from this filter.
* So if the block's attribute is not empty override the
* `excerpt_more` filter and return nothing. This will
* result in showing only one `read more` link at a time.
*/
add_filter('excerpt_more', $filter_excerpt_more);
$content = '<p class="wp-block-post-excerpt__excerpt">' . $excerpt;
$show_more_on_new_line = ! isset($attributes['showMoreOnNewLine']) || $attributes['showMoreOnNewLine'];
if ($show_more_on_new_line && ! empty($more_text)) {
$content .= '</p><p class="wp-block-post-excerpt__more-text">' . $more_text . '</p>';
} else {
$content .= " $more_text</p>";
}
remove_filter('excerpt_more', $filter_excerpt_more);
} else {
$content = '<p class="wp-block-post-excerpt__excerpt">' . $excerpt . '</p>';
}
$classes = array();
if (isset($attributes['textAlign'])) {
$classes[] = 'has-text-align-' . $attributes['textAlign'];
}
if (isset($attributes['style']['elements']['link']['color']['text'])) {
$classes[] = 'has-link-color';
}
$wrapper_attributes = get_block_wrapper_attributes(array('class' => implode(' ', $classes)));
return sprintf('<div %1$s>%2$s</div>', $wrapper_attributes, $content);
}
This function will,
- trim the excerpt if
excerptLength
is set and the number of words in the excerpt exceeds that value. - add a 'Read More' link if the excerpt will be trimmed.
NOTE: The issue I'm encountering is specific to Block Themes; I understand how to filter the text returned from the_excerpt
in a Classic Theme.
What I would like to only show read more text when when wp:post-excerpt
meets excerptLength
. However, when I use, for example,
<!-- wp:post-excerpt {"moreText":"Read More","excerptLength":40, "showMoreOnNewLine":false} /-->
in a template/pattern, all posts on the pages that use this template/pattern have a "Read More" link, even if the except text length had not met the value excerptLength
(shows even if there is no excerpt).
Referencing the source for Excerpt linked to from https://developer.wordpress.org/block-editor/reference-guides/core-blocks/#excerpt, I see an easy fix: move the except_more
filter logic into the if ( isset( $excerpt_length )
conditional. I suppose then my question is more of a general one: how would I go about overriding function render_block_core_post_excerpt
(source: https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/post-excerpt/index.php)? Add logic in functions.php
that checks for the existence of function render_block_core_post_excerpt
, deregister it, then redefine and register the override? Would the action hook be init
?
To be perfectly clear, I already have a excerpt_more
filter in functions.php
that works as expected in a Classic Theme style query loop that calls the_excerpt
. It does not affect the results of <!-- wp:post-excerpt -->
.
EDIT: For anyone curious, following from WordPress Buddha's answer, the override function I ended up using is as follows,
// Source: https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/post-excerpt/index.php
function render_block_core_post_excerpt_override($attributes, $content, $block)
{
if (! isset($block->context['postId'])) {
return '';
}
/*
* The purpose of the excerpt length setting is to limit the length of both
* automatically generated and user-created excerpts.
* Because the excerpt_length filter only applies to auto generated excerpts,
* wp_trim_words is used instead.
*/
$excerpt_length = $attributes['excerptLength'];
$excerpt = get_the_excerpt($block->context['postId']);
if (isset($excerpt_length) && (str_word_count($excerpt) > $excerpt_length)) {
$excerpt = wp_trim_words($excerpt, $excerpt_length);
$more_text = ! empty($attributes['moreText']) ? '<a class="wp-block-post-excerpt__more-link" href="' . esc_url(get_the_permalink($block->context['postId'])) . '">' . wp_kses_post($attributes['moreText']) . '</a>' : '';
$filter_excerpt_more = static function ($more) use ($more_text) {
return empty($more_text) ? $more : '';
};
/**
* Some themes might use `excerpt_more` filter to handle the
* `more` link displayed after a trimmed excerpt. Since the
* block has a `more text` attribute we have to check and
* override if needed the return value from this filter.
* So if the block's attribute is not empty override the
* `excerpt_more` filter and return nothing. This will
* result in showing only one `read more` link at a time.
*/
add_filter('excerpt_more', $filter_excerpt_more);
$content = '<p class="wp-block-post-excerpt__excerpt">' . $excerpt;
$show_more_on_new_line = ! isset($attributes['showMoreOnNewLine']) || $attributes['showMoreOnNewLine'];
if ($show_more_on_new_line && ! empty($more_text)) {
$content .= '</p><p class="wp-block-post-excerpt__more-text">' . $more_text . '</p>';
} else {
$content .= " $more_text</p>";
}
remove_filter('excerpt_more', $filter_excerpt_more);
} else {
$content = '<p class="wp-block-post-excerpt__excerpt">' . $excerpt . '</p>';
}
$classes = array();
if (isset($attributes['textAlign'])) {
$classes[] = 'has-text-align-' . $attributes['textAlign'];
}
if (isset($attributes['style']['elements']['link']['color']['text'])) {
$classes[] = 'has-link-color';
}
$wrapper_attributes = get_block_wrapper_attributes(array('class' => implode(' ', $classes)));
return sprintf('<div %1$s>%2$s</div>', $wrapper_attributes, $content);
}
This function will,
- trim the excerpt if
excerptLength
is set and the number of words in the excerpt exceeds that value. - add a 'Read More' link if the excerpt will be trimmed.
1 Answer
Reset to default 3To override the behavior of the render_block_core_post_excerpt function in a Block Theme, especially to customize the "Read More" link behavior based on the excerptLength, you'll need to unregister the original block and register your own customized version of it. This process involves a few steps:
Deregister the Original Block: You need to deregister the original post-excerpt block.
Register a Custom Block: Create and register a custom block that mimics the original block but includes your custom logic.
Override the Render Function: Implement your custom logic in the render callback for your new block.
Here's a basic outline of how you might approach this:
Step 1: Deregister the Original Block
You should deregister the original block. This is typically done on the init hook.
function wpb_custom_init() {
unregister_block_type('core/post-excerpt');
}
add_action('init', 'wpb_custom_init');
Step 2: Register a Custom Block
Next, you'll need to register your custom block. You can mostly reuse the settings from the original block, but you'll replace the render callback with your own function.
function wpb_register_custom_post_excerpt_block() {
register_block_type('core/post-excerpt', [
// Copy the settings from the original block, but override the 'render_callback'
'render_callback' => 'wpb_render_custom_post_excerpt',
]);
}
add_action('init', 'wpb_register_custom_post_excerpt_block');
Step 3: Implement the Custom Render Function
Now, implement your custom render function. This is where you'll add your custom logic to handle the "Read More" text based on the excerptLength
.
function wpb_render_custom_post_excerpt( $attributes, $content ) {
// Your custom logic here. You can refer to the original function's source code and modify as needed.
// Example:
$excerpt_length = isset($attributes['excerptLength']) ? $attributes['excerptLength'] : 55;
$more_text = isset($attributes['moreText']) ? $attributes['moreText'] : 'Read More';
$excerpt = get_the_excerpt();
if (strlen($excerpt) > $excerpt_length && !empty($more_text)) {
// Add your custom "Read More" logic here
}
// Return the modified excerpt
return $excerpt;
}
In this function, you will apply your own logic to determine whether to show the "Read More" text based on the excerptLength
. You can refer to the source code of the original render_block_core_post_excerpt
function for guidance and modify it according to your requirements.
Remember, this approach requires a good understanding of how block types are registered and rendered in WordPress, as well as familiarity with PHP and the WordPress block editor's internals. Testing in a development environment first is highly recommended to ensure everything works as expected.
本文标签:
版权声明:本文标题:theme development - Only show read more text when when wp:post-excerpt meets excerptLength 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736664383a1946586.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
render_block_core_post_excerpt()
) is not pluggable, i.e. it's not wrapped with aif ( ! function_exists() )
check. You could override the post excerpt block'srender_callback
, but perhaps you can first try overriding theexcerpt_length
value (to max40
)? (That block also overrides the value, to 100, but only on the admin and REST API sides - see source) – Sally CJ Commented Jan 31, 2024 at 5:20